From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/user32/tests/listbox.c | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/dlls/user32/tests/listbox.c b/dlls/user32/tests/listbox.c index 3adaaa0999e..869255ceb0d 100644 --- a/dlls/user32/tests/listbox.c +++ b/dlls/user32/tests/listbox.c @@ -2536,6 +2536,43 @@ static void test_LB_FINDSTRING(void) DestroyWindow( listbox ); }
+static void test_integral_resize(void) +{ + int scroll_height = GetSystemMetrics(SM_CYHSCROLL); + int edge_width = GetSystemMetrics(SM_CXEDGE); + int edge_height = GetSystemMetrics(SM_CYEDGE); + HWND parent, listbox; + RECT rect, expect; + int ret; + + parent = create_parent(); + listbox = CreateWindowExA(WS_EX_CLIENTEDGE, "listbox", NULL, + WS_CHILD | WS_HSCROLL, 0, 0, 199, 199, parent, NULL, NULL, NULL); + ok(!!listbox, "got error %lu\n", GetLastError()); + + ret = SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 300, 0); + ok(!ret, "got %d\n", ret); + + ret = SendMessageA(listbox, LB_SETITEMHEIGHT, 0, 40); + ok(!ret, "got %d\n", ret); + + SetWindowPos(listbox, 0, 0, 0, 199, 199, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + + /* The whole point of this functionality is to force an integral number of + * items to be onscreen, but native fails to account for the scrollbar. */ + + GetWindowRect(listbox, &rect); + SetRect(&expect, 100, 100, 299, 260 + (edge_height * 2)); + todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + + GetClientRect(listbox, &rect); + SetRect(&expect, 0, 0, 199 - (edge_width * 2), 160 - scroll_height); + todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + + DestroyWindow(listbox); + DestroyWindow(parent); +} + START_TEST(listbox) { const struct listbox_test SS = @@ -2636,4 +2673,5 @@ START_TEST(listbox) test_LB_SETSEL(); test_LBS_NODATA(); test_LB_FINDSTRING(); + test_integral_resize(); }
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/comctl32/tests/listbox.c | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c index 8a9db99f386..9a51d078891 100644 --- a/dlls/comctl32/tests/listbox.c +++ b/dlls/comctl32/tests/listbox.c @@ -2959,6 +2959,43 @@ static void test_keypresses(void) DestroyWindow(list); }
+static void test_integral_resize(void) +{ + int scroll_height = GetSystemMetrics(SM_CYHSCROLL); + int edge_width = GetSystemMetrics(SM_CXEDGE); + int edge_height = GetSystemMetrics(SM_CYEDGE); + HWND parent, listbox; + RECT rect, expect; + int ret; + + parent = create_parent(); + listbox = CreateWindowExA(WS_EX_CLIENTEDGE, WC_LISTBOXA, NULL, + WS_CHILD | WS_HSCROLL, 0, 0, 199, 199, parent, NULL, NULL, NULL); + ok(!!listbox, "got error %lu\n", GetLastError()); + + ret = SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 300, 0); + ok(!ret, "got %d\n", ret); + + ret = SendMessageA(listbox, LB_SETITEMHEIGHT, 0, 40); + ok(!ret, "got %d\n", ret); + + SetWindowPos(listbox, 0, 0, 0, 199, 199, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + + /* The whole point of this functionality is to force an integral number of + * items to be onscreen, but native fails to account for the scrollbar. */ + + GetWindowRect(listbox, &rect); + SetRect(&expect, 100, 100, 299, 260 + (edge_height * 2)); + todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + + GetClientRect(listbox, &rect); + SetRect(&expect, 0, 0, 199 - (edge_width * 2), 160 - scroll_height); + todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + + DestroyWindow(listbox); + DestroyWindow(parent); +} + START_TEST(listbox) { ULONG_PTR ctx_cookie; @@ -2992,6 +3029,7 @@ START_TEST(listbox) test_LBS_NODATA(); test_LB_FINDSTRING(); test_keypresses(); + test_integral_resize();
uninit_winevent_hook();
From: Michael Müller michael@fds-team.de
Signed-off-by: Michael Müller michael@fds-team.de Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38142 --- dlls/user32/listbox.c | 21 +++++++++++++++++---- dlls/user32/tests/listbox.c | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index 65a5d24533a..19988ae1247 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -458,18 +458,31 @@ static void LISTBOX_UpdateSize( LB_DESCR *descr ) descr->height = rect.bottom - rect.top; if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE)) { + int height = descr->height; INT remaining; RECT rect;
+ /* The whole point of integral height is to ensure that partial items + * aren't displayed. Native seems to fail to take the horizontal + * scrollbar into account (while successfully taking into account e.g. + * WS_EX_CLIENTEDGE), so it ends up obscuring partial items anyway. + * + * It's not clear if native is trying to work from + * the window rect as opposed to the client rect [and badly + * reimplementing AdjustWindowRect()] or poorly working around the case + * where the horizontal scrollbar is repeatedly toggled (which could + * unnecessarily shrink the scrollbar every time it happens). */ + if (GetWindowLongW( descr->self, GWL_STYLE ) & WS_HSCROLL) + height += GetSystemMetrics( SM_CYHSCROLL ); + GetWindowRect( descr->self, &rect ); if(descr->item_height != 0) - remaining = descr->height % descr->item_height; + remaining = height % descr->item_height; else remaining = 0; - if ((descr->height > descr->item_height) && remaining) + if ((height > descr->item_height) && remaining) { - TRACE("[%p]: changing height %d -> %d\n", - descr->self, descr->height, descr->height - remaining ); + TRACE( "[%p]: changing height %d -> %d\n", descr->self, height, height - remaining ); NtUserSetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top - remaining, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE ); diff --git a/dlls/user32/tests/listbox.c b/dlls/user32/tests/listbox.c index 869255ceb0d..0c5dde29410 100644 --- a/dlls/user32/tests/listbox.c +++ b/dlls/user32/tests/listbox.c @@ -2563,11 +2563,11 @@ static void test_integral_resize(void)
GetWindowRect(listbox, &rect); SetRect(&expect, 100, 100, 299, 260 + (edge_height * 2)); - todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect));
GetClientRect(listbox, &rect); SetRect(&expect, 0, 0, 199 - (edge_width * 2), 160 - scroll_height); - todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect));
DestroyWindow(listbox); DestroyWindow(parent);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/comctl32/listbox.c | 21 +++++++++++++++++---- dlls/comctl32/tests/listbox.c | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/listbox.c b/dlls/comctl32/listbox.c index 3d55fc2ad83..c770c2470ed 100644 --- a/dlls/comctl32/listbox.c +++ b/dlls/comctl32/listbox.c @@ -460,18 +460,31 @@ static void LISTBOX_UpdateSize( LB_DESCR *descr ) descr->height = rect.bottom - rect.top; if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE)) { + int height = descr->height; INT remaining; RECT rect;
+ /* The whole point of integral height is to ensure that partial items + * aren't displayed. Native seems to fail to take the horizontal + * scrollbar into account (while successfully taking into account e.g. + * WS_EX_CLIENTEDGE), so it ends up obscuring partial items anyway. + * + * It's not clear if native is trying to work from + * the window rect as opposed to the client rect [and badly + * reimplementing AdjustWindowRect()] or poorly working around the case + * where the horizontal scrollbar is repeatedly toggled (which could + * unnecessarily shrink the scrollbar every time it happens). */ + if (GetWindowLongW( descr->self, GWL_STYLE ) & WS_HSCROLL) + height += GetSystemMetrics( SM_CYHSCROLL ); + GetWindowRect( descr->self, &rect ); if(descr->item_height != 0) - remaining = descr->height % descr->item_height; + remaining = height % descr->item_height; else remaining = 0; - if ((descr->height > descr->item_height) && remaining) + if ((height > descr->item_height) && remaining) { - TRACE("[%p]: changing height %d -> %d\n", - descr->self, descr->height, descr->height - remaining ); + TRACE( "[%p]: changing height %d -> %d\n", descr->self, height, height - remaining ); SetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top - remaining, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE ); diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c index 9a51d078891..8ac595a355b 100644 --- a/dlls/comctl32/tests/listbox.c +++ b/dlls/comctl32/tests/listbox.c @@ -2986,11 +2986,11 @@ static void test_integral_resize(void)
GetWindowRect(listbox, &rect); SetRect(&expect, 100, 100, 299, 260 + (edge_height * 2)); - todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect));
GetClientRect(listbox, &rect); SetRect(&expect, 0, 0, 199 - (edge_width * 2), 160 - scroll_height); - todo_wine ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect)); + ok(EqualRect(&rect, &expect), "expected %s, got %s\n", wine_dbgstr_rect(&expect), wine_dbgstr_rect(&rect));
DestroyWindow(listbox); DestroyWindow(parent);
This merge request was approved by Elizabeth Figura.