Sunday, August 24, 2008

Adding Tooltip To An ActiveX Control

By default, ActiveX controls do not support tooltips. This article demonstrates how to add tooltip to an ActiveX control. This control can be used to add tooltips to ActiveX controls that we develop. Steps Involved: We have used the 'MFC ActiveX Control Wizard' to develop the 'mytooltip' control. The steps involved are enumerated below:

(a) Select 'MFC ActiveX Control Wizard' as new project type with project name as 'mytooltip'. Click on 'OK'. to let the wizard generate the code.

(b) Open the 'stdafx.h' file associated with the project and add the following line: #include

The header file 'afxcmn.h' contains declarations for MFC classes that serve as wrappers to Windows Common Controls including CToolTipCtrl. Add the following lines to COleControl-derived class CMytooltipCtrl located in 'mytooltipctl.h': CToolTipCtrl m_ttip; Use ClassWizard to add an OnCreate( ) handler to the message map. It is in this routine that the ToolTip control will be created. Add the following code to this handler:

m_ttip.Create ( this ) ;
m_ttip.AddTool ( this, LPCTSTR ( m_toolTipText ) ) ;
m_ttip.SetTipBkColor ( RGB ( 255,255,0 ) ) ;
m_ttip.SetTipTextColor ( RGB ( 255,0,0 ) ) ;

Alter CMytooltipCtrl::DoPropExchange( ) by adding code to initialize the m_toolTipText and m_showToolTip properties:

PX_Bool(pPX, _T("ShowToolTip"), m_showToolTip, FALSE);
PX_String(pPX, _T("ToolTipText"), m_toolTipText, _T(""));

To allow the user of the control some control over the ToolTip functionality, use ClassWizard to add the following Automation properties to the CBasicCtrl class:

External Name: ShowToolTip ToolTipText
Type: BOOL CString
Variable name: m_showToolTip m_toolTipText
Notification function: OnShowToolTipChanged OnToolTipTextChanged

ShowToolTip will allow the user to suppress the display of the tooltip, and ToolTipText will track the text that is to be displayed when the tooltip is visible. To make this work we have added a virtual function PreTranslateMessage( ) to the control class and called RelayEvent( ) function from it.

Directory Copy Control

Frequently we wish to build a control which copies one directory to another. The standard 'File' dialog is not of much use here since it cannot be used as a control inside another dialog. Also the standard 'File' dialog permits selection of only files and not of directories. To meet this requirement we have developed here an ActiveX directory control. We have used the 'MFC ActiveX Control Wizard' to develop the dircopy control. The steps involved are enumerated below:

  1. Select 'MFC ActiveX Control Wizard' as new project type with project name as 'DirCopy'. Click on 'OK'.

  2. In Step 1 of 2 select '1' for 'How many controls would you like your project to have?'. Click on 'Next'. Click on 'Finish' to let the wizard generate the code.

Next we have added an OnCreate( ) handler to the CDirCopyCtrl class. From the OnCreate( ) handler we have made a provision to create tooltips. For more information on tooltips to an activex control see 'ToolTips to an activx control' in the same website. and then we have laoded a bitmap. In OnDraw( ) handler we have built the folder bitmap using BitBlt( ) . We have added OnLButtonDown( ) handler to CDirCopyCtrl. In this handler we have written a code for popping up a copy dialog, so whenever we click left mouse button on the folder bitmap a copy dialog gets popped up. This dilaog box contains two edit boxes one for source and another for target directory. We can also browse for the directoy using the 'Browse' button present on the copy dialog . Whenever we click on the 'Browse' button 'dirdialog' gets popped up and helps you to browse the directory from the treeview control. After browsing both the directory paths we can click on copy button to copy the directory.



ActiveX Directory Control

This article demonstrates use of stock property pages in an ActiveX control. The system provides three stock property pages that ActiveX controls can use: a color page for color properties, a picture page for picture properties and a font page for font properties. Here we have created an edit control whose properties can be changed using the color and a font property page. This control has been developed using 'MFC ActiveX Control Wizard'. While going through the steps of the Wizard we chose 1 control for ' ' and 'EDIT' window as a subclass. To add property pages to the control do the following:

  1. Open 'MFC ClassWizard' dialog box. Select the 'Automation' tab sheet. Click on the 'Add Property' button.

  2. From the 'External Name' combo box select 'Font' and 'Back Color'. By adding external names we can interact with the property pages.

  3. Add the following two lines:

PROPPAGEID(CLSID_CFontPropPage)
PROPPAGEID(CLSID_CColorPropPage)
between
BEGIN_PROPPAGEIDS( )
END_PROPPAGEIDS( )

This helps in adding property pages to the 'Properties' dialog of our control. We have used the color property page to select the color for the background of the edit window and font property page to select the style of text which appears in the edit window. To paint the background of the edit control we have added following lines in the OnDraw( ) function of the CStockpagesCtrl class.

COLORREF clrBackGround = TranslateColor ( GetBackColor( ) ) ;
CBrush* prevbrush ;
CBrush brBackGround ( clrBackGround ) ;
pdc -> FillRect ( rcBounds, &brBackGround ) ;
prevbrush = pdc -> SelectObject ( &brBackGround ) ;
pdc -> SelectObject ( prevbrush ) ;
CRect rc ( rcBounds ) ;
pdc -> DrawEdge ( rc, EDGE_SUNKEN, BF_RECT ) ;

As we type in the edit window we get the default backgorund color of the text. This brings a bad effect of erasing the background color of the edit window. To prevent this we have to make the default background color of the text as transparent. For this we have added a message handler CtlColor( ) for the message ON_WM_CTLCOLOR_REFLECT( ) and have added the following code to it:

pDC->SetBkMode(TRANSPARENT);

To change the font of text we just have to select the type from the property page and the effect is seen without writing a single line of code.


Client Program That Uses Directory List And File List

This program uses two ActiveX controls: a 'Dir' control and a 'Filelist' control. Creation of these controls has been discussed in the first two articles of the section 'ActiveX' in this same site. We have created the a dialog-based project called 'client' using MFC AppWizard. To use the ActiveX controls they have to be registered with the Windows registry. If you want to register these controls on your machine you will have to download these controls from the first two articles in the section 'ActiveX' on this site. Once registered these controls can be inserted in the dialog box. using the following procedure: From the 'Project' menu select 'Add To Project' then select 'Components and Controls'. A dialog box will be popped up. Open 'Registered ActiveX Controls' folder. Search for the control to be inserted; in our case 'Dir' control and 'Filelist' control. Double click on both the controls to insert them in the project. The bitmaps of these controls would now be visible in the 'Controls' toolbar of the dialog editor. Pick both and paste them side by side. You can see the preview of both in the dialog box. The dialog that we created is shown in Figure 1. Run the application to see the effect. The two controls are independent of one another. Our client program helps them to interact. When we select any directory from the 'Dir' control our client program recieves an event with full path of the selected directory. The client program then calls SetPath( ) and SetFormat( ) functions of the 'Filelist' control. Hence whenever we select the directory from the 'Dir' control the files present in the specified directory are listed in 'Filelist' control. When we click on the filename from the 'Filelist' control our client program recieves an event with full path of the selected filename which is then displayed in the edit box.


File List Control

Like the standard 'File' dialog that lists files of the specified types we wish to create a control that would list files of the specified type present in the specified directory. As against the standard 'File' dialog this control can be embedded into a dialog or a form. Steps Involved: We have used the 'MFC ActiveX Control Wizard' to develop the directory control. The steps involved are enumerated below:

(a) Select 'MFC ActiveX Control Wizard' as new project type with project name as 'filelist'. Click on 'OK'.

(b) In Step 1 of 2 select '1' for 'How many controls would you like your project to have?'. Click on 'Next'.

(c) In Step 2 of 2 select 'SysListView32' for 'Which window class, if any, should this control subclass?'. Click on 'Finish' to let the wizard generate the code.

Click on the 'Class View' tab and in the PreCreateWindow( ) virtual function you can see the line cs.lpszClass = _T("SysListView32"); This line indicates that SysListView32 window class has been made as a subclass of the listexplorer control. Hence the messages would be received by the control class before reaching the SysListView32 window class. To change the style of the tree window we have added:

cs.style |= WS_CHILD | WS_BORDER | LVS_SMALLICON | LVS_SHOWSELALWAYS ;

Next we have added an OnCreate( ) handler to the CFilelistCtrl class. From the OnCreate( ) handler we have called addtolist( ) function. This function finds the files depending on the type of the specified directory. The default type is '*.*' and the default specified directory is 'c:\'. The default type and the directory are represented by two member variables of the CFilelistCtrl class. The addtolist( ) function uses a pointer to CListCtrl class's object to add filenames to the list control. The pointer variable has been defined as a public data member of the CListexplorerCtrl class. The pointer has been initailised with the handle of the list control in the OnCreate( ) handler. On selecting items (filenames) from the list control we have fired an event consisting the fullpath with filename. This is done in onitemchanged( ) function which gets called on selecting any item. The event has been fired by using the function FireGetPathFromList( ) function. We have also added a custom property page which consists of two edit boxes one for the type of file to be listed and the second for the directory path. This requires two property variables 'path' and 'format' to be added. Using these two variables we can access values from the custom property page in DoPropExchange( ) function. As we add two property variables (path and format) two functions(OnPathChanged( ) and OnFormatChanged( ) respectively) are added to the CFilelistCtrl class. These functions get called as we click on 'Apply' button of the property dialog box. From these functions we have called addtolist( ) function to reflect the changes in the list control. If we run this program the control will register itself with the Windows registry on that machine. A dialog box would be displayed asking for the exe file to be used as a container for this control. We can 'Microsoft's ActiveX Test Container' to display the control. Here we have to insert our control from the 'Insert control' box. The container contains of a splitter window. The upper window displays the control and the lower window displays the events generated by the control.

ActiveX Directory Control

Frequently we wish to display a list of directories as a control inside a dialog. The standard 'File' dialog is not of much use here since it cannot be used as a control inside another dialog. Also the standard 'File' dialog permits selection of only files and not of directories. To meet this requirement we have developed here an ActiveX directory control. Steps Involved:
We have used the 'MFC ActiveX Control Wizard' to develop the directory control. The steps involved are enumerated below:

  1. Select 'MFC ActiveX Control Wizard' as new project type with project name as 'Dir'. Click on 'OK'.

  2. In Step 1 of 2 select '1' for 'How many controls would you like your project to have?'. Click on 'Next'.

  3. In Step 2 of 2 select 'SysTreeView32' for 'Which window class, if any, should this control subclass?'. Click on 'Finish' to let the wizard generate the code.

Click on the 'Class View' tab and in the PreCreateWindow( ) virtual function you can see the line

cs.lpszClass = _T ( "SysTreeView32" ) ;

This line indicates that SystreeView32 window class has been made as a subclass of the directory control. Hence the messages would be received by the control class before reaching the SystreeView32 window class. To change the style of the tree window we have added:

cs.style |= TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | WS_BORDER ;

Next we have added an OnCreate( ) handler to the CDirCtrl class. From the OnCreate( ) handler adddrives( ) function has been called that adds drives to the CString variable. This function in turn calls adddriveitems( ) to add to the tree control drives and a '+' against each drive. The adddriveitems( ) function uses a pointer to CTreeView object to add items to the tree control. This pointer has been defined as a pubic member variable of CDirCtrl class and has been intialised with the handle on the tree control. When we click on '+' sign or double click on the drive name in the tree control, the control tries to send a notification message to the parent that the item is being expanded. Since there is no parent in this control and we want that the control should get the notification we have added the following entry in the message map of CDirCtrl class.

ON_NOTIFY_REFLECT ( TVN_ITEMEXPANDING, onexpanding )

This results into the onexpanding( ) function getting called whenever a notification arrives. This function first deletes the empty enter which was added to get the '+' sign. Secondly, it calls adddir( ) function to add subdirectories of the selected drive. The sub-directories having more directories inside them would get '+' sign before them. On double clicking such sub-directories the control will receive the reflected notification message. Again the control would be transferred to the onexpanding( ) function which will now list the sub-sub-directories of the selected directory. On double clicking the item or single clicking the '-' of the expanded directory, the control gets the reflected message. This time we delete all the entries under this item by calling the deleteallchild( ) function. As we select item in the tree control the control fires an event to the container with the full path of the selected directory. To accomplish this an event with the name sendpath( ) has been added to the CDirCtrl class. The sendpath( ) event has been fired from the handler onSelChange( ) that gets called on selection of any item. If we run this program the control will register itself with the Windows registry on that machine. A dialog box would be displayed asking for the exe file to be used as a container for this control. We can 'Microsoft's ActiveX Test Container' to display the control. Here we have to insert our control from the 'Insert control' box. The container contains of a splitter window. The upper window displays the control and the lower window displays the events generated by the control.

Your Title