Alex Henrie : user32: Correct dialog focus behavior.
Alexandre Julliard
julliard at winehq.org
Thu Aug 16 15:26:13 CDT 2012
Module: wine
Branch: master
Commit: 4b67e6c778a8b8dcd74b56e866c13687345cfed4
URL: http://source.winehq.org/git/wine.git/?a=commit;h=4b67e6c778a8b8dcd74b56e866c13687345cfed4
Author: Alex Henrie <alexhenrie24 at gmail.com>
Date: Mon Aug 6 17:13:15 2012 -0600
user32: Correct dialog focus behavior.
---
dlls/user32/defdlg.c | 21 ++++++++++++++-------
dlls/user32/tests/dialog.c | 42 +++++++++++++++++++++++++++++++++++-------
2 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/dlls/user32/defdlg.c b/dlls/user32/defdlg.c
index fecd417..e4b55f3 100644
--- a/dlls/user32/defdlg.c
+++ b/dlls/user32/defdlg.c
@@ -55,9 +55,9 @@ static DLGPROC DEFDLG_GetDlgProc( HWND hwnd )
* DEFDLG_SetFocus
*
* Set the focus to a control of the dialog, selecting the text if
- * the control is an edit dialog.
+ * the control is an edit dialog that has DLGC_HASSETSEL.
*/
-static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
+static void DEFDLG_SetFocus( HWND hwndCtrl )
{
if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
@@ -83,7 +83,7 @@ static void DEFDLG_SaveFocus( HWND hwnd )
/***********************************************************************
* DEFDLG_RestoreFocus
*/
-static void DEFDLG_RestoreFocus( HWND hwnd )
+static void DEFDLG_RestoreFocus( HWND hwnd, BOOL justActivate )
{
DIALOGINFO *infoPtr;
@@ -92,12 +92,19 @@ static void DEFDLG_RestoreFocus( HWND hwnd )
/* Don't set the focus back to controls if EndDialog is already called.*/
if (infoPtr->flags & DF_END) return;
if (!IsWindow(infoPtr->hwndFocus) || infoPtr->hwndFocus == hwnd) {
+ if (justActivate) return;
/* If no saved focus control exists, set focus to the first visible,
non-disabled, WS_TABSTOP control in the dialog */
infoPtr->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
+ /* If there are no WS_TABSTOP controls, set focus to the first visible,
+ non-disabled control in the dialog */
+ if (!infoPtr->hwndFocus) infoPtr->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE );
if (!IsWindow( infoPtr->hwndFocus )) return;
}
- DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
+ if (justActivate)
+ SetFocus( infoPtr->hwndFocus );
+ else
+ DEFDLG_SetFocus( infoPtr->hwndFocus );
/* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
sometimes losing focus when receiving WM_SETFOCUS messages. */
@@ -250,12 +257,12 @@ static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
return DefWindowProcA( hwnd, msg, wParam, lParam );
case WM_ACTIVATE:
- if (wParam) DEFDLG_RestoreFocus( hwnd );
+ if (wParam) DEFDLG_RestoreFocus( hwnd, TRUE );
else DEFDLG_SaveFocus( hwnd );
return 0;
case WM_SETFOCUS:
- DEFDLG_RestoreFocus( hwnd );
+ DEFDLG_RestoreFocus( hwnd, FALSE );
return 0;
case DM_SETDEFID:
@@ -280,7 +287,7 @@ static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
HWND hwndDest = (HWND)wParam;
if (!lParam)
hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
- if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
+ if (hwndDest) DEFDLG_SetFocus( hwndDest );
DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
}
return 0;
diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c
index 6bd34b3..0ebab4c 100644
--- a/dlls/user32/tests/dialog.c
+++ b/dlls/user32/tests/dialog.c
@@ -828,7 +828,7 @@ static const char * GetHwndString(HWND hw)
return "unknown handle";
}
-static void test_initial_focus(void)
+static void test_focus(void)
{
/* Test 1:
* This test intentionally returns FALSE in response to WM_INITDIALOG
@@ -900,6 +900,8 @@ static void test_initial_focus(void)
HRSRC hResource;
HANDLE hTemplate;
DLGTEMPLATE* pTemplate;
+ HWND hTextbox;
+ DWORD selectionStart = 0xdead, selectionEnd = 0xbeef;
hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG", RT_DIALOG);
hTemplate = LoadResource(g_hinst, hResource);
@@ -912,6 +914,20 @@ static void test_initial_focus(void)
ok ((g_hwndInitialFocusT1 == 0),
"Focus should not be set for an invisible DS_CONTROL dialog %p.\n", g_hwndInitialFocusT1);
+ /* Also make sure that WM_SETFOCUS selects the textbox's text */
+ hTextbox = GetDlgItem(hDlg, 200);
+ SendMessage(hTextbox, WM_SETTEXT, 0, (LPARAM)"Hello world");
+
+ SendMessage(hDlg, WM_SETFOCUS, 0, 0);
+ SendMessage(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd);
+ ok(selectionStart == 0 && selectionEnd == 11, "Text selection after WM_SETFOCUS is [%i, %i) expected [0, 11)\n", selectionStart, selectionEnd);
+
+ /* but WM_ACTIVATE does not */
+ SendMessage(hTextbox, EM_SETSEL, 0, 0);
+ SendMessage(hDlg, WM_ACTIVATE, WA_ACTIVE, 0);
+ SendMessage(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd);
+ ok(selectionStart == 0 && selectionEnd == 0, "Text selection after WM_ACTIVATE is [%i, %i) expected [0, 0)\n", selectionStart, selectionEnd);
+
DestroyWindow(hDlg);
}
@@ -929,13 +945,25 @@ static void test_initial_focus(void)
pTemplate = LockResource(hTemplate);
hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0);
- g_hwndInitialFocusT1 = GetFocus();
+ ok(hDlg != 0, "Failed to create test dialog.\n");
hLabel = GetDlgItem(hDlg, 200);
- ok (hDlg != 0, "Failed to create test dialog.\n");
- ok ((g_hwndInitialFocusT1 == hLabel),
- "Focus should have been set to the first control, expected (%p) got (%p).\n",
- hLabel, g_hwndInitialFocusT1);
+ ok(GetFocus() == hLabel, "Focus not set to label, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
+
+ DestroyWindow(hDlg);
+
+ /* Also check focus after WM_ACTIVATE and WM_SETFOCUS */
+ hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, NULL, 0);
+ ok(hDlg != 0, "Failed to create test dialog.\n");
+ hLabel = GetDlgItem(hDlg, 200);
+
+ SetFocus(NULL);
+ SendMessage(hDlg, WM_ACTIVATE, WA_ACTIVE, 0);
+ ok(GetFocus() == NULL, "Focus set on WM_ACTIVATE, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
+
+ SetFocus(NULL);
+ SendMessage(hDlg, WM_SETFOCUS, 0, 0);
+ ok(GetFocus() == hLabel, "Focus not set to label on WM_SETFOCUS, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
DestroyWindow(hDlg);
}
@@ -1404,7 +1432,7 @@ START_TEST(dialog)
test_GetNextDlgItem();
test_IsDialogMessage();
test_WM_NEXTDLGCTL();
- test_initial_focus();
+ test_focus();
test_GetDlgItem();
test_GetDlgItemText();
test_DialogBoxParamA();
More information about the wine-cvs
mailing list