|
|
Examining the Run-Time TextBelow is an example of the run-time text that the VI6 Transition DTC produces. This is a client side DTC so it produces client side text to produce DHTML transition effects. You can view the run-time time of any DTC by right clicking on it in the VI6 Editor and selecting Show Run-Time Text <META HTTP-EQUIV="Page-Enter" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Page-Exit" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Site-Enter" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Site-Exit" CONTENT="revealTrans(Duration=1.000,Transition=1)"> How the DTC remembers its settingsThe DTC stores the values of all the options you select in an Object tag that is not normally visible in the VI6 editor. However, if your open your asp or HTML page in notepad, or select Always View as Text from the right mouse menu, you will see something like the following <!--METADATA TYPE="DesignerControl" startspan <OBJECT classid="clsid:8EA785B1-4738-11D1-B47C-00A0C959BB15" id=PageTransitions1 style="LEFT: 0px; TOP: 0px"> <PARAM NAME="EnterPageDuration" VALUE="1"> <PARAM NAME="EnterPageTransition" VALUE="1"> <PARAM NAME="EnterPageType" VALUE="0"> <PARAM NAME="ExitPageDuration" VALUE="1"> <PARAM NAME="ExitPageTransition" VALUE="1"> <PARAM NAME="ExitPageType" VALUE="0"> <PARAM NAME="EnterSiteDuration" VALUE="1"> <PARAM NAME="EnterSiteTransition" VALUE="1"> <PARAM NAME="EnterSiteType" VALUE="0"> <PARAM NAME="ExitSiteDuration" VALUE="1"> <PARAM NAME="ExitSiteTransition" VALUE="1"> <PARAM NAME="ExitSiteType" VALUE="0"> </OBJECT> --> <META HTTP-EQUIV="Page-Enter" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Page-Exit" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Site-Enter" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <META HTTP-EQUIV="Site-Exit" CONTENT="revealTrans(Duration=1.000,Transition=1)"> <!--METADATA TYPE="DesignerControl" endspan--> First we have an opening HTML comment tag and METADATA tag informing us that what is to come is a designer control (<!-- METADATA TYPE="DesignerControl" startspan>). This HTML comment encloses the OBJECT tag that is used to create the DTC during design time. The comment is closed after the OBJECT tag (</OBJECT>-->). Since this is an HTML comment it is ignored by the browser and stripped out when an asp page is processed at run-time. Following that is the literal run-time text that the DTC has produced. This is what is processed at run-time by the browser or the asp processing. The last line is another HTML Comment with another METADATA TYPE="DesignerControl" tag that indicates to the DTC at design time that this is the end of the DTC stuff. What you need to create a DTCYou can create a DTC in any program capable of producing ActiveX Controls, including: Ø Microsoft Visual C++ 4.1 or later Ø Microsoft Visual Basic version 5.0 or later Ø Borland Delphi or C++ Ø Symantec C++ You'll need the "Microsoft Visual InterDev 6.0 design-time control (DTC) software development kit" too; this provides the type libraries that implement the interfaces for the DTC as well as interfaces for integration with VI6 (so that you can use the Query Builder, URL Picker, and Colour Picker in your DTC). Creating a simple DTCWe are going to use VB6 to produce a simple DTC that will create some VBScript for an asp page. This DTC will be called DateTimeDTC and will create script that will display the current date and time. Just to make it a bit more interesting the DTC will offer a choice of formatting options. Creating the VB projectFirst we need to create the VB Project. Start VB and select an ActiveX Control Project. I called my project ISB and my user control DateTimeDTC. Next we need to add references to the DTC SDK type libraries (you need to have installed the Microsoft DTC SDK for these). Select Project > References and add the following:
If you don't see them in the references list then they will be located in the Include directory provided with the SDK by default, so you can browse to find them there. Create the DTC UI as follows
Creating the Control PropertiesWe are going to have two sets of properties - one for the font formatting, and one for the date / time formatting options. Each of these will be a property page. For the font formatting we are going to use the standard font property page, but for the date / time one we will cook our own. If you want you can use the Visual Basic ActiveX Control Interface Wizard (available on the Add-Ins menu) to create the properties for you. I don't want to concentrate on creating properties here (it's the same for any ActiveX Control) so see the attached Sample code for the actual details of creating the property procedures. Persisting the PropertiesWe want the properties to persist. This is achieved through the use of a property bag object. When you use a control in a VB application the property bag maintains state by writing values into the form file that is the container for the control, and uses an equivalent FRX file (which is a binary data file used to store binary information for the form (.FRM) file with the same file name.) to store binary values such as those that represent images or objects. When we use our control in Visual InterDev the property bag becomes the PARAM values of the OBJECT Tag in the <!--METADATA TYPE="DesignerControl>" span that we saw earlier. This means that the property bag can't hold binary values when implemented as a DTC for Visual InterDev, only text values. This is a limitation of DTC’s in VI6: We can’t store binary values using this mechanism, only text – there is no way to represent an image itself for example (although we could store the location of an image) We create our property bag using the standard UserControl_WriteProperties event procedure and we read them back using the standard UserControl_ReadProperties. These events are exposed in the Visual Basic editor for a user control. So the following procedure will store our properties in the property bag whenever they are changed. 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) PropBag.WriteProperty "DateTimeFormat", m_DateTimeFormat, m_def_DateTimeFormat PropBag.WriteProperty "FontName", m_Font.Name, Ambient.Font.Name PropBag.WriteProperty "FontSize", m_Font.Size, Ambient.Font.Size PropBag.WriteProperty "FontBold", m_Font.Bold, Ambient.Font.Bold PropBag.WriteProperty "FontItalic", m_Font.Italic, Ambient.Font.Italic PropBag.WriteProperty "FontUnderline", m_Font.Underline, Ambient.Font.Underline PropBag.WriteProperty "FontStrikethrough", m_Font.Strikethrough, Ambient.Font.Strikethrough PropBag.WriteProperty "AutoUpdate", m_AutoUpdate, m_def_AutoUpdate End Sub A couple of points: The WriteProperty method of the property bag has an optional default value as the last parameter. Specifying a default as I have done here can reduce the size of the property bag because the value is only written if it is different to the default. Also note that I have split the M_Font object variable into separate properties (FontName, FontSize etc). This is because the property bag, as created in VI6 doesn't support objects so we need to create strings instead. When the DTC is eventually created, registered and included on a web page these properties will look something like the following: <OBJECT classid="clsid:2E02E305-377C-11D3-8DFF-0000E8E0E14E" id=TimeStampDTC1 style="LEFT: 0px; TOP: 0px" VIEWASTEXT> <PARAM NAME="_ExtentX" VALUE="4101"> <PARAM NAME="_ExtentY" VALUE="979"> <PARAM NAME="DateTimeFormat" VALUE="1"> <PARAM NAME="FontName" VALUE="Viner Hand ITC"> <PARAM NAME="FontSize" VALUE="24"> <PARAM NAME="FontBold" VALUE="-1"> <PARAM NAME="FontItalic" VALUE="-1"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikethrough" VALUE="0"> <PARAM NAME="AutoUpdate" VALUE="0"> </OBJECT> To read the properties back, we write the following in the UserControl_ReadProperties event. Private Sub UserControl_ReadProperties(PropBag As PropertyBag) m_DateTimeFormat = PropBag.ReadProperty("DateTimeFormat", m_def_DateTimeFormat) m_Font.Name = PropBag.ReadProperty("FontName", Ambient.Font.Name) m_Font.Size = PropBag.ReadProperty("FontSize", Ambient.Font.Size) m_Font.Bold = PropBag.ReadProperty("FontBold", Ambient.Font.Bold) m_Font.Italic = PropBag.ReadProperty("FontItalic", Ambient.Font.Italic) m_Font.Underline = PropBag.ReadProperty("FontUnderline", Ambient.Font.Underline) m_Font.Strikethrough = PropBag.ReadProperty("FontSize", Ambient.Font.Strikethrough) m_AutoUpdate = PropBag.ReadProperty("AutoUpdate", m_def_AutoUpdate) End Sub Creating the run-time textThe whole purpose of the DTC is to create run-time text. Our DTC is going to create some server side VBScript that will display the date or time, in various formats depending on the options the user of the DTC has selected. We use the IProvideRuntimeText_GetRuntimeText() method to do this; it is the interface method that generates the output of the DTC in the container. My procedure looks like this: Private Function IProvideRuntimeText_GetRuntimeText() As String Dim s As String 'Build a font tag with DHTML sytle tag for font size s = "<FONT face='" & m_Font.Name & "' Style='FONT-SIZE=" & m_Font.Size 'Add DHTML strikethough if its been selected If m_Font.Strikethrough Then s = s & ";TEXT-DECORATION: line-through" 'close the FONT tag s = s & "'>" 'Add other formating as required If m_Font.Bold Then s = s & "<STRONG>" If m_Font.Italic Then s = s & "<EM>" If m_Font.Underline Then s = s & "<U>" 'Create the date time in correct format s = s & vbLf 'make's run time text layout neater If m_AutoUpdate Then s = s & "<% response.write (FormatDateTime(Now, " & m_DateTimeFormat & "))%>" Else s = s & FormatDateTime(Now, m_DateTimeFormat) End If 'Close formatting tags If m_Font.Underline Then s = s & "</U>" If m_Font.Italic Then s = s & "</EM>" If m_Font.Bold Then s = s & "</STRONG>" s = s & vbLf & "</FONT>" 'return the string IProvideRuntimeText_GetRuntimeText = s End Function An example of the run-time text that this procedure could produce is shown below: <FONT face='Viner Hand ITC' Style='FONT-SIZE=26.25'><STRONG><EM> <% response.write (FormatDateTime(Now, 3))%></EM></STRONG> </FONT> Creating the User Interface to our DTCThe recommended way to create a user interface for a DTC is to use property pages. Although you can create in-line interfaces on the control itself, these may not be supported in all containers apps in the future (according to Microsoft). So it's best to go for Property Pages. Again this is a standard ActiveX Control technique so I'm not going to go into details here, however the sample code shows how this works. Creating and Registering the ControlOnce you have created the control and the Property Pages, save your VB project then select File > Make DateTimeDTC.ocx. This will build and register your control under the format ProjectName.UserControlName, so if you used the names I suggested it would be registered as ISB.DateTimeDTC. If you need to register it again or on another computer then you can use the regsvr32 program followed by the location of the file. For example: regsvr32 c:\myprojects\dtc\DateTimeDTC.ocx However this will register the control as an ActiveX control only, not as a DTC. To mark it as a DTC you need to run the Regsvrdcprogram followed by the ProgID. This program comes with the Microsoft DTC SDK and is installed in the tools directory. For example Regsvrdc ISB.DateTimeDTC Using your control in Visual InterDevOnce your control has been registered and marked as a DTC you can use it like any other DTC within a container application such as VI6. In VI6 you add it to your toolbox by right clicking the toolbox and selecting Customise Toolbox. In the resulting dialog select the DTC tab and your control should be there.
Put a tick in the check box, click OK and your control awaits you. Now you can drag it onto the page and then right click and select properties to show your property pages. After you have made changes to the properties, right click on the page and select Show Run-Time Text. You'll see the text that the IProvideRuntimeText_GetRuntimeText() procedure has created. Sharing Information Between DTC'sThe DTC we created in the previous section works in isolation. That is it can't communicate with any other DTC's on the page. However, many of the DTC's that ship with VI6 can share information. For example the recordset DTC publishes the name of the recordset and the grid DTC then subscribes to that information so that it can build a table showing relevant data. How Do DTC's Share informationThe mechanism for sharing information between DTC's is the Choice Engine. This is like an Information Manager for the page. DTC's that wish to make information available to other DTC's will publish information to the Choices Engine. DTC's that wish to subscribe to information published by others notify the Choice Engine about what sort of information they are interested in. The Choice Engine then keeps all the DTC's up to date with all the latest information that they need. Taking a look at the choices on a VI6 page.The DTC SDK comes with a DTC called the Choice Inspector that allows us to examine the choices that are available on the page. This is a useful tool for debugging and for understanding the choices that DTC's provide, as well as the choices VI6 provides, since it too uses the Choice Engine to publish information that the DTC's can use. Refer to the SDK documentation for details on registering and using this DTC. Static Choices and Dynamic ChoicesChoices can be Static or they can be Dynamic. A Static Choice exists until it is explicitly removed in code. Static does not mean that the properties of the Choice are static, just that the Choice itself will persist over time - the properties (such as Text) can change. Static Choices are more efficient than dynamic ones and are the recommended Choice type. A Dynamic Choice is one that is recreated each time it is needed and then, if there is no subscribing DTC, will disappear just as quickly. A Dynamic Choice would be used if the source for the Choice was constantly changing. For example a recordset DTC publishes a dynamic choice for each field in the recordset. When you change the definition or name of the recordset the choices are published again. Creating A DTC that publishes a Static Choice.We are going to walkthrough the creation of a DTC that will publish a choice and a second DTC that will subscribe to that choice. To keep things simpler and more focused we are going to create an in-line interface to the DTC rather than the recommended Property Pages. The Publishing DTC, which we will call NavHeaderDTC, will Ø Allow the web developer to select from a list a pre-built Navigation Bars for the page Ø Create the asp script that will include the appropriate navigation bar header file. Ø Publish the name of the selected navigation bar to the choice engine The Subscribing DTC, which we will call NavFooterDTC, will Ø Subscribe to the NavHeaderDTC choice of Navigation Bar Ø Create the asp script that will include the appropriate navigation bar footer file. Creating the Publishing DTCStart a new VB project and select ActiveX Control. Rename the project to ISB and the User Control to NavHeaderDTC. Select Project > References and add the following:
Open the User Control form and add a frame control then put in three options buttons as in the diagram
The Design Time Control Site ObjectWe need a Design Time Control Site Object to create this object so that we can publish and subscribe to the Choice Engine. To get such an object what we need to do is implement the iDesignTimeControl interface and then assign a variable (of type iDesignTimeControlSite) in the iDesignTimeControl_DesignTimeControlSite method. That object variable is then what we use to communicate with the Choice Engine. Ok, lets go for the code… Open the code window for the User Control and add the following to the General Declarations section. Implements IprovideRuntimeText Implements IdesignTimeControl Dim myDTCSite As IdesignTimeControlSite Dim m_NavBar As String Dim chNavBar As Choice The first interface (IprovideRuntimeText)we met earlier when creating our first DTC. This gives us the GetRuntimeText method that we use to create the run-time text from our DTC. The second interface IdesignTimeControl creates an object that we use to interface with the Choice Engine. One of the events that it exposes is DesignTimeControlSite - this is called when the Choice Engine first comes across the DTC in a document, and allows us to set the site object that we use to publish and subscribe to the Choice Engine. We need to declare a variable of type IdesignTimeControlSite to assign to that site object. Finally we have declared a m_NavBar variable that will hold then name of our selected Nav Bar for the public property procedures, and a chNavBar choice variable that is used to define the choice sent to the Choice Engine. Writing the Code that Creates the ChoiceOnce you typed these lines you will see that VB has added IdesignTimeControl to the code windows object drop down box, together with the events for that object:
Select the DesignTimeControlSite [PropertySet] event and enter the following Private Property Set IDesignTimeControl_DesignTimeControlSite(ByVal RHS As DTC60.IDesignTimeControlSite) 'set the DTC Site object Set MyDTCSite = RHS 'create and publish the choice Set chNavBar = MyDTCSite.Choices.AddChoice(Nothing, m_NavBar, "ISB.NAVBAR") End Property This code assigns a MyDTCSite object to the correct DTC Site from the container app and then, after deciding which Nav Bar has been chosen publishes that choice using the AddChoice method. Adding Stub FunctionsUnfortunately once we have implemented IdesignTimeControl VB needs to have all the methods created in the code window even if we don't use them. This is a standard in VB whenever you Implement any type Interface not just the DTC ones, and it’s something we just need to live with. The easiest way is to select them from the drop down box at the top right of the window. Creating and Persisting the PropertyAs in the first DTC created at the start of this chapter we need to create public property procedures for our navbar property and then persist them with a property bag. See the sample code for details. Create the Run-Time textWe need to create the run-time text that the DTC will generate. For the purposes of this example the DTC will generate server side code that includes the appropriate page for the Nav Bar header. Private Function IProvideRuntimeText_GetRuntimeText() As String Dim s As String s = "<!--#Include file=" & m_navBar & "Header.asp -->" IProvideRuntimeText_GetRuntimeText = s End Function Creating and Registering the ControlSave your VB project then select File > Make NavHeaderDTC.ocx. This will build and register your control under the format ProjectName.UserControlName, so if you used the names I suggested it would be registered as ISB.NavHeaderDTC. If you need to register it again or on another computer then you can use the regsvr32 program followed by the location of the file. For example: regsvr32 c:\myprojects\dtc\NavHeaderDTC.ocx However this will register the control as an ActiveX control only, not as a DTC. To mark it as a DTC you need to run the Regsvrdcprogram followed by the ProgID. This program comes with the Microsoft DTC SDK and is installed in the tools directory. For example Regsvrdc ISB.NavHeaderDTC Testing Your ControlAdd your control to the VI6 Toolbar then drag it onto an asp page. Drag a Choice Inspector DTC below it. As you change the properties on the NavHeaderDTC you should see the Choice Inspector revealing the changes to the description for your ISB.NAVBAR choice type. The Text column will update if you refresh the page. You will need to create Funkyheader.asp, Fishyheader.asp, and Fancyheader.asp pages (with no HTML headers or @ directives at the top of the page as in the standard asp template – remember these pages are included in the pages that the DTC is on, so they form part of an existing page rather than a whole new one) if you want to preview the page in the browser, so that the include actually works. Creating a DTC that publishes a Dynamic ChoiceIf you want to make a Choice dynamic instead of static, then call the AddChoice method directly on the Choices collection passed to the OnGetChoices procedure. This is shown below. Private Sub IDesignTimeControl_OnGetChoices(ByVal dynamChoices As DTC60.Choices) Dim mydynamchoices As Choices Set mydynamchoices = dynamChoices Set chNavBar = mydynamchoices.AddChoice(Nothing, m_navBar, "ISB.NAVBAR") End Sub Remember that dynamic choices are temporary: once the rebind is over, they are discarded unless a ChoiceSink is bound to them. Dynamic Choices are needed if the source for the choice is changing (but not if just the value of a property is changing – a static choice can handle that). For example a if a set of dynamic choices describe the folder structure of a file system, (with one dynamic choice per folder) then the folders may be renamed, deleted or added to. The dynamic choices will need to republish the correct list of folders at each rebind. If a subscribing DTC subscribes to these choices then the Choices are kept so that the DTC can refer to them, but if there are no Subscribing DTC’S (e.g. no bound ChoiceSinks) then the dynamic choices are discarded until the next rebind (when they are recreated again). A static choice in comparison would never show the new or changed folders as new choices, but it would be able show the properties that were defined by the choice (for example the folder size) Creating a Subscribing DTCWe now want to create a NavFooterDTC that subscribes to the ISB.NavBar Choice. This one will have no properties and will just create a server side include that includes the relevant footer Nav Bar. First create a new VB ActiveX Control project and change the project name to ISB and the User Control Name to NavFooterDTC. Add a simple label to the control that displays its name.
Select Project > References and add the following references:
Getting StartedOk open the code window and let's add our interfaces and declare some variables. Implements IProvideRuntimeText Implements IDesignTimeControl Dim MyDTCSite As IDesignTimeControlSite Dim MyChoiceSink As ChoiceSink Dim m_fnavBar As String The Choice Sink is used to filter out the choices that have been published so that only the ones of interest are given to our DTC. We set both these object variables in the following procedure. Private Property Set IDesignTimeControl_DesignTimeControlSite(ByVal RHS As DTC60.IDesignTimeControlSite) Set MyDTCSite = RHS Set MyChoiceSink = MyDTCSite.ChoiceSinks.AddChoiceSink("ISB.NAVBAR") End Property The MyChoiceSink object can now be used to detect choices of type "ISB.NAVBAR". This is the type of choice we created in our Publishing DTC. Creating An Event Handler for when the Choice ChangesThe following method is triggered whenever there is a choice change in the choice engine. We can use our MyChoiceSink variable to check if it is a choice of interest and if so change the caption on the label. Private Sub IDesignTimeControl_OnChoiceChange(ByVal ChoiceSink As DTC60.ChoiceSink, ByVal Change As DTC60.dtcChoiceChange) If ChoiceSink Is MyChoiceSink Then Dim ch As Choice Set ch = MyChoiceSink.BoundChoice If Not ch Is Nothing Then Label1.Caption = ch.Description Else Label1.Caption = "" End If End If End Sub Persisiting the valueAgain we are going to use a property bag to persist the value of the Nav Bar name: Private Sub UserControl_ReadProperties(PropBag As PropertyBag) m_fnavBar = PropBag.ReadProperty("fNavBar", "Fancy") End Sub Private Sub UserControl_WriteProperties(PropBag As PropertyBag) PropBag.WriteProperty "fNavBar", m_fnavBar, "Fancy" End Sub Write the Run-Time TextFinally we are going to create the run-time text Private Function IProvideRuntimeText_GetRuntimeText() As String Dim s As String s = "<!--#Include file=" & Label1.Caption & "Footer.asp-->" End Function Add the stub functionsDon't forget to add the stub functions for all the unused procedures for the IdesignTimeControl object. VB would warn you if you tried to compile without doing this. Testing the DTCCompile and register the control and run regsvrdc on it to make it a DTC. Add it to your VI6 toolbox then drag it to the bottom of the page that has the NavBarHeader DTC on it. As you change the properties of the header, the footer should change too.
Subscribing to Dynamic ChoicesIf you want your DTC to bind to a dynamic choice then use the OnRebind method instead of a ChoiceSink. Dynamic choices only exist during a rebind. Private Sub IDesignTimeControl_OnRebind(ByVal Choices As DTC60.Choices) 'Dynamic binding happens here Dim cf As ChoiceFilter Dim chs As Choices Dim ch As Choice 'create a choice filter for our choice type Set cf = MyDTCSite.CreateChoiceFilter("ISB.NAVBAR") 'create a choices object with all our selected choices in Set chs = Choices.Filter(cf) 'loop through the choices that have been published For Each ch In chs 'do something with ch Next End Sub What's Next?We've successfully built a publishing and subscribing DTC that demonstrates the use of the Choice Engine. If you want to take the Choice Engine further you need to investigate the other methods and properties that are available for the Choice Object. These are summarised below. The SDK has a complete reference for the Choice Object model, which you may want to investigate. Communicating With Visual InterDev 6The DTC SDK provides a dbservice object that gives an interface to the standard VI6 URL Picker, Colour Picker and Query Builder. This means that you can use these features in your own DTC. We can also take advantage of Choices that are published by the VI6 Environment. You would have seen these when you were playing with the Choice Inspector. However Microsoft warns us that these Choices may or may not be carried forward to future versions of Visual InterDev. Calling VI6 ServicesTo use the URL Picker, Colour Picker or Query Builder in your DTC you need to add a reference to the following:
And then Implement the following Implements IProvideRuntimeText Implements IDesignTimeControl Implements IQueryBuilderSink IQueryBuilderSink provides the interface for the pickers as well as the Query Builder, even though it's name suggest otherwise. InitialisationTo use any or all of the services we first need to get a reference to the BuilderWizardManager service provided by this Data Services Support Type Library. This is the object that provides the methods and properties used when calling the VI6 Services. The following is standard code that will achieve that. First though we need to declare a variable of type iBuilderWizardManager and add some constants to the General Declarations section of our module that provide the Class ID's for the services we are going to use: Dim mSrvBldWzMgr As IBuilderWizardManager Const sidBldWizMgr = "{95FC88C2-9FCB-11CF-A405-00AA00C00940}" Const iidBldWizMgr = "{95FC88C3-9FCB-11CF-A405-00AA00C00940}" Here's the InitBldWzMrg procedure that creates the reference: Private Sub InitBldWzMrg() Dim oleObject As IOleObject Dim serviceProvider As IServiceProvider ' Get the IOleObject interface of this control. Set oleObject = Me ' Get the IOleClientSite of this control Set serviceProvider = oleObject.GetClientSite
' Create the reference to the BuilderWizardManager service. Set mSrvBldWzMgr = serviceProvider.QueryService(IIDFromString (sidBldWizMgr), IIDFromString(iidBldWizMgr))
End Sub Calling the URL PickerTo call the URL Picker we first need to add some more constants to the Global Declarations section of our module: Const catURLPicker = "{73CEF3D9-AE85-11cf-A406-00AA00C00940}" Const iidURLPicker = "{12428687-A9D9-11CF-8904-00AA00BDCB98}" We then create a URL Picker object using the GetBuilder method on the Service Builder Wizard Manager and then use the Execute method on it. Unfortunately these methods aren't documented in the SDK, but you can get an idea of them by looking at the Object browser. The GetBuilder method takes the following form: Function GetBuilder(rguidBuilder As VBGUID, grfGetOpt As Long, hwndPromptOwner As Long, objpApp As Object, hwndBuilderOwner As Long, riidBuilder As VBGUID) As Unknown The main parameters we need to know about here are rguidBuilder and the riidBuilder, which are the constants we declared earlier and identify the URL picker among the available ones. The Execute method is the only method or property available for a URLPicker object and takes the form: Function Execute(pIDispatch As Object, hwnd As Long, URL, BaseURL As String, AdditionalFilters As String, DialogTitle As String, TargetFrame, dwFlags As Long) As Boolean The URL parameter of this method returns with the value of the selected URL. The other parameters look after the presentation of the URL dialog (title, baseurl etc). So putting it all together the following code will invoke the URL builder on the click of the cmdURL button and put the selected URL in the txtResults textbox. Private Sub cmdURL_Click() Dim URLPicker As IURLPicker Dim vURL As Variant Dim vFrame As Variant Dim objShell As Object Dim hwndShell As Long
If mSrvBldWzMgr Is Nothing Then Exit Sub
Set URLPicker = mSrvBldWzMgr.GetBuilder( _ IIDFromString(catURLPicker), _ BLDGETOPT_FAUTOMAPGUID, _ ContainerHwnd, _ objShell, _ hwndShell, _ IIDFromString(iidURLPicker))
' Show the URL picker
If URLPicker.Execute(objShell, ContainerHwnd, vURL, "", "", "Enter or select a URL", vFrame, _ URLP_CREATEURLTITLE + URLP_ABSOLUTEURLTYPE + URLP_DISALLOWDOCRELATIVEURLTYPE + _ URLP_DISALLOWROOTRELATIVEURLTYPE + URLP_DISALLOWASPOBJMETHODTYPE) Then
txtResults.Text = vURL End If End Sub Calling the Color PickerCalling the Color Picker is similar to the URL Picker. Again we need to add some constants to the Global Declarations section of the module: Const catColorPicker = "{73CEF3DA-AE85-11cf-A406-00AA00C00940}" Const iidColorPicker = "{533AC2A3-1ACE-11D1-A787-0000F80272EA}" Then we create a variable of IHTMLColorPicker type by calling the GetBuilder method on the Service Builder Wizard Manager, and call the execute method on this object. The Execute method (the only member for this object) for the Color Picker object takes this form: Function Execute(objApp As Object, hwndOwner As Long, pvarColor) As Boolean The pvarColor parameter returns the colour that has been selected in the HTML form. So putting it all together: Private Sub cmdColor_Click() Dim colorPicker As IHTMLColorPicker Dim vColor As Variant Dim objShell As Object Dim hwndShell As Long
If mSrvBldWzMgr Is Nothing Then Exit Sub
Set colorPicker = mSrvBldWzMgr.GetBuilder( _ IIDFromString(catColorPicker), _ BLDGETOPT_FAUTOMAPGUID, _ ContainerHwnd, _ objShell, _ hwndShell, _ IIDFromString(iidColorPicker))
' Show the color picker
If colorPicker.Execute(objShell, hwndShell, vColor) Then txtResults.Text = vColor End If
End Sub Calling The SQL BuilderThe SQL Builder requires a little more work, but follows a similar pattern to begin with. Lets create the constants that we'll need (again in Global Declarations) Const guidService = "{af31b8c0-bdcc-11d0-b218-00c04fd70811}" Const iidService = "{6FF02AB1-809B-11d1-9D27-006008058731}" Before we can use the builder we need to get a list of all the Data Environment connections to present to the user and to base the SQL Builder on. We do this by asking the IDTCExtendededServices to publish all the names of them as Dynamic Choices. This is achieved through the UsesDataBaseServices method of the an IDTCExtendededServices object as seen below: Private Sub InitDataServices() Dim oleobject As IOleObject Dim serviceProvider As IServiceProvider Dim srvDTCServices As IDTCExtendedServices Set oleobject = Me
Set serviceProvider = oleobject.GetClientSite
'Get interface for the IDTCExtendedServices service. Set srvDTCServices = serviceProvider.QueryService(IIDFromString(guidService), IIDFromString(iidService)) 'Set srvDTCServices = serviceProvider.QueryService(IIDFromString(guidService), IIDFromString(iidService)) If Not srvDTCServices Is Nothing Then 'Tell Extended Services to publish the Choices srvDTCServices.UsesDataBaseServices End If End Sub This procedure doesn't return the names of the connections; it just has them published in the Choices Engine as Dynamic Choices. So to go and get them and put them in a combo box we need to first declare a site variable in Global Declarations: Dim myDTCSite As IdesignTimeControlSite While we're at it lets create a module level variable for the SQLQueryBuilder object too. Dim mSQLBulder As Object Now we need to assign the myDTCSite object a reference to the current site in the IDesignTimeControl_DesignTimeControlSite method: Private Property Set IDesignTimeControl_DesignTimeControlSite(ByVal RHS As DTC60.IDesignTimeControlSite) Set myDTCSite = RHS End Property Next we need to get a reference to a querybuilder object. This is achieved in the rebind method of the IDesignTimeControl interface. Private Sub IDesignTimeControl_OnRebind(ByVal Choices As DTC60.Choices) Dim cf As ChoiceFilter Dim chs As Choices Dim ch As Choice
'set choice filter to the type of choice we want Set cf = myDTCSite.CreateChoiceFilter("VID98.DataSourceName") 'get all the choices that match the filter Set chs = Choices.Filter(cf)
'loop through all the choices For Each ch In chs 'set our query builder object to the query builder Set mSQLBuilder = ch.Tags("QueryBuilder") If Not mSQLBuilder Is Nothing Then Exit Sub Next
End Sub This code just finds the first valid connection and then exits with the mSQLBuilder object set to that one. You could enhance this by presenting the user with a list of connections to choose from in say a combo box then matching the text selected of the combo to the text property of the choice. If the choices published by the Extended Services were static rather than dynamic we would have used a ChoiceSink in the onChoiceChange method (as we did in the Creating A Subscribing DTC above) to collect them in rather than the OnRebind Method. We now have an mSQLBuilder object, which has a LaunchQueryBuilder which we can take advantage of. Private Sub cmdSQL_Click() If (Not mSQLBuilder Is Nothing) Then mSQLBuilder.SetQueryBuilderSink Me mSQLBuilder.LaunchQueryBuilder "Query Builder" End If End Sub When the cmdSQL button is clicked, we first check to see if the mSQLBuild variable has something in it. The QueryBuilder requires a sink object that implements the IQueryBuilderSink interface, so we set that to Me (a reference to the current control i.e. our DTC), then launch the Query Builder on the last line. The LaunchQueryBuilder method does not return any parameters; instead the IQueryBuilderSink interface provides the following two methods Private Property Let IQueryBuilderSink_SQLString(ByVal RHS As String) ' The query builder will call this method when ' it's being dismissed and the user answered ' 'yes' to the 'Save changes' prompt. txtResults.Text = RHS End Property Private Property Get IQueryBuilderSink_SQLString() As String ' The query builder calls this method ' before bringing up its UI. It's ' our chance to specify the initial text of the query. IQueryBuilderSink_SQLString = txtResults.Text End Property Evaluating the EnvironmentWe've seen above how VI6 publishes dynamic choices of type VID98.DataSourceName, which contain all of the data connections in a project. There are two other types that it publishes: An Environment Choice and a State Choice. These are detailed in the SDK documentation. Distributing a DTCYou distribute your DTC the same way as any other ActiveX control with the exception that they have to be marked as DTC's by you installation process. To do this you need to create a registration file with a section as follows for each DTC you have created [HKEY_CLASSES_ROOT\CLSID\{675E2CCD-540C-11D2-A0B8-0000F81E0CE1}\Implemented Categories] [HKEY_CLASSES_ROOT\CLSID\{675E2CCD-540C-11D2-A0B8-0000F81E0CE1}\Implemented Categories\{73CEF3DD-AE85-11CF-A406-00AA00C00940}] The CLSID number needs to match exactly the classid of your DTC. You can find the CLSID of your DTC by looking in the registry (using Regedit and looking under the HKEY_CLASSES_ROOT key for the progid, which is in the form ProjectName.UserControlName) or by using the OLEView program that ships with Visual Interdev. |
|
|
|
|
|
| |
Information Online swimming pool builder chicago web site design spfxmasks Cheap Web Hosting conference calling Versace sunglasses answering service |
Email TopXML
|
|
Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP |