Author: Hu Jian, Department of network science, School of Computer Science, Beijing University of Technology
When using the Appwizard of vc6.0/5.0 to generate the MDI application, we found that the customer background of the MDI main window is the same as that of the dark gray. Vc6.0/5.0 does not provide a method to modify its background color. Even SDK programming does not have a good way to modify the background color. So that Microsoft products such as Office are also a gray background. Is there a way to set the background to your favorite color?
During the learning process, I found a method to change the window color of the customer area at will. Using this method, you can set the customer's window to a 256-color background or even a Bitmap bitmap, so that the animation and so on. The multimedia effect of the program is greatly enhanced.
First, the basic principle of MDI client Window Programming is introduced.
1. MDI customer window
The main frame window of an MDI application contains a special subwindow called the mdiclient window. The mdiclient window is used to manage the customer zone of the main framework window. The mdiclient window itself has its own subwindow, that is, the document window derived from cmdichildwnd, that is, the MDI subwindow. The MDI main frame window is used to manage mdiclient subwindows. When the control bar (menu bar, status bar, etc.) changes, the mdiclient window is reconfigured in the MDI main frame window. The mdiclient subwindow manages all the MDI subwindows. The parent window is responsible for passing some commands to the Child Window. Therefore, messages sent from a message queue to an MDI subwindow are transmitted by the mdiclient window, and messages sent to the mdiclient window and the MDI subwindow are transmitted by the main framework window. In this way, we can intercept the re-draw message about the mdiclient window in the main framework window and then add our own code.
Ii. MDI client Window Programming Method
It is difficult to program the MDI client window. The reason is that the customer zone of mdiframewnd is completely overwritten by the mdiclient window. In this way, the background color and the optical mark of the mdiframewnd in the MDI main window do not work. At the same time, Microsoft does not support using the mdiclient window as a subclass. The mdiclient window can only use the standard background color and cursor. Therefore, the message processing function of wm_paint cannot be simply reloaded for the MDI client window as for the normal window.
There are two ways to change the MDI customer window background.
Use the cmdiframewnd: createclient function:
Createclient (maid, cmenu * pwindowmenu );
The parameter lpcreatestruct is a pointer to the createstruct structure. In the createstruct structure, the lpszclass item points to the wndclass structure of the window class. You can change the background fl and cursor of the mdiclient window by changing the hbrbackground and hcursor items in the wndclass structure. Because this function creates a new mdiclient window object, it must be called in the oncreate member function of the reloaded main window. This method is complex. You must manually create an MDI customer window and cannot use the features automatically provided by Appwizard. Moreover, you can only use a limited 16-color background brush for Windows 95. This document uses the second method.
In the message queue of the main framework window, wm_paint messages sent to the MDI customer window are intercepted and a flag message is sent to the main framework window. Operate the MDI customer window in the message processing function of this flag. This method is simple, but there are several points worth noting.
First, how to intercept the message wm_paint in the MDI customer window. MFC provides the pretranslatemessage (MSG * PMSG) function. It pre-interprets the message before it is sent to the translatemessage and dispatchmessage functions. You can overload this function to intercept the message wm_paint in the MDI client window:
Bool pretranslatemessage (MSG * PMSG)
{
If (PMSG-> hwnd = m_hwndmdiclient & PMSG-> message = wm_paint)
Postmessage (wm_paint );
Return cmdiframewnd: pretranslatemessage (PMSG );
}
Next, for simplicity, set the flag message to the wm_paint of the MDI main window. In the message processing function of wm_paint in the MDI Main Window, add and increase the code that draws the MDI customer window. You can also customize messages, but it is a little more complicated.
Finally, the operations on the MDI customer window are completed in the main window. How to obtain the device description table of the MDI customer window in the main window. In fact, there is m_hwndmdiclient in the MDI main window class. Obtain the device description table in the customer window as follows:
DC. m_hdc =: getdc (this-> m_hwndmdiclient );
Then you can perform operations on the customer window.
Iii. Instances
Set the customer window to a 256-color background.
Use Appwizard to generate an MDI application test.
Add the following code to the function test. cpp:
Bool ctestapp: initinstance ()
{
Afxenablecontrolcontainer ();
# Ifdef _ afxdll
Enable3dcontrols (); // call this when using MFC in a shared DLL
# Else
Enable3dcontrolsstatic (); // call this when linking to MFC statically
# Endif
Setregistrykey (_ T ("Local Appwizard-generated Applications "));
Loadstdprofilesettings (); // Load Standard INI File options (including MRU)
Cmultidoctemplate * pdoctemplate;
Pdoctemplate = new cmultidoctemplate (
Idr_testtype,
Runtime_class (ctestdoc ),
Runtime_class (cchildframe), // custom MDI child frame
Runtime_class (ctestview ));
Adddoctemplate (pdoctemplate );
// Create main MDI frame window
Cmainframe * pmainframe = new cmainframe;
If (! Pmainframe-> loadframe (idr_mainframe ))
Return false;
M_pmainwnd = pmainframe;
// Parse command line for standard shell commands, DDE, file open
Ccommandlineinfo using info;
Parsecommandline (partition info );
// Dispatch commands specified on the command line
If (! Processshellcommand (cmdinfo ))
Return false;
// The main window has been initialized, so show and update it.
Pmainframe-> showwindow (m_ncmdshow );
// ****** Add the code header ******
Afxgetmainwnd ()-> postmessage (wm_paint );
// ****** Add the end of the Code ******
Pmainframe-> updatewindow ();
Return true;
}
Ensure that the client window is updated at the beginning.
Use classward to add the pretranslatemessage message processing function to the cmainframe class as follows:
Bool pretranslatemessage (MSG * PMSG)
{// ****** Add the code header ******
If (PMSG-> hwnd = m_hwndmdiclient & PMSG-> message = wm_paint)
Postmessage (wm_paint );
// ****** Add the end of the Code ******
Return cmdiframewnd: pretranslatemessage (PMSG );
}
Add the following to the wmpaint message processing function in the main window:
Void cmainframe: onpaint ()
{
// ****** Add the code header ******
Cmdiframewnd: onpaint ();
Crect RC;
Cdc dc;
DC. m_hdc =: getdc (this-> m_hwndmdiclient );
Cbrush Br (RGB (120,200, 40); // 256 color brush
DC. SelectObject (& Br );
DC. getclientrect (& rc); // This sentence does not appear in vc7.0 and needs to be queried.
DC. patblt (RC. Left, RC. Top, RC. Width (), RC. Height (), patcopy );
Releasedc (& DC );
// ****** Add the end of the Code ******
}
Set the customer window as a Bitmap bitmap.
1, 2, 3 in the same example.
4. Add your favorite bitmap to the resource and set it to idb_bitmap1. Add the cbitmap class member m_bmp to the main window class. And initialize at the end of the cmdiframewnd: oncreate () function:
M_bmp .loadbitmap (idb_bitmap1 );
5. Add the following to the wm_paint message processing function in the main window:
Void cmainframe: onpaint ()
{
// ****** Add the code header ******
Cmdiframewnd: onpaint ();
Crect RC, memrc;
Cdc dc, memdc;
DC. m_hdc =: getdc (this-> m_hwndmdiclient );
Memdc. createcompatibledc (& DC );
Memdc. SelectObject (& m_bmp );
Getclientrect (& rc );
DC. bitblt (RC. Top, RC. Left, RC. Width (), RC. Height ()
, & Memdc, RC. Top, RC. Left, srccopy );
Releasedc (& memdc );
Releasedc (& DC );
// ****** Add the end of the Code ******
}
Improvements and supplements to an in-depth article on MDI client Window Programming
To the sea
I read the article titled in-depth MDI client Window Programming published by your newspaper. I am very interested in it. I think it is very good. The whole window is shown in (Omitted:
However, the disadvantage is that when I drag the MDI child window with the mouse, the situation shown in Figure 2 (Omitted) appears:
How can I erase the background? But when I minimize the entire framework window and restore it, the background of the customer window becomes normal again. How can this happen? Is there an error in vc6.0/5.0? No, this is because when we drag the MDI child window, the customer window does not reproduce the result in time. So how can we correct it? When dragging the subwindow with the mouse, we should send a message that redraws the background of the customer window to the main frame window in the current active subwindow. The onmove message processing function is added to the cchildframe using classward:
Void cchildframe: onmove (int x, int y)
{Javasichildwnd: onmove (x, y); // Add code
Cmdiframewnd * p_mframe = getmdiframe ();
P_mframe-> postmessage (wm_paint); // Add code}
Compile and run the program again. The problem just now is gone. Everything is fine. No matter how you drag the MDI subwindow, the background will not be erased.
However, there is another problem. When I move the mouse over the border of the MDI child window and drag the border to narrow down the size of the MDI child window, figure 3 appears:
Similarly, when the size of the MDI sub-window changes, we also need to send a re-painting background message to the main frame window using classward to add the onsize message processing function to the cchildframe as follows:
Void cchildframe: onsize (uint ntype, int CX, int CY) {cmdichildwnd: onsize (ntype, CX, CY); // Add code
Cmdiframewnd * p_mframe = getmdiframe ();
P _ mframe-> postmessage (wm_paint); // Add code}
Compile and run the program again.
Cstring strdisplay;
Strdisplay. Format ("holexposion: % d, holeypos: % d", holexposion, holeypos );
Afxmessagebox (strdisplay );