From 0d0bfa4cce3c76b003748aa327fc18bb8d6f4b41 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 27 Oct 2006 16:22:02 +0100 Subject: [PATCH] user32: The hiword of the return value from LB_ITEMFROMPOINT should be a hittest on the item that's returned and not a hittest on the client area as MSDN states. --- dlls/user/listbox.c | 38 +++++++++++++++----- dlls/user/tests/listbox.c | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/dlls/user/listbox.c b/dlls/user/listbox.c index ae9a8e37347..59c4f29c116 100644 --- a/dlls/user/listbox.c +++ b/dlls/user/listbox.c @@ -2731,16 +2731,38 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg, { POINT pt; RECT rect; + int index; + BOOL hit = TRUE; - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - rect.left = 0; - rect.top = 0; - rect.right = descr->width; - rect.bottom = descr->height; + /* The hiword of the return value is not a client area + hittest as suggested by MSDN, but rather a hittest on + the returned listbox item. */ - return MAKELONG( LISTBOX_GetItemFromPoint(descr, pt.x, pt.y), - !PtInRect( &rect, pt ) ); + if(descr->nb_items == 0) + return 0x1ffff; /* win9x returns 0x10000, we copy winnt */ + + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + SetRect(&rect, 0, 0, descr->width, descr->height); + + if(!PtInRect(&rect, pt)) + { + pt.x = min(pt.x, rect.right - 1); + pt.x = max(pt.x, 0); + pt.y = min(pt.y, rect.bottom - 1); + pt.y = max(pt.y, 0); + hit = FALSE; + } + + index = LISTBOX_GetItemFromPoint(descr, pt.x, pt.y); + + if(index == -1) + { + index = descr->nb_items - 1; + hit = FALSE; + } + return MAKELONG(index, hit ? 0 : 1); } case LB_SETCARETINDEX16: diff --git a/dlls/user/tests/listbox.c b/dlls/user/tests/listbox.c index 7bbec60f1d5..435dc91c8ef 100644 --- a/dlls/user/tests/listbox.c +++ b/dlls/user/tests/listbox.c @@ -429,6 +429,79 @@ static void test_listbox_height(void) DestroyWindow( hList ); } +static void test_itemfrompoint(void) +{ + HWND hList = CreateWindow( "ListBox", "list test", 0, + 1, 1, 600, 100, NULL, NULL, NULL, NULL ); + LONG r, id; + RECT rc; + + /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000 */ + r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); + ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + + r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 )); + ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + + r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 )); + ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); + ok( id == 0, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi1"); + ok( id == 1, "item id wrong\n"); + + r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); + ok( r == 0x1, "ret %x\n", r ); + + r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 37 )); + ok( r == 0x10001, "ret %x\n", r ); + + + + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi2"); + ok( id == 2, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi3"); + ok( id == 3, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi4"); + ok( id == 4, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi5"); + ok( id == 5, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi6"); + ok( id == 6, "item id wrong\n"); + id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi7"); + ok( id == 7, "item id wrong\n"); + + /* Set the listbox up so that id 1 is at the top, this leaves 5 + partially visible at the bottom and 6, 7 are invisible */ + + SendMessage( hList, LB_SETTOPINDEX, 1, 0); + r = SendMessage( hList, LB_GETTOPINDEX, 0, 0); + ok( r == 1, "top %d\n", r); + + r = SendMessage( hList, LB_GETITEMRECT, 5, (LPARAM)&rc); + ok( r == 1, "ret %x\n", r); + r = SendMessage( hList, LB_GETITEMRECT, 6, (LPARAM)&rc); + ok( r == 0, "ret %x\n", r); + + r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) ); + ok( r == 1, "ret %x\n", r); + + r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) ); + ok( r == 0x10001, "ret %x\n", r ); + + r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) ); + ok( r == 0x10001, "ret %x\n", r ); + + r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) ); + ok( r == 0x10005, "item %x\n", r ); + + r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) ); + ok( r == 0x10005, "item %x\n", r ); + + DestroyWindow( hList ); +} + START_TEST(listbox) { const struct listbox_test SS = @@ -503,4 +576,5 @@ START_TEST(listbox) test_ownerdraw(); test_selection(); test_listbox_height(); + test_itemfrompoint(); }