src/gui/widown.c line 3607-3628
- BOOL GUIAPI EnableWindow (HWND hWnd, BOOL fEnable)
- {
- BOOL fOldStatus;
- MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
- if (IsMainWindow (hWnd)) {
- fOldStatus = SendMessage (HWND_DESKTOP, MSG_ENABLEMAINWIN,
- (WPARAM)hWnd, (LPARAM)fEnable);
- }
- else {
- PCONTROL pControl;
- pControl = (PCONTROL)hWnd;
- fOldStatus = !(pControl->dwStyle & WS_DISABLED);
- }
- SendNotifyMessage (hWnd, MSG_ENABLE, fEnable, 0);
- return fOldStatus;
- }
这里的两个参数hWnd指定要操作的窗口句柄, fEnable指定enable 或者disable hWnd指定的窗口。然后判断下指定的窗口是否为主窗口。如果是,则向桌面线程发送消息MSG_ENABLEMAINWIN,并附带hWnd和fEnable信息。这个消息的处理代码在src/kernel/desktop-comm.c中定义
src/kernel/desktop-comm.c line 2146-2169
- case MSG_ENABLEMAINWIN:
- iRet = !(pWin->dwStyle & WS_DISABLED);
- if ( (!(pWin->dwStyle & WS_DISABLED) && !lParam)
- || ((pWin->dwStyle & WS_DISABLED) && lParam) ) {
- if (lParam)
- pWin->dwStyle &= ~WS_DISABLED;
- else
- pWin->dwStyle |= WS_DISABLED;
- if (pWin->dwStyle & WS_DISABLED) {
- if (__mg_capture_wnd && GetMainWindowPtrOfControl (__mg_capture_wnd) == pWin)
- __mg_capture_wnd = 0;
- if (__mg_active_mainwnd == pWin) {
- dskChangActiveWindow (NULL);
- break;
- }
- }
- SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
- }
- break;
从这段代码可以看出,如果是disable窗口,首先此窗口中捕获鼠标的控件会释放鼠标。如果这个被disable的窗口是当前活动窗口,则调用函数dskChangActiveWindow改变当前活动窗口
src/kernel/desktop-comm.c line 507-534
- static PMAINWIN dskChangActiveWindow (PMAINWIN pWin)
- {
- PMAINWIN pOldActive;
- if (__mg_ime_wnd && (__mg_ime_wnd == (HWND)pWin))
- return __mg_active_mainwnd;
- if ((pWin == __mg_active_mainwnd)
- || (pWin && (pWin->dwExStyle & WS_EX_TOOLWINDOW)))
- return __mg_active_mainwnd;
- pOldActive = __mg_active_mainwnd;
- DesktopSetActiveWindow (pWin);
- if (pOldActive && (pOldActive->dwStyle & WS_VISIBLE)) {
- SendAsyncMessage ((HWND)pOldActive, MSG_NCACTIVATE, FALSE, 0);
- SendNotifyMessage ((HWND)pOldActive, MSG_ACTIVE, FALSE, 0);
- SendNotifyMessage ((HWND)pOldActive, MSG_KILLFOCUS, (HWND)pWin, 0);
- }
- if (pWin) {
- SendAsyncMessage ((HWND)pWin, MSG_NCACTIVATE, TRUE, 0);
- SendNotifyMessage ((HWND)pWin, MSG_ACTIVE, TRUE, 0);
- SendNotifyMessage ((HWND)pWin, MSG_SETFOCUS, (HWND)pOldActive, 0);
- }
- return pOldActive;
- }
在调用此函数时,给他传递的参数为NULL,所以在此函数中调用DesktopSetActiveWindow (pWin)设置当前活动窗口时,当前活动窗口将被设置为NULL,即没有活动窗口,此时按键不会有任何窗口进行响应。
再回头看桌面线程对MSG_ENABLEMAINWIN消息的处理,
src/kernel/desktop-comm.c line 2146-2169
- case MSG_ENABLEMAINWIN:
- iRet = !(pWin->dwStyle & WS_DISABLED);
- if ( (!(pWin->dwStyle & WS_DISABLED) && !lParam)
- || ((pWin->dwStyle & WS_DISABLED) && lParam) ) {
- if (lParam)
- pWin->dwStyle &= ~WS_DISABLED;
- else
- pWin->dwStyle |= WS_DISABLED;
- if (pWin->dwStyle & WS_DISABLED) {
- if (__mg_capture_wnd && GetMainWindowPtrOfControl (__mg_capture_wnd) == pWin)
- __mg_capture_wnd = 0;
- if (__mg_active_mainwnd == pWin) {
- dskChangActiveWindow (NULL);
- break;
- }
- }
- SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
- }
- break;
如果是enable窗口的话,则向此窗口发送MSG_NCPAINT消息。这个消息会由DefaultMainWinProc(hWnd,message,wParam,lParam)函数处理,最终会在函数DefaultPaintMsgHandler(PMAINWIN pWin, int message, WPARAM wParam, LPARAM lParam)中对此消息处理。
src/gui/window.c line 2257-2259
- case MSG_NCPAINT:
- wndDrawNCFrame (pWin, (HDC)wParam, (const RECT*)lParam);
- break;
处理时调用wndDrawNCFrame (pWin, (HDC)wParam, (const RECT*)lParam);将窗口的非窗户区边框进行重绘。
注意,在这里并没有设置活动窗口,如果窗口原来是活动的,在被disable后,再enable,他将不再是活动窗口,也就不会接收任何按键消息。需用函数SetActiveWindow将窗口设置为活动的。