Keywords: Non-modal, modal,Hook,Wh_cbt,CBTProc,
1, Intention
Sometimes we want to display a non-modal window as a modal window. For exampleIESelect "print" under the "file" menu, and the "print" dialog box is non-modal (maybe we do not knowMicrosoftIn general, the "print" dialog box here should be modal ). In this case, how does one display the "print" dialog box as a modal mode?Black Box)?
2, Simple implementation
Simply put, when a modal window is displayed, its parent window isDisableSo the modal window is displayed as "Modal", so you only need to display the parent window before the non-modal windowDisableThis can be achieved as follows:
......
Afxgetmainwnd ()-> enablewindow (false );//Set the Main WindowDisableThe displayed non-modal window becomes modal.
Showmodelesswindow ();
......
The problem is that the non-modal window is returned immediately after it is displayed.EnableOfCodeWhere is it? The stupid way is to use the clock to constantly check whether the displayed non-modal window is closed. If it is closed, the parent window isEnable.
Of course, a better approach is needed.
3,Wh_cbt hook
Wh_cbt For more information about hooks, see Msdn All we need to know is that the system will call Wh_cbt Hook function, which is exactly what we need. Specifically, before the non-modal window is displayed Wh_cbt After the hook processing function, the handle created in the non-modal window can be stored in Ncode Is Hcbt_createwnd (create window) Hour from Wparam Obtain the parameters, save them, and Ncode Is Hcbt_destroywnd (destruction window) Time and Wparam Parameters are compared. If they match, Enable Status.
2, Implementation
1)First, define two variables, which are global static variables.
Static hhook g_hhook = NULL;
Static hwnd g_hwnddialog = NULL;//Used to save the window handle
2)Add another functionCbtprocBecause it is a callback function, be sure to declare itStatic.
Static lresult callbackCbtproc(INT ncode, wparam, lparam );
3)Hook
Suppose the following is a function that calls the "print" dialog box in a browser.
Void CMyhtmlView: onfileprint ()
{
Afxgetmainwnd ()-> enablewindow (false );
G_hwnddialog = 0;//It may be called multiple times. You need to reset the variable that saves the window handle.
G_hhook = setwindowshookex (wh_cbt, cbtproc, null, getcurrentthreadid ());
If (! G_hhook)
{
Afxgetmainwnd ()-> enablewindow (true );
Return;
}
Call the "print" dialog box
}
Lresult callback CMyhtmlView: cbtproc (INT ncode, wparam, lparam)
{
Switch (ncode)
{
Case hcbt_createwnd:
{
Hwnd = (hwnd) wparam;
Lpcbt_createwnd pcbt = (lpcbt_createwnd) lparam;
Lpcreatestruct PCs = pcbt-> lpcs;
If (DWORD) PCs-> lpszclass = 0x00008002) // #32770, "Print" dialog box Class Name
{
If (g_hwnddialog = 0)
G_hwnddialog = hwnd;//Save the "print" window handle only once
}
Break;
}
Case hcbt_destroywnd:
{
Hwnd = (hwnd) wparam;
If (hwnd = g_hwnddialog)
{
Afxgetmainwnd ()-> enablewindow (true );//Restore window status
Unhookwindowshookex (g_hhook );//Remove hook
}
Break;
}
}
Return callnexthookex (g_hhook, ncode, wparam, lparam );
}
It's easy. More importantly, this method works.
References:
Msdn:Cbtproc
Reference address: Use wh_cbt hook to display the non-modal dialog box as the Modal Dialog Box