1 /* Unit test suite for header control.
3 * Copyright 2005 Vijay Kiran Kamuju
4 * Copyright 2007 Shanren Zhou
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
26 #include "wine/test.h"
30 typedef struct tagEXPECTEDNOTIFY
37 typedef LRESULT (*CUSTOMDRAWPROC
)(int n
, NMCUSTOMDRAW
*nm
);
39 static CUSTOMDRAWPROC g_CustomDrawProc
;
40 static int g_CustomDrawCount
;
41 static DRAWITEMSTRUCT g_DrawItem
;
42 static BOOL g_DrawItemReceived
;
43 static DWORD g_customheight
;
45 static EXPECTEDNOTIFY expectedNotify
[10];
46 static INT nExpectedNotify
= 0;
47 static INT nReceivedNotify
= 0;
48 static INT unexpectedNotify
[10];
49 static INT nUnexpectedNotify
= 0;
51 static HWND hHeaderParentWnd
;
52 static HWND hWndHeader
;
55 #define compare(val, exp, fmt) ok((val) == (exp), #val " value: " fmt ", expected: " fmt "\n", (val), (exp))
57 #define expect(expected, got) ok(expected == got, "expected %d, got %d\n", expected,got)
59 #define NUM_MSG_SEQUENCES 2
60 #define PARENT_SEQ_INDEX 0
61 #define HEADER_SEQ_INDEX 1
63 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
65 static const struct message create_parent_wnd_seq
[] = {
66 { WM_GETMINMAXINFO
, sent
},
67 { WM_NCCREATE
, sent
},
68 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
73 static const struct message add_header_to_parent_seq_interactive
[] = {
74 { WM_NOTIFYFORMAT
, sent
|lparam
, 0, NF_QUERY
},
75 { WM_QUERYUISTATE
, sent
},
76 { WM_PARENTNOTIFY
, sent
|wparam
, 1 },
77 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
78 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
79 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
80 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
81 { WM_NCACTIVATE
, sent
|wparam
, 1 },
82 { WM_ACTIVATE
, sent
|wparam
, 1 },
83 { WM_IME_SETCONTEXT
, sent
|defwinproc
|wparam
, 1 },
84 { WM_IME_NOTIFY
, sent
|defwinproc
|wparam
, 2 },
85 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, 0 },
86 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
87 { WM_SIZE
, sent
|wparam
, 0 },
88 { WM_MOVE
, sent
|wparam
, 0 },
92 static const struct message add_header_to_parent_seq
[] = {
93 { WM_NOTIFYFORMAT
, sent
|lparam
, 0, NF_QUERY
},
94 { WM_QUERYUISTATE
, sent
|optional
},
95 { WM_PARENTNOTIFY
, sent
},
99 static const struct message insertItem_seq
[] = {
100 { HDM_INSERTITEM
, sent
|wparam
, 0 },
101 { HDM_INSERTITEM
, sent
|wparam
, 1 },
102 { HDM_INSERTITEM
, sent
|wparam
, 2 },
103 { HDM_INSERTITEM
, sent
|wparam
, 3 },
107 static const struct message getItem_seq
[] = {
108 { HDM_GETITEM
, sent
|wparam
, 3 },
109 { HDM_GETITEM
, sent
|wparam
, 0 },
114 static const struct message deleteItem_getItemCount_seq
[] = {
115 { HDM_DELETEITEM
, sent
|wparam
, 3 },
116 { HDM_GETITEMCOUNT
, sent
},
117 { HDM_DELETEITEM
, sent
|wparam
, 3 },
118 { HDM_GETITEMCOUNT
, sent
},
119 { HDM_DELETEITEM
, sent
|wparam
, 2 },
120 { HDM_GETITEMCOUNT
, sent
},
124 static const struct message orderArray_seq
[] = {
125 { HDM_SETORDERARRAY
, sent
|wparam
, 2 },
126 { HDM_GETORDERARRAY
, sent
|wparam
, 2 },
130 static const struct message setItem_seq
[] = {
131 { HDM_SETITEM
, sent
|wparam
, 0 },
132 { HDM_SETITEM
, sent
|wparam
, 1 },
136 static const struct message getItemRect_seq
[] = {
137 { HDM_GETITEMRECT
, sent
|wparam
, 1 },
138 { HDM_GETITEMRECT
, sent
|wparam
, 0 },
139 { HDM_GETITEMRECT
, sent
|wparam
, 10 },
143 static const struct message layout_seq
[] = {
144 { HDM_LAYOUT
, sent
},
148 static const struct message orderToIndex_seq
[] = {
149 { HDM_ORDERTOINDEX
, sent
|wparam
, 1 },
153 static const struct message hittest_seq
[] = {
154 { HDM_HITTEST
, sent
},
155 { HDM_HITTEST
, sent
},
156 { HDM_HITTEST
, sent
},
160 static const struct message setHotDivider_seq_interactive
[] = {
161 { HDM_SETHOTDIVIDER
, sent
|wparam
, TRUE
},
162 { WM_PAINT
, sent
|defwinproc
},
163 { WM_NCPAINT
, sent
|defwinproc
},
164 { WM_ERASEBKGND
, sent
|defwinproc
},
165 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 100 },
166 { WM_PAINT
, sent
|defwinproc
},
167 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 1},
168 { WM_PAINT
, sent
|defwinproc
},
172 static const struct message setHotDivider_seq_noninteractive
[] = {
173 { HDM_SETHOTDIVIDER
, sent
|wparam
, TRUE
},
174 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 100 },
175 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 1},
179 static const struct message imageMessages_seq
[] = {
180 { HDM_SETIMAGELIST
, sent
},
181 { HDM_GETIMAGELIST
, sent
},
182 { HDM_CREATEDRAGIMAGE
, sent
},
186 static const struct message filterMessages_seq_interactive
[] = {
187 { HDM_SETFILTERCHANGETIMEOUT
, sent
|wparam
|lparam
, 1, 100 },
188 { HDM_CLEARFILTER
, sent
|wparam
|lparam
, 0, 1 },
189 { HDM_EDITFILTER
, sent
|wparam
|lparam
, 1, 0 },
190 { WM_PARENTNOTIFY
, sent
|wparam
|defwinproc
, WM_CREATE
},
191 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
192 { WM_COMMAND
, sent
|defwinproc
},
196 static const struct message filterMessages_seq_noninteractive
[] = {
197 { HDM_SETFILTERCHANGETIMEOUT
, sent
|wparam
|lparam
, 1, 100 },
198 { HDM_CLEARFILTER
, sent
|wparam
|lparam
, 0, 1 },
199 { HDM_EDITFILTER
, sent
|wparam
|lparam
, 1, 0 },
200 { WM_PARENTNOTIFY
, sent
|wparam
|defwinproc
|optional
, WM_CREATE
},
201 { WM_COMMAND
, sent
|defwinproc
|optional
},
205 static const struct message unicodeformatMessages_seq
[] = {
206 { HDM_SETUNICODEFORMAT
, sent
|wparam
, TRUE
},
207 { HDM_GETUNICODEFORMAT
, sent
},
211 static const struct message bitmapmarginMessages_seq
[] = {
212 { HDM_GETBITMAPMARGIN
, sent
},
217 static void expect_notify(INT iCode
, BOOL fUnicode
, HDITEMA
*lpItem
)
219 assert(nExpectedNotify
< 10);
220 expectedNotify
[nExpectedNotify
].iCode
= iCode
;
221 expectedNotify
[nExpectedNotify
].fUnicode
= fUnicode
;
222 expectedNotify
[nExpectedNotify
].hdItem
= *lpItem
;
226 static void dont_expect_notify(INT iCode
)
228 assert(nUnexpectedNotify
< 10);
229 unexpectedNotify
[nUnexpectedNotify
++] = iCode
;
232 static BOOL
notifies_received(void)
234 BOOL fRet
= (nExpectedNotify
== nReceivedNotify
);
235 nExpectedNotify
= nReceivedNotify
= 0;
236 nUnexpectedNotify
= 0;
240 static LONG
addItem(HWND hdex
, int idx
, LPSTR text
)
243 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
;
245 hdItem
.pszText
= text
;
246 hdItem
.cchTextMax
= 0;
247 return SendMessage(hdex
, HDM_INSERTITEMA
, idx
, (LPARAM
)&hdItem
);
250 static LONG
setItem(HWND hdex
, int idx
, LPSTR text
, BOOL fCheckNotifies
)
254 hdexItem
.mask
= HDI_TEXT
;
255 hdexItem
.pszText
= text
;
256 hdexItem
.cchTextMax
= 0;
259 expect_notify(HDN_ITEMCHANGINGA
, FALSE
, &hdexItem
);
260 expect_notify(HDN_ITEMCHANGEDA
, FALSE
, &hdexItem
);
262 ret
= SendMessage(hdex
, HDM_SETITEMA
, idx
, (LPARAM
)&hdexItem
);
264 ok(notifies_received(), "setItem(): not all expected notifies were received\n");
268 static LONG
setItemUnicodeNotify(HWND hdex
, int idx
, LPSTR text
, LPWSTR wText
)
273 hdexItem
.mask
= HDI_TEXT
;
274 hdexItem
.pszText
= text
;
275 hdexItem
.cchTextMax
= 0;
277 hdexNotify
.mask
= HDI_TEXT
;
278 hdexNotify
.pszText
= wText
;
280 expect_notify(HDN_ITEMCHANGINGW
, TRUE
, (HDITEMA
*)&hdexNotify
);
281 expect_notify(HDN_ITEMCHANGEDW
, TRUE
, (HDITEMA
*)&hdexNotify
);
282 ret
= SendMessage(hdex
, HDM_SETITEMA
, idx
, (LPARAM
)&hdexItem
);
283 ok(notifies_received(), "setItemUnicodeNotify(): not all expected notifies were received\n");
287 static LONG
delItem(HWND hdex
, int idx
)
289 return SendMessage(hdex
, HDM_DELETEITEM
, idx
, 0);
292 static LONG
getItemCount(HWND hdex
)
294 return SendMessage(hdex
, HDM_GETITEMCOUNT
, 0, 0);
297 static LONG
getItem(HWND hdex
, int idx
, LPSTR textBuffer
)
300 hdItem
.mask
= HDI_TEXT
;
301 hdItem
.pszText
= textBuffer
;
302 hdItem
.cchTextMax
= MAX_CHARS
;
303 return SendMessage(hdex
, HDM_GETITEMA
, idx
, (LPARAM
)&hdItem
);
306 static void addReadDelItem(HWND hdex
, HDITEMA
*phdiCreate
, int maskRead
, HDITEMA
*phdiRead
)
308 ok(SendMessage(hdex
, HDM_INSERTITEMA
, 0, (LPARAM
)phdiCreate
)!=-1, "Adding item failed\n");
309 ZeroMemory(phdiRead
, sizeof(HDITEMA
));
310 phdiRead
->mask
= maskRead
;
311 ok(SendMessage(hdex
, HDM_GETITEMA
, 0, (LPARAM
)phdiRead
)!=0, "Getting item data failed\n");
312 ok(SendMessage(hdex
, HDM_DELETEITEM
, 0, 0)!=0, "Deleting item failed\n");
315 static HWND
create_header_control (void)
322 handle
= CreateWindowEx(0, WC_HEADER
, NULL
,
323 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
325 hHeaderParentWnd
, NULL
, NULL
, NULL
);
328 if (winetest_interactive
)
329 ShowWindow (hHeaderParentWnd
, SW_SHOW
);
331 GetClientRect(hHeaderParentWnd
,&rectwin
);
332 hlayout
.prc
= &rectwin
;
333 hlayout
.pwpos
= &winpos
;
334 SendMessageA(handle
,HDM_LAYOUT
,0,(LPARAM
) &hlayout
);
335 SetWindowPos(handle
, winpos
.hwndInsertAfter
, winpos
.x
, winpos
.y
,
336 winpos
.cx
, winpos
.cy
, 0);
341 static void compare_items(INT iCode
, HDITEMA
*hdi1
, HDITEMA
*hdi2
, BOOL fUnicode
)
343 ok(hdi1
->mask
== hdi2
->mask
, "Notify %d mask mismatch (%08x != %08x)\n", iCode
, hdi1
->mask
, hdi2
->mask
);
344 if (hdi1
->mask
& HDI_WIDTH
)
346 ok(hdi1
->cxy
== hdi2
->cxy
, "Notify %d cxy mismatch (%08x != %08x)\n", iCode
, hdi1
->cxy
, hdi2
->cxy
);
348 if (hdi1
->mask
& HDI_TEXT
)
350 if (hdi1
->pszText
== LPSTR_TEXTCALLBACKA
)
352 ok(hdi1
->pszText
== LPSTR_TEXTCALLBACKA
, "Notify %d - only one item is LPSTR_TEXTCALLBACK\n", iCode
);
359 WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)hdi1
->pszText
, -1, buf1
, 260, NULL
, NULL
);
360 WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)hdi2
->pszText
, -1, buf2
, 260, NULL
, NULL
);
361 ok(lstrcmpW((LPWSTR
)hdi1
->pszText
, (LPWSTR
)hdi2
->pszText
)==0,
362 "Notify %d text mismatch (L\"%s\" vs L\"%s\")\n",
367 ok(strcmp(hdi1
->pszText
, hdi2
->pszText
)==0,
368 "Notify %d text mismatch (\"%s\" vs \"%s\")\n",
369 iCode
, hdi1
->pszText
, hdi2
->pszText
);
374 static char pszFirstItem
[] = "First Item";
375 static char pszSecondItem
[] = "Second Item";
376 static char pszThirdItem
[] = "Third Item";
377 static char pszFourthItem
[] = "Fourth Item";
378 static char pszReplaceItem
[] = "Replace Item";
379 static char pszOutOfRangeItem
[] = "Out Of Range Item";
381 static char *str_items
[] =
382 {pszFirstItem
, pszSecondItem
, pszThirdItem
, pszFourthItem
, pszReplaceItem
, pszOutOfRangeItem
};
384 static char pszUniTestA
[] = "TST";
385 static WCHAR pszUniTestW
[] = {'T','S','T',0};
388 #define TEST_GET_ITEM(i,c)\
389 { res = getItem(hWndHeader, i, buffer);\
390 ok(res != 0, "Getting item[%d] using valid index failed unexpectedly (%d)\n", i, res);\
391 ok(strcmp(str_items[c], buffer) == 0, "Getting item[%d] returned \"%s\" expecting \"%s\"\n", i, buffer, str_items[c]);\
394 #define TEST_GET_ITEMCOUNT(i)\
395 { res = getItemCount(hWndHeader);\
396 ok(res == i, "Got Item Count as %d\n", res);\
399 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
401 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
402 static LONG defwndproc_counter
= 0;
406 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
407 msg
.message
= message
;
408 msg
.flags
= sent
|wparam
|lparam
;
409 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
412 add_message(sequences
, HEADER_SEQ_INDEX
, &msg
);
414 defwndproc_counter
++;
415 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
416 defwndproc_counter
--;
421 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
423 static LONG defwndproc_counter
= 0;
427 /* do not log painting messages */
428 if (message
!= WM_PAINT
&&
429 message
!= WM_ERASEBKGND
&&
430 message
!= WM_NCPAINT
&&
431 message
!= WM_NCHITTEST
&&
432 message
!= WM_GETTEXT
&&
433 message
!= WM_GETICON
&&
434 message
!= WM_DEVICECHANGE
)
437 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
439 msg
.message
= message
;
440 msg
.flags
= sent
|wparam
|lparam
;
441 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
444 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
447 defwndproc_counter
++;
448 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
449 defwndproc_counter
--;
454 static BOOL
register_parent_wnd_class(void)
459 cls
.lpfnWndProc
= parent_wnd_proc
;
462 cls
.hInstance
= GetModuleHandleA(NULL
);
464 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
465 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
466 cls
.lpszMenuName
= NULL
;
467 cls
.lpszClassName
= "Header test parent class";
468 return RegisterClassA(&cls
);
471 static HWND
create_custom_parent_window(void)
473 if (!register_parent_wnd_class())
476 return CreateWindowExA(0, "Header test parent class", "Header Message Sequence Testing",
477 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
478 672+2*GetSystemMetrics(SM_CXSIZEFRAME
),
479 226+GetSystemMetrics(SM_CYCAPTION
)+2*GetSystemMetrics(SM_CYSIZEFRAME
),
480 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
483 static HWND
create_custom_header_control(HWND hParent
, BOOL preloadHeaderItems
)
492 static char firstHeaderItem
[] = "Name";
493 static char secondHeaderItem
[] = "Size";
494 static char *items
[] = {secondHeaderItem
, firstHeaderItem
};
496 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
| HDI_FORMAT
;
497 hdItem
.fmt
= HDF_LEFT
;
499 hdItem
.cchTextMax
= 260;
502 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
504 childHandle
= CreateWindowEx(0, WC_HEADER
, NULL
,
505 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
507 hParent
, NULL
, NULL
, NULL
);
509 if (preloadHeaderItems
)
511 for ( loopcnt
= 0 ; loopcnt
< 2 ; loopcnt
++ )
513 hdItem
.pszText
= items
[loopcnt
];
514 retVal
= SendMessage(childHandle
, HDM_INSERTITEM
, loopcnt
, (LPARAM
) &hdItem
);
515 ok(retVal
== loopcnt
, "Adding item %d failed with return value %d\n", ( loopcnt
+ 1 ), retVal
);
519 if (winetest_interactive
)
520 ShowWindow (hParent
, SW_SHOW
);
522 GetClientRect(hParent
,&rectwin
);
523 hlayout
.prc
= &rectwin
;
524 hlayout
.pwpos
= &winpos
;
525 SendMessageA(childHandle
,HDM_LAYOUT
,0,(LPARAM
) &hlayout
);
526 SetWindowPos(childHandle
, winpos
.hwndInsertAfter
, winpos
.x
, winpos
.y
,
527 winpos
.cx
, winpos
.cy
, 0);
529 oldproc
= (WNDPROC
)SetWindowLongPtrA(childHandle
, GWLP_WNDPROC
,
530 (LONG_PTR
)header_subclass_proc
);
531 SetWindowLongPtrA(childHandle
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
535 static void check_auto_format(void)
539 static CHAR text
[] = "Test";
540 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
542 /* Windows implicitly sets some format bits in INSERTITEM */
544 /* HDF_STRING is automatically set and cleared for no text */
545 hdiCreate
.mask
= HDI_TEXT
|HDI_WIDTH
|HDI_FORMAT
;
546 hdiCreate
.pszText
= text
;
548 hdiCreate
.fmt
=HDF_CENTER
;
549 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
550 ok(hdiRead
.fmt
== (HDF_STRING
|HDF_CENTER
), "HDF_STRING not set automatically (fmt=%x)\n", hdiRead
.fmt
);
552 hdiCreate
.mask
= HDI_WIDTH
|HDI_FORMAT
;
553 hdiCreate
.pszText
= text
;
554 hdiCreate
.fmt
= HDF_CENTER
|HDF_STRING
;
555 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
556 ok(hdiRead
.fmt
== (HDF_CENTER
), "HDF_STRING should be automatically cleared (fmt=%x)\n", hdiRead
.fmt
);
558 /* HDF_BITMAP is automatically set and cleared for a NULL bitmap or no bitmap */
559 hdiCreate
.mask
= HDI_BITMAP
|HDI_WIDTH
|HDI_FORMAT
;
560 hdiCreate
.hbm
= CreateBitmap(16, 16, 1, 8, NULL
);
561 hdiCreate
.fmt
= HDF_CENTER
;
562 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
563 ok(hdiRead
.fmt
== (HDF_BITMAP
|HDF_CENTER
), "HDF_BITMAP not set automatically (fmt=%x)\n", hdiRead
.fmt
);
564 DeleteObject(hdiCreate
.hbm
);
566 hdiCreate
.hbm
= NULL
;
567 hdiCreate
.fmt
= HDF_CENTER
|HDF_BITMAP
;
568 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
569 ok(hdiRead
.fmt
== HDF_CENTER
, "HDF_BITMAP not cleared automatically for NULL bitmap (fmt=%x)\n", hdiRead
.fmt
);
571 hdiCreate
.mask
= HDI_WIDTH
|HDI_FORMAT
;
572 hdiCreate
.fmt
= HDF_CENTER
|HDF_BITMAP
;
573 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
574 ok(hdiRead
.fmt
== HDF_CENTER
, "HDF_BITMAP not cleared automatically for no bitmap (fmt=%x)\n", hdiRead
.fmt
);
576 /* HDF_IMAGE is automatically set but not cleared */
577 hdiCreate
.mask
= HDI_IMAGE
|HDI_WIDTH
|HDI_FORMAT
;
578 hdiCreate
.iImage
= 17;
579 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
580 ok(hdiRead
.fmt
== (HDF_IMAGE
|HDF_CENTER
), "HDF_IMAGE not set automatically (fmt=%x)\n", hdiRead
.fmt
);
582 hdiCreate
.mask
= HDI_WIDTH
|HDI_FORMAT
;
583 hdiCreate
.fmt
= HDF_CENTER
|HDF_IMAGE
;
584 hdiCreate
.iImage
= 0;
585 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
586 ok(hdiRead
.fmt
== (HDF_CENTER
|HDF_IMAGE
), "HDF_IMAGE shouldn't be cleared automatically (fmt=%x)\n", hdiRead
.fmt
);
589 static void check_auto_fields(void)
593 static CHAR text
[] = "Test";
596 /* Windows stores the format, width, lparam even if they are not in the item's mask */
597 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
598 hdiCreate
.mask
= HDI_TEXT
;
600 hdiCreate
.pszText
= text
;
601 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_WIDTH
, &hdiRead
);
602 TEST_GET_ITEMCOUNT(6);
603 ok(hdiRead
.cxy
== hdiCreate
.cxy
, "cxy should be automatically set\n");
605 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
606 hdiCreate
.mask
= HDI_TEXT
;
607 hdiCreate
.pszText
= text
;
608 hdiCreate
.lParam
= 0x12345678;
609 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_LPARAM
, &hdiRead
);
610 TEST_GET_ITEMCOUNT(6);
611 ok(hdiRead
.lParam
== hdiCreate
.lParam
, "lParam should be automatically set\n");
613 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
614 hdiCreate
.mask
= HDI_TEXT
;
615 hdiCreate
.pszText
= text
;
616 hdiCreate
.fmt
= HDF_STRING
|HDF_CENTER
;
617 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
618 TEST_GET_ITEMCOUNT(6);
619 ok(hdiRead
.fmt
== hdiCreate
.fmt
, "fmt should be automatically set\n");
621 /* others fields are not set */
622 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
623 hdiCreate
.mask
= HDI_TEXT
;
624 hdiCreate
.pszText
= text
;
625 hdiCreate
.hbm
= CreateBitmap(16, 16, 1, 8, NULL
);
626 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_BITMAP
, &hdiRead
);
627 TEST_GET_ITEMCOUNT(6);
628 ok(hdiRead
.hbm
== NULL
, "hbm should not be automatically set\n");
629 DeleteObject(hdiCreate
.hbm
);
631 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
632 hdiCreate
.mask
= HDI_IMAGE
;
633 hdiCreate
.iImage
= 17;
634 hdiCreate
.pszText
= text
;
635 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_TEXT
, &hdiRead
);
636 TEST_GET_ITEMCOUNT(6);
637 ok(hdiRead
.pszText
==NULL
, "pszText shouldn't be automatically set\n");
639 /* field from comctl >4.0 not tested as the system probably won't touch them */
642 static void check_mask(void)
645 static CHAR text
[] = "ABC";
648 /* don't create items if the mask is zero */
649 ZeroMemory(&hdi
, sizeof(hdi
));
656 hdi
.cchTextMax
= 260;
657 ret
= SendMessage(hWndHeader
, HDM_INSERTITEM
, 0, (LPARAM
)&hdi
);
658 ok(ret
== -1, "Creating an item with a zero mask should have failed\n");
659 if (ret
!= -1) SendMessage(hWndHeader
, HDM_DELETEITEM
, 0, 0);
661 /* with a non-zero mask creation will succeed */
662 ZeroMemory(&hdi
, sizeof(hdi
));
663 hdi
.mask
= HDI_LPARAM
;
664 ret
= SendMessage(hWndHeader
, HDM_INSERTITEM
, 0, (LPARAM
)&hdi
);
665 ok(ret
!= -1, "Adding item with non-zero mask failed\n");
667 SendMessage(hWndHeader
, HDM_DELETEITEM
, 0, 0);
669 /* in SETITEM if the mask contains a unknown bit, it is ignored */
670 ZeroMemory(&hdi
, sizeof(hdi
));
671 hdi
.mask
= 0x08000000 | HDI_LPARAM
| HDI_IMAGE
;
674 ret
= SendMessage(hWndHeader
, HDM_INSERTITEM
, 0, (LPARAM
)&hdi
);
675 ok(ret
!= -1, "Adding item failed\n");
680 ZeroMemory(&hdi
, sizeof(hdi
));
681 hdi
.mask
= HDI_LPARAM
| HDI_IMAGE
;
682 SendMessage(hWndHeader
, HDM_GETITEM
, 0, (LPARAM
)&hdi
);
683 ok(hdi
.lParam
== 133, "comctl32 4.0 field not set\n");
684 ok(hdi
.iImage
== 17, "comctl32 >4.0 field not set\n");
686 /* but in GETITEM if an unknown bit is set, comctl32 uses only version 4.0 fields */
687 ZeroMemory(&hdi
, sizeof(hdi
));
688 hdi
.mask
= 0x08000000 | HDI_LPARAM
| HDI_IMAGE
;
689 SendMessage(hWndHeader
, HDM_GETITEM
, 0, (LPARAM
)&hdi
);
690 ok(hdi
.lParam
== 133, "comctl32 4.0 field not read\n");
691 ok(hdi
.iImage
== 0, "comctl32 >4.0 field shouldn't be read\n");
693 SendMessage(hWndHeader
, HDM_DELETEITEM
, 0, 0);
697 static void test_header_control (void)
700 static char buffer
[MAX_CHARS
];
703 hWndHeader
= create_header_control ();
705 for (i
= 3; i
>= 0; i
--)
707 TEST_GET_ITEMCOUNT(3-i
);
708 res
= addItem(hWndHeader
, 0, str_items
[i
]);
709 ok(res
== 0, "Adding simple item failed (%d)\n", res
);
712 TEST_GET_ITEMCOUNT(4);
713 res
= addItem(hWndHeader
, 99, str_items
[i
+1]);
714 ok(res
!= -1, "Adding Out of Range item should fail with -1 got (%d)\n", res
);
715 TEST_GET_ITEMCOUNT(5);
716 res
= addItem(hWndHeader
, 5, str_items
[i
+1]);
717 ok(res
!= -1, "Adding Out of Range item should fail with -1 got (%d)\n", res
);
718 TEST_GET_ITEMCOUNT(6);
720 for (i
= 0; i
< 4; i
++) { TEST_GET_ITEM(i
,i
); TEST_GET_ITEMCOUNT(6); }
722 res
=getItem(hWndHeader
, 99, buffer
);
723 ok(res
== 0, "Getting Out of Range item should fail with 0 (%d), got %s\n", res
,buffer
);
724 res
=getItem(hWndHeader
, 5, buffer
);
725 ok(res
== 1, "Getting Out of Range item should fail with 1 (%d), got %s\n", res
,buffer
);
726 res
=getItem(hWndHeader
, -2, buffer
);
727 ok(res
== 0, "Getting Out of Range item should fail with 0 (%d), got %s\n", res
,buffer
);
729 if (winetest_interactive
)
731 UpdateWindow(hHeaderParentWnd
);
732 UpdateWindow(hWndHeader
);
735 TEST_GET_ITEMCOUNT(6);
736 res
=setItem(hWndHeader
, 99, str_items
[5], FALSE
);
737 ok(res
== 0, "Setting Out of Range item should fail with 0 (%d)\n", res
);
738 res
=setItem(hWndHeader
, 5, str_items
[5], TRUE
);
739 ok(res
== 1, "Setting Out of Range item should fail with 1 (%d)\n", res
);
740 res
=setItem(hWndHeader
, -2, str_items
[5], FALSE
);
741 ok(res
== 0, "Setting Out of Range item should fail with 0 (%d)\n", res
);
742 TEST_GET_ITEMCOUNT(6);
744 for (i
= 0; i
< 4; i
++)
746 res
= setItem(hWndHeader
, i
, str_items
[4], TRUE
);
747 ok(res
!= 0, "Setting %d item failed (%d)\n", i
+1, res
);
749 TEST_GET_ITEMCOUNT(6);
752 SendMessageA(hWndHeader
, HDM_SETUNICODEFORMAT
, TRUE
, 0);
753 setItemUnicodeNotify(hWndHeader
, 3, pszUniTestA
, pszUniTestW
);
754 SendMessageA(hWndHeader
, WM_NOTIFYFORMAT
, (WPARAM
)hHeaderParentWnd
, NF_REQUERY
);
755 setItem(hWndHeader
, 3, str_items
[4], TRUE
);
757 dont_expect_notify(HDN_GETDISPINFOA
);
758 dont_expect_notify(HDN_GETDISPINFOW
);
759 addItem(hWndHeader
, 0, LPSTR_TEXTCALLBACKA
);
760 setItem(hWndHeader
, 0, str_items
[4], TRUE
);
761 /* unexpected notifies cleared by notifies_received in setItem */
762 dont_expect_notify(HDN_GETDISPINFOA
);
763 dont_expect_notify(HDN_GETDISPINFOW
);
764 setItem(hWndHeader
, 0, LPSTR_TEXTCALLBACKA
, TRUE
);
765 /* unexpected notifies cleared by notifies_received in setItem */
766 delItem(hWndHeader
, 0);
769 TEST_GET_ITEMCOUNT(6);
771 TEST_GET_ITEMCOUNT(6);
773 TEST_GET_ITEMCOUNT(6);
775 res
= delItem(hWndHeader
, 5);
776 ok(res
== 1, "Deleting Out of Range item should fail with 1 (%d)\n", res
);
777 res
= delItem(hWndHeader
, -2);
778 ok(res
== 0, "Deleting Out of Range item should fail with 0 (%d)\n", res
);
779 TEST_GET_ITEMCOUNT(5);
781 res
= delItem(hWndHeader
, 3);
782 ok(res
!= 0, "Deleting using out of range index failed (%d)\n", res
);
783 TEST_GET_ITEMCOUNT(4);
784 res
= delItem(hWndHeader
, 0);
785 ok(res
!= 0, "Deleting using out of range index failed (%d)\n", res
);
786 TEST_GET_ITEMCOUNT(3);
787 res
= delItem(hWndHeader
, 0);
788 ok(res
!= 0, "Deleting using out of range index failed (%d)\n", res
);
789 TEST_GET_ITEMCOUNT(2);
790 res
= delItem(hWndHeader
, 0);
791 ok(res
!= 0, "Deleting using out of range index failed (%d)\n", res
);
792 TEST_GET_ITEMCOUNT(1);
794 DestroyWindow(hWndHeader
);
797 static void test_hdm_getitemrect(HWND hParent
)
804 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
805 hChild
= create_custom_header_control(hParent
, TRUE
);
806 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
807 "adder header control to parent", FALSE
);
809 retVal
= SendMessage(hChild
, HDM_GETITEMRECT
, 1, (LPARAM
) &rect
);
810 ok(retVal
== TRUE
, "Getting item rect should TRUE, got %d\n", retVal
);
811 /* check bounding rectangle information of 2nd header item */
812 expect(80, rect
.left
);
814 expect(160, rect
.right
);
815 expect(g_customheight
, rect
.bottom
);
817 retVal
= SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
) &rect
);
819 ok(retVal
== TRUE
, "Getting item rect should TRUE, got %d\n", retVal
);
820 /* check bounding rectangle information of 1st header item */
821 expect(0, rect
.left
);
824 expect(80, rect
.right
);
825 expect(g_customheight
, rect
.bottom
);
827 retVal
= SendMessage(hChild
, HDM_GETITEMRECT
, 10, (LPARAM
) &rect
);
828 ok(retVal
== 0, "Getting rect of nonexistent item should return 0, got %d\n", retVal
);
830 ok_sequence(sequences
, HEADER_SEQ_INDEX
, getItemRect_seq
, "getItemRect sequence testing", FALSE
);
831 DestroyWindow(hChild
);
834 static void test_hdm_layout(HWND hParent
)
841 hdLayout
.prc
= &rect
;
842 hdLayout
.pwpos
= &windowPos
;
844 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
845 hChild
= create_custom_header_control(hParent
, TRUE
);
846 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
847 "adder header control to parent", FALSE
);
849 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
850 retVal
= SendMessage(hChild
, HDM_LAYOUT
, 0, (LPARAM
) &hdLayout
);
851 expect(TRUE
, retVal
);
853 ok_sequence(sequences
, HEADER_SEQ_INDEX
, layout_seq
, "layout sequence testing", FALSE
);
855 DestroyWindow(hChild
);
858 static void test_hdm_ordertoindex(HWND hParent
)
863 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
864 hChild
= create_custom_header_control(hParent
, TRUE
);
865 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
866 "adder header control to parent", FALSE
);
868 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
869 retVal
= SendMessage(hChild
, HDM_ORDERTOINDEX
, 1, 0);
872 ok_sequence(sequences
, HEADER_SEQ_INDEX
, orderToIndex_seq
, "orderToIndex sequence testing", FALSE
);
873 DestroyWindow(hChild
);
876 static void test_hdm_hittest(HWND hParent
)
881 HDHITTESTINFO hdHitTestInfo
;
882 const int firstItemRightBoundary
= 80;
883 const int secondItemRightBoundary
= 160;
884 const int bottomBoundary
= g_customheight
;
886 pt
.x
= firstItemRightBoundary
- 1;
887 pt
.y
= bottomBoundary
- 1;
888 hdHitTestInfo
.pt
= pt
;
891 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
892 hChild
= create_custom_header_control(hParent
, TRUE
);
893 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
894 "adder header control to parent", FALSE
);
896 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
897 retVal
= SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
) &hdHitTestInfo
);
899 expect(0, hdHitTestInfo
.iItem
);
900 expect(HHT_ONDIVIDER
, hdHitTestInfo
.flags
);
902 pt
.x
= secondItemRightBoundary
- 1;
903 pt
.y
= bottomBoundary
- 1;
904 hdHitTestInfo
.pt
= pt
;
905 retVal
= SendMessage(hChild
, HDM_HITTEST
, 1, (LPARAM
) &hdHitTestInfo
);
907 expect(1, hdHitTestInfo
.iItem
);
908 expect(HHT_ONDIVIDER
, hdHitTestInfo
.flags
);
910 pt
.x
= secondItemRightBoundary
;
911 pt
.y
= bottomBoundary
+ 1;
912 hdHitTestInfo
.pt
= pt
;
913 retVal
= SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
) &hdHitTestInfo
);
915 expect(-1, hdHitTestInfo
.iItem
);
916 expect(HHT_BELOW
, hdHitTestInfo
.flags
);
918 ok_sequence(sequences
, HEADER_SEQ_INDEX
, hittest_seq
, "hittest sequence testing", FALSE
);
920 DestroyWindow(hChild
);
923 static void test_hdm_sethotdivider(HWND hParent
)
927 /* low word: x coordinate = 5
928 * high word: y coordinate = 5
931 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
932 hChild
= create_custom_header_control(hParent
, TRUE
);
933 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
934 "adder header control to parent", FALSE
);
936 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
937 retVal
= SendMessage(hChild
, HDM_SETHOTDIVIDER
, TRUE
, MAKELPARAM(5, 5));
940 retVal
= SendMessage(hChild
, HDM_SETHOTDIVIDER
, FALSE
, 100);
942 retVal
= SendMessage(hChild
, HDM_SETHOTDIVIDER
, FALSE
, 1);
944 if (winetest_interactive
)
945 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setHotDivider_seq_interactive
,
946 "setHotDivider sequence testing", TRUE
);
948 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setHotDivider_seq_noninteractive
,
949 "setHotDivider sequence testing", FALSE
);
951 DestroyWindow(hChild
);
954 static void test_hdm_imageMessages(HWND hParent
)
956 HIMAGELIST hImageList
= ImageList_Create (4, 4, 0, 1, 0);
960 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
961 hChild
= create_custom_header_control(hParent
, TRUE
);
962 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
963 "adder header control to parent", FALSE
);
965 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
967 hIml
= (HIMAGELIST
) SendMessage(hChild
, HDM_SETIMAGELIST
, 0, (LPARAM
) hImageList
);
968 ok(hIml
== NULL
, "Expected NULL, got %p\n", hIml
);
970 hIml
= (HIMAGELIST
) SendMessage(hChild
, HDM_GETIMAGELIST
, 0, 0);
971 ok(hIml
!= NULL
, "Expected non-NULL handle, got %p\n", hIml
);
973 hIml
= (HIMAGELIST
) SendMessage(hChild
, HDM_CREATEDRAGIMAGE
, 0, 0);
974 ok(hIml
!= NULL
, "Expected non-NULL handle, got %p\n", hIml
);
975 ImageList_Destroy(hIml
);
977 ok_sequence(sequences
, HEADER_SEQ_INDEX
, imageMessages_seq
, "imageMessages sequence testing", FALSE
);
979 DestroyWindow(hChild
);
982 static void test_hdm_filterMessages(HWND hParent
)
987 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
988 hChild
= create_custom_header_control(hParent
, TRUE
);
990 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
991 "adder header control to parent", FALSE
);
993 timeout
= SendMessage(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, 100);
994 SendMessage(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, timeout
);
996 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
998 /* msdn incorrectly states that return value
999 * is the index of the filter control being
1000 * modified. The sendMessage here should
1001 * return previous filter timeout value
1004 retVal
= SendMessage(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, 100);
1005 expect(timeout
, retVal
);
1009 retVal
= SendMessage(hChild
, HDM_CLEARFILTER
, 0, 1);
1011 win_skip("HDM_CLEARFILTER needs 5.80\n");
1015 retVal
= SendMessage(hChild
, HDM_EDITFILTER
, 1, 0);
1017 win_skip("HDM_EDITFILTER needs 5.80\n");
1021 if (winetest_interactive
)
1022 ok_sequence(sequences
, HEADER_SEQ_INDEX
, filterMessages_seq_interactive
,
1023 "filterMessages sequence testing", TRUE
);
1025 ok_sequence(sequences
, HEADER_SEQ_INDEX
, filterMessages_seq_noninteractive
,
1026 "filterMessages sequence testing", FALSE
);
1027 /* Some Win9x versions don't send a WM_KILLFOCUS.
1028 * Set the focus explicitly to the parent to avoid a crash.
1031 DestroyWindow(hChild
);
1035 static void test_hdm_unicodeformatMessages(HWND hParent
)
1040 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1041 hChild
= create_custom_header_control(hParent
, TRUE
);
1042 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1043 "adder header control to parent", FALSE
);
1045 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1046 retVal
= SendMessage(hChild
, HDM_SETUNICODEFORMAT
, TRUE
, 0);
1048 retVal
= SendMessage(hChild
, HDM_GETUNICODEFORMAT
, 0, 0);
1051 ok_sequence(sequences
, HEADER_SEQ_INDEX
, unicodeformatMessages_seq
,
1052 "unicodeformatMessages sequence testing", FALSE
);
1053 DestroyWindow(hChild
);
1056 static void test_hdm_bitmapmarginMessages(HWND hParent
)
1061 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1062 hChild
= create_custom_header_control(hParent
, TRUE
);
1063 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1064 "adder header control to parent", FALSE
);
1066 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1067 retVal
= SendMessage(hChild
, HDM_GETBITMAPMARGIN
, 0, 0);
1069 win_skip("HDM_GETBITMAPMARGIN needs 5.80\n");
1073 ok_sequence(sequences
, HEADER_SEQ_INDEX
, bitmapmarginMessages_seq
,
1074 "bitmapmarginMessages sequence testing", FALSE
);
1075 DestroyWindow(hChild
);
1078 static void test_hdm_index_messages(HWND hParent
)
1085 static const int lpiarray
[2] = {1, 0};
1086 static int lpiarrayReceived
[2];
1087 static char firstHeaderItem
[] = "Name";
1088 static char secondHeaderItem
[] = "Size";
1089 static char thirdHeaderItem
[] = "Type";
1090 static char fourthHeaderItem
[] = "Date Modified";
1091 static char *items
[] = {firstHeaderItem
, secondHeaderItem
, thirdHeaderItem
, fourthHeaderItem
};
1094 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
| HDI_FORMAT
;
1095 hdItem
.fmt
= HDF_LEFT
;
1097 hdItem
.cchTextMax
= 260;
1099 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1100 hChild
= create_custom_header_control(hParent
, FALSE
);
1101 if (winetest_interactive
)
1102 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq_interactive
,
1103 "adder header control to parent", TRUE
);
1105 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1106 "adder header control to parent", FALSE
);
1107 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1108 for ( loopcnt
= 0 ; loopcnt
< 4 ; loopcnt
++ )
1110 hdItem
.pszText
= items
[loopcnt
];
1111 retVal
= SendMessage(hChild
, HDM_INSERTITEM
, loopcnt
, (LPARAM
) &hdItem
);
1112 ok(retVal
== loopcnt
, "Adding item %d failed with return value %d\n", ( loopcnt
+ 1 ), retVal
);
1114 ok_sequence(sequences
, HEADER_SEQ_INDEX
, insertItem_seq
, "insertItem sequence testing", FALSE
);
1116 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1118 retVal
= SendMessage(hChild
, HDM_DELETEITEM
, 3, (LPARAM
) &hdItem
);
1119 ok(retVal
== TRUE
, "Deleting item 3 should return TRUE, got %d\n", retVal
);
1120 retVal
= SendMessage(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1121 ok(retVal
== 3, "Getting item count should return 3, got %d\n", retVal
);
1123 retVal
= SendMessage(hChild
, HDM_DELETEITEM
, 3, (LPARAM
) &hdItem
);
1124 ok(retVal
== FALSE
, "Deleting already-deleted item should return FALSE, got %d\n", retVal
);
1125 retVal
= SendMessage(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1126 ok(retVal
== 3, "Getting item count should return 3, got %d\n", retVal
);
1128 retVal
= SendMessage(hChild
, HDM_DELETEITEM
, 2, (LPARAM
) &hdItem
);
1129 ok(retVal
== TRUE
, "Deleting item 2 should return TRUE, got %d\n", retVal
);
1130 retVal
= SendMessage(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1131 ok(retVal
== 2, "Getting item count should return 2, got %d\n", retVal
);
1133 ok_sequence(sequences
, HEADER_SEQ_INDEX
, deleteItem_getItemCount_seq
,
1134 "deleteItem_getItemCount sequence testing", FALSE
);
1136 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1138 retVal
= SendMessage(hChild
, HDM_GETITEM
, 3, (LPARAM
) &hdItem
);
1139 ok(retVal
== FALSE
, "Getting already-deleted item should return FALSE, got %d\n", retVal
);
1141 retVal
= SendMessage(hChild
, HDM_GETITEM
, 0, (LPARAM
) &hdItem
);
1142 ok(retVal
== TRUE
, "Getting the 1st header item should return TRUE, got %d\n", retVal
);
1144 ok_sequence(sequences
, HEADER_SEQ_INDEX
, getItem_seq
, "getItem sequence testing", FALSE
);
1146 /* check if the item is the right one */
1147 strcmpResult
= strcmp(hdItem
.pszText
, firstHeaderItem
);
1148 expect(0, strcmpResult
);
1149 expect(80, hdItem
.cxy
);
1151 iSize
= SendMessage(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1153 /* item should be updated just after accepting new array */
1154 ShowWindow(hChild
, SW_HIDE
);
1155 retVal
= SendMessage(hChild
, HDM_SETORDERARRAY
, iSize
, (LPARAM
) lpiarray
);
1156 expect(TRUE
, retVal
);
1158 retVal
= SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
) &rect
);
1159 expect(TRUE
, retVal
);
1160 ok(rect
.left
!= 0, "Expected updated rectangle\n");
1162 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1164 retVal
= SendMessage(hChild
, HDM_SETORDERARRAY
, iSize
, (LPARAM
) lpiarray
);
1165 ok(retVal
== TRUE
, "Setting header items order should return TRUE, got %d\n", retVal
);
1167 retVal
= SendMessage(hChild
, HDM_GETORDERARRAY
, iSize
, (LPARAM
) lpiarrayReceived
);
1168 ok(retVal
== TRUE
, "Getting header items order should return TRUE, got %d\n", retVal
);
1170 ok_sequence(sequences
, HEADER_SEQ_INDEX
, orderArray_seq
, "set_get_orderArray sequence testing", FALSE
);
1172 /* check if the array order is set correctly and the size of the array is correct. */
1174 expect(lpiarray
[0], lpiarrayReceived
[0]);
1175 expect(lpiarray
[1], lpiarrayReceived
[1]);
1177 hdItem
.mask
= HDI_FORMAT
;
1178 hdItem
.fmt
= HDF_CENTER
| HDF_STRING
;
1180 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1182 retVal
= SendMessage(hChild
, HDM_SETITEM
, 0, (LPARAM
) &hdItem
);
1183 ok(retVal
== TRUE
, "Aligning 1st header item to center should return TRUE, got %d\n", retVal
);
1184 hdItem
.fmt
= HDF_RIGHT
| HDF_STRING
;
1185 retVal
= SendMessage(hChild
, HDM_SETITEM
, 1, (LPARAM
) &hdItem
);
1186 ok(retVal
== TRUE
, "Aligning 2nd header item to right should return TRUE, got %d\n", retVal
);
1188 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setItem_seq
, "setItem sequence testing", FALSE
);
1189 DestroyWindow(hChild
);
1192 static void test_hdf_fixedwidth(HWND hParent
)
1200 hChild
= create_custom_header_control(hParent
, FALSE
);
1202 hdItem
.mask
= HDI_WIDTH
| HDI_FORMAT
;
1203 hdItem
.fmt
= HDF_FIXEDWIDTH
;
1206 ret
= SendMessage(hChild
, HDM_INSERTITEM
, 0, (LPARAM
)&hdItem
);
1209 /* try to change width */
1210 rect
.right
= rect
.bottom
= 0;
1211 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1212 ok(rect
.right
!= 0, "Expected not zero width\n");
1213 ok(rect
.bottom
!= 0, "Expected not zero height\n");
1215 SendMessage(hChild
, WM_LBUTTONDOWN
, 0, MAKELPARAM(rect
.right
, rect
.bottom
/ 2));
1216 SendMessage(hChild
, WM_MOUSEMOVE
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1217 SendMessage(hChild
, WM_LBUTTONUP
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1219 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1221 if (hdItem
.cxy
!= rect
.right
)
1223 win_skip("HDF_FIXEDWIDTH format not supported\n");
1224 DestroyWindow(hChild
);
1228 /* try to adjust with message */
1229 hdItem
.mask
= HDI_WIDTH
;
1232 ret
= SendMessage(hChild
, HDM_SETITEM
, 0, (LPARAM
)&hdItem
);
1236 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1237 expect(90, rect
.right
);
1239 /* hittesting doesn't report ondivider flag for HDF_FIXEDWIDTH */
1240 ht
.pt
.x
= rect
.right
- 1;
1241 ht
.pt
.y
= rect
.bottom
/ 2;
1242 SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1243 expect(HHT_ONHEADER
, ht
.flags
);
1245 /* try to adjust with message */
1246 hdItem
.mask
= HDI_FORMAT
;
1249 ret
= SendMessage(hChild
, HDM_SETITEM
, 0, (LPARAM
)&hdItem
);
1253 ht
.pt
.y
= rect
.bottom
/ 2;
1254 SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1255 expect(HHT_ONDIVIDER
, ht
.flags
);
1257 DestroyWindow(hChild
);
1260 static void test_hds_nosizing(HWND hParent
)
1268 hChild
= create_custom_header_control(hParent
, FALSE
);
1270 memset(&hdItem
, 0, sizeof(hdItem
));
1271 hdItem
.mask
= HDI_WIDTH
;
1274 ret
= SendMessage(hChild
, HDM_INSERTITEM
, 0, (LPARAM
)&hdItem
);
1277 /* HDS_NOSIZING only blocks hittesting */
1278 ret
= GetWindowLong(hChild
, GWL_STYLE
);
1279 SetWindowLong(hChild
, GWL_STYLE
, ret
| HDS_NOSIZING
);
1281 /* try to change width with mouse gestures */
1282 rect
.right
= rect
.bottom
= 0;
1283 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1284 ok(rect
.right
!= 0, "Expected not zero width\n");
1285 ok(rect
.bottom
!= 0, "Expected not zero height\n");
1287 SendMessage(hChild
, WM_LBUTTONDOWN
, 0, MAKELPARAM(rect
.right
, rect
.bottom
/ 2));
1288 SendMessage(hChild
, WM_MOUSEMOVE
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1289 SendMessage(hChild
, WM_LBUTTONUP
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1291 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1293 if (hdItem
.cxy
!= rect
.right
)
1295 win_skip("HDS_NOSIZING style not supported\n");
1296 DestroyWindow(hChild
);
1300 /* this style doesn't set HDF_FIXEDWIDTH for items */
1301 hdItem
.mask
= HDI_FORMAT
;
1302 ret
= SendMessage(hChild
, HDM_GETITEM
, 0, (LPARAM
)&hdItem
);
1304 ok(!(hdItem
.fmt
& HDF_FIXEDWIDTH
), "Unexpected HDF_FIXEDWIDTH\n");
1306 /* try to adjust with message */
1307 hdItem
.mask
= HDI_WIDTH
;
1310 ret
= SendMessage(hChild
, HDM_SETITEM
, 0, (LPARAM
)&hdItem
);
1314 SendMessage(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1315 expect(90, rect
.right
);
1317 /* hittesting doesn't report ondivider flags for HDS_NOSIZING */
1318 ht
.pt
.x
= rect
.right
- 1;
1319 ht
.pt
.y
= rect
.bottom
/ 2;
1320 SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1321 expect(HHT_ONHEADER
, ht
.flags
);
1323 /* try to adjust with message */
1324 ret
= GetWindowLong(hChild
, GWL_STYLE
);
1325 SetWindowLong(hChild
, GWL_STYLE
, ret
& ~HDS_NOSIZING
);
1328 ht
.pt
.y
= rect
.bottom
/ 2;
1329 SendMessage(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1330 expect(HHT_ONDIVIDER
, ht
.flags
);
1332 DestroyWindow(hChild
);
1335 #define TEST_NMCUSTOMDRAW(draw_stage, item_spec, lparam, _left, _top, _right, _bottom) \
1336 ok(nm->dwDrawStage == draw_stage, "Invalid dwDrawStage %d vs %d\n", draw_stage, nm->dwDrawStage); \
1337 if (item_spec != -1) \
1338 ok(nm->dwItemSpec == item_spec, "Invalid dwItemSpec %d vs %ld\n", item_spec, nm->dwItemSpec); \
1339 ok(nm->lItemlParam == lparam, "Invalid lItemlParam %d vs %ld\n", lparam, nm->lItemlParam); \
1340 ok((nm->rc.top == _top && nm->rc.bottom == _bottom && nm->rc.left == _left && nm->rc.right == _right) || \
1341 broken(draw_stage != CDDS_ITEMPREPAINT), /* comctl32 < 5.80 */ \
1342 "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", _left, _top, _right, _bottom, \
1343 nm->rc.left, nm->rc.top, nm->rc.right, nm->rc.bottom);
1345 static LRESULT
customdraw_1(int n
, NMCUSTOMDRAW
*nm
)
1347 if (nm
== NULL
) { /* test ended */
1348 ok(n
==1, "NM_CUSTOMDRAW messages: %d, expected: 1\n", n
);
1355 /* don't test dwItemSpec - it's 0 no comctl5 but 1308756 on comctl6 */
1356 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1360 ok(FALSE
, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n
, nm
->dwDrawStage
);
1364 static LRESULT
customdraw_2(int n
, NMCUSTOMDRAW
*nm
)
1366 if (nm
== NULL
) { /* test ended */
1367 ok(n
==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n
);
1374 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1375 return CDRF_NOTIFYITEMDRAW
;
1377 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1380 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 1, 5, 50, 0, 150, g_customheight
);
1383 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1387 ok(FALSE
, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n
, nm
->dwDrawStage
);
1391 static LRESULT
customdraw_3(int n
, NMCUSTOMDRAW
*nm
)
1393 if (nm
== NULL
) { /* test ended */
1394 ok(n
==5, "NM_CUSTOMDRAW messages: %d, expected: 5\n", n
);
1401 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1402 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTERASE
|CDRF_NOTIFYPOSTPAINT
|CDRF_SKIPDEFAULT
;
1404 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1407 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 1, 5, 50, 0, 150, g_customheight
);
1410 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1413 TEST_NMCUSTOMDRAW(CDDS_POSTPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1417 ok(FALSE
, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n
, nm
->dwDrawStage
);
1422 static LRESULT
customdraw_4(int n
, NMCUSTOMDRAW
*nm
)
1424 if (nm
== NULL
) { /* test ended */
1425 ok(n
==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n
);
1432 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1433 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
1435 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1438 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1441 TEST_NMCUSTOMDRAW(CDDS_POSTPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1445 ok(FALSE
, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n
, nm
->dwDrawStage
);
1449 static void run_customdraw_scenario(CUSTOMDRAWPROC proc
)
1451 g_CustomDrawProc
= proc
;
1452 g_CustomDrawCount
= 0;
1453 InvalidateRect(hWndHeader
, NULL
, TRUE
);
1454 UpdateWindow(hWndHeader
);
1455 proc(g_CustomDrawCount
, NULL
);
1456 g_CustomDrawProc
= NULL
;
1459 static void test_customdraw(void)
1464 CHAR name
[] = "Test";
1465 hWndHeader
= create_header_control();
1466 GetClientRect(hWndHeader
, &rect
);
1467 ok(rect
.right
- rect
.left
== 670 && rect
.bottom
- rect
.top
== g_customheight
,
1468 "Tests will fail as header size is %dx%d instead of 670x%d\n",
1469 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, g_customheight
);
1471 for (i
= 0; i
< 3; i
++)
1473 ZeroMemory(&item
, sizeof(item
));
1474 item
.mask
= HDI_TEXT
|HDI_WIDTH
;
1475 item
.cxy
= 50*(i
+1);
1476 item
.pszText
= name
;
1478 SendMessage(hWndHeader
, HDM_INSERTITEM
, i
, (LPARAM
)&item
);
1481 run_customdraw_scenario(customdraw_1
);
1482 run_customdraw_scenario(customdraw_2
);
1483 run_customdraw_scenario(customdraw_3
);
1485 ZeroMemory(&item
, sizeof(item
));
1486 item
.mask
= HDI_FORMAT
;
1487 item
.fmt
= HDF_OWNERDRAW
;
1488 SendMessage(hWndHeader
, HDM_SETITEM
, 1, (LPARAM
)&item
);
1489 g_DrawItem
.CtlID
= 0;
1490 g_DrawItem
.CtlType
= ODT_HEADER
;
1491 g_DrawItem
.hwndItem
= hWndHeader
;
1492 g_DrawItem
.itemID
= 1;
1493 g_DrawItem
.itemState
= 0;
1494 SendMessage(hWndHeader
, HDM_GETITEMRECT
, 1, (LPARAM
)&g_DrawItem
.rcItem
);
1495 run_customdraw_scenario(customdraw_4
);
1496 ok(g_DrawItemReceived
, "WM_DRAWITEM not received\n");
1497 DestroyWindow(hWndHeader
);
1499 g_DrawItem
.CtlType
= 0;
1500 g_DrawItemReceived
= FALSE
;
1503 static void check_order(const int expected_id
[], const int expected_order
[],
1504 int count
, const char *type
)
1509 ok(getItemCount(hWndHeader
) == count
, "Invalid item count in order tests\n");
1510 for (i
= 0; i
< count
; i
++)
1512 hdi
.mask
= HDI_LPARAM
|HDI_ORDER
;
1513 SendMessage(hWndHeader
, HDM_GETITEMA
, i
, (LPARAM
)&hdi
);
1514 ok(hdi
.lParam
== expected_id
[i
],
1515 "Invalid item ids after '%s'- item %d has lParam %d\n", type
, i
, (int)hdi
.lParam
);
1516 ok(hdi
.iOrder
== expected_order
[i
],
1517 "Invalid item order after '%s'- item %d has iOrder %d\n", type
, i
, hdi
.iOrder
);
1521 static void test_header_order (void)
1523 const int rand1
[] = {0, 1, 1, 0, 4};
1524 const int rand2
[] = {4, 5, 6, 7, 4};
1525 const int rand3
[] = {5, 5, 1, 6, 1};
1526 const int rand4
[] = {1, 5, 2, 7, 6, 1, 4, 2, 3, 2};
1527 const int rand5
[] = {7, 8, 5, 6, 7, 2, 1, 9, 10, 10};
1528 const int rand6
[] = {2, 8, 3, 4, 0};
1530 const int ids1
[] = {3, 0, 2, 1, 4};
1531 const int ord1
[] = {0, 1, 2, 3, 4};
1532 const int ids2
[] = {3, 9, 7, 0, 2, 1, 4, 8, 6, 5};
1533 const int ord2
[] = {0, 4, 7, 1, 2, 3, 9, 8, 6, 5};
1534 const int ord3
[] = {0, 3, 9, 2, 1, 8, 7, 6, 5, 4};
1535 const int ids4
[] = {9, 0, 1, 8, 6};
1536 const int ord4
[] = {1, 0, 4, 3, 2};
1542 hWndHeader
= create_header_control();
1544 ZeroMemory(&hdi
, sizeof(HDITEMA
));
1545 hdi
.mask
= HDI_TEXT
| HDI_LPARAM
;
1546 hdi
.pszText
= buffer
;
1547 strcpy(buffer
, "test");
1549 for (i
= 0; i
< 5; i
++)
1552 SendMessage(hWndHeader
, HDM_INSERTITEMA
, rand1
[i
], (LPARAM
)&hdi
);
1555 check_order(ids1
, ord1
, 5, "insert without iOrder");
1557 hdi
.mask
|= HDI_ORDER
;
1558 for (i
= 0; i
< 5; i
++)
1561 hdi
.iOrder
= rand2
[i
];
1562 SendMessage(hWndHeader
, HDM_INSERTITEMA
, rand3
[i
], (LPARAM
)&hdi
);
1565 check_order(ids2
, ord2
, 10, "insert with order");
1567 hdi
.mask
= HDI_ORDER
;
1568 for (i
=0; i
<10; i
++)
1570 hdi
.iOrder
= rand5
[i
];
1571 SendMessage(hWndHeader
, HDM_SETITEMA
, rand4
[i
], (LPARAM
)&hdi
);
1574 check_order(ids2
, ord3
, 10, "setitems changing order");
1577 SendMessage(hWndHeader
, HDM_DELETEITEM
, rand6
[i
], 0);
1578 check_order(ids4
, ord4
, 5, "deleteitem");
1580 DestroyWindow(hWndHeader
);
1583 static LRESULT CALLBACK
HeaderTestWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1590 NMHEADERA
*hdr
= (NMHEADER
*)lParam
;
1591 EXPECTEDNOTIFY
*expected
;
1594 if (hdr
->hdr
.code
== NM_CUSTOMDRAW
)
1595 if (g_CustomDrawProc
)
1596 return g_CustomDrawProc(g_CustomDrawCount
++, (NMCUSTOMDRAW
*)hdr
);
1598 for (i
=0; i
<nUnexpectedNotify
; i
++)
1599 ok(hdr
->hdr
.code
!= unexpectedNotify
[i
], "Received invalid notify %d\n", hdr
->hdr
.code
);
1601 if (nReceivedNotify
>= nExpectedNotify
|| hdr
->hdr
.hwndFrom
!= hWndHeader
)
1604 expected
= &expectedNotify
[nReceivedNotify
];
1605 if (hdr
->hdr
.code
!= expected
->iCode
)
1609 compare_items(hdr
->hdr
.code
, &expected
->hdItem
, hdr
->pitem
, expected
->fUnicode
);
1614 di
= (DRAWITEMSTRUCT
*)lParam
;
1615 ok(g_DrawItem
.CtlType
!= 0, "Unexpected WM_DRAWITEM\n");
1616 if (g_DrawItem
.CtlType
== 0) return 0;
1617 g_DrawItemReceived
= TRUE
;
1618 compare(di
->CtlType
, g_DrawItem
.CtlType
, "%d");
1619 compare(di
->CtlID
, g_DrawItem
.CtlID
, "%d");
1620 compare(di
->hwndItem
, g_DrawItem
.hwndItem
, "%p");
1621 compare(di
->itemID
, g_DrawItem
.itemID
, "%d");
1622 compare(di
->itemState
, g_DrawItem
.itemState
, "%d");
1623 compare(di
->rcItem
.left
, g_DrawItem
.rcItem
.left
, "%d");
1624 compare(di
->rcItem
.top
, g_DrawItem
.rcItem
.top
, "%d");
1625 compare(di
->rcItem
.right
, g_DrawItem
.rcItem
.right
, "%d");
1626 compare(di
->rcItem
.bottom
, g_DrawItem
.rcItem
.bottom
, "%d");
1634 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
1640 static int init(void)
1643 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
1645 INITCOMMONCONTROLSEX iccex
;
1650 hComctl32
= GetModuleHandleA("comctl32.dll");
1651 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
1652 if (!pInitCommonControlsEx
)
1654 skip("InitCommonControlsEx() is missing. Skipping the tests\n");
1658 iccex
.dwSize
= sizeof(iccex
);
1659 iccex
.dwICC
= ICC_USEREX_CLASSES
;
1660 pInitCommonControlsEx(&iccex
);
1662 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1665 wc
.hInstance
= GetModuleHandleA(NULL
);
1667 wc
.hCursor
= LoadCursorA(NULL
, IDC_ARROW
);
1668 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
1669 wc
.lpszMenuName
= NULL
;
1670 wc
.lpszClassName
= "HeaderTestClass";
1671 wc
.lpfnWndProc
= HeaderTestWndProc
;
1672 RegisterClassA(&wc
);
1674 /* The height of the header control depends on the height of the system font.
1675 The height of the system font is dpi dependent */
1677 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
1678 GetTextMetricsA(hdc
, &tm
);
1679 /* 2 dot extra space are needed for the border */
1680 g_customheight
= tm
.tmHeight
+ 2;
1681 trace("customdraw height: %d (dpi: %d)\n", g_customheight
, GetDeviceCaps(hdc
, LOGPIXELSY
));
1682 SelectObject(hdc
, hOldFont
);
1685 hHeaderParentWnd
= CreateWindowExA(0, "HeaderTestClass", "Header test", WS_OVERLAPPEDWINDOW
,
1686 CW_USEDEFAULT
, CW_USEDEFAULT
, 672+2*GetSystemMetrics(SM_CXSIZEFRAME
),
1687 226+GetSystemMetrics(SM_CYCAPTION
)+2*GetSystemMetrics(SM_CYSIZEFRAME
),
1688 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1689 assert(hHeaderParentWnd
!= NULL
);
1690 ShowWindow(hHeaderParentWnd
, SW_SHOW
);
1694 /* maximum 8 items allowed */
1695 static void check_orderarray(HWND hwnd
, DWORD start
, DWORD set
, DWORD expected
,
1700 DWORD ret
, array
= 0;
1702 count
= SendMessage(hwnd
, HDM_GETITEMCOUNT
, 0, 0);
1705 for(i
= 1; i
<=count
; i
++)
1706 order
[i
-1] = start
>>(4*(count
-i
)) & 0xf;
1708 ret
= SendMessage(hwnd
, HDM_SETORDERARRAY
, count
, (LPARAM
)order
);
1709 ok_(__FILE__
, line
)(ret
, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret
);
1712 for(i
= 1; i
<=count
; i
++)
1713 order
[i
-1] = set
>>(4*(count
-i
)) & 0xf;
1714 ret
= SendMessage(hwnd
, HDM_SETORDERARRAY
, count
, (LPARAM
)order
);
1715 ok_(__FILE__
, line
)(ret
, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret
);
1717 /* check actual order */
1718 ret
= SendMessage(hwnd
, HDM_GETORDERARRAY
, count
, (LPARAM
)order
);
1719 ok_(__FILE__
, line
)(ret
, "Expected HDM_GETORDERARAY to succeed, got %d\n", ret
);
1720 for(i
= 1; i
<=count
; i
++)
1721 array
|= order
[i
-1]<<(4*(count
-i
));
1725 ok_(__FILE__
, line
)(array
== expected
, "Expected %x, got %x\n", expected
, array
);
1728 ok_(__FILE__
, line
)(array
== expected
, "Expected %x, got %x\n", expected
, array
);
1731 static void test_hdm_orderarray(void)
1737 hwnd
= create_header_control();
1740 addItem(hwnd
, 0, NULL
);
1741 addItem(hwnd
, 1, NULL
);
1742 addItem(hwnd
, 2, NULL
);
1744 ret
= SendMessage(hwnd
, HDM_GETORDERARRAY
, 3, (LPARAM
)order
);
1747 win_skip("HDM_GETORDERARRAY not implemented.\n");
1748 DestroyWindow(hwnd
);
1752 expect(0, order
[0]);
1753 expect(1, order
[1]);
1754 expect(2, order
[2]);
1758 /* null pointer, crashes native */
1759 ret
= SendMessage(hwnd
, HDM_SETORDERARRAY
, 3, 0);
1762 /* count out of limits */
1763 ret
= SendMessage(hwnd
, HDM_SETORDERARRAY
, 5, (LPARAM
)order
);
1765 /* count out of limits */
1766 ret
= SendMessage(hwnd
, HDM_SETORDERARRAY
, 2, (LPARAM
)order
);
1769 /* try with out of range item index */
1770 /* (0,1,2)->(1,0,3) => (1,0,2) */
1771 check_orderarray(hwnd
, 0x120, 0x103, 0x102, FALSE
, __LINE__
);
1772 /* (1,0,2)->(3,0,1) => (0,2,1) */
1773 check_orderarray(hwnd
, 0x102, 0x301, 0x021, TRUE
, __LINE__
);
1774 /* (0,2,1)->(2,3,1) => (2,0,1) */
1775 check_orderarray(hwnd
, 0x021, 0x231, 0x201, FALSE
, __LINE__
);
1777 /* (0,1,2)->(0,2,2) => (0,1,2) */
1778 check_orderarray(hwnd
, 0x012, 0x022, 0x012, FALSE
, __LINE__
);
1780 addItem(hwnd
, 3, NULL
);
1782 /* (0,1,2,3)->(0,1,2,2) => (0,1,3,2) */
1783 check_orderarray(hwnd
, 0x0123, 0x0122, 0x0132, FALSE
, __LINE__
);
1784 /* (0,1,2,3)->(0,1,3,3) => (0,1,2,3) */
1785 check_orderarray(hwnd
, 0x0123, 0x0133, 0x0123, FALSE
, __LINE__
);
1786 /* (0,1,2,3)->(0,4,2,3) => (0,1,2,3) */
1787 check_orderarray(hwnd
, 0x0123, 0x0423, 0x0123, FALSE
, __LINE__
);
1788 /* (0,1,2,3)->(4,0,1,2) => (0,1,3,2) */
1789 check_orderarray(hwnd
, 0x0123, 0x4012, 0x0132, TRUE
, __LINE__
);
1790 /* (0,1,3,2)->(4,0,1,4) => (0,3,1,2) */
1791 check_orderarray(hwnd
, 0x0132, 0x4014, 0x0312, TRUE
, __LINE__
);
1792 /* (0,1,2,3)->(4,1,0,2) => (1,0,3,2) */
1793 check_orderarray(hwnd
, 0x0123, 0x4102, 0x1032, TRUE
, __LINE__
);
1794 /* (0,1,2,3)->(0,1,4,2) => (0,1,2,3) */
1795 check_orderarray(hwnd
, 0x0123, 0x0142, 0x0132, FALSE
, __LINE__
);
1796 /* (0,1,2,3)->(4,4,4,4) => (0,1,2,3) */
1797 check_orderarray(hwnd
, 0x0123, 0x4444, 0x0123, FALSE
, __LINE__
);
1798 /* (0,1,2,3)->(4,4,1,2) => (0,1,3,2) */
1799 check_orderarray(hwnd
, 0x0123, 0x4412, 0x0132, TRUE
, __LINE__
);
1800 /* (0,1,2,3)->(4,4,4,1) => (0,2,3,1) */
1801 check_orderarray(hwnd
, 0x0123, 0x4441, 0x0231, TRUE
, __LINE__
);
1802 /* (0,1,2,3)->(1,4,4,4) => (1,0,2,3) */
1803 check_orderarray(hwnd
, 0x0123, 0x1444, 0x1023, FALSE
, __LINE__
);
1804 /* (0,1,2,3)->(4,2,4,1) => (0,2,3,1) */
1805 check_orderarray(hwnd
, 0x0123, 0x4241, 0x0231, FALSE
, __LINE__
);
1806 /* (0,1,2,3)->(4,2,0,1) => (2,0,3,1) */
1807 check_orderarray(hwnd
, 0x0123, 0x4201, 0x2031, TRUE
, __LINE__
);
1808 /* (3,2,1,0)->(4,2,0,1) => (3,2,0,1) */
1809 check_orderarray(hwnd
, 0x3210, 0x4201, 0x3201, FALSE
, __LINE__
);
1811 DestroyWindow(hwnd
);
1817 ULONG_PTR ctx_cookie
;
1824 test_header_control();
1825 test_header_order();
1826 test_hdm_orderarray();
1829 DestroyWindow(hHeaderParentWnd
);
1831 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1832 parent_hwnd
= create_custom_parent_window();
1833 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent windows", FALSE
);
1835 test_hdm_index_messages(parent_hwnd
);
1836 test_hdm_getitemrect(parent_hwnd
);
1837 test_hdm_hittest(parent_hwnd
);
1838 test_hdm_layout(parent_hwnd
);
1839 test_hdm_ordertoindex(parent_hwnd
);
1840 test_hdm_sethotdivider(parent_hwnd
);
1841 test_hdm_imageMessages(parent_hwnd
);
1842 test_hdm_filterMessages(parent_hwnd
);
1843 test_hdm_unicodeformatMessages(parent_hwnd
);
1844 test_hdm_bitmapmarginMessages(parent_hwnd
);
1846 if (!load_v6_module(&ctx_cookie
, &hCtx
))
1848 DestroyWindow(parent_hwnd
);
1852 /* this is a XP SP3 failure workaround */
1853 hwnd
= CreateWindowExA(0, WC_HEADER
, NULL
,
1854 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
1856 parent_hwnd
, NULL
, GetModuleHandleA(NULL
), NULL
);
1858 if (!IsWindow(hwnd
))
1860 win_skip("FIXME: failed to create Header window.\n");
1861 unload_v6_module(ctx_cookie
, hCtx
);
1862 DestroyWindow(parent_hwnd
);
1866 DestroyWindow(hwnd
);
1868 /* comctl32 version 6 tests start here */
1869 test_hdf_fixedwidth(parent_hwnd
);
1870 test_hds_nosizing(parent_hwnd
);
1872 unload_v6_module(ctx_cookie
, hCtx
);
1874 DestroyWindow(parent_hwnd
);