The WNDCTRL Reusable Class


Sample image of WndCtrl

Click here for larger image


Sample image of WndCtrl

Click here for larger image

Environment: Windows 95/98, Windows NT/2000, Visual C++ 5 & 6

CWndCtrl


Background:

I made this ‘re-usable’ class as part of a project i am working on. The project interface had some special requirements, which could only have been met by some extensive coding OR by making the re-usable class explained below. I named this class ‘WndCtrl‘.

Introduction:

I know it is bad practice to have an ‘introduction’ after a background but …

This class basically accomodates the existance of some hidden controls/windows. A WndCtrl object has two states, namely
an OPEN state and a CLOSED state. You have to add the controls you want to m_WndCtrl. The controls are created when the WndCtrl is opened, and hidden/destroyed when the WndCtrl is closed. The WndCtrl will be the ‘Parent’ of all the controls added to it. The WndCtrl has the capability to be resized/repositioned in either CLOSED or OPEN state. However, the size of the Closed state is static and cannot be changed. Whatever resizing is done, will be for the Open state of WndCtrl.

Base Class:

The WndCtrl class has been derived from the ‘generic CWnd’ MFC class.

WndCtrl:

A WndCtrl is a Window consisting of two permanent “STATIC” controls and a variable list of controls added after creation.
The first static control is the Open Status Indicator. The Open Status Indicator is also used to change the Open
Status of WndCtrl
. The Open Status Indicator is a two state bitmap static control. The second static control is the
Title. The title is specified during creation.

Image indicating the 'Open Status Indicator' and the 'Title'

States:

As stated above, a WndCtrl has two states, Open or Closed. A WndCtrl will be in the closed state upon initialization. The two states are shown in the following image taken from the demo application given bellow:

Image of Closed State of WndCtrl

Image of Open State of WndCtrl

The open and closed states of WndCtrl can be toggled by two ways. Namely, by clicking on the Open Status Indicator, and by using the following function:


//specify false to close the WndCtrl
bool OpenWndCtrl(bool bOpen = TRUE);

Creation:

A WndCtrl is created by using its overloaded Create function. (See the list of prototypes of functions below). The Create function internally calls the CWnd::CreateEx function. The WndCtrl is initially in the Closed state. The Closed size of WndCtrl cannot be changed, unless changes are made in the WndCtrl class. Suppose the u have declared a WndCtrl object by the name of m_WndCtrl. Use the following general code to create the object:


m_WndCtrl.Create (“Title”,
WS_???, //WINDOW STYLES
WS_EX_???, //EXTENDED WINDOW STYLES
int x,
int y,
pParent,
id );

Adding Controls:

Without the addition of controls, a WndCtrl object will not open (unless you change the CWndCtrl Class). Controls can be added to a WndCtrl object by using the AddControl() function. Use the following general code to add a control with variable name of m_ctrl to the WndCtrl Object m_WndCtrl:


m_WndCtrl.AddControl(&m_ctrl,
CRect(?,?,?,?), //Client Coods of the WndCtrl
CLASS NAME, //Registered control class name
“Control Window Text”,
WINDOW/CONTROL STYLES, // Don’t need WS_CHILD OR WS_VISIBLE
EXTENDED WINDOW/CONTROL STYLES,
id);

Note 1: Without the additions of controls, the WndCtrl Object will not open.

Note 2: The control window will be clipped or hidden if the coods and the open height of the WndCtrl are not compatible.

Setting Height and Width(optional):

The default open height and width of a WndCtrl are 300 and 300 respectively. The changing of the open heights and widths can be done by calling the following functions:

SetOpenHeight(height);
SetOpenWidth(width);

where height and width are the new required heights and widths

Incrementing Height and Width(optional):

As an added feature, the open height and width of a control can be
incremeted or decremeted, in either the closed or open state. The WndCtrl
resizes and repositions automatically. This can be used for resizing controls
in the WndCtrl. The following functions are used for this purpose:

IncrementOpenHeight(increment);
IncrementOpenWidth(increment);

where increment is the positive or negative difference,
between the current height and the new required height

Control Variables:

All the controls added to the WndCtrl are Children of that WndCtrl. But these controls are accessible by the Parent View of the WndCtrl, for that Parent View supplies the pointer to the child control. All operations are possible on the variable of the added control in the Parent View of the WndCtrl.

Menu:

The WndCtls comes with a menu. The menu can be accesseb by doubleclicking the right mouse button on the title. You can add item to the menu by using the following function:


void AddMenuItem(UINT nFlags,
UINT iMenuItemID=0,
LPCTSTR strMenuItemText=0);

In order to add a separator, use the following code:


m_WndCtrl.AddMenuItem(MF_SEPARATOR);

In order to add a menu string use the following code:


m_WndCtrl.AddMenuItem(MF_STRING,0x2323,”Menu Item”);
//0x2323 is the menu item id
//and “Menu Item” is the menu item text

Messaging:

All the controls added to the WndCtrl are Children of that WndCtrl. Hence all the WM_COMMAND messages are sent to the WndCtrl, however, these messages are immediately forwarded to the Parent View using the SendMessage() function. Hence all the control handling is done in the Parent View of the WndCtrl, as is the case for normal controls in a View. All other messages are sent to the message handler of WndProc. You will have to do anyother message forwarding yourselves.

Notification Messages:

Aside from the Child Control messages, the WndCtrl sends its own custom messages to the Parent View upon certain events. These notification messages, and their details are listed bellow:


WCM_OPENING [WM_USER+2]
{
This message is sent when the WndCtrl is about to open
LOWORD (wParam) contains the ID of the WndCtrl
lParam contains the handle to the WndCtrl
}

WCM_OPEN [WM_USER+3]
{
This message is sent when the WndCtrl has changed
its state from Closed to Open
LOWORD (wParam) contains the ID of the WndCtrl
lParam contains the handle to the WndCtrl
}

WCM_CLOSING [WM_USER+4]
{
This message is sent when the WndCtrl is about to close
LOWORD (wParam) contains the ID of the WndCtrl
lParam contains the handle to the WndCtrl
}

WCM_CLOSE [WM_USER+5]
{
This message is sent when the WndCtrl has changed
its state from Open to Closed
LOWORD (wParam) contains the ID of the WndCtrl
lParam contains the handle to the WndCtrl
}

WCM_REPOSITIONWND [WM_USER+1]
{
This message is sent when the WndCtrl has changed its state
from Closed to Open OR Vice-Versa
LOWORD (wParam) contains the ID of the WndCtrl
lParam contains the handle to the WndCtrl
}

These messages are provided to the Parent View so that certain required events can be triggered upon receiving the concerned notification message. As an example, one may wish to stop the user from opening the WndCtrl if a flag is not set. The following code (psuedo) can be used upon receipt of the message WCM_OPENING:


if ( !flag )
{
CWndCtrl::StopOpen(); //used to stop the opening of WndCtrl
}

Similarly, if one wants to stop the Closing of the WndCtrl, the following code (psuedo) can be used to upon the receipt of the message WCM_CLOSING:


if ( !flag )
{
CWndCtrl::StopClose(); //used to stop the closing of WndCtrl
}

Repositioning:

All repositioning of WndCtrls is done via the WM_REPOSITIONWND message. This message is sent when the WndCtrl is either opened, closed or moved. Suppose u have three WndCtrl objects, namely m_ctrl1, m_ctrl2, and m_ctrl3. m_ctrl2 is below m_ctrl1 and m_ctrl3 is below m_ctrl2. Their repositioning upon opening and closing can be done by using the following code upon the receipt of the message WCM_REPOSITIONWND:


//if m_ctrl1 is sending the message
if ( LOWORD(wParam) == ID_CTRL1 )
{
m_ctrl1.GetWindowRect(&rect1);
m_ctrl2.GetWindowRect(&rect2);
ScreenToClient(&rect1); ScreenToClient(&rect2);
m_ctrl2.RepositionWindow(rect2.left,
rect1.bottom
+ [ANY distance You want]);
}
//if m_ctrl2 is sending the message
else if ( LOWORD(wParam) == ID_CTRL2 )
{
m_ctrl2.GetWindowRect(&rect2);
m_ctrl3.GetWindowRect(&rect3);
ScreenToClient(&rect2); ScreenToClient(&rect3);
m_ctrl3.RepositionWindow(rect3.left,
rect2.bottom
+ [ANY distance You want]);
}

Explanation: When m_ctrl1 will be opened, it will sent the message WCM_REPOSITIONWND, upon this the upper ‘if block’ will be executed. In the statement, ‘m_ctrl2.RepositionWindow ( … )’, m_ctrl2 will send the message WCM_REPOSITIONWND. Upon this the lower ‘else if block’ will be executed. Hence recursively repositioning the three WndCtrls.

Class Operations


Protytypes:


virtual BOOL Create(CString title, DWORD dwStyle,
DWORD dwExStyle, int x, int y,
CWnd* pParent, UINT id);
//used to create the WndCtrl

void AddControl(CWnd *cwnd, CRect rect, CString strClass,
CString strCaption, DWORD dwStyle,
DWORD dwExStyle, UINT id);
//Used to add a control to the WndCtrl

void AddMenuItem(UINT nFlags, UINT iMenuItemID=0,
LPCTSTR strMenuItemText=0);
//Used to add a menu Item to the WndCtrl Menu

UINT GetControl(CWnd& cWnd);
//returns the ID of the child control specified by cWnd

CWnd* GetControl(UINT ctrlID);
//returns a pointer to the control witht the id ‘ctrlID

bool OpenWndCtrl(bool bOpen = TRUE);
//Programatically opens/closes the WndCtrl

void SetOpenWidth(int width);
//sets the open width of the WndCtrl

void SetOpenHeight(int height);
//sets the open height of the WndCtrl

int IncrementOpenWidth(int increment);
//increments the open width of the WndCtrl.
//The previous open width is returned

int IncrementOpenHeight(int increment);
//increments the open height of the WndCtrl.
//The previous open height is returned

void StopOpen();
//Stops the Opening of the WndCtrl for one instance

void StopClose();
//Stops the Closing of the WndCtrl for one instance

bool GetOpenStatus();
//Retrieved the open status of the WndCtrl.
//TRUE for open and FALSE for closed

RECT RepositionWindow(int x, int y);
//Repositions the window to the new coordinates

void SetTitle(CString title);
//sets the title of the WndCtrl to title

void GetTitle(CString& title);
//stores the title of the WndCtrl in title

void SetOpenWndCtrlStyle(DWORD dwStyle, DWORD dwExStyle);
//sets the WndCtrl style and exStyle to dwStyle
//and dwExStyle for the open state

void GetOpenWndCtrlStyle(DWORD& dwStyle, DWORD& dwExStyle);
//stores the WndCtrl style and exStyle in dwStyle
//and dwExStyle for the open state

HBRUSH CreateTitleBrush(UINT Red, UINT Green, UINT Blue);
//creates a Title Brush, by the RGB values provided

HBRUSH SetTitleBrush(HBRUSH brush);
//sets the title brush to brush and
//returns the previous brush

HBRUSH GetTitleBrush();
//returns the coloring brush of the title

CFont* GetTitleFont();
//returns the font of the title

void SetTitleFont(int pointSize, CString faceName);
//sets the title font to the font specifications
//supplied by pointSize and faceName
//pointSize is the size in 10s you want to use …
//e.g. for a font size of 10, pass 100
//faceName is the font type you want to use …
//e.g. for arial font, pass “Arial”

Authors Note:

I made WndCtrl for open use but please give credit where its due… I would really like some input from you guys.

Downloads

Download demo project – 31 Kb

Download source – 6 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read