1 /* Unit test suite for tab control.
3 * Copyright 2003 Vitaliy Margolen
4 * Copyright 2007 Hagop Hagopian
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/test.h"
28 #define DEFAULT_MIN_TAB_WIDTH 54
29 #define TAB_PADDING_X 6
30 #define EXTRA_ICON_PADDING 3
33 #define NUM_MSG_SEQUENCES 2
34 #define PARENT_SEQ_INDEX 0
35 #define TAB_SEQ_INDEX 1
37 #define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
38 #define expect_str(expected, got)\
39 ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
41 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
43 static HIMAGELIST (WINAPI
*pImageList_Create
)(INT
,INT
,UINT
,INT
,INT
);
44 static BOOL (WINAPI
*pImageList_Destroy
)(HIMAGELIST
);
45 static INT (WINAPI
*pImageList_GetImageCount
)(HIMAGELIST
);
46 static INT (WINAPI
*pImageList_ReplaceIcon
)(HIMAGELIST
,INT
,HICON
);
48 static void CheckSize(HWND hwnd
, INT width
, INT height
, const char *msg
, int line
)
52 SendMessageA(hwnd
, TCM_GETITEMRECT
, 0, (LPARAM
)&r
);
53 if (width
>= 0 && height
< 0)
54 ok_(__FILE__
,line
) (width
== r
.right
- r
.left
, "%s: Expected width [%d] got [%d]\n",
55 msg
, width
, r
.right
- r
.left
);
56 else if (height
>= 0 && width
< 0)
57 ok_(__FILE__
,line
) (height
== r
.bottom
- r
.top
, "%s: Expected height [%d] got [%d]\n",
58 msg
, height
, r
.bottom
- r
.top
);
60 ok_(__FILE__
,line
) ((width
== r
.right
- r
.left
) && (height
== r
.bottom
- r
.top
),
61 "%s: Expected [%d,%d] got [%d,%d]\n", msg
, width
, height
,
62 r
.right
- r
.left
, r
.bottom
- r
.top
);
65 #define CHECKSIZE(hwnd,width,height,msg) CheckSize(hwnd,width,height,msg,__LINE__)
67 static void TabCheckSetSize(HWND hwnd
, INT set_width
, INT set_height
, INT exp_width
,
68 INT exp_height
, const char *msg
, int line
)
70 SendMessageA(hwnd
, TCM_SETITEMSIZE
, 0,
71 MAKELPARAM((set_width
>= 0) ? set_width
: 0, (set_height
>= 0) ? set_height
: 0));
72 if (winetest_interactive
) RedrawWindow (hwnd
, NULL
, 0, RDW_UPDATENOW
);
73 CheckSize(hwnd
, exp_width
, exp_height
, msg
, line
);
76 #define TABCHECKSETSIZE(hwnd,set_width,set_height,exp_width,exp_height,msg) \
77 TabCheckSetSize(hwnd,set_width,set_height,exp_width,exp_height,msg,__LINE__)
80 static DRAWITEMSTRUCT g_drawitem
;
81 static HWND parent_wnd
;
82 static LRESULT tcn_selchanging_result
;
84 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
86 static const struct message empty_sequence
[] = {
90 static const struct message get_row_count_seq
[] = {
91 { TCM_GETROWCOUNT
, sent
|wparam
|lparam
, 0, 0 },
95 static const struct message getset_cur_focus_seq
[] = {
96 { TCM_SETCURFOCUS
, sent
|lparam
, 0 },
97 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
98 { TCM_SETCURFOCUS
, sent
|lparam
, 0 },
99 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
100 { TCM_SETCURSEL
, sent
|lparam
, 0 },
101 { TCM_SETCURFOCUS
, sent
|lparam
, 0 },
102 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
106 static const struct message getset_cur_sel_seq
[] = {
107 { TCM_SETCURSEL
, sent
|lparam
, 0 },
108 { TCM_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
109 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
110 { TCM_SETCURSEL
, sent
|lparam
, 0 },
111 { TCM_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
112 { TCM_SETCURSEL
, sent
|lparam
, 0 },
113 { TCM_SETCURSEL
, sent
|lparam
, 0 },
114 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
118 static const struct message getset_extended_style_seq
[] = {
119 { TCM_GETEXTENDEDSTYLE
, sent
|wparam
|lparam
, 0, 0 },
120 { TCM_SETEXTENDEDSTYLE
, sent
},
121 { TCM_GETEXTENDEDSTYLE
, sent
|wparam
|lparam
, 0, 0 },
122 { TCM_SETEXTENDEDSTYLE
, sent
},
123 { TCM_GETEXTENDEDSTYLE
, sent
|wparam
|lparam
, 0, 0 },
127 static const struct message getset_unicode_format_seq
[] = {
128 { CCM_SETUNICODEFORMAT
, sent
|lparam
, 0 },
129 { CCM_GETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
130 { CCM_SETUNICODEFORMAT
, sent
|lparam
, 0 },
131 { CCM_GETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
132 { CCM_SETUNICODEFORMAT
, sent
|lparam
, 0 },
136 static const struct message getset_item_seq
[] = {
137 { TCM_SETITEMA
, sent
},
138 { TCM_GETITEMA
, sent
},
139 { TCM_GETITEMA
, sent
},
143 static const struct message getset_tooltip_seq
[] = {
144 { WM_NOTIFYFORMAT
, sent
|optional
},
145 { WM_QUERYUISTATE
, sent
|wparam
|lparam
|optional
, 0, 0 },
146 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
147 { WM_NOTIFYFORMAT
, sent
|optional
},
148 { TCM_SETTOOLTIPS
, sent
|lparam
, 0 },
149 { TCM_GETTOOLTIPS
, sent
|wparam
|lparam
, 0, 0 },
150 { TCM_SETTOOLTIPS
, sent
|lparam
, 0 },
151 { TCM_GETTOOLTIPS
, sent
|wparam
|lparam
, 0, 0 },
155 static const struct message getset_tooltip_parent_seq
[] = {
156 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
160 static const struct message insert_focus_seq
[] = {
161 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
162 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
163 { TCM_INSERTITEMA
, sent
|wparam
, 1 },
164 { WM_NOTIFYFORMAT
, sent
|defwinproc
|optional
},
165 { WM_QUERYUISTATE
, sent
|defwinproc
|optional
},
166 { WM_PARENTNOTIFY
, sent
|defwinproc
|optional
},
167 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
168 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
169 { TCM_INSERTITEMA
, sent
|wparam
, 2 },
170 { WM_NOTIFYFORMAT
, sent
|defwinproc
|optional
},
171 { WM_QUERYUISTATE
, sent
|defwinproc
|optional
, },
172 { WM_PARENTNOTIFY
, sent
|defwinproc
|optional
},
173 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
174 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
175 { TCM_SETCURFOCUS
, sent
|wparam
|lparam
, -1, 0 },
176 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
177 { TCM_INSERTITEMA
, sent
|wparam
, 3 },
178 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
182 static const struct message delete_focus_seq
[] = {
183 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
184 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
185 { TCM_DELETEITEM
, sent
|wparam
|lparam
, 1, 0 },
186 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
187 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
188 { TCM_SETCURFOCUS
, sent
|wparam
|lparam
, -1, 0 },
189 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
190 { TCM_DELETEITEM
, sent
|wparam
|lparam
, 0, 0 },
191 { TCM_GETITEMCOUNT
, sent
|wparam
|lparam
, 0, 0 },
192 { TCM_GETCURFOCUS
, sent
|wparam
|lparam
, 0, 0 },
196 static const struct message rbuttonup_seq
[] = {
197 { WM_RBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
198 { WM_CONTEXTMENU
, sent
|defwinproc
},
202 static const struct message full_selchange_parent_seq
[] = {
203 { WM_NOTIFY
, sent
|id
, 0, 0, TCN_SELCHANGING
},
204 { WM_NOTIFY
, sent
|id
, 0, 0, TCN_SELCHANGE
},
208 static const struct message selchanging_parent_seq
[] = {
209 { WM_NOTIFY
, sent
|id
, 0, 0, TCN_SELCHANGING
},
213 static const struct message selchange_parent_seq
[] = {
214 { WM_NOTIFY
, sent
|id
, 0, 0, TCN_SELCHANGE
},
218 static const struct message setfocus_parent_seq
[] = {
219 { WM_NOTIFY
, sent
|id
, 0, 0, TCN_FOCUSCHANGE
},
224 create_tabcontrol (DWORD style
, DWORD mask
)
228 static char text1
[] = "Tab 1",
229 text2
[] = "Wide Tab 2",
232 handle
= CreateWindowA(WC_TABCONTROLA
, "TestTab",
233 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| style
, 10, 10, 300, 100, NULL
,
235 ok(handle
!= NULL
, "failed to create tab wnd\n");
237 SetWindowLongA(handle
, GWL_STYLE
, WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| style
);
238 SendMessageA(handle
, WM_SETFONT
, 0, (LPARAM
)hFont
);
240 tcNewTab
.mask
= mask
;
241 tcNewTab
.pszText
= text1
;
243 SendMessageA(handle
, TCM_INSERTITEMA
, 0, (LPARAM
)&tcNewTab
);
244 tcNewTab
.pszText
= text2
;
246 SendMessageA(handle
, TCM_INSERTITEMA
, 1, (LPARAM
)&tcNewTab
);
247 tcNewTab
.pszText
= text3
;
249 SendMessageA(handle
, TCM_INSERTITEMA
, 2, (LPARAM
)&tcNewTab
);
251 if (winetest_interactive
)
253 ShowWindow (handle
, SW_SHOW
);
254 RedrawWindow (handle
, NULL
, 0, RDW_UPDATENOW
);
261 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
263 static LONG defwndproc_counter
= 0;
264 struct message msg
= { 0 };
267 /* do not log painting messages */
268 if (message
!= WM_PAINT
&&
269 message
!= WM_ERASEBKGND
&&
270 message
!= WM_NCPAINT
&&
271 message
!= WM_NCHITTEST
&&
272 message
!= WM_GETTEXT
&&
273 message
!= WM_GETICON
&&
274 message
!= WM_DEVICECHANGE
)
276 msg
.message
= message
;
277 msg
.flags
= sent
|wparam
|lparam
;
278 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
281 if (message
== WM_NOTIFY
&& lParam
)
282 msg
.id
= ((NMHDR
*)lParam
)->code
;
283 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
286 /* dump sent structure data */
287 if (message
== WM_DRAWITEM
)
288 g_drawitem
= *(DRAWITEMSTRUCT
*)lParam
;
290 if (message
== WM_NOTIFY
)
292 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
293 if (nmhdr
&& nmhdr
->code
== TCN_SELCHANGING
)
294 return tcn_selchanging_result
;
297 defwndproc_counter
++;
298 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
299 defwndproc_counter
--;
304 static BOOL
registerParentWindowClass(void)
309 cls
.lpfnWndProc
= parent_wnd_proc
;
312 cls
.hInstance
= GetModuleHandleA(NULL
);
314 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
315 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
316 cls
.lpszMenuName
= NULL
;
317 cls
.lpszClassName
= "Tab test parent class";
318 return RegisterClassA(&cls
);
321 static HWND
createParentWindow(void)
323 if (!registerParentWindowClass())
326 return CreateWindowExA(0, "Tab test parent class", "Tab test parent window",
327 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
, 0, 0, 100, 100,
328 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
331 static LRESULT WINAPI
tab_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
333 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
334 static LONG defwndproc_counter
= 0;
335 struct message msg
= { 0 };
338 /* do not log painting messages */
339 if (message
!= WM_PAINT
&&
340 message
!= WM_ERASEBKGND
&&
341 message
!= WM_NCPAINT
&&
342 message
!= WM_NCHITTEST
&&
343 message
!= WM_GETTEXT
&&
344 message
!= WM_GETICON
&&
345 message
!= WM_DEVICECHANGE
)
347 msg
.message
= message
;
348 msg
.flags
= sent
|wparam
|lparam
;
349 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
352 add_message(sequences
, TAB_SEQ_INDEX
, &msg
);
355 defwndproc_counter
++;
356 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
357 defwndproc_counter
--;
362 static HWND
createFilledTabControl(HWND parent_wnd
, DWORD style
, DWORD mask
, INT nTabs
)
370 GetClientRect(parent_wnd
, &rect
);
372 tabHandle
= CreateWindowA(WC_TABCONTROLA
, "TestTab",
373 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| style
, 0, 0, rect
.right
,
374 rect
.bottom
, parent_wnd
, NULL
, NULL
, 0);
375 ok(tabHandle
!= NULL
, "failed to create tab wnd\n");
377 oldproc
= (WNDPROC
)SetWindowLongPtrA(tabHandle
, GWLP_WNDPROC
, (LONG_PTR
)tab_subclass_proc
);
378 SetWindowLongPtrA(tabHandle
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
380 tcNewTab
.mask
= mask
;
382 for (i
= 0; i
< nTabs
; i
++)
384 char tabName
[MAX_TABLEN
];
386 sprintf(tabName
, "Tab %d", i
+1);
387 tcNewTab
.pszText
= tabName
;
389 SendMessageA(tabHandle
, TCM_INSERTITEMA
, i
, (LPARAM
)&tcNewTab
);
392 if (winetest_interactive
)
394 ShowWindow (tabHandle
, SW_SHOW
);
395 RedrawWindow (tabHandle
, NULL
, 0, RDW_UPDATENOW
);
402 static HWND
create_tooltip (HWND hTab
, char toolTipText
[])
407 LPSTR lptstr
= toolTipText
;
410 /* Creating a tooltip window*/
411 hwndTT
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
, NULL
,
412 WS_POPUP
| TTS_NOPREFIX
| TTS_ALWAYSTIP
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
413 CW_USEDEFAULT
, hTab
, NULL
, 0, NULL
);
419 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
421 GetClientRect (hTab
, &rect
);
423 /* Initialize members of toolinfo*/
424 ti
.cbSize
= sizeof(TTTOOLINFOA
);
425 ti
.uFlags
= TTF_SUBCLASS
;
429 ti
.lpszText
= lptstr
;
433 /* Add toolinfo structure to the tooltip control */
434 SendMessageA(hwndTT
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
439 static void test_tab(INT nMinTabWidth
)
443 HIMAGELIST himl
= pImageList_Create(21, 21, ILC_COLOR
, 3, 4);
449 hwTab
= create_tabcontrol(TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
);
450 SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
451 /* Get System default MinTabWidth */
452 if (nMinTabWidth
< 0)
453 nMinTabWidth
= SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
456 dpi
= GetDeviceCaps(hdc
, LOGPIXELSX
);
457 hOldFont
= SelectObject(hdc
, (HFONT
)SendMessageA(hwTab
, WM_GETFONT
, 0, 0));
458 GetTextExtentPoint32A(hdc
, "Tab 1", strlen("Tab 1"), &size
);
459 trace("Tab1 text size: size.cx=%d size.cy=%d\n", size
.cx
, size
.cy
);
460 SelectObject(hdc
, hOldFont
);
461 ReleaseDC(hwTab
, hdc
);
463 trace (" TCS_FIXEDWIDTH tabs no icon...\n");
464 CHECKSIZE(hwTab
, dpi
, -1, "default width");
465 TABCHECKSETSIZE(hwTab
, 50, 20, 50, 20, "set size");
466 TABCHECKSETSIZE(hwTab
, 0, 1, 0, 1, "min size");
468 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
470 trace (" TCS_FIXEDWIDTH tabs with icon...\n");
471 TABCHECKSETSIZE(hwTab
, 50, 30, 50, 30, "set size > icon");
472 TABCHECKSETSIZE(hwTab
, 20, 20, 25, 20, "set size < icon");
473 TABCHECKSETSIZE(hwTab
, 0, 1, 25, 1, "min size");
475 DestroyWindow (hwTab
);
477 hwTab
= create_tabcontrol(TCS_FIXEDWIDTH
| TCS_BUTTONS
, TCIF_TEXT
|TCIF_IMAGE
);
478 SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
481 dpi
= GetDeviceCaps(hdc
, LOGPIXELSX
);
482 ReleaseDC(hwTab
, hdc
);
483 trace (" TCS_FIXEDWIDTH buttons no icon...\n");
484 CHECKSIZE(hwTab
, dpi
, -1, "default width");
485 TABCHECKSETSIZE(hwTab
, 20, 20, 20, 20, "set size 1");
486 TABCHECKSETSIZE(hwTab
, 10, 50, 10, 50, "set size 2");
487 TABCHECKSETSIZE(hwTab
, 0, 1, 0, 1, "min size");
489 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
491 trace (" TCS_FIXEDWIDTH buttons with icon...\n");
492 TABCHECKSETSIZE(hwTab
, 50, 30, 50, 30, "set size > icon");
493 TABCHECKSETSIZE(hwTab
, 20, 20, 25, 20, "set size < icon");
494 TABCHECKSETSIZE(hwTab
, 0, 1, 25, 1, "min size");
495 SendMessageA(hwTab
, TCM_SETPADDING
, 0, MAKELPARAM(4, 4));
496 TABCHECKSETSIZE(hwTab
, 0, 1, 25, 1, "set padding, min size");
498 DestroyWindow (hwTab
);
500 hwTab
= create_tabcontrol(TCS_FIXEDWIDTH
| TCS_BOTTOM
, TCIF_TEXT
|TCIF_IMAGE
);
501 SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
504 dpi
= GetDeviceCaps(hdc
, LOGPIXELSX
);
505 ReleaseDC(hwTab
, hdc
);
506 trace (" TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
507 CHECKSIZE(hwTab
, dpi
, -1, "no icon, default width");
509 TABCHECKSETSIZE(hwTab
, 20, 20, 20, 20, "no icon, set size 1");
510 TABCHECKSETSIZE(hwTab
, 10, 50, 10, 50, "no icon, set size 2");
511 TABCHECKSETSIZE(hwTab
, 0, 1, 0, 1, "no icon, min size");
513 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
515 TABCHECKSETSIZE(hwTab
, 50, 30, 50, 30, "with icon, set size > icon");
516 TABCHECKSETSIZE(hwTab
, 20, 20, 25, 20, "with icon, set size < icon");
517 TABCHECKSETSIZE(hwTab
, 0, 1, 25, 1, "with icon, min size");
518 SendMessageA(hwTab
, TCM_SETPADDING
, 0, MAKELPARAM(4, 4));
519 TABCHECKSETSIZE(hwTab
, 0, 1, 25, 1, "set padding, min size");
521 DestroyWindow (hwTab
);
523 hwTab
= create_tabcontrol(0, TCIF_TEXT
|TCIF_IMAGE
);
524 SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
526 trace (" non fixed width, with text...\n");
527 exp
= max(size
.cx
+TAB_PADDING_X
*2, (nMinTabWidth
< 0) ? DEFAULT_MIN_TAB_WIDTH
: nMinTabWidth
);
528 SendMessageA( hwTab
, TCM_GETITEMRECT
, 0, (LPARAM
)&rTab
);
529 ok( rTab
.right
- rTab
.left
== exp
|| broken(rTab
.right
- rTab
.left
== DEFAULT_MIN_TAB_WIDTH
),
530 "no icon, default width: Expected width [%d] got [%d]\n", exp
, rTab
.right
- rTab
.left
);
534 INT nTabWidth
= (nMinTabWidth
< 0) ? TabWidthPadded(i
, 2) : nMinTabWidth
;
536 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, 0);
537 SendMessageA(hwTab
, TCM_SETPADDING
, 0, MAKELPARAM(i
, i
));
539 TABCHECKSETSIZE(hwTab
, 50, 20, max(size
.cx
+ i
*2, nTabWidth
), 20, "no icon, set size");
540 TABCHECKSETSIZE(hwTab
, 0, 1, max(size
.cx
+ i
*2, nTabWidth
), 1, "no icon, min size");
542 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
543 nTabWidth
= (nMinTabWidth
< 0) ? TabWidthPadded(i
, 3) : nMinTabWidth
;
545 TABCHECKSETSIZE(hwTab
, 50, 30, max(size
.cx
+ 21 + i
*3, nTabWidth
), 30, "with icon, set size > icon");
546 TABCHECKSETSIZE(hwTab
, 20, 20, max(size
.cx
+ 21 + i
*3, nTabWidth
), 20, "with icon, set size < icon");
547 TABCHECKSETSIZE(hwTab
, 0, 1, max(size
.cx
+ 21 + i
*3, nTabWidth
), 1, "with icon, min size");
549 DestroyWindow (hwTab
);
551 hwTab
= create_tabcontrol(0, TCIF_IMAGE
);
552 SendMessageA(hwTab
, TCM_SETMINTABWIDTH
, 0, nMinTabWidth
);
554 trace (" non fixed width, no text...\n");
555 exp
= (nMinTabWidth
< 0) ? DEFAULT_MIN_TAB_WIDTH
: nMinTabWidth
;
556 SendMessageA( hwTab
, TCM_GETITEMRECT
, 0, (LPARAM
)&rTab
);
557 ok( rTab
.right
- rTab
.left
== exp
|| broken(rTab
.right
- rTab
.left
== DEFAULT_MIN_TAB_WIDTH
),
558 "no icon, default width: Expected width [%d] got [%d]\n", exp
, rTab
.right
- rTab
.left
);
562 INT nTabWidth
= (nMinTabWidth
< 0) ? TabWidthPadded(i
, 2) : nMinTabWidth
;
564 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, 0);
565 SendMessageA(hwTab
, TCM_SETPADDING
, 0, MAKELPARAM(i
, i
));
567 TABCHECKSETSIZE(hwTab
, 50, 20, nTabWidth
, 20, "no icon, set size");
568 TABCHECKSETSIZE(hwTab
, 0, 1, nTabWidth
, 1, "no icon, min size");
570 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
571 if (i
> 1 && nMinTabWidth
> 0 && nMinTabWidth
< DEFAULT_MIN_TAB_WIDTH
)
572 nTabWidth
+= EXTRA_ICON_PADDING
*(i
-1);
574 TABCHECKSETSIZE(hwTab
, 50, 30, nTabWidth
, 30, "with icon, set size > icon");
575 TABCHECKSETSIZE(hwTab
, 20, 20, nTabWidth
, 20, "with icon, set size < icon");
576 TABCHECKSETSIZE(hwTab
, 0, 1, nTabWidth
, 1, "with icon, min size");
579 DestroyWindow (hwTab
);
581 pImageList_Destroy(himl
);
584 static void test_width(void)
586 trace ("Testing with default MinWidth\n");
588 trace ("Testing with MinWidth set to -3\n");
590 trace ("Testing with MinWidth set to 24\n");
592 trace ("Testing with MinWidth set to 54\n");
594 trace ("Testing with MinWidth set to 94\n");
598 static void test_curfocus(void)
604 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
605 ok(hTab
!= NULL
, "Failed to create tab control\n");
607 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
609 /* Testing CurFocus with largest appropriate value */
610 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, nTabs
- 1, 0);
611 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
612 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
613 ok(ret
== nTabs
- 1, "Unexpected focus index %d.\n", ret
);
615 /* Testing CurFocus with negative value */
616 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, -10, 0);
617 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
618 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
619 ok(ret
== -1, "Unexpected focus index %d.\n", ret
);
621 /* Testing CurFocus with value larger than number of tabs */
622 ret
= SendMessageA(hTab
, TCM_SETCURSEL
, 1, 0);
623 ok(ret
== -1, "Unexpected focus index %d.\n", ret
);
625 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, nTabs
+ 1, 0);
626 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
627 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
628 ok(ret
== 1, "Unexpected focus index %d.\n", ret
);
630 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_cur_focus_seq
, "Set focused tab sequence", FALSE
);
631 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Set focused tab parent sequence", TRUE
);
636 hTab
= createFilledTabControl(parent_wnd
, TCS_BUTTONS
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
637 ok(hTab
!= NULL
, "Failed to create tab control\n");
639 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
641 /* Testing CurFocus with largest appropriate value */
642 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, nTabs
- 1, 0);
643 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
644 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
645 ok(ret
== nTabs
- 1, "Unexpected focus index %d.\n", ret
);
647 /* Testing CurFocus with negative value */
648 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, -10, 0);
649 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
650 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
652 ok(ret
== nTabs
- 1, "Unexpected focus index %d.\n", ret
);
654 /* Testing CurFocus with value larger than number of tabs */
655 ret
= SendMessageA(hTab
, TCM_SETCURSEL
, 1, 0);
657 ok(ret
== 0, "Unexpected focus index %d.\n", ret
);
659 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, nTabs
+ 1, 0);
660 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
661 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
663 ok(ret
== nTabs
- 1, "Unexpected focus index %d.\n", ret
);
665 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_cur_focus_seq
, "TCS_BUTTONS: set focused tab sequence", FALSE
);
666 ok_sequence(sequences
, PARENT_SEQ_INDEX
, setfocus_parent_seq
, "TCS_BUTTONS: set focused tab parent sequence", TRUE
);
671 static void test_cursel(void)
679 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
680 ok(hTab
!= NULL
, "Failed to create tab control\n");
682 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
684 /* Testing CurSel with largest appropriate value */
685 selectionIndex
= SendMessageA(hTab
, TCM_SETCURSEL
, nTabs
- 1, 0);
686 expect(0, selectionIndex
);
687 selectionIndex
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
688 expect(nTabs
-1, selectionIndex
);
690 /* Focus should switch with selection */
691 focusIndex
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
692 expect(nTabs
-1, focusIndex
);
694 /* Testing CurSel with negative value */
695 SendMessageA(hTab
, TCM_SETCURSEL
, -10, 0);
696 selectionIndex
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
697 expect(-1, selectionIndex
);
699 /* Testing CurSel with value larger than number of tabs */
700 selectionIndex
= SendMessageA(hTab
, TCM_SETCURSEL
, 1, 0);
701 expect(-1, selectionIndex
);
703 selectionIndex
= SendMessageA(hTab
, TCM_SETCURSEL
, nTabs
+ 1, 0);
704 expect(-1, selectionIndex
);
705 selectionIndex
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
706 expect(1, selectionIndex
);
708 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_cur_sel_seq
, "Getset curSel test sequence", FALSE
);
709 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Getset curSel test parent sequence", FALSE
);
711 /* selected item should have TCIS_BUTTONPRESSED state
712 It doesn't depend on button state */
713 memset(&tcItem
, 0, sizeof(TCITEMA
));
714 tcItem
.mask
= TCIF_STATE
;
715 tcItem
.dwStateMask
= TCIS_BUTTONPRESSED
;
716 selectionIndex
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
717 SendMessageA(hTab
, TCM_GETITEMA
, selectionIndex
, (LPARAM
)&tcItem
);
718 ok (tcItem
.dwState
& TCIS_BUTTONPRESSED
|| broken(tcItem
.dwState
== 0), /* older comctl32 */
719 "Selected item should have TCIS_BUTTONPRESSED\n");
721 /* now deselect all and check previously selected item state */
722 focusIndex
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
723 ok(focusIndex
== 1, "got %d\n", focusIndex
);
725 selectionIndex
= SendMessageA(hTab
, TCM_SETCURSEL
, -1, 0);
726 ok(selectionIndex
== 1, "got %d\n", selectionIndex
);
728 memset(&tcItem
, 0, sizeof(TCITEMA
));
730 /* focus is reset too */
731 focusIndex
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
732 ok(focusIndex
== -1, "got %d\n", focusIndex
);
734 tcItem
.mask
= TCIF_STATE
;
735 tcItem
.dwStateMask
= TCIS_BUTTONPRESSED
;
736 SendMessageA(hTab
, TCM_GETITEMA
, selectionIndex
, (LPARAM
)&tcItem
);
737 ok(tcItem
.dwState
== 0, "got state %d\n", tcItem
.dwState
);
742 static void test_extendedstyle(void)
745 DWORD prevExtendedStyle
;
749 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
750 ok(hTab
!= NULL
, "Failed to create tab control\n");
752 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
754 /* Testing Flat Separators */
755 extendedStyle
= SendMessageA(hTab
, TCM_GETEXTENDEDSTYLE
, 0, 0);
756 prevExtendedStyle
= SendMessageA(hTab
, TCM_SETEXTENDEDSTYLE
, 0, TCS_EX_FLATSEPARATORS
);
757 expect(extendedStyle
, prevExtendedStyle
);
759 extendedStyle
= SendMessageA(hTab
, TCM_GETEXTENDEDSTYLE
, 0, 0);
760 expect(TCS_EX_FLATSEPARATORS
, extendedStyle
);
762 /* Testing Register Drop */
763 prevExtendedStyle
= SendMessageA(hTab
, TCM_SETEXTENDEDSTYLE
, 0, TCS_EX_REGISTERDROP
);
764 expect(extendedStyle
, prevExtendedStyle
);
766 extendedStyle
= SendMessageA(hTab
, TCM_GETEXTENDEDSTYLE
, 0, 0);
768 expect(TCS_EX_REGISTERDROP
, extendedStyle
);
771 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_extended_style_seq
, "Getset extendedStyle test sequence", FALSE
);
772 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Getset extendedStyle test parent sequence", FALSE
);
777 static void test_unicodeformat(void)
783 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
784 ok(hTab
!= NULL
, "Failed to create tab control\n");
786 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
788 unicodeFormat
= SendMessageA(hTab
, TCM_SETUNICODEFORMAT
, TRUE
, 0);
790 expect(0, unicodeFormat
);
792 unicodeFormat
= SendMessageA(hTab
, TCM_GETUNICODEFORMAT
, 0, 0);
793 expect(1, unicodeFormat
);
795 unicodeFormat
= SendMessageA(hTab
, TCM_SETUNICODEFORMAT
, FALSE
, 0);
796 expect(1, unicodeFormat
);
797 unicodeFormat
= SendMessageA(hTab
, TCM_GETUNICODEFORMAT
, 0, 0);
798 expect(0, unicodeFormat
);
800 unicodeFormat
= SendMessageA(hTab
, TCM_SETUNICODEFORMAT
, TRUE
, 0);
801 expect(0, unicodeFormat
);
803 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_unicode_format_seq
, "Getset unicodeFormat test sequence", FALSE
);
804 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Getset unicodeFormat test parent sequence", FALSE
);
809 static void test_getset_item(void)
811 char szText
[32] = "New Label";
818 hTab
= CreateWindowA(
821 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| TCS_FIXEDWIDTH
| TCS_OWNERDRAWFIXED
,
823 parent_wnd
, NULL
, NULL
, 0);
825 ok(GetParent(hTab
) == NULL
, "got %p, expected null parent\n", GetParent(hTab
));
827 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, sizeof(LPARAM
)-1, 0);
828 ok(ret
== TRUE
, "got %d\n", ret
);
830 /* set some item data */
832 tcItem
.mask
= TCIF_PARAM
;
834 ret
= SendMessageA(hTab
, TCM_INSERTITEMA
, 0, (LPARAM
)&tcItem
);
835 ok(ret
== 0, "got %d\n", ret
);
837 /* all sizeof(LPARAM) returned anyway when using sizeof(LPARAM)-1 size */
838 memset(&lparam
, 0xaa, sizeof(lparam
));
839 tcItem
.lParam
= lparam
;
840 tcItem
.mask
= TCIF_PARAM
;
841 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 0, (LPARAM
)&tcItem
);
843 /* everything higher specified size is preserved */
844 memset(&lparam
, 0xff, sizeof(lparam
)-1);
845 ok(tcItem
.lParam
== lparam
, "Expected 0x%lx, got 0x%lx\n", lparam
, tcItem
.lParam
);
849 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
850 ok(hTab
!= NULL
, "Failed to create tab control\n");
852 /* passing invalid index should result in initialization to zero
853 for members mentioned in mask requested */
855 /* valid range here is [0,4] */
856 memset(&tcItem
, 0xcc, sizeof(tcItem
));
857 tcItem
.mask
= TCIF_PARAM
;
858 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 5, (LPARAM
)&tcItem
);
860 ok(tcItem
.lParam
== 0, "Expected zero lParam, got %lu\n", tcItem
.lParam
);
862 memset(&tcItem
, 0xcc, sizeof(tcItem
));
863 tcItem
.mask
= TCIF_IMAGE
;
864 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 5, (LPARAM
)&tcItem
);
866 expect(0, tcItem
.iImage
);
868 memset(&tcItem
, 0xcc, sizeof(tcItem
));
869 tcItem
.mask
= TCIF_TEXT
;
870 tcItem
.pszText
= szText
;
872 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 5, (LPARAM
)&tcItem
);
874 expect('a', szText
[0]);
876 memset(&tcItem
, 0xcc, sizeof(tcItem
));
877 tcItem
.mask
= TCIF_STATE
;
878 tcItem
.dwStateMask
= 0;
879 tcItem
.dwState
= TCIS_BUTTONPRESSED
;
880 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 5, (LPARAM
)&tcItem
);
882 ok(tcItem
.dwState
== 0, "Expected zero dwState, got %u\n", tcItem
.dwState
);
884 memset(&tcItem
, 0xcc, sizeof(tcItem
));
885 tcItem
.mask
= TCIF_STATE
;
886 tcItem
.dwStateMask
= TCIS_BUTTONPRESSED
;
887 tcItem
.dwState
= TCIS_BUTTONPRESSED
;
888 ret
= SendMessageA(hTab
, TCM_GETITEMA
, 5, (LPARAM
)&tcItem
);
890 ok(tcItem
.dwState
== 0, "Expected zero dwState\n");
892 /* check with negative index to be sure */
893 memset(&tcItem
, 0xcc, sizeof(tcItem
));
894 tcItem
.mask
= TCIF_PARAM
;
895 ret
= SendMessageA(hTab
, TCM_GETITEMA
, -1, (LPARAM
)&tcItem
);
897 ok(tcItem
.lParam
== 0, "Expected zero lParam, got %lu\n", tcItem
.lParam
);
899 memset(&tcItem
, 0xcc, sizeof(tcItem
));
900 tcItem
.mask
= TCIF_PARAM
;
901 ret
= SendMessageA(hTab
, TCM_GETITEMA
, -2, (LPARAM
)&tcItem
);
903 ok(tcItem
.lParam
== 0, "Expected zero lParam, got %lu\n", tcItem
.lParam
);
905 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
907 tcItem
.mask
= TCIF_TEXT
;
908 tcItem
.pszText
= &szText
[0];
909 tcItem
.cchTextMax
= sizeof(szText
);
911 strcpy(szText
, "New Label");
912 ok(SendMessageA(hTab
, TCM_SETITEMA
, 0, (LPARAM
)&tcItem
), "Setting new item failed.\n");
913 ok(SendMessageA(hTab
, TCM_GETITEMA
, 0, (LPARAM
)&tcItem
), "Getting item failed.\n");
914 expect_str("New Label", tcItem
.pszText
);
916 ok(SendMessageA(hTab
, TCM_GETITEMA
, 1, (LPARAM
)&tcItem
), "Getting item failed.\n");
917 expect_str("Tab 2", tcItem
.pszText
);
919 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_item_seq
, "Getset item test sequence", FALSE
);
920 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Getset item test parent sequence", FALSE
);
922 /* TCIS_BUTTONPRESSED doesn't depend on tab style */
923 memset(&tcItem
, 0, sizeof(tcItem
));
924 tcItem
.mask
= TCIF_STATE
;
925 tcItem
.dwStateMask
= TCIS_BUTTONPRESSED
;
926 tcItem
.dwState
= TCIS_BUTTONPRESSED
;
927 ok(SendMessageA(hTab
, TCM_SETITEMA
, 0, (LPARAM
)&tcItem
), "Setting new item failed.\n");
929 ok(SendMessageA(hTab
, TCM_GETITEMA
, 0, (LPARAM
)&tcItem
), "Getting item failed.\n");
932 ok (tcItem
.dwState
== TCIS_BUTTONPRESSED
, "TCIS_BUTTONPRESSED should be set.\n");
933 /* next highlight item, test that dwStateMask actually masks */
934 tcItem
.mask
= TCIF_STATE
;
935 tcItem
.dwStateMask
= TCIS_HIGHLIGHTED
;
936 tcItem
.dwState
= TCIS_HIGHLIGHTED
;
937 ok(SendMessageA(hTab
, TCM_SETITEMA
, 0, (LPARAM
)&tcItem
), "Setting new item failed.\n");
939 ok(SendMessageA(hTab
, TCM_GETITEMA
, 0, (LPARAM
)&tcItem
), "Getting item failed.\n");
940 ok (tcItem
.dwState
== TCIS_HIGHLIGHTED
, "TCIS_HIGHLIGHTED should be set.\n");
941 tcItem
.mask
= TCIF_STATE
;
942 tcItem
.dwStateMask
= TCIS_BUTTONPRESSED
;
944 ok(SendMessageA(hTab
, TCM_GETITEMA
, 0, (LPARAM
)&tcItem
), "Getting item failed.\n");
945 ok (tcItem
.dwState
== TCIS_BUTTONPRESSED
, "TCIS_BUTTONPRESSED should be set.\n");
947 else win_skip( "Item state mask not supported\n" );
952 static void test_getset_tooltips(void)
954 char toolTipText
[32] = "ToolTip Text Test";
955 HWND hTab
, toolTip
, hwnd
;
959 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
960 ok(hTab
!= NULL
, "Failed to create tab control\n");
962 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
964 toolTip
= create_tooltip(hTab
, toolTipText
);
965 ret
= SendMessageA(hTab
, TCM_SETTOOLTIPS
, (WPARAM
)toolTip
, 0);
966 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
967 hwnd
= (HWND
)SendMessageA(hTab
, TCM_GETTOOLTIPS
, 0, 0);
968 ok(toolTip
== hwnd
, "Unexpected tooltip window.\n");
970 ret
= SendMessageA(hTab
, TCM_SETTOOLTIPS
, 0, 0);
971 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
972 hwnd
= (HWND
)SendMessageA(hTab
, TCM_GETTOOLTIPS
, 0, 0);
973 ok(hwnd
== NULL
, "Unexpected tooltip window.\n");
974 ok(IsWindow(toolTip
), "Expected tooltip window to be alive.\n");
976 ok_sequence(sequences
, TAB_SEQ_INDEX
, getset_tooltip_seq
, "Getset tooltip test sequence", TRUE
);
977 ok_sequence(sequences
, PARENT_SEQ_INDEX
, getset_tooltip_parent_seq
, "Getset tooltip test parent sequence", TRUE
);
980 DestroyWindow(toolTip
);
983 static void test_adjustrect(void)
988 ok(parent_wnd
!= NULL
, "no parent window!\n");
990 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, 0, 0);
991 ok(hTab
!= NULL
, "Failed to create tab control\n");
993 r
= SendMessageA(hTab
, TCM_ADJUSTRECT
, FALSE
, 0);
996 r
= SendMessageA(hTab
, TCM_ADJUSTRECT
, TRUE
, 0);
1000 static void test_insert_focus(void)
1006 DWORD mask
= TCIF_TEXT
|TCIF_IMAGE
;
1007 static char tabName
[] = "TAB";
1008 tcNewTab
.mask
= mask
;
1009 tcNewTab
.pszText
= tabName
;
1011 ok(parent_wnd
!= NULL
, "no parent window!\n");
1013 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, mask
, 0);
1014 ok(hTab
!= NULL
, "Failed to create tab control\n");
1016 r
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
1019 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1021 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1022 expect(0, nTabsRetrieved
);
1024 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1027 tcNewTab
.iImage
= 1;
1028 r
= SendMessageA(hTab
, TCM_INSERTITEMA
, 1, (LPARAM
)&tcNewTab
);
1031 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1032 expect(1, nTabsRetrieved
);
1034 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1037 tcNewTab
.iImage
= 2;
1038 r
= SendMessageA(hTab
, TCM_INSERTITEMA
, 2, (LPARAM
)&tcNewTab
);
1041 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1042 expect(2, nTabsRetrieved
);
1044 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1047 r
= SendMessageA(hTab
, TCM_SETCURFOCUS
, -1, 0);
1050 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1053 tcNewTab
.iImage
= 3;
1054 r
= SendMessageA(hTab
, TCM_INSERTITEMA
, 3, (LPARAM
)&tcNewTab
);
1057 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1060 ok_sequence(sequences
, TAB_SEQ_INDEX
, insert_focus_seq
, "insert_focus test sequence", FALSE
);
1061 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "insert_focus parent test sequence", TRUE
);
1063 DestroyWindow(hTab
);
1066 static void test_delete_focus(void)
1072 ok(parent_wnd
!= NULL
, "no parent window!\n");
1074 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, 2);
1075 ok(hTab
!= NULL
, "Failed to create tab control\n");
1077 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1079 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1080 expect(2, nTabsRetrieved
);
1082 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1085 r
= SendMessageA(hTab
, TCM_DELETEITEM
, 1, 0);
1088 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1089 expect(1, nTabsRetrieved
);
1091 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1094 r
= SendMessageA(hTab
, TCM_SETCURFOCUS
, -1, 0);
1097 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1100 r
= SendMessageA(hTab
, TCM_DELETEITEM
, 0, 0);
1103 nTabsRetrieved
= SendMessageA(hTab
, TCM_GETITEMCOUNT
, 0, 0);
1104 expect(0, nTabsRetrieved
);
1106 r
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1109 ok_sequence(sequences
, TAB_SEQ_INDEX
, delete_focus_seq
, "delete_focus test sequence", FALSE
);
1110 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "delete_focus parent test sequence", TRUE
);
1112 DestroyWindow(hTab
);
1115 static void test_removeimage(void)
1117 static const BYTE bits
[32];
1122 HIMAGELIST himl
= pImageList_Create(16, 16, ILC_COLOR
, 3, 4);
1124 hicon
= CreateIcon(NULL
, 16, 16, 1, 1, bits
, bits
);
1125 pImageList_ReplaceIcon(himl
, -1, hicon
);
1126 pImageList_ReplaceIcon(himl
, -1, hicon
);
1127 pImageList_ReplaceIcon(himl
, -1, hicon
);
1129 hwTab
= create_tabcontrol(TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
);
1130 SendMessageA(hwTab
, TCM_SETIMAGELIST
, 0, (LPARAM
)himl
);
1132 memset(&item
, 0, sizeof(TCITEMA
));
1133 item
.mask
= TCIF_IMAGE
;
1135 for(i
= 0; i
< 3; i
++) {
1136 SendMessageA(hwTab
, TCM_GETITEMA
, i
, (LPARAM
)&item
);
1137 expect(i
, item
.iImage
);
1140 /* remove image middle image */
1141 SendMessageA(hwTab
, TCM_REMOVEIMAGE
, 1, 0);
1142 i
= pImageList_GetImageCount(himl
);
1143 ok(i
== 2, "Unexpected image count %d.\n", i
);
1145 SendMessageA(hwTab
, TCM_GETITEMA
, 0, (LPARAM
)&item
);
1146 expect(0, item
.iImage
);
1148 SendMessageA(hwTab
, TCM_GETITEMA
, 1, (LPARAM
)&item
);
1149 expect(-1, item
.iImage
);
1151 SendMessageA(hwTab
, TCM_GETITEMA
, 2, (LPARAM
)&item
);
1152 expect(1, item
.iImage
);
1153 /* remove first image */
1154 SendMessageA(hwTab
, TCM_REMOVEIMAGE
, 0, 0);
1155 i
= pImageList_GetImageCount(himl
);
1156 ok(i
== 1, "Unexpected image count %d.\n", i
);
1158 SendMessageA(hwTab
, TCM_GETITEMA
, 0, (LPARAM
)&item
);
1159 expect(-1, item
.iImage
);
1161 SendMessageA(hwTab
, TCM_GETITEMA
, 1, (LPARAM
)&item
);
1162 expect(-1, item
.iImage
);
1164 SendMessageA(hwTab
, TCM_GETITEMA
, 2, (LPARAM
)&item
);
1165 expect(0, item
.iImage
);
1166 /* remove the last one */
1167 SendMessageA(hwTab
, TCM_REMOVEIMAGE
, 0, 0);
1168 i
= pImageList_GetImageCount(himl
);
1169 ok(i
== 0, "Unexpected image count %d.\n", i
);
1170 for(i
= 0; i
< 3; i
++) {
1172 SendMessageA(hwTab
, TCM_GETITEMA
, i
, (LPARAM
)&item
);
1173 expect(-1, item
.iImage
);
1176 DestroyWindow(hwTab
);
1177 pImageList_Destroy(himl
);
1181 static void test_delete_selection(void)
1186 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, 4);
1187 ok(hTab
!= NULL
, "Failed to create tab control\n");
1189 ret
= SendMessageA(hTab
, TCM_SETCURSEL
, 3, 0);
1191 ret
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
1193 /* delete selected item - selection goes to -1 */
1194 ret
= SendMessageA(hTab
, TCM_DELETEITEM
, 3, 0);
1197 ret
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
1200 DestroyWindow(hTab
);
1203 static void test_TCM_SETITEMEXTRA(void)
1208 hTab
= CreateWindowA(
1211 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| TCS_FIXEDWIDTH
,
1213 parent_wnd
, NULL
, NULL
, 0);
1215 /* zero is valid size too */
1216 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, 0, 0);
1219 win_skip("TCM_SETITEMEXTRA not supported\n");
1220 DestroyWindow(hTab
);
1224 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, -1, 0);
1225 ok(ret
== FALSE
, "got %d\n", ret
);
1227 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, 2, 0);
1228 ok(ret
== TRUE
, "got %d\n", ret
);
1229 DestroyWindow(hTab
);
1231 /* it's not possible to change extra data size for control with tabs */
1232 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, 4);
1233 ok(hTab
!= NULL
, "Failed to create tab control\n");
1235 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, 2, 0);
1236 ok(ret
== FALSE
, "got %d\n", ret
);
1237 DestroyWindow(hTab
);
1240 static void test_TCS_OWNERDRAWFIXED(void)
1243 ULONG_PTR itemdata
, itemdata2
;
1248 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
|TCS_OWNERDRAWFIXED
, TCIF_TEXT
|TCIF_IMAGE
, 4);
1249 ok(hTab
!= NULL
, "Failed to create tab control\n");
1251 ok(GetParent(hTab
) == NULL
, "got %p, expected null parent\n", GetParent(hTab
));
1253 /* set some item data */
1254 memset(&lparam
, 0xde, sizeof(LPARAM
));
1256 item
.mask
= TCIF_PARAM
;
1257 item
.lParam
= lparam
;
1258 ret
= SendMessageA(hTab
, TCM_SETITEMA
, 0, (LPARAM
)&item
);
1259 ok(ret
== TRUE
, "got %d\n", ret
);
1261 memset(&g_drawitem
, 0, sizeof(g_drawitem
));
1263 ShowWindow(hTab
, SW_SHOW
);
1264 RedrawWindow(hTab
, NULL
, 0, RDW_UPDATENOW
);
1267 memset(&itemdata
, 0xde, 4);
1268 ok(g_drawitem
.itemData
== itemdata
, "got 0x%lx, expected 0x%lx\n", g_drawitem
.itemData
, itemdata
);
1270 DestroyWindow(hTab
);
1272 /* now with custom extra data length */
1273 hTab
= CreateWindowA(
1276 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| TCS_FIXEDWIDTH
| TCS_OWNERDRAWFIXED
,
1278 parent_wnd
, NULL
, NULL
, 0);
1280 ok(GetParent(hTab
) == NULL
, "got %p, expected null parent\n", GetParent(hTab
));
1282 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, sizeof(LPARAM
)+1, 0);
1283 ok(ret
== TRUE
, "got %d\n", ret
);
1285 /* set some item data */
1286 memset(&lparam
, 0xde, sizeof(LPARAM
));
1287 item
.mask
= TCIF_PARAM
;
1288 item
.lParam
= lparam
;
1290 ret
= SendMessageA(hTab
, TCM_INSERTITEMA
, 0, (LPARAM
)&item
);
1291 ok(ret
== 0, "got %d\n", ret
);
1293 memset(&g_drawitem
, 0, sizeof(g_drawitem
));
1295 ShowWindow(hTab
, SW_SHOW
);
1296 RedrawWindow(hTab
, NULL
, 0, RDW_UPDATENOW
);
1298 memset(&itemdata
, 0xde, sizeof(ULONG_PTR
));
1299 ok(*(ULONG_PTR
*)g_drawitem
.itemData
== itemdata
, "got 0x%lx, expected 0x%lx\n", g_drawitem
.itemData
, itemdata
);
1301 DestroyWindow(hTab
);
1303 /* same thing, but size smaller than default */
1304 hTab
= CreateWindowA(
1307 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| TCS_FOCUSNEVER
| TCS_FIXEDWIDTH
| TCS_OWNERDRAWFIXED
,
1309 parent_wnd
, NULL
, NULL
, 0);
1311 ok(GetParent(hTab
) == NULL
, "got %p, expected null parent\n", GetParent(hTab
));
1313 ret
= SendMessageA(hTab
, TCM_SETITEMEXTRA
, sizeof(LPARAM
)-1, 0);
1314 ok(ret
== TRUE
, "got %d\n", ret
);
1316 memset(&lparam
, 0xde, sizeof(lparam
));
1317 item
.mask
= TCIF_PARAM
;
1318 item
.lParam
= lparam
;
1320 ret
= SendMessageA(hTab
, TCM_INSERTITEMA
, 0, (LPARAM
)&item
);
1321 ok(ret
== 0, "got %d\n", ret
);
1323 memset(&g_drawitem
, 0, sizeof(g_drawitem
));
1325 ShowWindow(hTab
, SW_SHOW
);
1326 RedrawWindow(hTab
, NULL
, 0, RDW_UPDATENOW
);
1328 itemdata
= itemdata2
= 0;
1329 memset(&itemdata
, 0xde, 4);
1330 memset(&itemdata2
, 0xde, sizeof(LPARAM
)-1);
1331 ok(g_drawitem
.itemData
== itemdata
|| broken(g_drawitem
.itemData
== itemdata2
) /* win98 */,
1332 "got 0x%lx, expected 0x%lx\n", g_drawitem
.itemData
, itemdata
);
1334 DestroyWindow(hTab
);
1337 static void test_WM_CONTEXTMENU(void)
1341 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, 4);
1342 ok(hTab
!= NULL
, "Failed to create tab control\n");
1344 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1346 SendMessageA(hTab
, WM_RBUTTONUP
, 0, 0);
1348 ok_sequence(sequences
, TAB_SEQ_INDEX
, rbuttonup_seq
, "WM_RBUTTONUP response sequence", FALSE
);
1350 DestroyWindow(hTab
);
1353 struct tabcreate_style
{
1358 static const struct tabcreate_style create_styles
[] =
1360 { WS_CHILD
|TCS_BOTTOM
|TCS_VERTICAL
, WS_CHILD
|WS_CLIPSIBLINGS
|TCS_BOTTOM
|TCS_VERTICAL
|TCS_MULTILINE
},
1361 { WS_CHILD
|TCS_VERTICAL
, WS_CHILD
|WS_CLIPSIBLINGS
|TCS_VERTICAL
|TCS_MULTILINE
},
1365 static void test_create(void)
1367 const struct tabcreate_style
*ptr
= create_styles
;
1373 hTab
= CreateWindowA(WC_TABCONTROLA
, "TestTab", ptr
->style
,
1374 10, 10, 300, 100, parent_wnd
, NULL
, NULL
, 0);
1375 style
= GetWindowLongA(hTab
, GWL_STYLE
);
1376 ok(style
== ptr
->act_style
, "expected style 0x%08x, got style 0x%08x\n", ptr
->act_style
, style
);
1378 DestroyWindow(hTab
);
1383 static void init_functions(void)
1385 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
1387 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
1388 X(ImageList_Create
);
1389 X(ImageList_Destroy
);
1390 X(ImageList_GetImageCount
);
1391 X(ImageList_ReplaceIcon
);
1395 static void test_TCN_SELCHANGING(void)
1397 const INT nTabs
= 5;
1401 hTab
= createFilledTabControl(parent_wnd
, WS_CHILD
|TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
1402 ok(hTab
!= NULL
, "Failed to create tab control\n");
1404 /* Initially first tab is focused. */
1405 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1406 ok(ret
== 0, "Unexpected tab focus %d.\n", ret
);
1408 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1410 /* Setting focus to currently focused item should do nothing. */
1411 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, 0, 0);
1412 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
1414 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Set focus to focused tab sequence", FALSE
);
1416 /* Allow selection change. */
1417 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1419 tcn_selchanging_result
= 0;
1420 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, nTabs
- 1, 0);
1421 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
1423 ok_sequence(sequences
, PARENT_SEQ_INDEX
, full_selchange_parent_seq
, "Focus change allowed sequence", FALSE
);
1425 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1426 ok(ret
== nTabs
- 1, "Unexpected focused tab %d.\n", ret
);
1427 ret
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
1428 ok(ret
== nTabs
- 1, "Unexpected selected tab %d.\n", ret
);
1430 /* Forbid selection change. */
1431 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1433 tcn_selchanging_result
= 1;
1434 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, 0, 0);
1435 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
1437 ok_sequence(sequences
, PARENT_SEQ_INDEX
, selchanging_parent_seq
, "Focus change disallowed sequence", FALSE
);
1439 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1441 ok(ret
== nTabs
- 1, "Unexpected focused tab %d.\n", ret
);
1442 ret
= SendMessageA(hTab
, TCM_GETCURSEL
, 0, 0);
1444 ok(ret
== nTabs
- 1, "Unexpected selected tab %d.\n", ret
);
1446 /* Removing focus sends only TCN_SELCHANGE */
1447 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1449 ret
= SendMessageA(hTab
, TCM_SETCURFOCUS
, -1, 0);
1450 ok(ret
== 0, "Unexpected ret value %d.\n", ret
);
1452 ok_sequence(sequences
, PARENT_SEQ_INDEX
, selchange_parent_seq
, "Remove focus sequence", FALSE
);
1454 ret
= SendMessageA(hTab
, TCM_GETCURFOCUS
, 0, 0);
1455 ok(ret
== -1, "Unexpected focused tab %d.\n", ret
);
1457 tcn_selchanging_result
= 0;
1459 DestroyWindow(hTab
);
1462 static void test_TCM_GETROWCOUNT(void)
1464 const INT nTabs
= 5;
1468 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1470 hTab
= createFilledTabControl(parent_wnd
, TCS_FIXEDWIDTH
, TCIF_TEXT
|TCIF_IMAGE
, nTabs
);
1471 ok(hTab
!= NULL
, "Failed to create tab control\n");
1473 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1475 count
= SendMessageA(hTab
, TCM_GETROWCOUNT
, 0, 0);
1476 ok(count
== 1, "Unexpected row count %d.\n", count
);
1478 ok_sequence(sequences
, TAB_SEQ_INDEX
, get_row_count_seq
, "Get rowCount test sequence", FALSE
);
1479 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_sequence
, "Get rowCount test parent sequence", FALSE
);
1481 DestroyWindow(hTab
);
1488 lstrcpyA(logfont
.lfFaceName
, "Arial");
1489 memset(&logfont
, 0, sizeof(logfont
));
1490 logfont
.lfHeight
= -12;
1491 logfont
.lfWeight
= FW_NORMAL
;
1492 logfont
.lfCharSet
= ANSI_CHARSET
;
1493 hFont
= CreateFontIndirectA(&logfont
);
1497 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1499 parent_wnd
= createParentWindow();
1500 ok(parent_wnd
!= NULL
, "Failed to create parent window!\n");
1505 test_extendedstyle();
1506 test_unicodeformat();
1508 test_getset_tooltips();
1510 test_insert_focus();
1511 test_delete_focus();
1512 test_delete_selection();
1514 test_TCM_SETITEMEXTRA();
1515 test_TCS_OWNERDRAWFIXED();
1516 test_WM_CONTEXTMENU();
1518 test_TCN_SELCHANGING();
1519 test_TCM_GETROWCOUNT();
1521 DestroyWindow(parent_wnd
);