Environment: VC5/6, NT4, Win95/98, Win2k
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'.
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.
The WndCtrl class has been derived from the 'generic CWnd' MFC class.
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.
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:
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:
bool OpenWndCtrl(bool bOpen = TRUE); //specify false to close the WndCtrl
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 );
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, //This is the registered class name of the control or window "Control Window Text", WINDOW/CONTROL STYLES, // You do not need to add 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.
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
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
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.
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.
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 }
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 ( LOWORD(wParam) == ID_CTRL1 ) //if m_ctrl1 is sending the message { m_ctrl1.GetWindowRect(&rect1); m_ctrl2.GetWindowRect(&rect2); ScreenToClient(&rect1); ScreenToClient(&rect2); m_ctrl2.RepositionWindow ( rect2.left, rect1.bottom + [ANY distance You want]); } else if ( LOWORD(wParam) == ID_CTRL2 ) //if m_ctrl2 is sending the message { 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.
[your source code goes here]