Keywords: non-modal, modal, hook, wh_CBT, CBTPROC, 1, and intent. We want to display non-modular windows as a modal window. For example, in the "File" menu of IE, select "Print", the "Print" dialog box is non-modal (maybe we don't know how Microsoft's design intention, generally said that the "print" dialog box should be mode State). How do I display the "Print" dialog as modality in this case (this dialog is Black Box to us)? 2, simple implementation, when the modal window is displayed, its parent window is disable, so the modal window presents "modal", so as long as the parent window disable is displayed before displaying our non-modular window. ,as follows:
... AFXGETMAINWND () -> EnableWindow (false); // Turn the main window disable, the displayed non-modal window is modeled with showModelessWindow (); ... The problem is that the non-modal window is immediately returned immediately. Where are we put the code of the parent window Enable? The clumping method is to use the clock, constantly detect if the displayed non-modular window has been closed. If it is closed, the parent window enable. Of course, it is better way. 3, WH_CBT HOOK WH_CBT Hook Detailed Description, please refer to MSDN, we only need to know that the system will call the WH_CBT hook function before the window is created and destroyed, which is what we need. The specific is to hang our WH_CBT hook processing function before displaying the non-modal window, and the handle created by the non-modal window can be obtained from the WPARAM parameter when the ncode of the hook function is HCBT_CREATEWND (creating a window), saves it, And compare the WPARAM parameters when the ncode of the hook function is HCBT_DESTROYWND (destroy window), and if the match is matched, the Enable status of the main window is restored. 2. Implement 1) First define two variables, here is a global static variable.
Static hhook g_hhook = null; static hwnd g_hwnddialog = null; // to save window handle 2) Add a function CBTPROC, because it is a callback function, pay attention to static.
Static Lresult Callback CBTProc (int Ncode, WPARAM WPARAM, LPARAM LPARAM); 3) Hook assumes that below is a function that calls the "Print" dialog box in some browsers.
void CMyHtmlView :: OnFilePrint () {AfxGetMainWnd () -> EnableWindow (FALSE); g_hWndDialog = 0; // multiple calls may need to reset the stored window handle variable g_hHook = SetWindowsHookEx (WH_CBT, CbtProc, NULL, GetCurrentThreadId () ); If (! G_hhook) {AFXGETMAINWND () -> enableWindow (true); return;} call "Print" dialog
} LRESULT CALLBACK CMyHtmlView :: CbtProc (int nCode, WPARAM wParam, LPARAM lParam) {switch (nCode) {case HCBT_CREATEWND: {HWND hWnd = (HWND) wParam; LPCBT_CREATEWND pcbt = (LPCBT_CREATEWND) lParam; LPCREATESTRUCT pcs = pcbt-> lpcs ; if ((DWORD) PCS-> lpszclass == 0x00008002) / / # 32770, "Print" dialog class name {if (g_hwnddialog == 0) g_hwnddialog = hWnd; // Save only save the "Print" window handle } break;} case HCBT_DESTROYWND: {HWND hwnd = (HWND) wParam; if (hwnd == g_hWndDialog) {AfxGetMainWnd () -> EnableWindow (TRUE); // restore the window state UnhookWindowsHookEx (g_hHook); //} break removing hook }} Return CallNexthookex (g_hhook, ncode, wparam, lparam);} is simple, more importantly, this method is indeed valid.