Adding PSN_QUERYINITIALFOCUS helped fix some focus issues with the property sheet in bug 54862. Previously the listview in the tab control did not get focus from the start when it should have.
-- v3: comctl32/tests: Add test for PSN_QUERYINITIALFOCUS for the propsheet.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/propsheet.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/dlls/comctl32/propsheet.c b/dlls/comctl32/propsheet.c index b530a1a8094..74577e30c7a 100644 --- a/dlls/comctl32/propsheet.c +++ b/dlls/comctl32/propsheet.c @@ -582,6 +582,30 @@ static void HPSP_draw_text(HPROPSHEETPAGE hpsp, HDC hdc, BOOL title, RECT *r, UI }
#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");} + +static void notify_QueryInitialFocus(HWND hwndDlg, int index, PropSheetInfo* psInfo) +{ + PSHNOTIFY psn; + HWND hFocusableItem = NULL; + HWND hInitialFocus = NULL; + + hFocusableItem = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE); + + if (!hFocusableItem) + return; + + psn.hdr.code = PSN_QUERYINITIALFOCUS; + psn.hdr.hwndFrom = hwndDlg; + psn.hdr.idFrom = 0; + psn.lParam = 0; + hInitialFocus = (HWND) SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); + + if (hInitialFocus) + SetFocus(hInitialFocus); + else if (hFocusableItem) + SetFocus(hFocusableItem); +} + /****************************************************************************** * PROPSHEET_UnImplementedFlags * @@ -1655,7 +1679,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) { HWND hwndTabCtrl; HWND hwndLineHeader; - HWND control;
TRACE("active_page %d, index %d\n", psInfo->active_page, index); if (index == psInfo->active_page) @@ -1674,10 +1697,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) { PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags, psInfo->proppage[index].pszText); - - control = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE); - if(control != NULL) - SetFocus(control); }
if (psInfo->active_page != -1) @@ -1693,6 +1712,8 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) psInfo->active_page = index; psInfo->activeValid = TRUE;
+ notify_QueryInitialFocus(hwndDlg, index, psInfo); + if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) ) { hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER); @@ -1891,6 +1912,7 @@ static BOOL PROPSHEET_Apply(HWND hwndDlg, LPARAM lParam) psn.lParam = 0; hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); + notify_QueryInitialFocus(hwndPage, psInfo->active_page, psInfo); }
return TRUE;
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/tests/propsheet.c | 105 ++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+)
diff --git a/dlls/comctl32/tests/propsheet.c b/dlls/comctl32/tests/propsheet.c index 9bd1c08bd6a..17732aa81ad 100644 --- a/dlls/comctl32/tests/propsheet.c +++ b/dlls/comctl32/tests/propsheet.c @@ -1388,6 +1388,110 @@ static void test_invalid_hpropsheetpage(void) DestroyWindow(hdlg); }
+int bQueryInitialFocus = 0; +LRESULT CALLBACK TestDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam) +{ + LPNMHDR lpnmhdr; +switch (uMessage) + { + case WM_NOTIFY: + lpnmhdr = (NMHDR *)lParam; + switch (lpnmhdr->code) + { + case PSN_QUERYINITIALFOCUS: + { + bQueryInitialFocus = 1; + break; + } + default: + break; + } + break; + + default: + break; + } + + return FALSE; + +} + +static void test_QueryInitialFocus(void) +{ + PROPSHEETPAGEA psp[2]; + PROPSHEETHEADERA psh; + HWND tabCtrl = NULL; + HWND hp; + RECT rc; + LPARAM lp; + + memset(&psh, 0, sizeof(psh)); + memset(psp, 0, sizeof(psp[0]) * 2); + psp[0].dwSize = sizeof(PROPSHEETPAGEA); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = GetModuleHandleA(NULL);; + psp[0].pszTemplate = (const char*) MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc = (DLGPROC) TestDlgProc; + psp[0].pszTitle = "Page1"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGEA); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = GetModuleHandleA(NULL); + psp[1].pszTemplate = (const char*) MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc = (DLGPROC) TestDlgProc; + psp[1].pszTitle = "Page2"; + psp[1].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADERA); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent = GetDesktopWindow(); + psh.pszCaption = "Modeless Property Sheet"; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGEA); + psh.ppsp = (LPCPROPSHEETPAGEA)&psp; + + hp = (HWND) pPropertySheetA(&psh); + tabCtrl = (HWND)SendMessageA(hp, PSM_GETTABCONTROL, 0, 0); + + //Test PSN_QUERYINITIALFOCUS gets sent on start + ok(bQueryInitialFocus, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + bQueryInitialFocus = 0; + + //Test changing of tabs + ok(tabCtrl != 0, "Could not test changing tabs. No tab control found.\n"); + if(tabCtrl) + { + SendMessageA(tabCtrl, TCM_GETITEMRECT, 1, (LPARAM) &rc); + lp = MAKELPARAM(rc.left + ((rc.right-rc.left)/2), rc.top + ((rc.bottom-rc.top)/2)); + SendMessageA(tabCtrl, WM_LBUTTONDOWN, MK_LBUTTON, lp); + ok(bQueryInitialFocus, "Did not recieve PSN_QUERYINITIALFOCUS from changing tabs.\n"); + bQueryInitialFocus = 0; + } + + //Test Apply Button + SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_APPLYNOW, 0); + ok(bQueryInitialFocus, "Did not recieve PSN_QUERYINITIALFOCUS from apply button.\n"); + bQueryInitialFocus = 0; + + DestroyWindow(hp); + + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_WIZARD | PSH_MODELESS; + hp = (HWND) pPropertySheetA(&psh); + + //Test PSN_QUERYINITIALFOCUS gets sent on start + ok(bQueryInitialFocus, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + bQueryInitialFocus = 0; + + //Test Next Button + SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_NEXT, 0); + ok(bQueryInitialFocus, "Did not recieve PSN_QUERYINITIALFOCUS from next button.\n"); + bQueryInitialFocus = 0; + + DestroyWindow(hp); +} + static void init_comctl32_functions(void) { HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); @@ -1442,6 +1546,7 @@ START_TEST(propsheet) test_CreatePropertySheetPage(); test_page_dialog_texture(); test_invalid_hpropsheetpage(); + test_QueryInitialFocus();
if (!load_v6_module(&ctx_cookie, &ctx)) return;