Using the Component

[Previous] [Next]

Now it's time to take a look at how we can use the TipOfTheDay component from other applications. Although we won't delve into the details of how each language implements COM clients, we will show you sample code that uses the component from ASP, Visual Basic, and MFC and provide a couple of high-level insights.

Active Server Pages

Active Server Pages currently supports two scripting languages: VBScript and Microsoft JScript. As of this writing, neither of those languages supports early (vtable) binding of COM interfaces, so coclasses invoked in those environments must implement the IDispatch interface. Furthermore, VBScript—by far the most commonly used language within ASP—supports only a single data type: the VARIANT. As described earlier in the chapter, the TipOfTheDay component was designed with these two constraints in mind. Specifically, we made two design decisions to accommodate ASP. First, the ITipOfTheDay interface inherits from IDispatch rather than IUnknown, resulting in a dual interface. Second, the GetNextTip method uses a VARIANT [in, out] parameter to pass the updated cookie back to the caller. The accompanying trade-offs are that the component is more difficult to version (as you'll see shortly) and C++ clients have to coerce their data types to and from a VARIANT.

Listing 4-3 shows the sample code for a simple ASP page that leverages the TipOfTheDay component to embed a tip within the HTML that gets delivered to the browser. The bookmark required by the ITipOfTheDay::GetNextTip method is stored on the client machine using a browser cookie, as facilitated by using the Request and Response objects provided by the ASP run-time environment. Each time the user clicks the browser Refresh button while viewing this page, the cookie will be updated and a new tip will be shown.

Listing 4-3. An ASP page that uses the TipOfTheDay component.

 <%@ LANGUAGE="VBSCRIPT" %> <% If Request.Cookies("TipOfTheDay") = "" Then     Response.Cookies("TipOfTheDay") = "0" End If set tipOfDay = Server.CreateObject("TipServer.TipOfTheDay") lCookie = Request.Cookies("TipOfTheDay") tipText = tipOfDay.GetNextTip(lCookie) Response.Cookies("TipOfTheDay") = lCookie Response.Cookies("TipOfTheDay").Expires = #December 31, 1999# %> <HTML> <BODY> <P>The tip for the day is:</P> <P><FONT color=blue> <% Response.Write tipText & "<br>" %> </FONT></P> <P>(Click refresh to see the next tip).</P> </BODY> </HTML> 

Visual Basic

Visual Basic supports both vtable and dispatch interfaces. It can also support simple structures in addition to the primitive data types encapsulated by the VARIANT. Were it not for the need to support ASP clients, the ITipOfTheDay interface could have been derived from IUnknown instead of IDispatch. Furthermore, the GetNextTip method could have used a long instead of a VARIANT, like so:

 interface ITipOfTheDay : IDispatch {         [id(1), helpstring("method GetNextTip")]         HRESULT GetNextTip([in, out] long* pvCookie,                            [out, retval] BSTR* pbstrText); }; 

Although versions of Visual Basic previous to 4.0 didn't support vtable binding, Visual Basic can now call interface methods directly, without having to wade through the overhead of IDispatch. In this code snippet, the method calls are made via IDispatch:

 Dim lCookie Dim tip As Object Private Sub Form_Load()     lCookie = 0     Set tip = CreateObject("TipServer.TipOfTheDay")     tipText = tip.GetNextTip(lCookie) End Sub Private Sub nextTip_Click()     tipText = tip.GetNextTip(lCookie) End Sub 

In the following code snippet, method calls are resolved using early binding and thus are made directly via the vtable:

 Dim lCookie Dim tip As ITipOfTheDay Private Sub Form_Load()     lCookie = 0     Set tip = New TIPSERVERLib.TipOfTheDay     tipText = tip.GetNextTip(lCookie) End Sub Private Sub nextTip_Click()     tipText = tip.GetNextTip(lCookie) End Sub 

As you can see, the difference between the two snippets is subtle, but the second is significantly more efficient than the first.

To support early binding, the type library for the TipServer DLL must be registered in the Visual Basic References dialog box.

Visual C++/MFC

To show the use of our component from within MFC, we created a simple SDI application using the AppWizard and added the Visual C++ "Tip of the Day" component. Then we ripped out the automatically generated tip storage code and replaced it with calls to the TipOfTheDay COM component, as shown in Listing 4-4.

Listing 4-4. Modifying the Tip Of The Day dialog box to use our COM component.

 #import "../TipServer/TipServer.tlb" no_namespace class CTipDlg : public CDialog { protected:     variant_t vtCookie;     ITipOfTheDayPtr m_tipOfDay;      };   static const TCHAR szSection[] = _T("Tip"); static const TCHAR szIntStartup[] = _T("StartUp"); static const TCHAR szCookie[] = _T("Cookie"); CTipDlg::CTipDlg(CWnd* pParent /*=NULL*/)     : CDialog(IDD_TIP, pParent) {     //{{AFX_DATA_INIT(CTipDlg)     m_bStartup = TRUE;     //}}AFX_DATA_INIT     CWinApp* pApp = AfxGetApp();     m_bStartup = !pApp->GetProfileInt(szSection, szIntStartup, 0);     vtCookie = (long)pApp->GetProfileInt(szSection, szCookie, 0);     HRESULT hResult =          m_tipOfDay.CreateInstance("TipServer.TipOfTheDay");     if(SUCCEEDED(hResult))         GetNextTipString(m_strTip); } CTipDlg::~CTipDlg() {     CWinApp* pApp = AfxGetApp();     ::VariantChangeType(&vtCookie, &vtCookie, 0, VT_I4);     pApp->WriteProfileInt(szSection, szCookie, vtCookie.lVal); } void CTipDlg::GetNextTipString(CString& strNext) {     strNext = (BSTR)(m_tipOfDay->GetNextTip(&vtCookie)); } 

The application is still responsible for rendering the text within the fancy dialog box (see Figure 4-10), but the same engine ASP and Visual Basic use can be shared by the MFC program. Now that's code reuse!

Figure 4-10. The MFC application using the TipOfTheDay component.

Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127 © 2008-2017.
If you may any questions please contact us: