mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 06:05:48 +00:00
[COMCTL32_WINETEST] Sync with Wine Staging 2.9. CORE-13362
svn path=/trunk/; revision=74903
This commit is contained in:
parent
b44a9ed6f6
commit
afc72d800f
21 changed files with 700 additions and 90 deletions
|
@ -24,6 +24,7 @@ list(APPEND SOURCE
|
|||
subclass.c
|
||||
syslink.c
|
||||
tab.c
|
||||
taskdialog.c
|
||||
toolbar.c
|
||||
tooltips.c
|
||||
trackbar.c
|
||||
|
|
|
@ -160,8 +160,9 @@ static void test_play(void)
|
|||
|
||||
SetLastError(0xdeadbeef);
|
||||
res = SendMessageA(hAnimateWnd, ACM_PLAY, (WPARAM) -1, MAKELONG(0, -1));
|
||||
err = GetLastError();
|
||||
ok(res == 0, "Play should have failed\n");
|
||||
ok(err == ERROR_RESOURCE_NAME_NOT_FOUND, "Expected 1814, got %u\n", err);
|
||||
ok(err == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", err);
|
||||
destroy_animate();
|
||||
|
||||
create_animate(0, 0);
|
||||
|
|
|
@ -124,8 +124,8 @@ static BOOL ignore_message( UINT message )
|
|||
static LRESULT CALLBACK button_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR ref_data)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
if (ignore_message( message )) return pDefSubclassProc(hwnd, message, wParam, lParam);
|
||||
|
||||
|
@ -160,8 +160,8 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam
|
|||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
static LONG beginpaint_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
if (ignore_message( message )) return 0;
|
||||
|
||||
|
@ -171,17 +171,6 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam
|
|||
message == WM_DRAWITEM || message == WM_COMMAND ||
|
||||
message == WM_IME_SETCONTEXT)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
/* ignore */
|
||||
case WM_NCHITTEST:
|
||||
return HTCLIENT;
|
||||
case WM_SETCURSOR:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_NCMOUSEMOVE:
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|parent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
|
|
|
@ -90,8 +90,8 @@ static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wPar
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
|
|
|
@ -142,15 +142,14 @@ static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, DATETIME_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
|
|
|
@ -394,7 +394,7 @@ static char pszOutOfRangeItem[] = "Out Of Range Item";
|
|||
|
||||
static char *str_items[] =
|
||||
{pszFirstItem, pszSecondItem, pszThirdItem, pszFourthItem, pszReplaceItem, pszOutOfRangeItem};
|
||||
|
||||
|
||||
static char pszUniTestA[] = "TST";
|
||||
static WCHAR pszUniTestW[] = {'T','S','T',0};
|
||||
|
||||
|
@ -414,15 +414,14 @@ static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, HEADER_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
|
@ -1572,7 +1571,6 @@ static void test_header_order (void)
|
|||
{
|
||||
hdi.lParam = i;
|
||||
SendMessageA(hWndHeader, HDM_INSERTITEMA, rand1[i], (LPARAM)&hdi);
|
||||
rand();
|
||||
}
|
||||
check_order(ids1, ord1, 5, "insert without iOrder");
|
||||
|
||||
|
@ -1582,7 +1580,6 @@ static void test_header_order (void)
|
|||
hdi.lParam = i + 5;
|
||||
hdi.iOrder = rand2[i];
|
||||
SendMessageA(hWndHeader, HDM_INSERTITEMA, rand3[i], (LPARAM)&hdi);
|
||||
rand(); rand();
|
||||
}
|
||||
check_order(ids2, ord2, 10, "insert with order");
|
||||
|
||||
|
@ -1591,7 +1588,6 @@ static void test_header_order (void)
|
|||
{
|
||||
hdi.iOrder = rand5[i];
|
||||
SendMessageA(hWndHeader, HDM_SETITEMA, rand4[i], (LPARAM)&hdi);
|
||||
rand(); rand();
|
||||
}
|
||||
check_order(ids2, ord3, 10, "setitems changing order");
|
||||
|
||||
|
|
|
@ -922,36 +922,34 @@ static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, IN
|
|||
char *data;
|
||||
HRESULT hr;
|
||||
|
||||
trace("%s\n", comment);
|
||||
|
||||
ret = ImageList_GetImageCount(himl);
|
||||
ok(ret == cur, "expected image count %d got %d\n", cur, ret);
|
||||
ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
|
||||
|
||||
ret = ImageList_GetIconSize(himl, &cxx, &cyy);
|
||||
ok(ret, "ImageList_GetIconSize failed\n");
|
||||
ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
|
||||
ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
|
||||
ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
|
||||
ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
|
||||
|
||||
init_memstream(&stream);
|
||||
ret = ImageList_Write(himl, &stream.IStream_iface);
|
||||
ok(ret, "ImageList_Write failed\n");
|
||||
ok(ret, "%s: ImageList_Write failed\n", comment);
|
||||
|
||||
hr = GetHGlobalFromStream(stream.stream, &hglobal);
|
||||
ok(hr == S_OK, "Failed to get hglobal, %#x\n", hr);
|
||||
ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr);
|
||||
|
||||
IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
|
||||
|
||||
data = GlobalLock(hglobal);
|
||||
|
||||
ok(data != 0, "ImageList_Write didn't write any data\n");
|
||||
ok(stat.cbSize.LowPart > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
|
||||
ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
|
||||
ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
|
||||
|
||||
check_ilhead_data(data, cx, cy, cur, max, grow, flags);
|
||||
size = check_bitmap_data(data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
|
||||
width, height, flags & 0xfe, comment);
|
||||
if (size < stat.cbSize.LowPart - sizeof(ILHEAD)) /* mask is present */
|
||||
{
|
||||
ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n", stat.cbSize.LowPart, size );
|
||||
ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
|
||||
check_bitmap_data(data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
|
||||
width, height, 1, comment);
|
||||
}
|
||||
|
@ -960,7 +958,7 @@ static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, IN
|
|||
mv.QuadPart = 0;
|
||||
IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
|
||||
himl2 = ImageList_Read(&stream.IStream_iface);
|
||||
ok(himl2 != NULL, "Failed to deserialize imagelist\n");
|
||||
ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
|
||||
ImageList_Destroy(himl2);
|
||||
|
||||
GlobalUnlock(hglobal);
|
||||
|
@ -2220,6 +2218,29 @@ static void test_color_table(UINT ilc)
|
|||
ImageList_Destroy(himl);
|
||||
}
|
||||
|
||||
static void test_copy(void)
|
||||
{
|
||||
HIMAGELIST dst, src;
|
||||
BOOL ret;
|
||||
int count;
|
||||
|
||||
dst = ImageList_Create(5, 11, ILC_COLOR, 1, 1);
|
||||
count = ImageList_GetImageCount(dst);
|
||||
ok(!count, "ImageList not empty.\n");
|
||||
src = createImageList(7, 13);
|
||||
count = ImageList_GetImageCount(src);
|
||||
ok(count > 2, "Tests need an ImageList with more than 2 images\n");
|
||||
|
||||
/* ImageList_Copy() cannot copy between two ImageLists */
|
||||
ret = ImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
|
||||
ok(!ret, "ImageList_Copy() should have returned FALSE\n");
|
||||
count = ImageList_GetImageCount(dst);
|
||||
ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
|
||||
|
||||
ImageList_Destroy(dst);
|
||||
ImageList_Destroy(src);
|
||||
}
|
||||
|
||||
static void test_IImageList_Clone(void)
|
||||
{
|
||||
IImageList *imgl, *imgl2;
|
||||
|
@ -2370,6 +2391,7 @@ START_TEST(imagelist)
|
|||
test_iconsize();
|
||||
test_color_table(ILC_COLOR4);
|
||||
test_color_table(ILC_COLOR8);
|
||||
test_copy();
|
||||
|
||||
FreeLibrary(hComCtl32);
|
||||
|
||||
|
|
|
@ -710,8 +710,8 @@ static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
|
@ -744,15 +744,14 @@ static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wPar
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
|
||||
/* all we need is sizing */
|
||||
if (message == WM_WINDOWPOSCHANGING ||
|
||||
|
@ -5076,12 +5075,30 @@ static void test_finditem(void)
|
|||
fi.psz = f;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
fi.flags = LVFI_STRING | LVFI_PARTIAL;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
fi.flags = LVFI_PARTIAL;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
/* partial string search, inserted text was "foo" */
|
||||
strcpy(f, "fo");
|
||||
fi.flags = LVFI_STRING | LVFI_PARTIAL;
|
||||
fi.psz = f;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
fi.flags = LVFI_STRING;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(-1, r);
|
||||
|
||||
fi.flags = LVFI_PARTIAL;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
/* partial string search, part after start char */
|
||||
strcpy(f, "oo");
|
||||
fi.flags = LVFI_STRING | LVFI_PARTIAL;
|
||||
|
@ -5112,12 +5129,22 @@ static void test_finditem(void)
|
|||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(-1, r);
|
||||
|
||||
strcpy(f, "o");
|
||||
fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL;
|
||||
fi.psz = f;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(-1, r);
|
||||
|
||||
strcpy(f, "f");
|
||||
fi.flags = LVFI_SUBSTRING | LVFI_STRING;
|
||||
fi.psz = f;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL;
|
||||
r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
|
||||
expect(0, r);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
@ -5549,6 +5576,43 @@ static void test_LVM_SETITEMTEXT(void)
|
|||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void test_LVM_REDRAWITEMS(void)
|
||||
{
|
||||
HWND list;
|
||||
DWORD ret;
|
||||
|
||||
list = create_listview_control(LVS_ICON);
|
||||
ok(list != NULL, "failed to create listview window\n");
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0);
|
||||
expect(TRUE, ret);
|
||||
|
||||
insert_item(list, 0);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, -1, 0);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, -1);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 1);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 2);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 1, 0);
|
||||
expect(TRUE, ret);
|
||||
|
||||
ret = SendMessageA(list, LVM_REDRAWITEMS, 2, 3);
|
||||
expect(TRUE, ret);
|
||||
|
||||
DestroyWindow(list);
|
||||
}
|
||||
|
||||
static void test_imagelists(void)
|
||||
{
|
||||
HWND hwnd, header;
|
||||
|
@ -5923,6 +5987,7 @@ START_TEST(listview)
|
|||
test_createdragimage();
|
||||
test_dispinfo();
|
||||
test_LVM_SETITEMTEXT();
|
||||
test_LVM_REDRAWITEMS();
|
||||
test_imagelists();
|
||||
test_deleteitem();
|
||||
test_insertitem();
|
||||
|
|
|
@ -202,29 +202,6 @@ static void test_Alloc(void)
|
|||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
}
|
||||
|
||||
static void test_TaskDialogIndirect(void)
|
||||
{
|
||||
HINSTANCE hinst;
|
||||
void *ptr, *ptr2;
|
||||
|
||||
hinst = LoadLibraryA("comctl32.dll");
|
||||
|
||||
ptr = GetProcAddress(hinst, "TaskDialogIndirect");
|
||||
if (!ptr)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
/* Skipped on 2k3 */
|
||||
skip("TaskDialogIndirect not exported by name\n");
|
||||
#else
|
||||
win_skip("TaskDialogIndirect not exported by name\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
ptr2 = GetProcAddress(hinst, (const CHAR*)345);
|
||||
ok(ptr == ptr2, "got wrong pointer for ordinal 345, %p expected %p\n", ptr2, ptr);
|
||||
}
|
||||
|
||||
static void test_LoadIconWithScaleDown(void)
|
||||
{
|
||||
static const WCHAR nonexisting_fileW[] = {'n','o','n','e','x','i','s','t','i','n','g','.','i','c','o',0};
|
||||
|
@ -413,7 +390,6 @@ START_TEST(misc)
|
|||
return;
|
||||
|
||||
test_builtin_classes();
|
||||
test_TaskDialogIndirect();
|
||||
test_LoadIconWithScaleDown();
|
||||
|
||||
unload_v6_module(ctx_cookie, hCtx);
|
||||
|
|
|
@ -624,15 +624,14 @@ static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, MONTHCAL_SEQ_INDEX, &msg);
|
||||
|
||||
/* some debug output for style changing */
|
||||
|
|
|
@ -371,7 +371,7 @@ static void ok_sequence_(struct msg_sequence **seq, int sequence_index,
|
|||
|
||||
if(todo && !failcount) /* succeeded yet marked todo */
|
||||
{
|
||||
dump++;
|
||||
if (!strcmp(winetest_platform, "wine")) dump++;
|
||||
todo_wine
|
||||
{
|
||||
ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
|
||||
|
|
|
@ -30,7 +30,10 @@
|
|||
#define NUM_MSG_SEQUENCES 1
|
||||
#define PAGER_SEQ_INDEX 0
|
||||
|
||||
static HWND parent_wnd;
|
||||
static HWND parent_wnd, child1_wnd, child2_wnd;
|
||||
|
||||
#define CHILD1_ID 1
|
||||
#define CHILD2_ID 2
|
||||
|
||||
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||
|
||||
|
@ -42,6 +45,29 @@ static const struct message set_child_seq[] = {
|
|||
{ WM_NCCALCSIZE, sent|wparam, TRUE },
|
||||
{ WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE },
|
||||
{ WM_WINDOWPOSCHANGED, sent },
|
||||
{ WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD1_ID },
|
||||
{ WM_NCCALCSIZE, sent|wparam|id|optional, TRUE, 0, CHILD1_ID },
|
||||
{ WM_CHILDACTIVATE, sent|id, 0, 0, CHILD1_ID },
|
||||
{ WM_WINDOWPOSCHANGED, sent|id, 0, 0, CHILD1_ID },
|
||||
{ WM_SIZE, sent|id|defwinproc|optional, 0, 0, CHILD1_ID },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* This differs from the above message list only in the child window that is
|
||||
* expected to receive the child messages. No message is sent to the old child.
|
||||
* Also child 2 is hidden while child 1 is visible. The pager does not make the
|
||||
* hidden child visible. */
|
||||
static const struct message switch_child_seq[] = {
|
||||
{ PGM_SETCHILD, sent },
|
||||
{ WM_WINDOWPOSCHANGING, sent },
|
||||
{ WM_NCCALCSIZE, sent|wparam, TRUE },
|
||||
{ WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE },
|
||||
{ WM_WINDOWPOSCHANGED, sent },
|
||||
{ WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD2_ID },
|
||||
{ WM_NCCALCSIZE, sent|wparam|id, TRUE, 0, CHILD2_ID },
|
||||
{ WM_CHILDACTIVATE, sent|id, 0, 0, CHILD2_ID },
|
||||
{ WM_WINDOWPOSCHANGED, sent|id, 0, 0, CHILD2_ID },
|
||||
{ WM_SIZE, sent|id|defwinproc, 0, 0, CHILD2_ID },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -52,7 +78,20 @@ static const struct message set_pos_seq[] = {
|
|||
{ WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE },
|
||||
{ WM_WINDOWPOSCHANGED, sent },
|
||||
{ WM_MOVE, sent|optional },
|
||||
/* The WM_SIZE handler sends WM_WINDOWPOSCHANGING, WM_CHILDACTIVATE
|
||||
* and WM_WINDOWPOSCHANGED (which sends WM_MOVE) to the child.
|
||||
* Another WM_WINDOWPOSCHANGING is sent afterwards.
|
||||
*
|
||||
* The 2nd WM_WINDOWPOSCHANGING is unconditional, but the comparison
|
||||
* function is too simple to roll back an accepted message, so we have
|
||||
* to mark the 2nd message optional. */
|
||||
{ WM_SIZE, sent|optional },
|
||||
{ WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD1_ID }, /* Actually optional. */
|
||||
{ WM_CHILDACTIVATE, sent|id, 0, 0, CHILD1_ID }, /* Actually optional. */
|
||||
{ WM_WINDOWPOSCHANGED, sent|id|optional, TRUE, 0, CHILD1_ID},
|
||||
{ WM_MOVE, sent|id|optional|defwinproc, 0, 0, CHILD1_ID },
|
||||
{ WM_WINDOWPOSCHANGING, sent|id|optional, 0, 0, CHILD1_ID }, /* Actually not optional. */
|
||||
{ WM_CHILDACTIVATE, sent|id|optional, 0, 0, CHILD1_ID }, /* Actually not optional. */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -145,13 +184,12 @@ static HWND create_parent_window(void)
|
|||
static LRESULT WINAPI pager_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
struct message msg;
|
||||
struct message msg = { 0 };
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, PAGER_SEQ_INDEX, &msg);
|
||||
return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
@ -170,9 +208,55 @@ static HWND create_pager_control( DWORD style )
|
|||
return hwnd;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI child_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent | wparam | lparam;
|
||||
if (defwndproc_counter)
|
||||
msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
|
||||
if (hwnd == child1_wnd)
|
||||
msg.id = CHILD1_ID;
|
||||
else if (hwnd == child2_wnd)
|
||||
msg.id = CHILD2_ID;
|
||||
else
|
||||
msg.id = 0;
|
||||
|
||||
add_message(sequences, PAGER_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
ret = DefWindowProcA(hwnd, message, wParam, lParam);
|
||||
defwndproc_counter--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL register_child_wnd_class(void)
|
||||
{
|
||||
WNDCLASSA cls;
|
||||
|
||||
cls.style = 0;
|
||||
cls.lpfnWndProc = child_proc;
|
||||
cls.cbClsExtra = 0;
|
||||
cls.cbWndExtra = 0;
|
||||
cls.hInstance = GetModuleHandleA(NULL);
|
||||
cls.hIcon = 0;
|
||||
cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
|
||||
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = "Pager test child class";
|
||||
return RegisterClassA(&cls);
|
||||
}
|
||||
|
||||
static void test_pager(void)
|
||||
{
|
||||
HWND pager, child;
|
||||
HWND pager;
|
||||
RECT rect, rect2;
|
||||
|
||||
pager = create_pager_control( PGS_HORZ );
|
||||
|
@ -181,16 +265,36 @@ static void test_pager(void)
|
|||
win_skip( "Pager control not supported\n" );
|
||||
return;
|
||||
}
|
||||
child = CreateWindowA( "BUTTON", "button", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 300, 300,
|
||||
|
||||
register_child_wnd_class();
|
||||
|
||||
child1_wnd = CreateWindowA( "Pager test child class", "button", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 300, 300,
|
||||
pager, 0, GetModuleHandleA(0), 0 );
|
||||
child2_wnd = CreateWindowA("Pager test child class", "button", WS_CHILD | WS_BORDER, 0, 0, 300, 300,
|
||||
pager, 0, GetModuleHandleA(0), 0);
|
||||
|
||||
flush_sequences( sequences, NUM_MSG_SEQUENCES );
|
||||
SendMessageA( pager, PGM_SETCHILD, 0, (LPARAM)child );
|
||||
ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "set child", TRUE);
|
||||
SendMessageA( pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd );
|
||||
ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "set child", FALSE);
|
||||
GetWindowRect( pager, &rect );
|
||||
ok( rect.right - rect.left == 100 && rect.bottom - rect.top == 100,
|
||||
"pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top );
|
||||
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
SendMessageA(pager, PGM_SETCHILD, 0, (LPARAM)child2_wnd);
|
||||
ok_sequence(sequences, PAGER_SEQ_INDEX, switch_child_seq, "switch to invisible child", FALSE);
|
||||
GetWindowRect(pager, &rect);
|
||||
ok(rect.right - rect.left == 100 && rect.bottom - rect.top == 100,
|
||||
"pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top);
|
||||
ok(!IsWindowVisible(child2_wnd), "Child window 2 is visible\n");
|
||||
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
SendMessageA(pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd);
|
||||
ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "switch to visible child", FALSE);
|
||||
GetWindowRect(pager, &rect);
|
||||
ok(rect.right - rect.left == 100 && rect.bottom - rect.top == 100,
|
||||
"pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top);
|
||||
|
||||
flush_sequences( sequences, NUM_MSG_SEQUENCES );
|
||||
SendMessageA( pager, PGM_SETPOS, 0, 10 );
|
||||
ok_sequence(sequences, PAGER_SEQ_INDEX, set_pos_seq, "set pos", TRUE);
|
||||
|
|
|
@ -713,7 +713,7 @@ static const struct message property_sheet_seq[] = {
|
|||
|
||||
static void save_message(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, INT receiver)
|
||||
{
|
||||
struct message msg;
|
||||
struct message msg = { 0 };
|
||||
|
||||
if (message < WM_USER &&
|
||||
message != WM_GETICON &&
|
||||
|
@ -990,6 +990,141 @@ if (0)
|
|||
DestroyWindow(hdlg);
|
||||
}
|
||||
|
||||
struct custom_proppage
|
||||
{
|
||||
union
|
||||
{
|
||||
PROPSHEETPAGEA pageA;
|
||||
PROPSHEETPAGEW pageW;
|
||||
} u;
|
||||
unsigned int addref_called;
|
||||
unsigned int release_called;
|
||||
};
|
||||
|
||||
static UINT CALLBACK proppage_callback_a(HWND hwnd, UINT msg, PROPSHEETPAGEA *psp)
|
||||
{
|
||||
struct custom_proppage *cpage = (struct custom_proppage *)psp->lParam;
|
||||
PROPSHEETPAGEA *psp_orig = &cpage->u.pageA;
|
||||
|
||||
ok(hwnd == NULL, "Expected NULL hwnd, got %p\n", hwnd);
|
||||
|
||||
ok(psp->lParam && psp->lParam != (LPARAM)psp, "Expected newly allocated page description, got %lx, %p\n",
|
||||
psp->lParam, psp);
|
||||
ok(psp_orig->pszTitle == psp->pszTitle, "Expected same page title pointer\n");
|
||||
ok(!lstrcmpA(psp_orig->pszTitle, psp->pszTitle), "Expected same page title string\n");
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case PSPCB_ADDREF:
|
||||
ok(psp->dwSize > PROPSHEETPAGEA_V1_SIZE, "Expected ADDREF for V2+ only, got size %u\n", psp->dwSize);
|
||||
cpage->addref_called++;
|
||||
break;
|
||||
case PSPCB_RELEASE:
|
||||
ok(psp->dwSize >= PROPSHEETPAGEA_V1_SIZE, "Unexpected RELEASE, got size %u\n", psp->dwSize);
|
||||
cpage->release_called++;
|
||||
break;
|
||||
default:
|
||||
ok(0, "Unexpected message %u\n", msg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UINT CALLBACK proppage_callback_w(HWND hwnd, UINT msg, PROPSHEETPAGEW *psp)
|
||||
{
|
||||
struct custom_proppage *cpage = (struct custom_proppage *)psp->lParam;
|
||||
PROPSHEETPAGEW *psp_orig = &cpage->u.pageW;
|
||||
|
||||
ok(hwnd == NULL, "Expected NULL hwnd, got %p\n", hwnd);
|
||||
ok(psp->lParam && psp->lParam != (LPARAM)psp, "Expected newly allocated page description, got %lx, %p\n",
|
||||
psp->lParam, psp);
|
||||
ok(psp_orig->pszTitle == psp->pszTitle, "Expected same page title pointer\n");
|
||||
ok(!lstrcmpW(psp_orig->pszTitle, psp->pszTitle), "Expected same page title string\n");
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case PSPCB_ADDREF:
|
||||
ok(psp->dwSize > PROPSHEETPAGEW_V1_SIZE, "Expected ADDREF for V2+ only, got size %u\n", psp->dwSize);
|
||||
cpage->addref_called++;
|
||||
break;
|
||||
case PSPCB_RELEASE:
|
||||
ok(psp->dwSize >= PROPSHEETPAGEW_V1_SIZE, "Unexpected RELEASE, got size %u\n", psp->dwSize);
|
||||
cpage->release_called++;
|
||||
break;
|
||||
default:
|
||||
ok(0, "Unexpected message %u\n", msg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void test_CreatePropertySheetPage(void)
|
||||
{
|
||||
static const WCHAR titleW[] = {'T','i','t','l','e',0};
|
||||
struct custom_proppage page;
|
||||
HPROPSHEETPAGE hpsp;
|
||||
BOOL ret;
|
||||
|
||||
memset(&page.u.pageA, 0, sizeof(page.u.pageA));
|
||||
page.u.pageA.dwFlags = PSP_USECALLBACK;
|
||||
page.u.pageA.pfnDlgProc = page_dlg_proc_messages;
|
||||
page.u.pageA.pfnCallback = proppage_callback_a;
|
||||
page.u.pageA.lParam = (LPARAM)&page;
|
||||
page.u.pageA.pszTitle = "Title";
|
||||
|
||||
/* Only minimal size validation is performed */
|
||||
for (page.u.pageA.dwSize = PROPSHEETPAGEA_V1_SIZE - 1; page.u.pageA.dwSize <= PROPSHEETPAGEA_V4_SIZE + 1; page.u.pageA.dwSize++)
|
||||
{
|
||||
page.addref_called = 0;
|
||||
hpsp = CreatePropertySheetPageA(&page.u.pageA);
|
||||
|
||||
if (page.u.pageA.dwSize < PROPSHEETPAGEA_V1_SIZE)
|
||||
ok(hpsp == NULL, "Expected failure, size %u\n", page.u.pageA.dwSize);
|
||||
else
|
||||
{
|
||||
ok(hpsp != NULL, "Failed to create a page, size %u\n", page.u.pageA.dwSize);
|
||||
ok(page.addref_called == (page.u.pageA.dwSize > PROPSHEETPAGEA_V1_SIZE) ? 1 : 0, "Expected ADDREF callback message\n");
|
||||
}
|
||||
|
||||
if (hpsp)
|
||||
{
|
||||
page.release_called = 0;
|
||||
ret = DestroyPropertySheetPage(hpsp);
|
||||
ok(ret, "Failed to destroy a page\n");
|
||||
ok(page.release_called == 1, "Expected RELEASE callback message\n");
|
||||
}
|
||||
}
|
||||
|
||||
memset(&page.u.pageW, 0, sizeof(page.u.pageW));
|
||||
page.u.pageW.dwFlags = PSP_USECALLBACK;
|
||||
page.u.pageW.pfnDlgProc = page_dlg_proc_messages;
|
||||
page.u.pageW.pfnCallback = proppage_callback_w;
|
||||
page.u.pageW.lParam = (LPARAM)&page;
|
||||
page.u.pageW.pszTitle = titleW;
|
||||
|
||||
for (page.u.pageW.dwSize = PROPSHEETPAGEW_V1_SIZE - 1; page.u.pageW.dwSize <= PROPSHEETPAGEW_V4_SIZE + 1; page.u.pageW.dwSize++)
|
||||
{
|
||||
page.addref_called = 0;
|
||||
hpsp = CreatePropertySheetPageW(&page.u.pageW);
|
||||
|
||||
if (page.u.pageW.dwSize < PROPSHEETPAGEW_V1_SIZE)
|
||||
ok(hpsp == NULL, "Expected failure, size %u\n", page.u.pageW.dwSize);
|
||||
else
|
||||
{
|
||||
ok(hpsp != NULL, "Failed to create a page, size %u\n", page.u.pageW.dwSize);
|
||||
ok(page.addref_called == (page.u.pageW.dwSize > PROPSHEETPAGEW_V1_SIZE) ? 1 : 0, "Expected ADDREF callback message\n");
|
||||
}
|
||||
|
||||
if (hpsp)
|
||||
{
|
||||
page.release_called = 0;
|
||||
ret = DestroyPropertySheetPage(hpsp);
|
||||
ok(ret, "Failed to destroy a page\n");
|
||||
ok(page.release_called == 1, "Expected RELEASE callback message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(propsheet)
|
||||
{
|
||||
test_title();
|
||||
|
@ -1001,4 +1136,5 @@ START_TEST(propsheet)
|
|||
test_messages();
|
||||
test_PSM_ADDPAGE();
|
||||
test_PSM_INSERTPAGE();
|
||||
test_CreatePropertySheetPage();
|
||||
}
|
||||
|
|
|
@ -146,15 +146,14 @@ static WNDPROC syslink_oldproc;
|
|||
static LRESULT WINAPI syslink_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, SYSLINK_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
|
|
|
@ -304,8 +304,8 @@ create_tabcontrol (DWORD style, DWORD mask)
|
|||
static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
/* do not log painting messages */
|
||||
if (message != WM_PAINT &&
|
||||
|
@ -321,7 +321,6 @@ static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam
|
|||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, PARENT_SEQ_INDEX, &msg);
|
||||
}
|
||||
|
||||
|
@ -367,8 +366,8 @@ static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam,
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
/* do not log painting messages */
|
||||
if (message != WM_PAINT &&
|
||||
|
@ -384,7 +383,6 @@ static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam,
|
|||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, TAB_SEQ_INDEX, &msg);
|
||||
}
|
||||
|
||||
|
|
58
rostests/winetests/comctl32/taskdialog.c
Normal file
58
rostests/winetests/comctl32/taskdialog.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Unit tests for the task dialog control.
|
||||
*
|
||||
* Copyright 2017 Fabian Maurer for the Wine project
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "commctrl.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "v6util.h"
|
||||
|
||||
static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
|
||||
|
||||
START_TEST(taskdialog)
|
||||
{
|
||||
ULONG_PTR ctx_cookie;
|
||||
void *ptr_ordinal;
|
||||
HINSTANCE hinst;
|
||||
HANDLE hCtx;
|
||||
|
||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||
return;
|
||||
|
||||
/* Check if task dialogs are available */
|
||||
hinst = LoadLibraryA("comctl32.dll");
|
||||
|
||||
pTaskDialogIndirect = (void *)GetProcAddress(hinst, "TaskDialogIndirect");
|
||||
if (!pTaskDialogIndirect)
|
||||
{
|
||||
win_skip("TaskDialogIndirect not exported by name\n");
|
||||
unload_v6_module(ctx_cookie, hCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_ordinal = GetProcAddress(hinst, (const char *)345);
|
||||
ok(pTaskDialogIndirect == ptr_ordinal, "got wrong pointer for ordinal 345, %p expected %p\n",
|
||||
ptr_ordinal, pTaskDialogIndirect);
|
||||
|
||||
unload_v6_module(ctx_cookie, hCtx);
|
||||
}
|
|
@ -23,6 +23,7 @@ extern void func_status(void);
|
|||
extern void func_subclass(void);
|
||||
extern void func_syslink(void);
|
||||
extern void func_tab(void);
|
||||
extern void func_taskdialog(void);
|
||||
extern void func_toolbar(void);
|
||||
extern void func_tooltips(void);
|
||||
extern void func_trackbar(void);
|
||||
|
@ -51,6 +52,7 @@ const struct test winetest_testlist[] =
|
|||
{ "subclass", func_subclass },
|
||||
{ "syslink", func_syslink },
|
||||
{ "tab", func_tab },
|
||||
{ "taskdialog", func_taskdialog },
|
||||
{ "toolbar", func_toolbar },
|
||||
{ "tooltips", func_tooltips },
|
||||
{ "trackbar", func_trackbar },
|
||||
|
|
|
@ -2276,7 +2276,8 @@ static void test_save(void)
|
|||
{
|
||||
HWND wnd = NULL;
|
||||
TBSAVEPARAMSW params;
|
||||
static const WCHAR subkey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','T','e','s','t',0};
|
||||
static const WCHAR subkey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
|
||||
'W','i','n','e','T','e','s','t',0};
|
||||
static const WCHAR value[] = {'t','o','o','l','b','a','r','t','e','s','t',0};
|
||||
LONG res;
|
||||
HKEY key;
|
||||
|
|
|
@ -442,15 +442,14 @@ static HWND create_parent_window(void){
|
|||
static LRESULT WINAPI trackbar_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, TRACKBAR_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
|
|
|
@ -54,6 +54,21 @@ static BOOL g_v6;
|
|||
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
||||
static struct msg_sequence *item_sequence[1];
|
||||
|
||||
static void flush_events(void)
|
||||
{
|
||||
MSG msg;
|
||||
int diff = 200;
|
||||
int min_timeout = 100;
|
||||
DWORD time = GetTickCount() + diff;
|
||||
|
||||
while (diff > 0)
|
||||
{
|
||||
if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
diff = time - GetTickCount();
|
||||
}
|
||||
}
|
||||
|
||||
static const struct message FillRootSeq[] = {
|
||||
{ TVM_INSERTITEMA, sent },
|
||||
{ TVM_INSERTITEMA, sent },
|
||||
|
@ -201,6 +216,13 @@ static const struct message test_get_set_unicodeformat_seq[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message test_right_click_seq[] = {
|
||||
{ WM_RBUTTONDOWN, sent|wparam, MK_RBUTTON },
|
||||
{ WM_CAPTURECHANGED, sent|defwinproc },
|
||||
{ TVM_GETNEXTITEM, sent|wparam|lparam|defwinproc, TVGN_CARET, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message parent_expand_seq[] = {
|
||||
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
|
||||
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
|
||||
|
@ -342,6 +364,12 @@ static const struct message parent_vk_return_seq[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message parent_right_click_seq[] = {
|
||||
{ WM_NOTIFY, sent|id, 0, 0, NM_RCLICK },
|
||||
{ WM_CONTEXTMENU, sent },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static HWND hMainWnd;
|
||||
|
||||
static HTREEITEM hRoot, hChild;
|
||||
|
@ -383,15 +411,14 @@ static LRESULT WINAPI TreeviewWndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
|||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
WNDPROC lpOldProc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
struct message msg = { 0 };
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
|
||||
|
||||
defwndproc_counter++;
|
||||
|
@ -1099,7 +1126,7 @@ static void test_get_set_unicodeformat(void)
|
|||
static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
RECT rect;
|
||||
HTREEITEM visibleItem;
|
||||
|
@ -1111,8 +1138,6 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam,
|
|||
msg.lParam = lParam;
|
||||
if (message == WM_NOTIFY && lParam)
|
||||
msg.id = ((NMHDR*)lParam)->code;
|
||||
else
|
||||
msg.id = 0;
|
||||
|
||||
/* log system messages, except for painting */
|
||||
if (message < WM_USER &&
|
||||
|
@ -1299,6 +1324,13 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case NM_RCLICK:
|
||||
{
|
||||
HTREEITEM selected = (HTREEITEM)SendMessageA(((NMHDR *)lParam)->hwndFrom,
|
||||
TVM_GETNEXTITEM, TVGN_CARET, 0);
|
||||
ok(selected == hChild, "child item should still be selected\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2397,6 +2429,238 @@ static void test_TVS_FULLROWSELECT(void)
|
|||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void get_item_names_string(HWND hwnd, HTREEITEM item, char *str)
|
||||
{
|
||||
TVITEMA tvitem = { 0 };
|
||||
HTREEITEM child;
|
||||
char name[16];
|
||||
|
||||
if (!item)
|
||||
{
|
||||
item = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
|
||||
str[0] = 0;
|
||||
}
|
||||
|
||||
child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
|
||||
|
||||
tvitem.mask = TVIF_TEXT;
|
||||
tvitem.hItem = item;
|
||||
tvitem.pszText = name;
|
||||
tvitem.cchTextMax = sizeof(name);
|
||||
SendMessageA(hwnd, TVM_GETITEMA, 0, (LPARAM)&tvitem);
|
||||
strcat(str, tvitem.pszText);
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
get_item_names_string(hwnd, child, str);
|
||||
child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)child);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_treeview_sort_test(HWND hwnd)
|
||||
{
|
||||
static const char *itemnames[] =
|
||||
{
|
||||
"root", "Wasp", "Caribou", "Vacuum",
|
||||
"Ocelot", "Newspaper", "Litter bin"
|
||||
};
|
||||
|
||||
HTREEITEM root, children[2];
|
||||
TVINSERTSTRUCTA ins;
|
||||
unsigned i = 0;
|
||||
|
||||
SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
|
||||
|
||||
/* root, two children, with two children each */
|
||||
ins.hParent = TVI_ROOT;
|
||||
ins.hInsertAfter = TVI_ROOT;
|
||||
U(ins).item.mask = TVIF_TEXT;
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
ins.hParent = root;
|
||||
ins.hInsertAfter = TVI_LAST;
|
||||
U(ins).item.mask = TVIF_TEXT;
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
children[0] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
children[1] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
ins.hParent = children[0];
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
ins.hParent = children[1];
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
U(ins).item.pszText = (char *)itemnames[i++];
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
}
|
||||
|
||||
static void test_TVM_SORTCHILDREN(void)
|
||||
{
|
||||
static const char *initial_order = "rootWaspVacuumOcelotCaribouNewspaperLitter bin";
|
||||
static const char *sorted_order = "rootCaribouNewspaperLitter binWaspVacuumOcelot";
|
||||
TVINSERTSTRUCTA ins;
|
||||
char buff[256];
|
||||
HTREEITEM root;
|
||||
HWND hwnd;
|
||||
BOOL ret;
|
||||
|
||||
hwnd = create_treeview_control(0);
|
||||
|
||||
/* call on empty tree */
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
|
||||
ok(!ret, "Unexpected ret value %d\n", ret);
|
||||
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
|
||||
ok(!ret, "Unexpected ret value %d\n", ret);
|
||||
|
||||
/* add only root, sort from it */
|
||||
ins.hParent = TVI_ROOT;
|
||||
ins.hInsertAfter = TVI_ROOT;
|
||||
U(ins).item.mask = TVIF_TEXT;
|
||||
U(ins).item.pszText = (char *)"root";
|
||||
root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
ok(root != NULL, "Expected root node\n");
|
||||
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
|
||||
ok(!ret, "Unexpected ret value %d\n", ret);
|
||||
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
|
||||
ok(!ret, "Unexpected ret value %d\n", ret);
|
||||
|
||||
/* root, two children, with two children each */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, initial_order), "Wrong initial order %s, expected %s\n", buff, initial_order);
|
||||
|
||||
/* with NULL item nothing is sorted */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
|
||||
todo_wine
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
|
||||
|
||||
/* TVI_ROOT as item */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
|
||||
todo_wine
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
|
||||
|
||||
/* zero WPARAM, item is specified */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
|
||||
ok(root != NULL, "Failed to get root item\n");
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
|
||||
|
||||
/* non-zero WPARAM, NULL item */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, 0);
|
||||
todo_wine
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
|
||||
|
||||
/* TVI_ROOT as item */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)TVI_ROOT);
|
||||
todo_wine
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
|
||||
|
||||
/* non-zero WPARAM, item is specified */
|
||||
fill_treeview_sort_test(hwnd);
|
||||
root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
|
||||
ok(root != NULL, "Failed to get root item\n");
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
|
||||
|
||||
/* case insensitive comparison */
|
||||
SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
|
||||
|
||||
ins.hParent = TVI_ROOT;
|
||||
ins.hInsertAfter = TVI_ROOT;
|
||||
U(ins).item.mask = TVIF_TEXT;
|
||||
U(ins).item.pszText = (char *)"root";
|
||||
root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
ok(root != NULL, "Expected root node\n");
|
||||
|
||||
ins.hParent = root;
|
||||
ins.hInsertAfter = TVI_LAST;
|
||||
U(ins).item.pszText = (char *)"I1";
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
ins.hParent = root;
|
||||
ins.hInsertAfter = TVI_LAST;
|
||||
U(ins).item.pszText = (char *)"i1";
|
||||
SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
|
||||
|
||||
ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
|
||||
ok(ret, "Unexpected ret value %d\n", ret);
|
||||
get_item_names_string(hwnd, NULL, buff);
|
||||
ok(!strcmp(buff, "rootI1i1"), "Wrong sorted order %s\n", buff);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void test_right_click(void)
|
||||
{
|
||||
HWND hTree;
|
||||
HTREEITEM selected;
|
||||
RECT rc;
|
||||
LRESULT result;
|
||||
POINT pt;
|
||||
|
||||
hTree = create_treeview_control(0);
|
||||
fill_tree(hTree);
|
||||
|
||||
SendMessageA(hTree, TVM_ENSUREVISIBLE, 0, (LPARAM)hChild);
|
||||
SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
|
||||
selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
|
||||
ok(selected == hChild, "child item not selected\n");
|
||||
|
||||
*(HTREEITEM *)&rc = hRoot;
|
||||
result = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
|
||||
ok(result, "TVM_GETITEMRECT failed\n");
|
||||
|
||||
flush_events();
|
||||
|
||||
pt.x = (rc.left + rc.right) / 2;
|
||||
pt.y = (rc.top + rc.bottom) / 2;
|
||||
ClientToScreen(hMainWnd, &pt);
|
||||
|
||||
flush_events();
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
|
||||
PostMessageA(hTree, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(pt.x, pt.y));
|
||||
PostMessageA(hTree, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
|
||||
|
||||
flush_events();
|
||||
|
||||
ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_right_click_seq, "right click sequence", FALSE);
|
||||
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_right_click_seq, "parent right click sequence", FALSE);
|
||||
|
||||
selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
|
||||
ok(selected == hChild, "child item should still be selected\n");
|
||||
|
||||
DestroyWindow(hTree);
|
||||
}
|
||||
|
||||
START_TEST(treeview)
|
||||
{
|
||||
HMODULE hComctl32;
|
||||
|
@ -2473,6 +2737,8 @@ START_TEST(treeview)
|
|||
test_customdraw();
|
||||
test_WM_KEYDOWN();
|
||||
test_TVS_FULLROWSELECT();
|
||||
test_TVM_SORTCHILDREN();
|
||||
test_right_click();
|
||||
|
||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||
{
|
||||
|
|
|
@ -169,8 +169,8 @@ static const struct message test_updown_pos_nochange_seq[] = {
|
|||
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
/* log system messages, except for painting */
|
||||
if (message < WM_USER &&
|
||||
|
@ -187,7 +187,6 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
|
|||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = 0;
|
||||
add_message(sequences, PARENT_SEQ_INDEX, &msg);
|
||||
}
|
||||
|
||||
|
@ -232,8 +231,8 @@ static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam,
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
|
@ -272,8 +271,8 @@ static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
|
|||
{
|
||||
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||
static LONG defwndproc_counter = 0;
|
||||
struct message msg = { 0 };
|
||||
LRESULT ret;
|
||||
struct message msg;
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|wparam|lparam;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue