| Tenouk C & C++ | MFC Home | ATL Attributes 1 | C++, MFC, Winsock & WinInet 1 | Download | Site Index |


 

 

 

 

 

 

ATL - Attributes Tutorial on Visual C++ .Net part 2

 

 

 

 

 

 

Program examples compiled using Visual Studio/C++ .Net 2003 compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this tutorial are listed below. Don’t forget to read Tenouk’s small disclaimer. The supplementary note for this tutorial is the early stage of the .NET.

 

 

 

 

Step 4: Adding the Client Object

 

In this step, you will add a client object (named CDispCtl) to the client project. This client object will be implemented by a simple, lightweight control added by the Add Class dialog box.

 

Adding the client object to the project

 

  1. In Class View, right-click the DispClient project.

  2. On the shortcut menu, click Add and then click Add Class. The Add Class dialog box appears.

 

Figure 15: Adding a new class to DispClient.

 

Figure 15: Adding a new class to DispClient.

 

  1. From the ATL folder, double-click ATL Control. The ATL Control Wizard appears.

  1. In the Short name field, type DispCtl. The remaining fields are automatically completed.

 

Figure 16: ATL Control Wizard, Names page.

 

Figure 16: ATL Control Wizard, Names page.

 

 

  1. Click the Options tab.

  2. Select Minimal control.

  3. Change the Threading Model to Single.

 

Figure 17: ATL Control Wizard, Options page.

 

Figure 17: ATL Control Wizard, Options page.

 

  1. Click the Interfaces tab.

  2. Move IDataObject and IProvideClassInfo2 to the Supported column.

 

Figure 18: ATL Control Wizard, Interfaces page.

 

Figure 18: ATL Control Wizard, Interfaces page.

 

  1. Click Finish to generate the CDispCtl class.

 

CDispCtl inherits from all the ATL template classes required for a light control. Additionally, the class inherits from IDataObjectImp, providing methods to support Uniform Data Transfer, and IProvideClassInfo2Impl, allowing the access of type information for the object's coclass from other COM objects. Registration of the control is achieved using the registration_script attribute. The parameter on this attribute is the name of the registration script, in this case Control.rgs, which is the default registration script for controls.

Also included is a default implementation of the OnDraw() method.

The final step is to add the event_receiver attribute to the new class.

 

Adding an attribute to an existing class

 

  1. In Class View, double-click the DispClient node and click the CDispCtl class. This will display the class definition for CDispCtl.

  2. Just above the class definition is the attribute block for the class. Add event_receiver(com) to the attribute block. Don’t forget to put a comma at the end of the previous line of code.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------------------------------------------------------------------------------------------

Attributes Tutorial on Visual C++ .Net

 

Listing 5.

 

 

The resulting attribute list should resemble the following:

 

[

   coclass,

   threading("single"),

   progid("DispClient.DispCtl"),

   version(1.0),

   uuid("E26DD5C9-DE30-46FF-B6B6-51F31840B437"),

   registration_script("control.rgs"),

   event_receiver(com)

]

 

In the next step, you will add the needed interfaces to the control object.

 

Step 5: Adding the Client Interfaces

 

In this step, you will implement the various methods of the IDispCtl interface. To allow the client object to handle events fired from the _IDispServEvents interface you need to allow access to the interface exposed by the CDispServ class.

 

To allow the client object to handle events

 

  1. Open DispCtl.h in your source editor.

  2. Add the following line below the #include <atlctl.h> line:

 

#import "progid:DispServer.DispServ.1" embedded_idl, no_namespace

 

Attributes Tutorial on Visual C++ .Net

 

Listing 6.

 

This assumes that your class name is DispServer.

 

In the last step, we added a simple client object (CDispCtl) with an empty interface to the project. At this point, you need to add the following methods to the IDispCtl interface:

To add the methods to your interface

 

  1. In Class View, double-click the IDispCtl node under the DispClient project.

  2. In the Source editor, add the following lines to the IDispCtl interface:

 

[id(1), helpstring("method Connect")] HRESULT Connect();

[id(2), helpstring("method Disconnect")] HRESULT Disconnect();

[id(3), helpstring("method Send")] HRESULT Send(VARIANT data);

 

Attributes Tutorial on Visual C++ .Net

 

Listing 7.

 

The interface should now resemble the following code:

 

[

   object,

   uuid(...),

   dual,

   helpstring("IDispCtl Interface"),

   pointer_default(unique)

]

__interface IDispCtl : IDispatch

{

   [id(1), helpstring("method Connect")] HRESULT Connect();

   [id(2), helpstring("method Disconnect")] HRESULT Disconnect();

   [id(3), helpstring("method Send")] HRESULT Send(VARIANT data);

};

 

In the next step, you will add the implementation of the IDispCtl methods and modify other sections of code.

 

Step 6: Implementing the Client

 

In this step, you will implement IDispCtl's methods in CDispCtl, add an event handler, and modify the OnDraw() function.

 

Implementing the IDispCtl Interface

 

CDispCtl is where you will implement methods declared in IDispCtl. The implementation begins with adding the following three data members, used by the new methods:

To add the data members

 

  1. In Class View, double-click the IDispCtl node under the DispClient project.

  2. In the Source editor, add the following lines at the end of the CDispCtl class, in a private: section:

 

private:

   // Data

   bool m_bConnected;

   CComPtr<IDispServ> m_spIServ;

   CComVariant m_OutText;

 

Attributes Tutorial on Visual C++ .Net

 

Listing 8.

 

  1. To initialize the new data members, modify the default constructor to match the following:

 

CDispCtl()

{

   m_bConnected = false;

   m_OutText = L"Not connected";

}

 

Attributes Tutorial on Visual C++ .Net

 

Listing 9.

 

  1. To ensure that you disconnect from the server upon exiting, add a destructor for the CDispCtl class. Add the following directly below the default constructor declaration:

 

~CDispCtl()

{

   Disconnect();

}

 

Attributes Tutorial on Visual C++ .Net

 

Listing 10.

 

The first method you will implement is the Connect() method. This method creates an instance of CDispServ using CoCreateInstance() and connects the Transfer() event from the newly created instance of CDispServ to the event handler method, OnTransmit() (not yet implemented). The connection is achieved by the __hook keyword.

 

To implement the Connect() method

 

Below the data members created earlier, add the following code:

 

HRESULT Connect()

{

   HRESULT hr;

   hr = m_spIServ.CoCreateInstance(__uuidof(CDispServ));

   if (SUCCEEDED(hr))

   {

      hr = __hook(&_IDispServEvents::Transfer, m_spIServ, CDispCtl::OnTransmit);

   }

   if (hr == S_OK)

   {

      m_bConnected = true;

      m_OutText = L"Connected";

   }

   FireViewChange();

   return(hr);

}

 

Attributes Tutorial on Visual C++ .Net  

 

Listing 11.

 

The implementation of the Disconnect() method uses __unhook to disconnect the event and Release() to release the instance of CDispServ created earlier.

 

To implement the Disconnect() method

 

Below the Connect() method, add the following code directly:

 

HRESULT Disconnect()

{

   if (m_bConnected)

   {

      HRESULT hr = __unhook(&_IDispServEvents::Transfer, m_spIServ,CDispCtl::OnTransmit);

      if (SUCCEEDED(hr))

      {

         m_spIServ.Release();

         m_bConnected = false;

      }

      return(hr);

   }

   return(S_OK);

}

 

Attributes Tutorial on Visual C++ .Net

 

Listing 12.

 

Adding the Event Handler

 

For the control to respond to events fired from the server, you need to implement a handler (called OnTransmit()) for the Transmit() event. The OnTransmit() event handler takes the data passed in from the Transfer() event and places it in the m_OutText data member. It then calls FireViewChange() (not yet implemented), which updates the control by displaying the contents of the m_OutText data member.

 

To implement a handler for the Transmit event

 

Add the following code to the source file, below Disconnect():

 

HRESULT OnTransmit(VARIANT data)

{

   if (data.vt == VT_BSTR)

      m_OutText = data;

   FireViewChange();

   return(S_OK);

}

 

Attributes Tutorial on Visual C++ .Net

 

Listing 13.

 

The last method you will implement is the Send() method. This method sends data to the server object.

 

To implement the Send() method

 

Add the following code to the source file, below OnTransmit():

 

HRESULT Send(VARIANT data)

{

   if (m_bConnected)

      m_spIServ->Send(data);

   return(S_OK);

}

 

Attributes Tutorial on Visual C++ .Net

 

Listing 14.

 

Modifying the OnDraw() Method

 

The final modification you will make is to the CDispCtl::OnDraw method. The OnDraw() method needs to output the contents of the data member m_OutText to the screen.

 

To modify the OnDraw() method

 

Replace the body of the existing OnDraw() method with the following:

 

USES_CONVERSION;

LPCTSTR text = OLE2CT(m_OutText.bstrVal);

RECT& rc = *(RECT*)di.prcBounds;

Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);

TextOut(di.hdcDraw,

   (rc.left + rc.right) / 2,

   (rc.top + rc.bottom) / 2,

   text,

   lstrlen(text));

 

return S_OK;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Attributes Tutorial on Visual C++ .Net

 

Listing 15.

 

The DispClient control is now complete. Build the control by selecting Build DispClient from the Build menu.

 

Step 7: Using the Client Control

 

In this step, you will use the client control to invoke the methods.

 

To use the client control

 

  1. On the Tools menu, click ActiveX Control Test Container. This starts Tstcon32.exe.

  2. Click the New Control button on the toolbar to insert a client controls (CDispCtl).

 

Figure 19: Inserting new control to ActiveX Control Test Container.

 

Figure 19: Inserting new control to ActiveX Control Test Container.

 

Figure 20: Selecting control in ActiveX Control Test Container.

 

Figure 20: Selecting control in ActiveX Control Test Container.

 

Figure 21: CDispCtl object in ActiveX Control Test Container.

 

Figure 21: CDispCtl object in ActiveX Control Test Container.

 

  1. Right-click the control and click Invoke Method on the shortcut menu. The Invoke Method dialog box appears.

  2. Ensure that Method Name is set to Connect and click Invoke.

 

Figure 22: Invoking the Connect() method of the CDispCtl control in ActiveX Control Test Container.

 

Figure 22: Invoking the Connect() method of the CDispCtl control in ActiveX Control Test Container.

 

  1. Right-click the control and click Invoke Method on the shortcut menu. The Invoke Method dialog box appears.

  2. Set Method Name to Send.

  3. Change the parameter type on the Send method to VT_BSTR.

  4. Enter any string in the Parameter Value box.

 

Figure 23: Invoking the Send() method of the CDispCtl control in ActiveX Control Test Container.

 

Figure 23: Invoking the Send() method of the CDispCtl control in ActiveX Control Test Container.

 

  1. Click the Invoke button. The string is displayed in all connected controls.

 

Figure 24: CDispCtl in action.

 

Figure 24: CDispCtl in action.

 

--------------End-----------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. Porting & Migrating your older programs.

  4. MSDN Library

  5. DCOM at MSDN.

  6. COM+ at MSDN.

  7. COM at MSDN.

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | ATL Attributes 1 | C++, MFC, Winsock & WinInet 1 | Download | Site Index |