[COMCTL32_WINETEST] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68554
This commit is contained in:
Amine Khaldi 2015-07-22 19:30:52 +00:00
parent 3b13364f05
commit 44aca5e627
7 changed files with 916 additions and 22 deletions

View file

@ -321,6 +321,7 @@ static const struct message setstyle_seq[] =
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional },
{ WM_PAINT, sent|optional },
{ 0 }
};
@ -368,6 +369,7 @@ static const struct message setstate_seq[] =
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional },
{ WM_PAINT, sent|optional },
{ 0 }
};
@ -429,6 +431,7 @@ static const struct message setcheck_ignored_seq[] =
{
{ BM_SETCHECK, sent },
{ WM_APP, sent|wparam|lparam, 0, 0 },
{ WM_PAINT, sent|optional },
{ 0 }
};

View file

@ -179,6 +179,16 @@ static const struct message listview_ownerdata_switchto_seq[] = {
static const struct message listview_getorderarray_seq[] = {
{ LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
{ HDM_GETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID },
{ LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID },
{ HDM_GETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID },
{ 0 }
};
static const struct message listview_setorderarray_seq[] = {
{ LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
{ HDM_SETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID },
{ LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID },
{ HDM_SETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID },
{ 0 }
};
@ -1416,13 +1426,28 @@ static void test_items(void)
static void test_columns(void)
{
HWND hwnd;
HWND hwnd, header;
LVCOLUMNA column;
LVITEMA item;
INT order[2];
CHAR buff[5];
DWORD rc;
hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_LIST,
10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
ok(hwnd != NULL, "failed to create listview window\n");
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
ok(header == NULL, "got %p\n", header);
rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
ok(rc == 0, "got %d\n", rc);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
ok(header == NULL, "got %p\n", header);
DestroyWindow(hwnd);
hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT,
10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
ok(hwnd != NULL, "failed to create listview window\n");
@ -1460,8 +1485,24 @@ static void test_columns(void)
ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 0, 0);
expect(0, rc);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
/* LVM_SETCOLUMNORDERARRAY */
flush_sequences(sequences, NUM_MSG_SEQUENCES);
order[0] = 0;
order[1] = 1;
rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
expect(1, rc);
rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 0, 0);
expect(0, rc);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_setorderarray_seq, "set order array", FALSE);
/* after column added subitem is considered as present */
insert_item(hwnd, 0);
@ -3877,7 +3918,6 @@ static void test_getitemrect(void)
LVCOLUMNA col;
INT order[2];
POINT pt;
HDC hdc;
/* rectangle isn't empty for empty text items */
hwnd = create_listview_control(LVS_LIST);
@ -3891,9 +3931,9 @@ static void test_getitemrect(void)
expect(TRUE, r);
expect(0, rect.left);
expect(0, rect.top);
hdc = GetDC(hwnd);
todo_wine expect(((GetDeviceCaps(hdc, LOGPIXELSX) + 15) / 16) * 16, rect.right);
ReleaseDC(hwnd, hdc);
/* estimate it as width / height ratio */
todo_wine
ok((rect.right / rect.bottom) >= 5, "got right %d, bottom %d\n", rect.right, rect.bottom);
DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_REPORT);
@ -4557,6 +4597,12 @@ static void test_get_set_view(void)
style = GetWindowLongPtrA(hwnd, GWL_STYLE);
ok(style & LVS_LIST, "Expected style to be preserved\n");
/* now change window style to see if view is remapped */
style = GetWindowLongPtrA(hwnd, GWL_STYLE);
SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SHOWSELALWAYS);
ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
expect(LV_VIEW_SMALLICON, ret);
DestroyWindow(hwnd);
}
@ -4789,6 +4835,36 @@ static void test_getitemspacing(void)
DestroyWindow(hwnd);
}
static INT get_current_font_height(HWND listview)
{
TEXTMETRICA tm;
HFONT hfont;
HWND hwnd;
HDC hdc;
hwnd = (HWND)SendMessageA(listview, LVM_GETHEADER, 0, 0);
if (!hwnd)
hwnd = listview;
hfont = (HFONT)SendMessageA(hwnd, WM_GETFONT, 0, 0);
if (!hfont) {
hdc = GetDC(hwnd);
GetTextMetricsA(hdc, &tm);
ReleaseDC(hwnd, hdc);
}
else {
HFONT oldfont;
hdc = GetDC(0);
oldfont = SelectObject(hdc, hfont);
GetTextMetricsA(hdc, &tm);
SelectObject(hdc, oldfont);
ReleaseDC(0, hdc);
}
return tm.tmHeight;
}
static void test_getcolumnwidth(void)
{
HWND hwnd;
@ -4796,7 +4872,7 @@ static void test_getcolumnwidth(void)
DWORD_PTR style;
LVCOLUMNA col;
LVITEMA itema;
HDC hdc;
INT height;
/* default column width */
hwnd = create_listview_control(LVS_ICON);
@ -4820,9 +4896,8 @@ static void test_getcolumnwidth(void)
memset(&itema, 0, sizeof(itema));
SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
hdc = GetDC(hwnd);
todo_wine expect(((GetDeviceCaps(hdc, LOGPIXELSX) + 15) / 16) * 16, ret);
ReleaseDC(hwnd, hdc);
height = get_current_font_height(hwnd);
ok((ret / height) >= 6, "got width %d, height %d\n", ret, height);
DestroyWindow(hwnd);
}
@ -5106,10 +5181,18 @@ static void test_LVS_EX_HEADERINALLVIEWS(void)
static void test_hover(void)
{
HWND hwnd;
HWND hwnd, fg;
DWORD r;
hwnd = create_listview_control(LVS_ICON);
SetForegroundWindow(hwndparent);
fg = GetForegroundWindow();
if (fg != hwndparent)
{
skip("Window is not in the foreground. Skipping hover tests.\n");
DestroyWindow(hwnd);
return;
}
/* test WM_MOUSEHOVER forwarding */
flush_sequences(sequences, NUM_MSG_SEQUENCES);
@ -5641,6 +5724,30 @@ static void test_insertitem(void)
DestroyWindow(hwnd);
}
static void test_header_proc(void)
{
HWND hwnd, header, hdr;
WNDPROC proc1, proc2;
hwnd = create_listview_control(LVS_REPORT);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
ok(header != NULL, "got %p\n", header);
hdr = CreateWindowExA(0, WC_HEADERA, NULL,
WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ,
0, 0, 0, 0,
NULL, NULL, NULL, NULL);
ok(hdr != NULL, "got %p\n", hdr);
proc1 = (WNDPROC)GetWindowLongPtrW(header, GWLP_WNDPROC);
proc2 = (WNDPROC)GetWindowLongPtrW(hdr, GWLP_WNDPROC);
ok(proc1 == proc2, "got %p, expected %p\n", proc1, proc2);
DestroyWindow(hdr);
DestroyWindow(hwnd);
}
START_TEST(listview)
{
HMODULE hComctl32;
@ -5709,6 +5816,7 @@ START_TEST(listview)
test_imagelists();
test_deleteitem();
test_insertitem();
test_header_proc();
if (!load_v6_module(&ctx_cookie, &hCtx))
{
@ -5726,6 +5834,7 @@ START_TEST(listview)
test_deleteitem();
test_multiselect();
test_insertitem();
test_header_proc();
unload_v6_module(ctx_cookie, hCtx);

View file

@ -615,7 +615,9 @@ static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
static HWND create_monthcal_control(DWORD style)
{
WNDPROC oldproc;
RECT rect;
HWND hwnd;
BOOL ret;
hwnd = CreateWindowExA(0, MONTHCAL_CLASSA, "", WS_CHILD | WS_BORDER | WS_VISIBLE | style,
0, 0, 300, 400, parent_wnd, NULL, GetModuleHandleA(NULL), NULL);
@ -628,6 +630,13 @@ static HWND create_monthcal_control(DWORD style)
SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
/* make sure calendar grid is 2x1 */
ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rect);
ok(ret, "got %d\n", ret);
ret = SetWindowPos(hwnd, NULL, 0, 0, rect.right * 5 / 2, rect.bottom * 3 / 2, SWP_NOMOVE);
ok(ret, "got %d\n", ret);
return hwnd;
}

View file

@ -877,6 +877,7 @@ if (0)
r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
ok(r == 3, "got %d\n", r);
DestroyPropertySheetPage(hpsp[4]);
DestroyWindow(hdlg);
}

View file

@ -54,6 +54,40 @@ static const struct message ttgetdispinfo_parent_seq[] = {
{ 0 }
};
static const struct message save_parent_seq[] = {
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, -1 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 0 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 1 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 2 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 3 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 4 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 5 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_SAVE, 6 },
{ 0 }
};
static const struct message restore_parent_seq[] = {
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, -1 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 0 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 1 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 2 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 3 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 4 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 5 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 6 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 7 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 8 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 9 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 0xa },
{ WM_NOTIFY, sent|id, 0, 0, TBN_BEGINADJUST },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 0 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 1 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 2 },
{ WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 3 },
{ WM_NOTIFY, sent|id, 0, 0, TBN_ENDADJUST },
{ 0 }
};
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
@ -93,6 +127,8 @@ static void MakeButton(TBBUTTON *p, int idCommand, int fsStyle, int nString) {
p->iString = nString;
}
static void *alloced_str;
static LRESULT parent_wnd_notify(LPARAM lParam)
{
NMHDR *hdr = (NMHDR *)lParam;
@ -133,6 +169,135 @@ static LRESULT parent_wnd_notify(LPARAM lParam)
compare(nmdisp->dwMask, g_dwExpectedDispInfoMask, "%x");
ok(nmdisp->pszText == NULL, "pszText is not NULL\n");
break;
case TBN_SAVE:
{
NMTBSAVE *save = (NMTBSAVE *)lParam;
if (save->iItem == -1)
{
save->cbData = save->cbData * 2 + 11 * sizeof(DWORD);
save->pData = HeapAlloc( GetProcessHeap(), 0, save->cbData );
save->pData[0] = 0xcafe;
save->pCurrent = save->pData + 1;
}
else
{
save->pCurrent[0] = 0xcafe0000 + save->iItem;
save->pCurrent++;
}
/* Add on 5 more pseudo buttons. */
if (save->iItem == save->cButtons - 1)
{
save->pCurrent[0] = 0xffffffff;
save->pCurrent[1] = 0xcafe0007;
save->pCurrent[2] = 0xfffffffe;
save->pCurrent[3] = 0xcafe0008;
save->pCurrent[4] = 0x80000000;
save->pCurrent[5] = 0xcafe0009;
save->pCurrent[6] = 0x7fffffff;
save->pCurrent[7] = 0xcafe000a;
save->pCurrent[8] = 0x100;
save->pCurrent[9] = 0xcafe000b;
}
/* Return value is ignored */
return 1;
}
case TBN_RESTORE:
{
NMTBRESTORE *restore = (NMTBRESTORE *)lParam;
if (restore->iItem == -1)
{
ok( restore->cButtons == 25, "got %d\n", restore->cButtons );
ok( *restore->pCurrent == 0xcafe, "got %08x\n", *restore->pCurrent );
/* Skip the last one */
restore->cButtons = 11;
restore->pCurrent++;
/* BytesPerRecord is ignored */
restore->cbBytesPerRecord = 10;
}
else
{
ok( *restore->pCurrent == 0xcafe0000 + restore->iItem, "got %08x\n", *restore->pCurrent );
if (restore->iItem < 7 || restore->iItem == 10)
{
ok( restore->tbButton.iBitmap == -1, "got %08x\n", restore->tbButton.iBitmap );
if (restore->iItem < 7)
ok( restore->tbButton.idCommand == restore->iItem * 2 + 1, "%d: got %08x\n", restore->iItem, restore->tbButton.idCommand );
else
ok( restore->tbButton.idCommand == 0x7fffffff, "%d: got %08x\n", restore->iItem, restore->tbButton.idCommand );
ok( restore->tbButton.fsState == 0, "%d: got %02x\n", restore->iItem, restore->tbButton.fsState );
ok( restore->tbButton.fsStyle == 0, "%d: got %02x\n", restore->iItem, restore->tbButton.fsStyle );
}
else
{
ok( restore->tbButton.iBitmap == 8, "got %08x\n", restore->tbButton.iBitmap );
ok( restore->tbButton.idCommand == 0, "%d: got %08x\n", restore->iItem, restore->tbButton.idCommand );
if (restore->iItem == 7)
ok( restore->tbButton.fsState == 0, "%d: got %02x\n", restore->iItem, restore->tbButton.fsState );
else
ok( restore->tbButton.fsState == TBSTATE_HIDDEN, "%d: got %02x\n", restore->iItem, restore->tbButton.fsState );
ok( restore->tbButton.fsStyle == BTNS_SEP, "%d: got %02x\n", restore->iItem, restore->tbButton.fsStyle );
}
ok( restore->tbButton.dwData == 0, "got %08lx\n", restore->tbButton.dwData );
ok( restore->tbButton.iString == 0, "got %08lx\n", restore->tbButton.iString );
restore->tbButton.iBitmap = 0;
restore->tbButton.fsState = TBSTATE_ENABLED;
restore->tbButton.fsStyle = 0;
restore->tbButton.dwData = restore->iItem;
if (restore->iItem == 0)
{
restore->tbButton.iString = (INT_PTR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 8 );
strcpy( (char *)restore->tbButton.iString, "foo" );
}
else if (restore->iItem == 1)
restore->tbButton.iString = 2;
else
restore->tbButton.iString = -1;
restore->pCurrent++;
/* Altering cButtons after the 1st call makes no difference. */
restore->cButtons--;
}
/* Returning non-zero from the 1st call aborts the restore,
otherwise the return value is ignored. */
if (restore->iItem == -1) return 0;
return 1;
}
case TBN_GETBUTTONINFOA:
{
NMTOOLBARA *tb = (NMTOOLBARA *)lParam;
tb->tbButton.iBitmap = 0;
tb->tbButton.fsState = 0;
tb->tbButton.fsStyle = 0;
tb->tbButton.dwData = 0;
ok( tb->cchText == 128, "got %d\n", tb->cchText );
switch (tb->iItem)
{
case 0:
tb->tbButton.idCommand = 7;
alloced_str = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 8 );
strcpy( alloced_str, "foo" );
tb->tbButton.iString = (INT_PTR)alloced_str;
return 1;
case 1:
tb->tbButton.idCommand = 9;
tb->tbButton.iString = 0;
/* tb->pszText is ignored */
strcpy( tb->pszText, "foo" );
return 1;
case 2:
tb->tbButton.idCommand = 11;
tb->tbButton.iString = 3;
return 1;
}
return 0;
}
}
return 0;
}
@ -148,7 +313,31 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam,
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
if (message == WM_NOTIFY && lParam)
{
msg.id = ((NMHDR*)lParam)->code;
switch (msg.id)
{
case TBN_SAVE:
{
NMTBSAVE *save = (NMTBSAVE *)lParam;
msg.stage = save->iItem;
}
break;
case TBN_RESTORE:
{
NMTBRESTORE *restore = (NMTBRESTORE *)lParam;
msg.stage = restore->iItem;
}
break;
case TBN_GETBUTTONINFOA:
{
NMTOOLBARA *tb = (NMTOOLBARA *)lParam;
msg.stage = tb->iItem;
}
break;
}
}
/* log system messages, except for painting */
if (message < WM_USER &&
@ -748,7 +937,7 @@ static void tbsize_addbutton(tbsize_result_t *tbsr, int left, int top, int right
static tbsize_result_t *tbsize_results;
#define tbsize_results_num 24
#define tbsize_results_num 28
static void init_tbsize_results(void) {
int fontheight = system_font_height();
@ -991,6 +1180,18 @@ static void init_tbsize_results(void) {
tbsize_results[23] = init_tbsize_result(2, 0, 0, 672, 42, 67, 41);
tbsize_addbutton(&tbsize_results[23], 0, 2, 672, 25 + fontheight);
tbsize_addbutton(&tbsize_results[23], 0, 25 + fontheight, 672, 48 + 2*fontheight);
tbsize_results[24] = init_tbsize_result(1, 0, 0, 672, 42, 67, 40);
tbsize_addbutton(&tbsize_results[24], 0, 2, 11 + string_width(STRING2), 24);
tbsize_results[25] = init_tbsize_result(1, 0, 0, 672, 42, 67, 40);
tbsize_addbutton(&tbsize_results[25], 0, 2, 40, 24);
tbsize_results[26] = init_tbsize_result(1, 0, 0, 672, 42, 67, 40);
tbsize_addbutton(&tbsize_results[26], 0, 2, 40, 24);
tbsize_results[27] = init_tbsize_result(1, 0, 0, 672, 42, 67, 40);
tbsize_addbutton(&tbsize_results[27], 0, 2, 40, 24);
}
static void free_tbsize_results(void) {
@ -1062,12 +1263,18 @@ static TBBUTTON buttons3[] = {
{0, 32, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, 1},
{0, 33, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, (UINT_PTR)STRING2}
};
static TBBUTTON buttons4[] = {
{0, 40, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, (UINT_PTR)STRING2},
{0, 41, TBSTATE_ENABLED, 0, {0, }, 0, (UINT_PTR)STRING2},
{0, 41, TBSTATE_ENABLED, BTNS_SHOWTEXT, {0, }, 0, (UINT_PTR)STRING2}
};
static void test_sizes(void)
{
HWND hToolbar = NULL;
HIMAGELIST himl, himl2;
TBBUTTONINFOA tbinfo;
TBBUTTON button;
int style;
int i;
int fontheight = system_font_height();
@ -1083,9 +1290,13 @@ static void test_sizes(void)
check_sizes();
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
check_sizes();
SendMessageA(hToolbar, TB_GETBUTTON, 5, (LPARAM)&button);
ok(button.fsState == (TBSTATE_WRAP|TBSTATE_ENABLED), "got %08x\n", button.fsState);
/* after setting the TBSTYLE_WRAPABLE the TBSTATE_WRAP is ignored */
SetWindowLongA(hToolbar, GWL_STYLE, style|TBSTYLE_WRAPABLE);
check_sizes();
SendMessageA(hToolbar, TB_GETBUTTON, 5, (LPARAM)&button);
ok(button.fsState == TBSTATE_ENABLED, "got %08x\n", button.fsState);
/* adding new buttons with TBSTYLE_WRAPABLE doesn't add a new row */
SendMessageA(hToolbar, TB_ADDBUTTONSA, 2, (LPARAM)buttons1);
check_sizes();
@ -1094,6 +1305,11 @@ static void test_sizes(void)
for (i=0; i<15; i++)
SendMessageA(hToolbar, TB_ADDBUTTONSA, 2, (LPARAM)buttons1);
check_sizes_todo(0x4);
SendMessageA(hToolbar, TB_GETBUTTON, 31, (LPARAM)&button);
ok(button.fsState == (TBSTATE_WRAP|TBSTATE_ENABLED), "got %08x\n", button.fsState);
SetWindowLongA(hToolbar, GWL_STYLE, style);
SendMessageA(hToolbar, TB_GETBUTTON, 31, (LPARAM)&button);
ok(button.fsState == TBSTATE_ENABLED, "got %08x\n", button.fsState);
rebuild_toolbar_with_buttons(&hToolbar);
SendMessageA(hToolbar, TB_ADDBUTTONSA, 2, (LPARAM)buttons1);
@ -1300,8 +1516,41 @@ static void test_sizes(void)
{
tbinfo.dwMask = TBIF_SIZE;
ok(SendMessageA(hToolbar, TB_SETBUTTONINFOA, 33, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFOA failed\n");
tbsize_numtests++;
}
/* Single BTNS_AUTOSIZE button with string. */
rebuild_toolbar(&hToolbar);
ok(SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&buttons4[0]) == 1, "TB_ADDBUTTONSA failed\n");
ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(40, 20)) == 1, "TB_SETBUTTONSIZE failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
check_sizes();
/* Single non-BTNS_AUTOSIZE button with string. */
rebuild_toolbar(&hToolbar);
ok(SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&buttons4[1]) == 1, "TB_ADDBUTTONSA failed\n");
ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(40, 20)) == 1, "TB_SETBUTTONSIZE failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
check_sizes();
/* Single non-BTNS_AUTOSIZE button with string with TBSTYLE_EX_MIXEDBUTTONS set. */
rebuild_toolbar(&hToolbar);
SendMessageA(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
style = SendMessageA(hToolbar, TB_GETSTYLE, 0, 0);
ok(SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&buttons4[1]) == 1, "TB_ADDBUTTONSA failed\n");
ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(40, 20)) == 1, "TB_SETBUTTONSIZE failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
check_sizes();
/* Single non-BTNS_AUTOSIZE, BTNS_SHOWTEXT button with string with TBSTYLE_EX_MIXEDBUTTONS set. */
rebuild_toolbar(&hToolbar);
SendMessageA(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
style = SendMessageA(hToolbar, TB_GETSTYLE, 0, 0);
ok(SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&buttons4[2]) == 1, "TB_ADDBUTTONSA failed\n");
ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(40, 20)) == 1, "TB_SETBUTTONSIZE failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
check_sizes();
free_tbsize_results();
DestroyWindow(hToolbar);
}
@ -1338,12 +1587,12 @@ static void restore_recalc_state(HWND hToolbar)
RECT rect;
/* return to style with a 2px top margin */
SetWindowLongA(hToolbar, GWL_STYLE,
GetWindowLongA(hToolbar, GWL_STYLE) & ~TBSTYLE_FLAT);
SendMessageA(hToolbar, TB_GETSTYLE, 0, 0) & ~TBSTYLE_FLAT);
/* recalc */
SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&buttons3[3]);
/* top margin will be 0px if a recalc occurs */
SetWindowLongA(hToolbar, GWL_STYLE,
GetWindowLongA(hToolbar, GWL_STYLE) | TBSTYLE_FLAT);
SendMessageA(hToolbar, TB_GETSTYLE, 0, 0) | TBSTYLE_FLAT);
/* safety check */
SendMessageA(hToolbar, TB_GETITEMRECT, 1, (LPARAM)&rect);
ok(rect.top == 2, "Test will make no sense because initial top is %d instead of 2\n",
@ -1358,6 +1607,7 @@ static void test_recalc(void)
const int EX_STYLES_COUNT = 5;
int i;
BOOL recalc;
DWORD style;
/* Like TB_ADDBUTTONSA tested in test_sized, inserting a button without text
* results in a relayout, while adding one with text forces a recalc */
@ -1418,6 +1668,47 @@ static void test_recalc(void)
/* undocumented exstyle 0x2 seems to change the top margin, which
* interferes with these tests */
/* Show that a change in TBSTYLE_WRAPABLE causes a recalc */
prepare_recalc_test(&hToolbar);
style = SendMessageA(hToolbar, TB_GETSTYLE, 0, 0);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style);
recalc = did_recalc(hToolbar);
ok(!recalc, "recalc %d\n", recalc);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | CCS_BOTTOM);
recalc = did_recalc(hToolbar);
ok(!recalc, "recalc %d\n", recalc);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style | TBSTYLE_WRAPABLE);
recalc = did_recalc(hToolbar);
ok(recalc, "recalc %d\n", recalc);
restore_recalc_state(hToolbar);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style | TBSTYLE_WRAPABLE);
recalc = did_recalc(hToolbar);
ok(!recalc, "recalc %d\n", recalc);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style);
recalc = did_recalc(hToolbar);
ok(recalc, "recalc %d\n", recalc);
restore_recalc_state(hToolbar);
/* Changing CCS_VERT does not recalc */
SendMessageA(hToolbar, TB_SETSTYLE, 0, style | CCS_VERT);
recalc = did_recalc(hToolbar);
ok(!recalc, "recalc %d\n", recalc);
restore_recalc_state(hToolbar);
SendMessageA(hToolbar, TB_SETSTYLE, 0, style);
recalc = did_recalc(hToolbar);
ok(!recalc, "recalc %d\n", recalc);
restore_recalc_state(hToolbar);
/* Setting the window's style directly also causes recalc */
SetWindowLongA(hToolbar, GWL_STYLE, style | TBSTYLE_WRAPABLE);
recalc = did_recalc(hToolbar);
ok(recalc, "recalc %d\n", recalc);
DestroyWindow(hToolbar);
}
@ -1917,11 +2208,161 @@ static void test_TB_GET_SET_EXTENDEDSTYLE(void)
ok(style == TBSTYLE_EX_VERTICAL, "got style 0x%08x, expected 0x%08x\n", style, TBSTYLE_EX_VERTICAL);
style = SendMessageA(hwnd, TB_GETSTYLE, 0, 0);
todo_wine
ok(style == CCS_VERT, "got style 0x%08x, expected 0x%08x\n", style, CCS_VERT);
ok(style == CCS_VERT, "got style 0x%08x, expected CCS_VERT\n", style);
DestroyWindow(hwnd);
}
static void test_noresize(void)
{
HWND wnd;
int i;
TBBUTTON button = {0, 10, TBSTATE_ENABLED, 0, {0, }, 0, -1};
wnd = CreateWindowExA(0, TOOLBARCLASSNAMEA, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE | TBSTYLE_WRAPABLE, 0, 0, 100, 20,
hMainWnd, (HMENU)5, GetModuleHandleA(NULL), NULL);
SendMessageA(wnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
for (i=0; i<30; i++)
{
button.idCommand = 10 + i;
SendMessageA(wnd, TB_ADDBUTTONSA, 1, (LPARAM)&button);
}
SendMessageA(wnd, TB_SETSTATE, 10, TBSTATE_WRAP|TBSTATE_ENABLED);
/* autosize clears the wrap on button 0 */
SendMessageA(wnd, TB_AUTOSIZE, 0, 0);
for (i=0; i<30; i++)
{
SendMessageA(wnd, TB_GETBUTTON, i, (LPARAM)&button);
if (i % 4 == 3)
ok(button.fsState == (TBSTATE_WRAP|TBSTATE_ENABLED), "%d: got %08x\n", i, button.fsState);
else
ok(button.fsState == TBSTATE_ENABLED, "%d: got %08x\n", i, button.fsState);
}
/* changing the parent doesn't do anything */
MoveWindow(hMainWnd, 0,0, 400, 200, FALSE);
for (i=0; i<30; i++)
{
SendMessageA(wnd, TB_GETBUTTON, i, (LPARAM)&button);
if (i % 4 == 3)
ok(button.fsState == (TBSTATE_WRAP|TBSTATE_ENABLED), "%d: got %08x\n", i, button.fsState);
else
ok(button.fsState == TBSTATE_ENABLED, "%d: got %08x\n", i, button.fsState);
}
/* again nothing here */
SendMessageA(wnd, TB_AUTOSIZE, 0, 0);
for (i=0; i<30; i++)
{
SendMessageA(wnd, TB_GETBUTTON, i, (LPARAM)&button);
if (i % 4 == 3)
ok(button.fsState == (TBSTATE_WRAP|TBSTATE_ENABLED), "%d: got %08x\n", i, button.fsState);
else
ok(button.fsState == TBSTATE_ENABLED, "%d: got %08x\n", i, button.fsState);
}
DestroyWindow(wnd);
}
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 value[] = {'t','o','o','l','b','a','r','t','e','s','t',0};
LONG res;
HKEY key;
BYTE data[100];
DWORD size = sizeof(data), type, i, count;
TBBUTTON tb;
static const TBBUTTON more_btns[2] =
{
{0, 11, TBSTATE_HIDDEN, BTNS_BUTTON, {0}, 0, -1},
{0, 13, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, -1}
};
static const DWORD expect[] = {0xcafe, 1, 0xcafe0000, 3, 0xcafe0001, 5, 0xcafe0002, 7, 0xcafe0003,
9, 0xcafe0004, 11, 0xcafe0005, 13, 0xcafe0006, 0xffffffff, 0xcafe0007,
0xfffffffe, 0xcafe0008, 0x80000000, 0xcafe0009, 0x7fffffff, 0xcafe000a,
0x100, 0xcafe000b};
static const TBBUTTON expect_btns[] =
{
{0, 1, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
{0, 3, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 1, 2},
{0, 5, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 2, 0},
{0, 7, 0, BTNS_BUTTON, {0}, 0, (INT_PTR)"foo"},
{0, 9, 0, BTNS_BUTTON, {0}, 0, 0},
{0, 11, 0, BTNS_BUTTON, {0}, 0, 3},
{0, 13, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 6, 0},
{0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 7, 0},
{0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 8, 0},
{0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 9, 0},
{0, 0x7fffffff, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0xa, 0},
};
params.hkr = HKEY_CURRENT_USER;
params.pszSubKey = subkey;
params.pszValueName = value;
rebuild_toolbar_with_buttons( &wnd );
SendMessageW( wnd, TB_ADDBUTTONSW, sizeof(more_btns) / sizeof(more_btns[0]), (LPARAM)more_btns );
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageW( wnd, TB_SAVERESTOREW, TRUE, (LPARAM)&params );
ok( res, "saving failed\n" );
ok_sequence(sequences, PARENT_SEQ_INDEX, save_parent_seq, "save", FALSE);
DestroyWindow( wnd );
res = RegOpenKeyW( HKEY_CURRENT_USER, subkey, &key );
ok( !res, "got %08x\n", res );
res = RegQueryValueExW( key, value, NULL, &type, data, &size );
ok( !res, "got %08x\n", res );
ok( type == REG_BINARY, "got %08x\n", type );
ok( size == sizeof(expect), "got %08x\n", size );
ok( !memcmp( data, expect, size ), "mismatch\n" );
RegCloseKey( key );
wnd = NULL;
rebuild_toolbar( &wnd );
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageW( wnd, TB_SAVERESTOREW, FALSE, (LPARAM)&params );
ok( res, "restoring failed\n" );
ok_sequence(sequences, PARENT_SEQ_INDEX, restore_parent_seq, "restore", FALSE);
count = SendMessageW( wnd, TB_BUTTONCOUNT, 0, 0 );
ok( count == sizeof(expect_btns) / sizeof(expect_btns[0]), "got %d\n", count );
for (i = 0; i < count; i++)
{
res = SendMessageW( wnd, TB_GETBUTTON, i, (LPARAM)&tb );
ok( res, "got %d\n", res );
ok( tb.iBitmap == expect_btns[i].iBitmap, "%d: got %d\n", i, tb.iBitmap );
ok( tb.idCommand == expect_btns[i].idCommand, "%d: got %d\n", i, tb.idCommand );
ok( tb.fsState == expect_btns[i].fsState, "%d: got %02x\n", i, tb.fsState );
ok( tb.fsStyle == expect_btns[i].fsStyle, "%d: got %02x\n", i, tb.fsStyle );
ok( tb.dwData == expect_btns[i].dwData, "%d: got %lx\n", i, tb.dwData );
if (IS_INTRESOURCE(expect_btns[i].iString))
ok( tb.iString == expect_btns[i].iString, "%d: got %lx\n", i, tb.iString );
else
ok( !strcmp( (char *)tb.iString, (char *)expect_btns[i].iString ),
"%d: got %s\n", i, (char *)tb.iString );
/* In fact the ptr value set in TBN_GETBUTTONINFOA is simply copied */
if (tb.idCommand == 7)
ok( tb.iString == (INT_PTR)alloced_str, "string not set\n");
}
DestroyWindow( wnd );
RegOpenKeyW( HKEY_CURRENT_USER, subkey, &key );
RegDeleteValueW( key, value );
RegCloseKey( key );
}
START_TEST(toolbar)
{
WNDCLASSA wc;
@ -1964,6 +2405,8 @@ START_TEST(toolbar)
test_get_set_style();
test_create();
test_TB_GET_SET_EXTENDEDSTYLE();
test_noresize();
test_save();
PostQuitMessage(0);
while(GetMessageA(&msg,0,0,0)) {

View file

@ -26,6 +26,8 @@
#include <winnls.h>
#include <commctrl.h>
#include "resources.h"
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
static void test_create_tooltip(void)
@ -330,6 +332,30 @@ static void test_gettext(void)
SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
ok(toolinfoA.lpszText == NULL,
"expected NULL, got %p\n", toolinfoA.lpszText);
/* NULL hinst, valid resource id for text */
toolinfoA.cbSize = sizeof(TTTOOLINFOA);
toolinfoA.hwnd = NULL;
toolinfoA.hinst = NULL;
toolinfoA.uFlags = 0;
toolinfoA.uId = 0x1233ABCD;
toolinfoA.lpszText = MAKEINTRESOURCEA(IDS_TBADD1);
toolinfoA.lParam = 0xdeadbeef;
GetClientRect(hwnd, &toolinfoA.rect);
r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
ok(r, "failed to add a tool\n");
toolinfoA.hwnd = NULL;
toolinfoA.uId = 0x1233ABCD;
toolinfoA.lpszText = bufA;
SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
ok(strcmp(toolinfoA.lpszText, "abc") == 0, "lpszText should be an empty string\n");
toolinfoA.hinst = (HINSTANCE)0xdeadbee;
SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
ok(toolinfoA.hinst == NULL, "expected NULL, got %p\n", toolinfoA.hinst);
SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&toolinfoA);
}
else
{
@ -817,6 +843,154 @@ static void test_track(void)
DestroyWindow(parent);
}
static LRESULT CALLBACK info_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
return 0;
}
static void test_setinfo(void)
{
WNDCLASSA wc;
LRESULT lResult;
HWND parent, parent2, hwndTip, hwndTip2;
TTTOOLINFOA toolInfo = { 0 };
TTTOOLINFOA toolInfo2 = { 0 };
WNDPROC wndProc;
/* Create a class to use the custom draw wndproc */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "SetInfoClass";
wc.lpfnWndProc = info_wnd_proc;
RegisterClassA(&wc);
/* Create a main window */
parent = CreateWindowExA(0, "SetInfoClass", NULL,
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_VISIBLE,
50, 50,
300, 300,
NULL, NULL, NULL, 0);
ok(parent != NULL, "Creation of main window failed\n");
parent2 = CreateWindowExA(0, "SetInfoClass", NULL,
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_VISIBLE,
50, 50,
300, 300,
NULL, NULL, NULL, 0);
ok(parent2 != NULL, "Creation of main window failed\n");
/* Make it show */
ShowWindow(parent2, SW_SHOWNORMAL);
flush_events(100);
/* Create Tooltip */
hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
parent, NULL, GetModuleHandleA(NULL), 0);
ok(hwndTip != NULL, "Creation of tooltip window failed\n");
hwndTip2 = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
parent, NULL, GetModuleHandleA(NULL), 0);
ok(hwndTip2 != NULL, "Creation of tooltip window failed\n");
/* Make it topmost, as per the MSDN */
SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
/* Create a tool */
toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
toolInfo.hwnd = parent;
toolInfo.hinst = GetModuleHandleA(NULL);
toolInfo.uFlags = TTF_SUBCLASS;
toolInfo.uId = 0x1234ABCD;
toolInfo.lpszText = (LPSTR)"This is a test tooltip";
toolInfo.lParam = 0xdeadbeef;
GetClientRect (parent, &toolInfo.rect);
lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
ok(lResult, "Adding the tool to the tooltip failed\n");
toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
toolInfo.hwnd = parent2;
toolInfo.hinst = GetModuleHandleA(NULL);
toolInfo.uFlags = 0;
toolInfo.uId = 0x1234ABCE;
toolInfo.lpszText = (LPSTR)"This is a test tooltip";
toolInfo.lParam = 0xdeadbeef;
GetClientRect (parent, &toolInfo.rect);
lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
ok(lResult, "Adding the tool to the tooltip failed\n");
/* Try to Remove Subclass */
toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
toolInfo2.hwnd = parent;
toolInfo2.uId = 0x1234ABCD;
lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
ok(lResult, "GetToolInfo failed\n");
ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n");
wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
toolInfo2.uFlags &= ~TTF_SUBCLASS;
SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
ok(lResult, "GetToolInfo failed\n");
ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
/* Try to Add Subclass */
/* Make it topmost, as per the MSDN */
SetWindowPos(hwndTip2, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
toolInfo2.hwnd = parent2;
toolInfo2.uId = 0x1234ABCE;
lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
ok(lResult, "GetToolInfo failed\n");
ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC);
ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
toolInfo2.uFlags |= TTF_SUBCLASS;
SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
ok(lResult, "GetToolInfo failed\n");
ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n");
wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC);
ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
/* Clean up */
DestroyWindow(hwndTip);
DestroyWindow(hwndTip2);
DestroyWindow(parent);
DestroyWindow(parent2);
}
START_TEST(tooltips)
{
InitCommonControls();
@ -828,4 +1002,5 @@ START_TEST(tooltips)
test_longtextA();
test_longtextW();
test_track();
test_setinfo();
}

View file

@ -19,6 +19,7 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
@ -226,7 +227,8 @@ static const struct message parent_expand_empty_kb_seq[] = {
{ 0 }
};
static const struct message parent_singleexpand_seq[] = {
static const struct message parent_singleexpand_seq0[] = {
/* alpha expands */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
@ -235,6 +237,84 @@ static const struct message parent_singleexpand_seq[] = {
{ 0 }
};
static const struct message parent_singleexpand_seq1[] = {
/* bravo expands */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ 0 }
};
static const struct message parent_singleexpand_seq2[] = {
/* delta expands, bravo collapses */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ 0 }
};
static const struct message parent_singleexpand_seq3[] = {
/* foxtrot expands, alpha and delta collapse */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ 0 }
};
static const struct message parent_singleexpand_seq4[] = {
/* alpha expands, foxtrot collapses */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ 0 }
};
static const struct message parent_singleexpand_seq5[] = {
/* foxtrot expands while golf is selected, then golf expands and alpha collapses */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
{ 0 }
};
static const struct message parent_singleexpand_seq6[] = {
/* hotel does not expand and india does not collapse because they have no children */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ 0 }
};
static const struct message parent_singleexpand_seq7[] = {
/* india does not expand and hotel does not collapse because they have no children */
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
{ WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
{ 0 }
};
static const struct message parent_get_dispinfo_seq[] = {
{ WM_NOTIFY, sent|id, 0, 0, TVN_GETDISPINFOA },
{ 0 }
@ -1637,21 +1717,95 @@ static void test_expandedimage(void)
static void test_TVS_SINGLEEXPAND(void)
{
HWND hTree;
HTREEITEM alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india, juliet;
TVINSERTSTRUCTA ins;
char foo[] = "foo";
char context[32];
int i;
BOOL ret;
/* build a fairly complex tree
* - TVI_ROOT
* - alpha
* - bravo
* - charlie
* - delta
* - echo
* - foxtrot
* - golf
* - hotel
* - india
* - juliet
*/
struct
{
HTREEITEM *handle;
HTREEITEM *parent;
UINT final_state;
}
items[] =
{
{ &alpha, NULL, TVIS_EXPANDEDONCE },
{ &bravo, &alpha, TVIS_EXPANDEDONCE },
{ &charlie, &bravo, 0 },
{ &delta, &alpha, TVIS_EXPANDEDONCE },
{ &echo, &delta, 0 },
{ &foxtrot, NULL, TVIS_EXPANDEDONCE|TVIS_EXPANDED },
{ &golf, &foxtrot, TVIS_EXPANDEDONCE|TVIS_EXPANDED },
{ &hotel, &golf, 0 },
{ &india, &golf, TVIS_SELECTED },
{ &juliet, &foxtrot, 0 }
};
struct
{
HTREEITEM *select;
const struct message *sequence;
}
sequence_tests[] =
{
{ &alpha, parent_singleexpand_seq0 },
{ &bravo, parent_singleexpand_seq1 },
{ &delta, parent_singleexpand_seq2 },
{ &foxtrot, parent_singleexpand_seq3 },
{ &alpha, parent_singleexpand_seq4 },
{ &golf, parent_singleexpand_seq5 },
{ &hotel, parent_singleexpand_seq6 },
{ &india, parent_singleexpand_seq7 },
{ &india, empty_seq }
};
hTree = create_treeview_control(0);
SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
/* to avoid painting related notifications */
ShowWindow(hTree, SW_HIDE);
fill_tree(hTree);
for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
{
ins.hParent = items[i].parent ? *items[i].parent : TVI_ROOT;
ins.hInsertAfter = TVI_FIRST;
U(ins).item.mask = TVIF_TEXT;
U(ins).item.pszText = foo;
*items[i].handle = TreeView_InsertItemA(hTree, &ins);
}
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
ok(ret, "got %d\n", ret);
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_singleexpand_seq, "singleexpand notifications", FALSE);
for (i = 0; i < sizeof(sequence_tests)/sizeof(sequence_tests[0]); i++)
{
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(*sequence_tests[i].select));
ok(ret, "got %d\n", ret);
sprintf(context, "singleexpand notifications %d", i);
ok_sequence(sequences, PARENT_SEQ_INDEX, sequence_tests[i].sequence, context, FALSE);
}
for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
{
ret = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)(*items[i].handle), 0xFFFF);
ok(ret == items[i].final_state, "singleexpand items[%d]: expected state 0x%x got 0x%x\n",
i, items[i].final_state, ret);
}
/* a workaround for NT4 that sends expand notifications when nothing is about to expand */
ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hRoot);
ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
ok(ret, "got %d\n", ret);
fill_tree(hTree);
ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);