fixes from Wine. user32 dialog test: 55 executes, 7 failures Modified: trunk/reactos/lib/user32/windows/dialog.c Modified: trunk/reactos/lib/user32/windows/message.c _____
Modified: trunk/reactos/lib/user32/windows/dialog.c --- trunk/reactos/lib/user32/windows/dialog.c 2005-12-03 16:42:41 UTC (rev 19839) +++ trunk/reactos/lib/user32/windows/dialog.c 2005-12-03 17:21:37 UTC (rev 19840) @@ -848,8 +848,8 @@
return hwnd; }
+ if (modal && ownerEnabled) DIALOG_EnableOwner(owner); if( IsWindow(hwnd) ) DestroyWindow( hwnd ); - if (modal && ownerEnabled) DIALOG_EnableOwner(owner); return 0; }
@@ -917,43 +917,93 @@ */ static HWND DEFDLG_FindDefButton( HWND hwndDlg ) { - HWND hwndChild = GetWindow( hwndDlg, GW_CHILD ); + HWND hwndChild, hwndTmp; + + hwndChild = GetWindow( hwndDlg, GW_CHILD ); while (hwndChild) { if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON) break; + + /* Recurse into WS_EX_CONTROLPARENT controls */ + if (GetWindowLongW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT) + { + LONG dsStyle = GetWindowLongW( hwndChild, GWL_STYLE ); + if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) && + (hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL) + return hwndTmp; + } hwndChild = GetWindow( hwndChild, GW_HWNDNEXT ); } return hwndChild; }
/*********************************************************************** - * DEFDLG_SetDefButton + * DEFDLG_SetDefId * - * Set the new default button to be hwndNew. + * Set the default button id. */ -static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, - HWND hwndNew ) +static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam) { DWORD dlgcode=0; /* initialize just to avoid a warning */ + HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam); + INT old_id = dlgInfo->idResult; + + dlgInfo->idResult = wParam; if (hwndNew && !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON))) return FALSE; /* Destination is not a push button */
- if (dlgInfo->idResult) /* There's already a default pushbutton */ + /* Make sure the old default control is a valid push button ID */ + hwndOld = GetDlgItem( hwndDlg, old_id ); + if (!hwndOld || !(SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) + hwndOld = DEFDLG_FindDefButton( hwndDlg ); + if (hwndOld && hwndOld != hwndNew) + SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); + + if (hwndNew) { - HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult ); - if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) - SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); + if(dlgcode & DLGC_UNDEFPUSHBUTTON) + SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); } + return TRUE; +} + +/********************************************************************** * + * DEFDLG_SetDefButton + * + * Set the new default button to be hwndNew. + */ +static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew ) +{ + DWORD dlgcode=0; /* initialize just to avoid a warning */ + HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult ); + + if (hwndNew && + !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) + & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON))) + { + /** + * Need to draw only default push button rectangle. + * Since the next control is not a push button, need to draw the push + * button rectangle for the default control. + */ + hwndNew = hwndOld; + dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ); + } + + /* Make sure the old default control is a valid push button ID */ + if (!hwndOld || !(SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) + hwndOld = DEFDLG_FindDefButton( hwndDlg ); + if (hwndOld && hwndOld != hwndNew) + SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); + if (hwndNew) { - if(dlgcode==DLGC_UNDEFPUSHBUTTON) + if(dlgcode & DLGC_UNDEFPUSHBUTTON) SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); - dlgInfo->idResult = GetDlgCtrlID( hwndNew ); } - else dlgInfo->idResult = 0; return TRUE; }
@@ -1013,7 +1063,7 @@
case DM_SETDEFID: if (dlgInfo && !(dlgInfo->flags & DF_END)) - DEFDLG_SetDefButton( hwnd, dlgInfo, wParam ? GetDlgItem( hwnd, wParam ) : 0 ); + DEFDLG_SetDefId( hwnd, dlgInfo, wParam ); return 1;
case DM_GETDEFID: @@ -2094,99 +2144,70 @@ } #endif
+/********************************************************************** * + * DIALOG_FixOneChildOnChangeFocus + * + * Callback helper for DIALOG_FixChildrenOnChangeFocus + */
-/* - * @implemented +static BOOL CALLBACK DIALOG_FixOneChildOnChangeFocus (HWND hwndChild, + LPARAM lParam) +{ + /* If a default pushbutton then no longer default */ + if (DLGC_DEFPUSHBUTTON & SendMessageW (hwndChild, WM_GETDLGCODE, 0, 0)) + SendMessageW (hwndChild, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + return TRUE; +} + +/********************************************************************** * + * DIALOG_FixChildrenOnChangeFocus + * + * Following the change of focus that occurs for example after handling + * a WM_KEYDOWN VK_TAB in IsDialogMessage, some tidying of the dialog's + * children may be required. */ -BOOL -STDCALL -IsDialogMessageA( - HWND hDlg, - LPMSG lpMsg) +static void DIALOG_FixChildrenOnChangeFocus (HWND hwndDlg, HWND hwndNext) { - INT dlgCode = 0; + INT dlgcode_next = SendMessageW (hwndNext, WM_GETDLGCODE, 0, 0); + /* INT dlgcode_dlg = SendMessageW (hwndDlg, WM_GETDLGCODE, 0, 0); */ + /* Windows does ask for this. I don't know why yet */
- // FIXME: hooks - if (CallMsgFilterA( lpMsg, MSGF_DIALOGBOX )) return TRUE; + EnumChildWindows (hwndDlg, DIALOG_FixOneChildOnChangeFocus, 0);
- if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE; - - hDlg = DIALOG_FindMsgDestination(hDlg); - - switch(lpMsg->message) - { - case WM_KEYDOWN: - dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); - if (dlgCode & DLGC_WANTMESSAGE) break; - - switch(lpMsg->wParam) - { - case VK_TAB: - if (!(dlgCode & DLGC_WANTTAB)) - { - SendMessageA( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 ); - return TRUE; - } - break; - - case VK_RIGHT: - case VK_DOWN: - case VK_LEFT: - case VK_UP: - if (!(dlgCode & DLGC_WANTARROWS)) - { - BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP); - HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious ); - SendMessageA( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 ); - return TRUE; - } - break; - - case VK_CANCEL: - case VK_ESCAPE: - SendMessageA( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) ); - return TRUE; - - case VK_EXECUTE: - case VK_RETURN: - { - DWORD dw = SendMessageA( hDlg, DM_GETDEFID, 0, 0 ); - if (HIWORD(dw) == DC_HASDEFID) - { - SendMessageA( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), - (LPARAM)GetDlgItem(hDlg, LOWORD(dw))); - } - else - { - SendMessageA( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) ); - - } - } - return TRUE; - } - break; - - case WM_CHAR: - dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); - if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break; - if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break; - /* drop through */ - - case WM_SYSCHAR: - if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam )) - { - /* don't translate or dispatch */ - return TRUE; - } - break; - } - - TranslateMessage( lpMsg ); - DispatchMessageA( lpMsg ); - return TRUE; + /* If the button that is getting the focus WAS flagged as the default + * pushbutton then ask the dialog what it thinks the default is and + * set that in the default style. + */ + if (dlgcode_next & DLGC_DEFPUSHBUTTON) + { + DWORD def_id = SendMessageW (hwndDlg, DM_GETDEFID, 0, 0); + if (HIWORD(def_id) == DC_HASDEFID) + { + HWND hwndDef; + def_id = LOWORD(def_id); + hwndDef = GetDlgItem (hwndDlg, def_id); + if (hwndDef) + { + INT dlgcode_def = SendMessageW (hwndDef, WM_GETDLGCODE, 0, 0); + /* I know that if it is a button then it should already be a + * UNDEFPUSHBUTTON, since we have just told the buttons to + * change style. But maybe they ignored our request + */ + if ((dlgcode_def & DLGC_BUTTON) && + (dlgcode_def & DLGC_UNDEFPUSHBUTTON)) + { + SendMessageW (hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + } + } + } + } + else if ((dlgcode_next & DLGC_BUTTON) && (dlgcode_next & DLGC_UNDEFPUSHBUTTON)) + { + SendMessageW (hwndNext, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + /* I wonder why it doesn't send a DM_SETDEFID */ + } }
- /* * @implemented */ @@ -2214,13 +2235,53 @@ switch(lpMsg->wParam) { case VK_TAB: - if (!(dlgCode & DLGC_WANTTAB)) - { - SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 ); - return TRUE; - } - break; + if (!(dlgCode & DLGC_WANTTAB)) + { + /* I am not sure under which circumstances the TAB is handled + * each way. All I do know is that it does not always simply + * send WM_NEXTDLGCTL. (Personally I have never yet seen it + * do so but I presume someone has) + */ + if (GETDLGINFO(hDlg)) + SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 ); + else + { + /* It would appear that GetNextDlgTabItem can handle being + * passed hwndDlg rather than NULL but that is undocumented + * so let's do it properly + */ + HWND hwndFocus = GetFocus(); + HWND hwndNext = GetNextDlgTabItem (hDlg, + hwndFocus == hDlg ? NULL : hwndFocus, + GetKeyState (VK_SHIFT) & 0x8000); + if (hwndNext) + { + dlgCode = SendMessageW (hwndNext, WM_GETDLGCODE, + lpMsg->wParam, (LPARAM)lpMsg); + if (dlgCode & DLGC_HASSETSEL) + { + INT maxlen = 1 + SendMessageW (hwndNext, WM_GETTEXTLENGTH, 0, 0); + WCHAR *buffer = HeapAlloc (GetProcessHeap(), 0, maxlen * sizeof(WCHAR)); + if (buffer) + { + INT length; + SendMessageW (hwndNext, WM_GETTEXT, maxlen, (LPARAM) buffer); + length = wcslen (buffer); + HeapFree (GetProcessHeap(), 0, buffer); + SendMessageW (hwndNext, EM_SETSEL, 0, length); + } + } + SetFocus (hwndNext); + DIALOG_FixChildrenOnChangeFocus (hDlg, hwndNext); + } + else + return FALSE; + } + return TRUE;
+ } + break; + case VK_RIGHT: case VK_DOWN: case VK_LEFT: @@ -2241,10 +2302,15 @@
case VK_EXECUTE: case VK_RETURN: - { - DWORD dw = SendMessageW( hDlg, DM_GETDEFID, 0, 0 ); - if (HIWORD(dw) == DC_HASDEFID) + { + DWORD dw; + if ((GetFocus() == lpMsg->hwnd) && + (SendMessageW (lpMsg->hwnd, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) { + SendMessageW (hDlg, WM_COMMAND, MAKEWPARAM (GetDlgCtrlID(lpMsg->hwnd),BN_CLICKED), (LPARAM)lpMsg->hwnd); + } + else if (DC_HASDEFID == HIWORD(dw = SendMessageW (hDlg, DM_GETDEFID, 0, 0))) + { SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), (LPARAM)GetDlgItem(hDlg, LOWORD(dw))); } @@ -2449,4 +2515,3 @@
return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup); } - _____
Modified: trunk/reactos/lib/user32/windows/message.c --- trunk/reactos/lib/user32/windows/message.c 2005-12-03 16:42:41 UTC (rev 19839) +++ trunk/reactos/lib/user32/windows/message.c 2005-12-03 17:21:37 UTC (rev 19840) @@ -2114,3 +2114,55 @@
return TRUE; } + +/********************************************************************** * + * map_wparam_AtoW + * + * Convert the wparam of an ASCII message to Unicode. + */ +static WPARAM +map_wparam_AtoW( UINT message, WPARAM wparam ) +{ + switch(message) + { + case WM_CHARTOITEM: + case EM_SETPASSWORDCHAR: + case WM_CHAR: + case WM_DEADCHAR: + case WM_SYSCHAR: + case WM_SYSDEADCHAR: + case WM_MENUCHAR: + { + char ch[2]; + WCHAR wch[2]; + ch[0] = (wparam & 0xff); + ch[1] = (wparam >> 8); + MultiByteToWideChar(CP_ACP, 0, ch, 2, wch, 2); + wparam = MAKEWPARAM(wch[0], wch[1]); + } + break; + case WM_IME_CHAR: + { + char ch[2]; + WCHAR wch; + ch[0] = (wparam >> 8); + ch[1] = (wparam & 0xff); + if (ch[0]) MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1); + else MultiByteToWideChar(CP_ACP, 0, &ch[1], 1, &wch, 1); + wparam = MAKEWPARAM( wch, HIWORD(wparam) ); + } + break; + } + return wparam; +} + +/* + * @implemented + */ +BOOL WINAPI +IsDialogMessageA( HWND hwndDlg, LPMSG pmsg ) +{ + MSG msg = *pmsg; + msg.wParam = map_wparam_AtoW( msg.message, msg.wParam ); + return IsDialogMessageW( hwndDlg, &msg ); +}