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
25 #include "wine/test.h"
29 static HIMAGELIST (WINAPI
*pImageList_Create
)(int, int, UINT
, int, int);
30 static BOOL (WINAPI
*pImageList_Destroy
)(HIMAGELIST
);
32 typedef struct tagEXPECTEDNOTIFY
39 typedef LRESULT (*CUSTOMDRAWPROC
)(int n
, NMCUSTOMDRAW
*nm
);
41 static CUSTOMDRAWPROC g_CustomDrawProc
;
42 static int g_CustomDrawCount
;
43 static DRAWITEMSTRUCT g_DrawItem
;
44 static BOOL g_DrawItemReceived
;
45 static DWORD g_customheight
;
47 static EXPECTEDNOTIFY expectedNotify
[10];
48 static INT nExpectedNotify
= 0;
49 static INT nReceivedNotify
= 0;
50 static INT unexpectedNotify
[10];
51 static INT nUnexpectedNotify
= 0;
53 static HWND hHeaderParentWnd
;
54 static HWND hWndHeader
;
57 #define compare(val, exp, fmt) ok((val) == (exp), #val " value: " fmt ", expected: " fmt "\n", (val), (exp))
59 #define expect(expected,got) expect_(__LINE__, expected, got)
60 static inline void expect_(unsigned line
, DWORD expected
, DWORD got
)
62 ok_(__FILE__
, line
)(expected
== got
, "Expected %ld, got %ld\n", expected
, got
);
65 #define NUM_MSG_SEQUENCES 2
66 #define PARENT_SEQ_INDEX 0
67 #define HEADER_SEQ_INDEX 1
69 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
71 static const struct message create_parent_wnd_seq
[] = {
72 { WM_GETMINMAXINFO
, sent
},
73 { WM_NCCREATE
, sent
},
74 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
79 static const struct message add_header_to_parent_seq_interactive
[] = {
80 { WM_NOTIFYFORMAT
, sent
|lparam
, 0, NF_QUERY
},
81 { WM_QUERYUISTATE
, sent
},
82 { WM_PARENTNOTIFY
, sent
|wparam
, 1 },
83 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
84 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
85 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
86 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
87 { WM_NCACTIVATE
, sent
|wparam
, 1 },
88 { WM_ACTIVATE
, sent
|wparam
, 1 },
89 { WM_IME_SETCONTEXT
, sent
|defwinproc
|wparam
, 1 },
90 { WM_IME_NOTIFY
, sent
|defwinproc
|wparam
, 2 },
91 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, 0 },
92 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
93 { WM_SIZE
, sent
|wparam
, 0 },
94 { WM_MOVE
, sent
|wparam
, 0 },
98 static const struct message add_header_to_parent_seq
[] = {
99 { WM_NOTIFYFORMAT
, sent
|lparam
, 0, NF_QUERY
},
100 { WM_QUERYUISTATE
, sent
|optional
},
101 { WM_PARENTNOTIFY
, sent
},
105 static const struct message insertItem_seq
[] = {
106 { HDM_INSERTITEMA
, sent
|wparam
, 0 },
107 { HDM_INSERTITEMA
, sent
|wparam
, 1 },
108 { HDM_INSERTITEMA
, sent
|wparam
, 2 },
109 { HDM_INSERTITEMA
, sent
|wparam
, 3 },
113 static const struct message getItem_seq
[] = {
114 { HDM_GETITEMA
, sent
|wparam
, 3 },
115 { HDM_GETITEMA
, sent
|wparam
, 0 },
120 static const struct message deleteItem_getItemCount_seq
[] = {
121 { HDM_DELETEITEM
, sent
|wparam
, 3 },
122 { HDM_GETITEMCOUNT
, sent
},
123 { HDM_DELETEITEM
, sent
|wparam
, 3 },
124 { HDM_GETITEMCOUNT
, sent
},
125 { HDM_DELETEITEM
, sent
|wparam
, 2 },
126 { HDM_GETITEMCOUNT
, sent
},
130 static const struct message orderArray_seq
[] = {
131 { HDM_SETORDERARRAY
, sent
|wparam
, 2 },
132 { HDM_GETORDERARRAY
, sent
|wparam
, 2 },
136 static const struct message setItem_seq
[] = {
137 { HDM_SETITEMA
, sent
|wparam
, 0 },
138 { HDM_SETITEMA
, sent
|wparam
, 1 },
142 static const struct message getItemRect_seq
[] = {
143 { HDM_GETITEMRECT
, sent
|wparam
, 1 },
144 { HDM_GETITEMRECT
, sent
|wparam
, 0 },
145 { HDM_GETITEMRECT
, sent
|wparam
, 10 },
149 static const struct message layout_seq
[] = {
150 { HDM_LAYOUT
, sent
},
154 static const struct message orderToIndex_seq
[] = {
155 { HDM_ORDERTOINDEX
, sent
|wparam
, 1 },
159 static const struct message hittest_seq
[] = {
160 { HDM_HITTEST
, sent
},
161 { HDM_HITTEST
, sent
},
162 { HDM_HITTEST
, sent
},
166 static const struct message setHotDivider_seq_interactive
[] = {
167 { HDM_SETHOTDIVIDER
, sent
|wparam
, TRUE
},
168 { WM_PAINT
, sent
|defwinproc
},
169 { WM_NCPAINT
, sent
|defwinproc
},
170 { WM_ERASEBKGND
, sent
|defwinproc
},
171 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 100 },
172 { WM_PAINT
, sent
|defwinproc
},
173 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 1},
174 { WM_PAINT
, sent
|defwinproc
},
178 static const struct message setHotDivider_seq_noninteractive
[] = {
179 { HDM_SETHOTDIVIDER
, sent
|wparam
, TRUE
},
180 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 100 },
181 { HDM_SETHOTDIVIDER
, sent
|wparam
|lparam
, FALSE
, 1},
185 static const struct message imageMessages_seq
[] = {
186 { HDM_SETIMAGELIST
, sent
},
187 { HDM_GETIMAGELIST
, sent
},
188 { HDM_CREATEDRAGIMAGE
, sent
},
192 static const struct message filterMessages_seq_interactive
[] = {
193 { HDM_SETFILTERCHANGETIMEOUT
, sent
|wparam
|lparam
, 1, 100 },
194 { HDM_CLEARFILTER
, sent
|wparam
|lparam
, 0, 1 },
195 { HDM_EDITFILTER
, sent
|wparam
|lparam
, 1, 0 },
196 { WM_PARENTNOTIFY
, sent
|wparam
|defwinproc
, WM_CREATE
},
197 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
198 { WM_COMMAND
, sent
|defwinproc
},
202 static const struct message filterMessages_seq_noninteractive
[] = {
203 { HDM_SETFILTERCHANGETIMEOUT
, sent
|wparam
|lparam
, 1, 100 },
204 { HDM_CLEARFILTER
, sent
|wparam
|lparam
, 0, 1 },
205 { HDM_EDITFILTER
, sent
|wparam
|lparam
, 1, 0 },
206 { WM_PARENTNOTIFY
, sent
|wparam
|defwinproc
|optional
, WM_CREATE
},
207 { WM_COMMAND
, sent
|defwinproc
|optional
},
211 static const struct message unicodeformatMessages_seq
[] = {
212 { HDM_SETUNICODEFORMAT
, sent
|wparam
, TRUE
},
213 { HDM_GETUNICODEFORMAT
, sent
},
217 static const struct message bitmapmarginMessages_seq
[] = {
218 { HDM_GETBITMAPMARGIN
, sent
},
223 static void expect_notify(INT iCode
, BOOL fUnicode
, HDITEMA
*lpItem
)
225 ok(nExpectedNotify
< 10, "notification count %d\n", nExpectedNotify
);
226 if (nExpectedNotify
< 10)
228 expectedNotify
[nExpectedNotify
].iCode
= iCode
;
229 expectedNotify
[nExpectedNotify
].fUnicode
= fUnicode
;
230 expectedNotify
[nExpectedNotify
].hdItem
= *lpItem
;
235 static void dont_expect_notify(INT iCode
)
237 ok(nExpectedNotify
< 10, "notification count %d\n", nExpectedNotify
);
238 if (nExpectedNotify
< 10)
239 unexpectedNotify
[nUnexpectedNotify
++] = iCode
;
242 static BOOL
notifies_received(void)
244 BOOL fRet
= (nExpectedNotify
== nReceivedNotify
);
245 nExpectedNotify
= nReceivedNotify
= 0;
246 nUnexpectedNotify
= 0;
250 static LONG
addItem(HWND hdex
, int idx
, LPSTR text
)
253 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
;
255 hdItem
.pszText
= text
;
256 hdItem
.cchTextMax
= 0;
257 return SendMessageA(hdex
, HDM_INSERTITEMA
, idx
, (LPARAM
)&hdItem
);
260 static LONG
setItem(HWND hdex
, int idx
, LPSTR text
, BOOL fCheckNotifies
)
264 hdexItem
.mask
= HDI_TEXT
;
265 hdexItem
.pszText
= text
;
266 hdexItem
.cchTextMax
= 0;
269 expect_notify(HDN_ITEMCHANGINGA
, FALSE
, &hdexItem
);
270 expect_notify(HDN_ITEMCHANGEDA
, FALSE
, &hdexItem
);
272 ret
= SendMessageA(hdex
, HDM_SETITEMA
, idx
, (LPARAM
)&hdexItem
);
274 ok(notifies_received(), "setItem(): not all expected notifies were received\n");
278 static LONG
setItemUnicodeNotify(HWND hdex
, int idx
, LPSTR text
, LPWSTR wText
)
283 hdexItem
.mask
= HDI_TEXT
;
284 hdexItem
.pszText
= text
;
285 hdexItem
.cchTextMax
= 0;
287 hdexNotify
.mask
= HDI_TEXT
;
288 hdexNotify
.pszText
= wText
;
290 expect_notify(HDN_ITEMCHANGINGW
, TRUE
, (HDITEMA
*)&hdexNotify
);
291 expect_notify(HDN_ITEMCHANGEDW
, TRUE
, (HDITEMA
*)&hdexNotify
);
292 ret
= SendMessageA(hdex
, HDM_SETITEMA
, idx
, (LPARAM
)&hdexItem
);
293 ok(notifies_received(), "setItemUnicodeNotify(): not all expected notifies were received\n");
297 static LONG
delItem(HWND hdex
, int idx
)
299 return SendMessageA(hdex
, HDM_DELETEITEM
, idx
, 0);
302 static LONG
getItemCount(HWND hdex
)
304 return SendMessageA(hdex
, HDM_GETITEMCOUNT
, 0, 0);
307 static LONG
getItem(HWND hdex
, int idx
, LPSTR textBuffer
)
310 hdItem
.mask
= HDI_TEXT
;
311 hdItem
.pszText
= textBuffer
;
312 hdItem
.cchTextMax
= MAX_CHARS
;
313 return SendMessageA(hdex
, HDM_GETITEMA
, idx
, (LPARAM
)&hdItem
);
316 static void addReadDelItem(HWND hdex
, HDITEMA
*phdiCreate
, int maskRead
, HDITEMA
*phdiRead
)
318 ok(SendMessageA(hdex
, HDM_INSERTITEMA
, 0, (LPARAM
)phdiCreate
)!=-1, "Adding item failed\n");
319 ZeroMemory(phdiRead
, sizeof(HDITEMA
));
320 phdiRead
->mask
= maskRead
;
321 ok(SendMessageA(hdex
, HDM_GETITEMA
, 0, (LPARAM
)phdiRead
)!=0, "Getting item data failed\n");
322 ok(SendMessageA(hdex
, HDM_DELETEITEM
, 0, 0)!=0, "Deleting item failed\n");
325 static HWND
create_header_control (void)
332 handle
= CreateWindowExA(0, WC_HEADERA
, NULL
,
333 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
335 hHeaderParentWnd
, NULL
, NULL
, NULL
);
336 ok(handle
!= NULL
, "failed to create header window\n");
338 if (winetest_interactive
)
339 ShowWindow (hHeaderParentWnd
, SW_SHOW
);
341 GetClientRect(hHeaderParentWnd
,&rectwin
);
342 hlayout
.prc
= &rectwin
;
343 hlayout
.pwpos
= &winpos
;
344 SendMessageA(handle
, HDM_LAYOUT
, 0, (LPARAM
)&hlayout
);
345 SetWindowPos(handle
, winpos
.hwndInsertAfter
, winpos
.x
, winpos
.y
,
346 winpos
.cx
, winpos
.cy
, 0);
351 static void compare_items(INT iCode
, HDITEMA
*hdi1
, HDITEMA
*hdi2
, BOOL fUnicode
)
353 ok(hdi1
->mask
== hdi2
->mask
, "Notify %d mask mismatch (%08x != %08x)\n", iCode
, hdi1
->mask
, hdi2
->mask
);
354 if (hdi1
->mask
& HDI_WIDTH
)
356 ok(hdi1
->cxy
== hdi2
->cxy
, "Notify %d cxy mismatch (%08x != %08x)\n", iCode
, hdi1
->cxy
, hdi2
->cxy
);
358 if (hdi1
->mask
& HDI_TEXT
)
360 if (hdi1
->pszText
== LPSTR_TEXTCALLBACKA
)
362 ok(hdi1
->pszText
== LPSTR_TEXTCALLBACKA
, "Notify %d - only one item is LPSTR_TEXTCALLBACK\n", iCode
);
369 WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)hdi1
->pszText
, -1, buf1
, 260, NULL
, NULL
);
370 WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)hdi2
->pszText
, -1, buf2
, 260, NULL
, NULL
);
371 ok(lstrcmpW((LPWSTR
)hdi1
->pszText
, (LPWSTR
)hdi2
->pszText
)==0,
372 "Notify %d text mismatch (L\"%s\" vs L\"%s\")\n",
377 ok(strcmp(hdi1
->pszText
, hdi2
->pszText
)==0,
378 "Notify %d text mismatch (\"%s\" vs \"%s\")\n",
379 iCode
, hdi1
->pszText
, hdi2
->pszText
);
384 static char pszFirstItem
[] = "First Item";
385 static char pszSecondItem
[] = "Second Item";
386 static char pszThirdItem
[] = "Third Item";
387 static char pszFourthItem
[] = "Fourth Item";
388 static char pszReplaceItem
[] = "Replace Item";
389 static char pszOutOfRangeItem
[] = "Out Of Range Item";
391 static char *str_items
[] =
392 {pszFirstItem
, pszSecondItem
, pszThirdItem
, pszFourthItem
, pszReplaceItem
, pszOutOfRangeItem
};
394 static char pszUniTestA
[] = "TST";
395 static WCHAR pszUniTestW
[] = {'T','S','T',0};
398 #define TEST_GET_ITEM(i,c)\
399 { res = getItem(hWndHeader, i, buffer);\
400 ok(res != 0, "Getting item[%d] using valid index failed unexpectedly (%ld)\n", i, res);\
401 ok(strcmp(str_items[c], buffer) == 0, "Getting item[%d] returned \"%s\" expecting \"%s\"\n", i, buffer, str_items[c]);\
404 #define TEST_GET_ITEMCOUNT(i)\
405 { res = getItemCount(hWndHeader);\
406 ok(res == i, "Got Item Count as %ld\n", res);\
409 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
411 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
412 static LONG defwndproc_counter
= 0;
413 struct message msg
= { 0 };
416 msg
.message
= message
;
417 msg
.flags
= sent
|wparam
|lparam
;
418 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
421 add_message(sequences
, HEADER_SEQ_INDEX
, &msg
);
423 defwndproc_counter
++;
424 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
425 defwndproc_counter
--;
430 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
432 static LONG defwndproc_counter
= 0;
436 /* do not log painting messages */
437 if (message
!= WM_PAINT
&&
438 message
!= WM_ERASEBKGND
&&
439 message
!= WM_NCPAINT
&&
440 message
!= WM_NCHITTEST
&&
441 message
!= WM_GETTEXT
&&
442 message
!= WM_GETICON
&&
443 message
!= WM_DEVICECHANGE
)
446 msg
.message
= message
;
447 msg
.flags
= sent
|wparam
|lparam
;
448 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
452 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
455 defwndproc_counter
++;
456 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
457 defwndproc_counter
--;
462 static BOOL
register_parent_wnd_class(void)
467 cls
.lpfnWndProc
= parent_wnd_proc
;
470 cls
.hInstance
= GetModuleHandleA(NULL
);
472 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
473 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
474 cls
.lpszMenuName
= NULL
;
475 cls
.lpszClassName
= "Header test parent class";
476 return RegisterClassA(&cls
);
479 static HWND
create_custom_parent_window(void)
481 if (!register_parent_wnd_class())
484 return CreateWindowExA(0, "Header test parent class", "Header Message Sequence Testing",
485 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
486 672+2*GetSystemMetrics(SM_CXSIZEFRAME
),
487 226+GetSystemMetrics(SM_CYCAPTION
)+2*GetSystemMetrics(SM_CYSIZEFRAME
),
488 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
491 static HWND
create_custom_header_control(HWND hParent
, BOOL preloadHeaderItems
)
500 static char firstHeaderItem
[] = "Name";
501 static char secondHeaderItem
[] = "Size";
502 static char *items
[] = {secondHeaderItem
, firstHeaderItem
};
504 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
| HDI_FORMAT
;
505 hdItem
.fmt
= HDF_LEFT
;
507 hdItem
.cchTextMax
= 260;
509 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
511 childHandle
= CreateWindowExA(0, WC_HEADERA
, NULL
,
512 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
514 hParent
, NULL
, NULL
, NULL
);
515 ok(childHandle
!= NULL
, "failed to create child window\n");
516 if (preloadHeaderItems
)
518 for ( loopcnt
= 0 ; loopcnt
< 2 ; loopcnt
++ )
520 hdItem
.pszText
= items
[loopcnt
];
521 retVal
= SendMessageA(childHandle
, HDM_INSERTITEMA
, loopcnt
, (LPARAM
) &hdItem
);
522 ok(retVal
== loopcnt
, "Adding item %d failed with return value %d\n", ( loopcnt
+ 1 ), retVal
);
526 if (winetest_interactive
)
527 ShowWindow (hParent
, SW_SHOW
);
529 GetClientRect(hParent
,&rectwin
);
530 hlayout
.prc
= &rectwin
;
531 hlayout
.pwpos
= &winpos
;
532 SendMessageA(childHandle
,HDM_LAYOUT
,0,(LPARAM
) &hlayout
);
533 SetWindowPos(childHandle
, winpos
.hwndInsertAfter
, winpos
.x
, winpos
.y
,
534 winpos
.cx
, winpos
.cy
, 0);
536 oldproc
= (WNDPROC
)SetWindowLongPtrA(childHandle
, GWLP_WNDPROC
,
537 (LONG_PTR
)header_subclass_proc
);
538 SetWindowLongPtrA(childHandle
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
542 static void header_item_getback(HWND hwnd
, UINT mask
, HDITEMA
*item
)
546 ret
= SendMessageA(hwnd
, HDM_INSERTITEMA
, 0, (LPARAM
)item
);
547 ok(ret
!= -1, "Failed to add header item.\n");
549 memset(item
, 0, sizeof(*item
));
552 ret
= SendMessageA(hwnd
, HDM_GETITEMA
, 0, (LPARAM
)item
);
553 ok(ret
!= 0, "Failed to get item data.\n");
554 ret
= SendMessageA(hwnd
, HDM_DELETEITEM
, 0, 0);
555 ok(ret
!= 0, "Failed to delete item.\n");
558 static void test_item_auto_format(HWND parent
)
560 static char text
[] = "Test";
565 hwnd
= create_custom_header_control(parent
, FALSE
);
567 /* Windows implicitly sets some format bits in INSERTITEM */
569 /* HDF_STRING is automatically set and cleared for no text */
570 item
.mask
= HDI_TEXT
| HDI_WIDTH
| HDI_FORMAT
;
573 item
.fmt
= HDF_CENTER
;
574 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
575 ok(item
.fmt
== (HDF_STRING
| HDF_CENTER
), "Unexpected item format mask %#x.\n", item
.fmt
);
577 item
.mask
= HDI_WIDTH
| HDI_FORMAT
;
579 item
.fmt
= HDF_CENTER
| HDF_STRING
;
580 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
581 ok(item
.fmt
== HDF_CENTER
, "Unexpected item format mask %#x.\n", item
.fmt
);
583 /* HDF_BITMAP is automatically set and cleared for a NULL bitmap or no bitmap */
584 item
.mask
= HDI_BITMAP
| HDI_WIDTH
| HDI_FORMAT
;
585 item
.hbm
= hbm
= CreateBitmap(16, 16, 1, 8, NULL
);
586 item
.fmt
= HDF_CENTER
;
587 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
588 ok(item
.fmt
== (HDF_BITMAP
| HDF_CENTER
), "Unexpected item format mask %#x.\n", item
.fmt
);
591 item
.mask
= HDI_BITMAP
| HDI_WIDTH
| HDI_FORMAT
;
593 item
.fmt
= HDF_CENTER
| HDF_BITMAP
;
594 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
595 ok(item
.fmt
== HDF_CENTER
, "Unexpected item format mask %#x.\n", item
.fmt
);
597 item
.mask
= HDI_WIDTH
| HDI_FORMAT
;
598 item
.fmt
= HDF_CENTER
| HDF_BITMAP
;
599 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
600 ok(item
.fmt
== HDF_CENTER
, "Unexpected item format mask %#x.\n", item
.fmt
);
602 /* HDF_IMAGE is automatically set but not cleared */
603 item
.mask
= HDI_IMAGE
| HDI_WIDTH
| HDI_FORMAT
;
605 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
606 ok(item
.fmt
== (HDF_IMAGE
| HDF_CENTER
), "Unexpected item format mask %#x.\n", item
.fmt
);
608 item
.mask
= HDI_WIDTH
| HDI_FORMAT
;
609 item
.fmt
= HDF_CENTER
| HDF_IMAGE
;
611 header_item_getback(hwnd
, HDI_FORMAT
, &item
);
612 ok(item
.fmt
== (HDF_CENTER
| HDF_IMAGE
), "Unexpected item format mask %#x.\n", item
.fmt
);
617 static void check_auto_fields(void)
621 static CHAR text
[] = "Test";
624 /* Windows stores the format, width, lparam even if they are not in the item's mask */
625 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
626 hdiCreate
.mask
= HDI_TEXT
;
628 hdiCreate
.pszText
= text
;
629 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_WIDTH
, &hdiRead
);
630 TEST_GET_ITEMCOUNT(6);
631 ok(hdiRead
.cxy
== hdiCreate
.cxy
, "cxy should be automatically set\n");
633 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
634 hdiCreate
.mask
= HDI_TEXT
;
635 hdiCreate
.pszText
= text
;
636 hdiCreate
.lParam
= 0x12345678;
637 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_LPARAM
, &hdiRead
);
638 TEST_GET_ITEMCOUNT(6);
639 ok(hdiRead
.lParam
== hdiCreate
.lParam
, "lParam should be automatically set\n");
641 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
642 hdiCreate
.mask
= HDI_TEXT
;
643 hdiCreate
.pszText
= text
;
644 hdiCreate
.fmt
= HDF_STRING
|HDF_CENTER
;
645 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_FORMAT
, &hdiRead
);
646 TEST_GET_ITEMCOUNT(6);
647 ok(hdiRead
.fmt
== hdiCreate
.fmt
, "fmt should be automatically set\n");
649 /* others fields are not set */
650 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
651 hdiCreate
.mask
= HDI_TEXT
;
652 hdiCreate
.pszText
= text
;
653 hdiCreate
.hbm
= CreateBitmap(16, 16, 1, 8, NULL
);
654 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_BITMAP
, &hdiRead
);
655 TEST_GET_ITEMCOUNT(6);
656 ok(hdiRead
.hbm
== NULL
, "hbm should not be automatically set\n");
657 DeleteObject(hdiCreate
.hbm
);
659 ZeroMemory(&hdiCreate
, sizeof(HDITEMA
));
660 hdiCreate
.mask
= HDI_IMAGE
;
661 hdiCreate
.iImage
= 17;
662 hdiCreate
.pszText
= text
;
663 addReadDelItem(hWndHeader
, &hdiCreate
, HDI_TEXT
, &hdiRead
);
664 TEST_GET_ITEMCOUNT(6);
665 ok(hdiRead
.pszText
==NULL
, "pszText shouldn't be automatically set\n");
667 /* field from comctl >4.0 not tested as the system probably won't touch them */
670 static void check_mask(void)
673 static CHAR text
[] = "ABC";
676 /* don't create items if the mask is zero */
677 ZeroMemory(&hdi
, sizeof(hdi
));
684 hdi
.cchTextMax
= 260;
685 ret
= SendMessageA(hWndHeader
, HDM_INSERTITEMA
, 0, (LPARAM
)&hdi
);
686 ok(ret
== -1, "Creating an item with a zero mask should have failed\n");
687 if (ret
!= -1) SendMessageA(hWndHeader
, HDM_DELETEITEM
, 0, 0);
689 /* with a non-zero mask creation will succeed */
690 ZeroMemory(&hdi
, sizeof(hdi
));
691 hdi
.mask
= HDI_LPARAM
;
692 ret
= SendMessageA(hWndHeader
, HDM_INSERTITEMA
, 0, (LPARAM
)&hdi
);
693 ok(ret
!= -1, "Adding item with non-zero mask failed\n");
695 SendMessageA(hWndHeader
, HDM_DELETEITEM
, 0, 0);
697 /* in SETITEM if the mask contains a unknown bit, it is ignored */
698 ZeroMemory(&hdi
, sizeof(hdi
));
699 hdi
.mask
= 0x08000000 | HDI_LPARAM
| HDI_IMAGE
;
702 ret
= SendMessageA(hWndHeader
, HDM_INSERTITEMA
, 0, (LPARAM
)&hdi
);
703 ok(ret
!= -1, "Adding item failed\n");
708 ZeroMemory(&hdi
, sizeof(hdi
));
709 hdi
.mask
= HDI_LPARAM
| HDI_IMAGE
;
710 SendMessageA(hWndHeader
, HDM_GETITEMA
, 0, (LPARAM
)&hdi
);
711 ok(hdi
.lParam
== 133, "comctl32 4.0 field not set\n");
712 ok(hdi
.iImage
== 17, "comctl32 >4.0 field not set\n");
714 /* but in GETITEM if an unknown bit is set, comctl32 uses only version 4.0 fields */
715 ZeroMemory(&hdi
, sizeof(hdi
));
716 hdi
.mask
= 0x08000000 | HDI_LPARAM
| HDI_IMAGE
;
717 SendMessageA(hWndHeader
, HDM_GETITEMA
, 0, (LPARAM
)&hdi
);
718 ok(hdi
.lParam
== 133, "comctl32 4.0 field not read\n");
719 ok(hdi
.iImage
== 0, "comctl32 >4.0 field shouldn't be read\n");
721 SendMessageA(hWndHeader
, HDM_DELETEITEM
, 0, 0);
725 static void test_header_control (void)
728 static char buffer
[MAX_CHARS
];
731 hWndHeader
= create_header_control ();
733 for (i
= 3; i
>= 0; i
--)
735 TEST_GET_ITEMCOUNT(3-i
);
736 res
= addItem(hWndHeader
, 0, str_items
[i
]);
737 ok(res
== 0, "Adding simple item failed (%ld)\n", res
);
740 TEST_GET_ITEMCOUNT(4);
741 res
= addItem(hWndHeader
, 99, str_items
[i
+1]);
742 ok(res
!= -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res
);
743 TEST_GET_ITEMCOUNT(5);
744 res
= addItem(hWndHeader
, 5, str_items
[i
+1]);
745 ok(res
!= -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res
);
746 TEST_GET_ITEMCOUNT(6);
748 for (i
= 0; i
< 4; i
++) { TEST_GET_ITEM(i
,i
); TEST_GET_ITEMCOUNT(6); }
750 res
=getItem(hWndHeader
, 99, buffer
);
751 ok(res
== 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res
,buffer
);
752 res
=getItem(hWndHeader
, 5, buffer
);
753 ok(res
== 1, "Getting Out of Range item should fail with 1 (%ld), got %s\n", res
,buffer
);
754 res
=getItem(hWndHeader
, -2, buffer
);
755 ok(res
== 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res
,buffer
);
757 if (winetest_interactive
)
759 UpdateWindow(hHeaderParentWnd
);
760 UpdateWindow(hWndHeader
);
763 TEST_GET_ITEMCOUNT(6);
764 res
=setItem(hWndHeader
, 99, str_items
[5], FALSE
);
765 ok(res
== 0, "Setting Out of Range item should fail with 0 (%ld)\n", res
);
766 res
=setItem(hWndHeader
, 5, str_items
[5], TRUE
);
767 ok(res
== 1, "Setting Out of Range item should fail with 1 (%ld)\n", res
);
768 res
=setItem(hWndHeader
, -2, str_items
[5], FALSE
);
769 ok(res
== 0, "Setting Out of Range item should fail with 0 (%ld)\n", res
);
770 TEST_GET_ITEMCOUNT(6);
772 for (i
= 0; i
< 4; i
++)
774 res
= setItem(hWndHeader
, i
, str_items
[4], TRUE
);
775 ok(res
!= 0, "Setting %d item failed (%ld)\n", i
+1, res
);
777 TEST_GET_ITEMCOUNT(6);
780 SendMessageA(hWndHeader
, HDM_SETUNICODEFORMAT
, TRUE
, 0);
781 setItemUnicodeNotify(hWndHeader
, 3, pszUniTestA
, pszUniTestW
);
782 SendMessageA(hWndHeader
, WM_NOTIFYFORMAT
, (WPARAM
)hHeaderParentWnd
, NF_REQUERY
);
783 setItem(hWndHeader
, 3, str_items
[4], TRUE
);
785 dont_expect_notify(HDN_GETDISPINFOA
);
786 dont_expect_notify(HDN_GETDISPINFOW
);
787 addItem(hWndHeader
, 0, LPSTR_TEXTCALLBACKA
);
788 setItem(hWndHeader
, 0, str_items
[4], TRUE
);
789 /* unexpected notifies cleared by notifies_received in setItem */
790 dont_expect_notify(HDN_GETDISPINFOA
);
791 dont_expect_notify(HDN_GETDISPINFOW
);
792 setItem(hWndHeader
, 0, LPSTR_TEXTCALLBACKA
, TRUE
);
793 /* unexpected notifies cleared by notifies_received in setItem */
794 delItem(hWndHeader
, 0);
796 TEST_GET_ITEMCOUNT(6);
798 TEST_GET_ITEMCOUNT(6);
800 TEST_GET_ITEMCOUNT(6);
802 res
= delItem(hWndHeader
, 5);
803 ok(res
== 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res
);
804 res
= delItem(hWndHeader
, -2);
805 ok(res
== 0, "Deleting Out of Range item should fail with 0 (%ld)\n", res
);
806 TEST_GET_ITEMCOUNT(5);
808 res
= delItem(hWndHeader
, 3);
809 ok(res
!= 0, "Deleting using out of range index failed (%ld)\n", res
);
810 TEST_GET_ITEMCOUNT(4);
811 res
= delItem(hWndHeader
, 0);
812 ok(res
!= 0, "Deleting using out of range index failed (%ld)\n", res
);
813 TEST_GET_ITEMCOUNT(3);
814 res
= delItem(hWndHeader
, 0);
815 ok(res
!= 0, "Deleting using out of range index failed (%ld)\n", res
);
816 TEST_GET_ITEMCOUNT(2);
817 res
= delItem(hWndHeader
, 0);
818 ok(res
!= 0, "Deleting using out of range index failed (%ld)\n", res
);
819 TEST_GET_ITEMCOUNT(1);
821 DestroyWindow(hWndHeader
);
824 static void test_hdm_getitemrect(HWND hParent
)
831 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
832 hChild
= create_custom_header_control(hParent
, TRUE
);
833 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
834 "adder header control to parent", FALSE
);
836 retVal
= SendMessageA(hChild
, HDM_GETITEMRECT
, 1, (LPARAM
) &rect
);
837 ok(retVal
== TRUE
, "Getting item rect should TRUE, got %d\n", retVal
);
838 /* check bounding rectangle information of 2nd header item */
839 expect(80, rect
.left
);
841 expect(160, rect
.right
);
842 expect(g_customheight
, rect
.bottom
);
844 retVal
= SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
) &rect
);
846 ok(retVal
== TRUE
, "Getting item rect should TRUE, got %d\n", retVal
);
847 /* check bounding rectangle information of 1st header item */
848 expect(0, rect
.left
);
851 expect(80, rect
.right
);
852 expect(g_customheight
, rect
.bottom
);
854 retVal
= SendMessageA(hChild
, HDM_GETITEMRECT
, 10, (LPARAM
) &rect
);
855 ok(retVal
== 0, "Getting rect of nonexistent item should return 0, got %d\n", retVal
);
857 ok_sequence(sequences
, HEADER_SEQ_INDEX
, getItemRect_seq
, "getItemRect sequence testing", FALSE
);
858 DestroyWindow(hChild
);
861 static void test_hdm_layout(HWND hParent
)
868 hdLayout
.prc
= &rect
;
869 hdLayout
.pwpos
= &windowPos
;
871 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
872 hChild
= create_custom_header_control(hParent
, TRUE
);
873 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
874 "adder header control to parent", FALSE
);
876 windowPos
.hwnd
= (HWND
)0xdeadbeef;
877 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
878 retVal
= SendMessageA(hChild
, HDM_LAYOUT
, 0, (LPARAM
) &hdLayout
);
879 expect(TRUE
, retVal
);
880 ok(windowPos
.hwnd
== (HWND
)0xdeadbeef, "Unexpected value %p.\n", windowPos
.hwnd
);
881 ok(!windowPos
.hwndInsertAfter
, "Unexpected value %p.\n", windowPos
.hwndInsertAfter
);
883 ok_sequence(sequences
, HEADER_SEQ_INDEX
, layout_seq
, "layout sequence testing", FALSE
);
885 DestroyWindow(hChild
);
888 static void test_hdm_ordertoindex(HWND hParent
)
893 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
894 hChild
= create_custom_header_control(hParent
, TRUE
);
895 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
896 "adder header control to parent", FALSE
);
898 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
899 retVal
= SendMessageA(hChild
, HDM_ORDERTOINDEX
, 1, 0);
902 ok_sequence(sequences
, HEADER_SEQ_INDEX
, orderToIndex_seq
, "orderToIndex sequence testing", FALSE
);
903 DestroyWindow(hChild
);
906 static void test_hdm_hittest(HWND hParent
)
911 HDHITTESTINFO hdHitTestInfo
;
912 const int firstItemRightBoundary
= 80;
913 const int secondItemRightBoundary
= 160;
914 const int bottomBoundary
= g_customheight
;
916 pt
.x
= firstItemRightBoundary
- 1;
917 pt
.y
= bottomBoundary
- 1;
918 hdHitTestInfo
.pt
= pt
;
921 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
922 hChild
= create_custom_header_control(hParent
, TRUE
);
923 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
924 "adder header control to parent", FALSE
);
926 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
927 retVal
= SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
) &hdHitTestInfo
);
929 expect(0, hdHitTestInfo
.iItem
);
930 expect(HHT_ONDIVIDER
, hdHitTestInfo
.flags
);
932 pt
.x
= secondItemRightBoundary
- 1;
933 pt
.y
= bottomBoundary
- 1;
934 hdHitTestInfo
.pt
= pt
;
935 retVal
= SendMessageA(hChild
, HDM_HITTEST
, 1, (LPARAM
) &hdHitTestInfo
);
937 expect(1, hdHitTestInfo
.iItem
);
938 expect(HHT_ONDIVIDER
, hdHitTestInfo
.flags
);
940 pt
.x
= secondItemRightBoundary
;
941 pt
.y
= bottomBoundary
+ 1;
942 hdHitTestInfo
.pt
= pt
;
943 retVal
= SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
) &hdHitTestInfo
);
945 expect(-1, hdHitTestInfo
.iItem
);
946 expect(HHT_BELOW
, hdHitTestInfo
.flags
);
948 ok_sequence(sequences
, HEADER_SEQ_INDEX
, hittest_seq
, "hittest sequence testing", FALSE
);
950 DestroyWindow(hChild
);
953 static void test_hdm_sethotdivider(HWND hParent
)
957 /* low word: x coordinate = 5
958 * high word: y coordinate = 5
961 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
962 hChild
= create_custom_header_control(hParent
, TRUE
);
963 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
964 "adder header control to parent", FALSE
);
966 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
967 retVal
= SendMessageA(hChild
, HDM_SETHOTDIVIDER
, TRUE
, MAKELPARAM(5, 5));
970 retVal
= SendMessageA(hChild
, HDM_SETHOTDIVIDER
, FALSE
, 100);
972 retVal
= SendMessageA(hChild
, HDM_SETHOTDIVIDER
, FALSE
, 1);
974 if (winetest_interactive
)
975 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setHotDivider_seq_interactive
,
976 "setHotDivider sequence testing", TRUE
);
978 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setHotDivider_seq_noninteractive
,
979 "setHotDivider sequence testing", FALSE
);
981 DestroyWindow(hChild
);
984 static void test_hdm_imageMessages(HWND hParent
)
986 HIMAGELIST hImageList
= pImageList_Create (4, 4, 0, 1, 0);
991 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
992 hChild
= create_custom_header_control(hParent
, TRUE
);
993 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
994 "adder header control to parent", FALSE
);
996 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
998 hIml
= (HIMAGELIST
) SendMessageA(hChild
, HDM_SETIMAGELIST
, 0, (LPARAM
) hImageList
);
999 ok(hIml
== NULL
, "Expected NULL, got %p\n", hIml
);
1001 hIml
= (HIMAGELIST
) SendMessageA(hChild
, HDM_GETIMAGELIST
, 0, 0);
1002 ok(hIml
!= NULL
, "Expected non-NULL handle, got %p\n", hIml
);
1004 hIml
= (HIMAGELIST
) SendMessageA(hChild
, HDM_CREATEDRAGIMAGE
, 0, 0);
1005 ok(hIml
!= NULL
, "Expected non-NULL handle, got %p\n", hIml
);
1006 pImageList_Destroy(hIml
);
1008 ok_sequence(sequences
, HEADER_SEQ_INDEX
, imageMessages_seq
, "imageMessages sequence testing", FALSE
);
1010 DestroyWindow(hChild
);
1012 wasValid
= pImageList_Destroy(hImageList
);
1013 ok(wasValid
, "Header must not free image list at destruction!\n");
1016 static void test_hdm_filterMessages(HWND hParent
)
1019 int retVal
, timeout
;
1021 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1022 hChild
= create_custom_header_control(hParent
, TRUE
);
1023 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1024 "adder header control to parent", FALSE
);
1026 timeout
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 0, 0);
1027 ok(timeout
== 1000, "got %d\n", timeout
);
1029 timeout
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 0, 0);
1030 ok(timeout
== 1000, "got %d\n", timeout
);
1032 timeout
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 0, -100);
1033 ok(timeout
== 1000, "got %d\n", timeout
);
1035 timeout
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, 100);
1036 ok(timeout
== -100, "got %d\n", timeout
);
1037 retVal
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, timeout
);
1038 ok(retVal
== 100, "got %d\n", retVal
);
1040 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1042 /* msdn incorrectly states that return value
1043 * is the index of the filter control being
1044 * modified. The sendMessage here should
1045 * return previous filter timeout value
1048 retVal
= SendMessageA(hChild
, HDM_SETFILTERCHANGETIMEOUT
, 1, 100);
1049 expect(timeout
, retVal
);
1053 retVal
= SendMessageA(hChild
, HDM_CLEARFILTER
, 0, 1);
1055 win_skip("HDM_CLEARFILTER needs 5.80\n");
1059 retVal
= SendMessageA(hChild
, HDM_EDITFILTER
, 1, 0);
1061 win_skip("HDM_EDITFILTER needs 5.80\n");
1065 if (winetest_interactive
)
1066 ok_sequence(sequences
, HEADER_SEQ_INDEX
, filterMessages_seq_interactive
,
1067 "filterMessages sequence testing", TRUE
);
1069 ok_sequence(sequences
, HEADER_SEQ_INDEX
, filterMessages_seq_noninteractive
,
1070 "filterMessages sequence testing", FALSE
);
1071 DestroyWindow(hChild
);
1075 static void test_hdm_unicodeformatMessages(HWND hParent
)
1080 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1081 hChild
= create_custom_header_control(hParent
, TRUE
);
1082 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1083 "adder header control to parent", FALSE
);
1085 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1086 retVal
= SendMessageA(hChild
, HDM_SETUNICODEFORMAT
, TRUE
, 0);
1088 retVal
= SendMessageA(hChild
, HDM_GETUNICODEFORMAT
, 0, 0);
1091 ok_sequence(sequences
, HEADER_SEQ_INDEX
, unicodeformatMessages_seq
,
1092 "unicodeformatMessages sequence testing", FALSE
);
1093 DestroyWindow(hChild
);
1096 static void test_hdm_bitmapmarginMessages(HWND hParent
)
1101 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1102 hChild
= create_custom_header_control(hParent
, TRUE
);
1103 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1104 "adder header control to parent", FALSE
);
1106 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1107 retVal
= SendMessageA(hChild
, HDM_GETBITMAPMARGIN
, 0, 0);
1109 win_skip("HDM_GETBITMAPMARGIN needs 5.80\n");
1113 ok_sequence(sequences
, HEADER_SEQ_INDEX
, bitmapmarginMessages_seq
,
1114 "bitmapmarginMessages sequence testing", FALSE
);
1115 DestroyWindow(hChild
);
1118 static void test_hdm_index_messages(HWND hParent
)
1121 int retVal
, i
, iSize
;
1122 static const int lpiarray
[2] = {1, 0};
1123 static const char *item_texts
[] = {
1124 "Name", "Size", "Type", "Date Modified"
1131 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1132 hChild
= create_custom_header_control(hParent
, FALSE
);
1133 if (winetest_interactive
)
1134 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq_interactive
,
1135 "adder header control to parent", TRUE
);
1137 ok_sequence(sequences
, PARENT_SEQ_INDEX
, add_header_to_parent_seq
,
1138 "adder header control to parent", FALSE
);
1139 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1140 for (i
= 0; i
< ARRAY_SIZE(item_texts
); i
++)
1142 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
| HDI_FORMAT
;
1143 hdItem
.pszText
= (char*)item_texts
[i
];
1144 hdItem
.fmt
= HDF_LEFT
;
1147 retVal
= SendMessageA(hChild
, HDM_INSERTITEMA
, i
, (LPARAM
) &hdItem
);
1148 ok(retVal
== i
, "Adding item %d failed with return value %d\n", i
, retVal
);
1150 ok_sequence(sequences
, HEADER_SEQ_INDEX
, insertItem_seq
, "insertItem sequence testing", FALSE
);
1152 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1154 retVal
= SendMessageA(hChild
, HDM_DELETEITEM
, 3, (LPARAM
) &hdItem
);
1155 ok(retVal
== TRUE
, "Deleting item 3 should return TRUE, got %d\n", retVal
);
1156 retVal
= SendMessageA(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1157 ok(retVal
== 3, "Getting item count should return 3, got %d\n", retVal
);
1159 retVal
= SendMessageA(hChild
, HDM_DELETEITEM
, 3, (LPARAM
) &hdItem
);
1160 ok(retVal
== FALSE
, "Deleting already-deleted item should return FALSE, got %d\n", retVal
);
1161 retVal
= SendMessageA(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1162 ok(retVal
== 3, "Getting item count should return 3, got %d\n", retVal
);
1164 retVal
= SendMessageA(hChild
, HDM_DELETEITEM
, 2, (LPARAM
) &hdItem
);
1165 ok(retVal
== TRUE
, "Deleting item 2 should return TRUE, got %d\n", retVal
);
1166 retVal
= SendMessageA(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1167 ok(retVal
== 2, "Getting item count should return 2, got %d\n", retVal
);
1169 ok_sequence(sequences
, HEADER_SEQ_INDEX
, deleteItem_getItemCount_seq
,
1170 "deleteItem_getItemCount sequence testing", FALSE
);
1172 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1174 hdItem
.mask
= HDI_WIDTH
;
1175 retVal
= SendMessageA(hChild
, HDM_GETITEMA
, 3, (LPARAM
) &hdItem
);
1176 ok(retVal
== FALSE
, "Getting already-deleted item should return FALSE, got %d\n", retVal
);
1178 hdItem
.mask
= HDI_TEXT
| HDI_WIDTH
;
1179 hdItem
.pszText
= buffA
;
1180 hdItem
.cchTextMax
= ARRAY_SIZE(buffA
);
1181 retVal
= SendMessageA(hChild
, HDM_GETITEMA
, 0, (LPARAM
) &hdItem
);
1182 ok(retVal
== TRUE
, "Getting the 1st header item should return TRUE, got %d\n", retVal
);
1184 ok_sequence(sequences
, HEADER_SEQ_INDEX
, getItem_seq
, "getItem sequence testing", FALSE
);
1186 /* check if the item is the right one */
1187 ok(!strcmp(hdItem
.pszText
, item_texts
[0]), "got wrong item %s, expected %s\n",
1188 hdItem
.pszText
, item_texts
[0]);
1189 expect(80, hdItem
.cxy
);
1191 iSize
= SendMessageA(hChild
, HDM_GETITEMCOUNT
, 0, 0);
1193 /* item should be updated just after accepting new array */
1194 ShowWindow(hChild
, SW_HIDE
);
1195 retVal
= SendMessageA(hChild
, HDM_SETORDERARRAY
, iSize
, (LPARAM
) lpiarray
);
1196 expect(TRUE
, retVal
);
1198 retVal
= SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
) &rect
);
1199 expect(TRUE
, retVal
);
1200 ok(rect
.left
!= 0, "Expected updated rectangle\n");
1202 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1204 retVal
= SendMessageA(hChild
, HDM_SETORDERARRAY
, iSize
, (LPARAM
) lpiarray
);
1205 ok(retVal
== TRUE
, "Setting header items order should return TRUE, got %d\n", retVal
);
1207 retVal
= SendMessageA(hChild
, HDM_GETORDERARRAY
, 2, (LPARAM
) array
);
1208 ok(retVal
== TRUE
, "Getting header items order should return TRUE, got %d\n", retVal
);
1210 ok_sequence(sequences
, HEADER_SEQ_INDEX
, orderArray_seq
, "set_get_orderArray sequence testing", FALSE
);
1212 /* check if the array order is set correctly and the size of the array is correct. */
1214 ok(lpiarray
[0] == array
[0], "got %d, expected %d\n", array
[0], lpiarray
[0]);
1215 ok(lpiarray
[1] == array
[1], "got %d, expected %d\n", array
[1], lpiarray
[1]);
1217 hdItem
.mask
= HDI_FORMAT
;
1218 hdItem
.fmt
= HDF_CENTER
| HDF_STRING
;
1220 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1222 retVal
= SendMessageA(hChild
, HDM_SETITEMA
, 0, (LPARAM
) &hdItem
);
1223 ok(retVal
== TRUE
, "Aligning 1st header item to center should return TRUE, got %d\n", retVal
);
1224 hdItem
.fmt
= HDF_RIGHT
| HDF_STRING
;
1225 retVal
= SendMessageA(hChild
, HDM_SETITEMA
, 1, (LPARAM
) &hdItem
);
1226 ok(retVal
== TRUE
, "Aligning 2nd header item to right should return TRUE, got %d\n", retVal
);
1228 ok_sequence(sequences
, HEADER_SEQ_INDEX
, setItem_seq
, "setItem sequence testing", FALSE
);
1229 DestroyWindow(hChild
);
1232 static void test_hdf_fixedwidth(HWND hParent
)
1240 hChild
= create_custom_header_control(hParent
, FALSE
);
1242 hdItem
.mask
= HDI_WIDTH
| HDI_FORMAT
;
1243 hdItem
.fmt
= HDF_FIXEDWIDTH
;
1246 ret
= SendMessageA(hChild
, HDM_INSERTITEMA
, 0, (LPARAM
)&hdItem
);
1249 /* try to change width */
1250 rect
.right
= rect
.bottom
= 0;
1251 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1252 ok(rect
.right
!= 0, "Expected not zero width\n");
1253 ok(rect
.bottom
!= 0, "Expected not zero height\n");
1255 SendMessageA(hChild
, WM_LBUTTONDOWN
, 0, MAKELPARAM(rect
.right
, rect
.bottom
/ 2));
1256 SendMessageA(hChild
, WM_MOUSEMOVE
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1257 SendMessageA(hChild
, WM_LBUTTONUP
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1259 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1261 if (hdItem
.cxy
!= rect
.right
)
1263 win_skip("HDF_FIXEDWIDTH format not supported\n");
1264 DestroyWindow(hChild
);
1268 /* try to adjust with message */
1269 hdItem
.mask
= HDI_WIDTH
;
1272 ret
= SendMessageA(hChild
, HDM_SETITEMA
, 0, (LPARAM
)&hdItem
);
1276 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1277 expect(90, rect
.right
);
1279 /* hittesting doesn't report ondivider flag for HDF_FIXEDWIDTH */
1280 ht
.pt
.x
= rect
.right
- 1;
1281 ht
.pt
.y
= rect
.bottom
/ 2;
1282 SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1283 expect(HHT_ONHEADER
, ht
.flags
);
1285 /* try to adjust with message */
1286 hdItem
.mask
= HDI_FORMAT
;
1289 ret
= SendMessageA(hChild
, HDM_SETITEMA
, 0, (LPARAM
)&hdItem
);
1293 ht
.pt
.y
= rect
.bottom
/ 2;
1294 SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1295 expect(HHT_ONDIVIDER
, ht
.flags
);
1297 DestroyWindow(hChild
);
1300 static void test_hds_nosizing(HWND hParent
)
1308 hChild
= create_custom_header_control(hParent
, FALSE
);
1310 memset(&hdItem
, 0, sizeof(hdItem
));
1311 hdItem
.mask
= HDI_WIDTH
;
1314 ret
= SendMessageA(hChild
, HDM_INSERTITEMA
, 0, (LPARAM
)&hdItem
);
1317 /* HDS_NOSIZING only blocks hittesting */
1318 ret
= GetWindowLongA(hChild
, GWL_STYLE
);
1319 SetWindowLongA(hChild
, GWL_STYLE
, ret
| HDS_NOSIZING
);
1321 /* try to change width with mouse gestures */
1322 rect
.right
= rect
.bottom
= 0;
1323 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1324 ok(rect
.right
!= 0, "Expected not zero width\n");
1325 ok(rect
.bottom
!= 0, "Expected not zero height\n");
1327 SendMessageA(hChild
, WM_LBUTTONDOWN
, 0, MAKELPARAM(rect
.right
, rect
.bottom
/ 2));
1328 SendMessageA(hChild
, WM_MOUSEMOVE
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1329 SendMessageA(hChild
, WM_LBUTTONUP
, 0, MAKELPARAM(rect
.right
+ 20, rect
.bottom
/ 2));
1331 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1333 if (hdItem
.cxy
!= rect
.right
)
1335 win_skip("HDS_NOSIZING style not supported\n");
1336 DestroyWindow(hChild
);
1340 /* this style doesn't set HDF_FIXEDWIDTH for items */
1341 hdItem
.mask
= HDI_FORMAT
;
1342 ret
= SendMessageA(hChild
, HDM_GETITEMA
, 0, (LPARAM
)&hdItem
);
1344 ok(!(hdItem
.fmt
& HDF_FIXEDWIDTH
), "Unexpected HDF_FIXEDWIDTH\n");
1346 /* try to adjust with message */
1347 hdItem
.mask
= HDI_WIDTH
;
1350 ret
= SendMessageA(hChild
, HDM_SETITEMA
, 0, (LPARAM
)&hdItem
);
1354 SendMessageA(hChild
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
1355 expect(90, rect
.right
);
1357 /* hittesting doesn't report ondivider flags for HDS_NOSIZING */
1358 ht
.pt
.x
= rect
.right
- 1;
1359 ht
.pt
.y
= rect
.bottom
/ 2;
1360 SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1361 expect(HHT_ONHEADER
, ht
.flags
);
1363 /* try to adjust with message */
1364 ret
= GetWindowLongA(hChild
, GWL_STYLE
);
1365 SetWindowLongA(hChild
, GWL_STYLE
, ret
& ~HDS_NOSIZING
);
1368 ht
.pt
.y
= rect
.bottom
/ 2;
1369 SendMessageA(hChild
, HDM_HITTEST
, 0, (LPARAM
)&ht
);
1370 expect(HHT_ONDIVIDER
, ht
.flags
);
1372 DestroyWindow(hChild
);
1375 #define TEST_NMCUSTOMDRAW(draw_stage, item_spec, lparam, _left, _top, _right, _bottom) \
1376 ok(nm->dwDrawStage == draw_stage, "Invalid dwDrawStage %d vs %ld\n", draw_stage, nm->dwDrawStage); \
1377 if (item_spec != -1) \
1378 ok(nm->dwItemSpec == item_spec, "Invalid dwItemSpec %d vs %Id\n", item_spec, nm->dwItemSpec); \
1379 ok(nm->lItemlParam == lparam, "Invalid lItemlParam %d vs %Id\n", lparam, nm->lItemlParam); \
1380 ok((nm->rc.top == _top && nm->rc.bottom == _bottom && nm->rc.left == _left && nm->rc.right == _right) || \
1381 broken(draw_stage != CDDS_ITEMPREPAINT), /* comctl32 < 5.80 */ \
1382 "Invalid rect (%d,%d)-(%d,%ld) vs %s\n", _left, _top, _right, _bottom, \
1383 wine_dbgstr_rect(&nm->rc));
1385 static LRESULT
customdraw_1(int n
, NMCUSTOMDRAW
*nm
)
1387 if (nm
== NULL
) { /* test ended */
1388 ok(n
==1, "NM_CUSTOMDRAW messages: %d, expected: 1\n", n
);
1395 /* don't test dwItemSpec - it's 0 no comctl5 but 1308756 on comctl6 */
1396 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1400 ok(FALSE
, "Too many custom draw messages (n=%d, nm->dwDrawStage=%ld)\n", n
, nm
->dwDrawStage
);
1404 static LRESULT
customdraw_2(int n
, NMCUSTOMDRAW
*nm
)
1406 if (nm
== NULL
) { /* test ended */
1407 ok(n
==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n
);
1414 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1415 return CDRF_NOTIFYITEMDRAW
;
1417 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1420 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 1, 5, 50, 0, 150, g_customheight
);
1423 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1427 ok(FALSE
, "Too many custom draw messages (n=%d, nm->dwDrawStage=%ld)\n", n
, nm
->dwDrawStage
);
1431 static LRESULT
customdraw_3(int n
, NMCUSTOMDRAW
*nm
)
1433 if (nm
== NULL
) { /* test ended */
1434 ok(n
==5, "NM_CUSTOMDRAW messages: %d, expected: 5\n", n
);
1441 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1442 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTERASE
|CDRF_NOTIFYPOSTPAINT
|CDRF_SKIPDEFAULT
;
1444 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1447 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 1, 5, 50, 0, 150, g_customheight
);
1450 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1453 TEST_NMCUSTOMDRAW(CDDS_POSTPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1457 ok(FALSE
, "Too many custom draw messages (n=%d, nm->dwDrawStage=%ld)\n", n
, nm
->dwDrawStage
);
1462 static LRESULT
customdraw_4(int n
, NMCUSTOMDRAW
*nm
)
1464 if (nm
== NULL
) { /* test ended */
1465 ok(n
==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n
);
1472 TEST_NMCUSTOMDRAW(CDDS_PREPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1473 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
1475 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 0, 0, 0, 0, 50, g_customheight
);
1478 TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT
, 2, 10, 150, 0, 300, g_customheight
);
1481 TEST_NMCUSTOMDRAW(CDDS_POSTPAINT
, -1, 0, 0, 0, 670, g_customheight
);
1485 ok(FALSE
, "Too many custom draw messages (n=%d, nm->dwDrawStage=%ld)\n", n
, nm
->dwDrawStage
);
1489 static void run_customdraw_scenario(CUSTOMDRAWPROC proc
)
1491 g_CustomDrawProc
= proc
;
1492 g_CustomDrawCount
= 0;
1493 InvalidateRect(hWndHeader
, NULL
, TRUE
);
1494 UpdateWindow(hWndHeader
);
1495 proc(g_CustomDrawCount
, NULL
);
1496 g_CustomDrawProc
= NULL
;
1499 static void test_customdraw(void)
1504 CHAR name
[] = "Test";
1505 hWndHeader
= create_header_control();
1506 GetClientRect(hWndHeader
, &rect
);
1507 ok(rect
.right
- rect
.left
== 670 && rect
.bottom
- rect
.top
== g_customheight
,
1508 "Tests will fail as header size is %ldx%ld instead of 670x%ld\n",
1509 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, g_customheight
);
1511 for (i
= 0; i
< 3; i
++)
1513 ZeroMemory(&item
, sizeof(item
));
1514 item
.mask
= HDI_TEXT
|HDI_WIDTH
;
1515 item
.cxy
= 50*(i
+1);
1516 item
.pszText
= name
;
1518 SendMessageA(hWndHeader
, HDM_INSERTITEMA
, i
, (LPARAM
)&item
);
1521 run_customdraw_scenario(customdraw_1
);
1522 run_customdraw_scenario(customdraw_2
);
1523 run_customdraw_scenario(customdraw_3
);
1525 ZeroMemory(&item
, sizeof(item
));
1526 item
.mask
= HDI_FORMAT
;
1527 item
.fmt
= HDF_OWNERDRAW
;
1528 SendMessageA(hWndHeader
, HDM_SETITEMA
, 1, (LPARAM
)&item
);
1529 g_DrawItem
.CtlID
= 0;
1530 g_DrawItem
.CtlType
= ODT_HEADER
;
1531 g_DrawItem
.hwndItem
= hWndHeader
;
1532 g_DrawItem
.itemID
= 1;
1533 g_DrawItem
.itemState
= 0;
1534 SendMessageA(hWndHeader
, HDM_GETITEMRECT
, 1, (LPARAM
)&g_DrawItem
.rcItem
);
1535 run_customdraw_scenario(customdraw_4
);
1536 ok(g_DrawItemReceived
, "WM_DRAWITEM not received\n");
1537 DestroyWindow(hWndHeader
);
1539 g_DrawItem
.CtlType
= 0;
1540 g_DrawItemReceived
= FALSE
;
1543 static void check_order(const int expected_id
[], const int expected_order
[],
1544 int count
, const char *type
)
1549 ok(getItemCount(hWndHeader
) == count
, "Invalid item count in order tests\n");
1550 for (i
= 0; i
< count
; i
++)
1552 hdi
.mask
= HDI_LPARAM
|HDI_ORDER
;
1553 SendMessageA(hWndHeader
, HDM_GETITEMA
, i
, (LPARAM
)&hdi
);
1554 ok(hdi
.lParam
== expected_id
[i
],
1555 "Invalid item ids after '%s'- item %d has lParam %d\n", type
, i
, (int)hdi
.lParam
);
1556 ok(hdi
.iOrder
== expected_order
[i
],
1557 "Invalid item order after '%s'- item %d has iOrder %d\n", type
, i
, hdi
.iOrder
);
1561 static void test_header_order (void)
1563 const int rand1
[] = {0, 1, 1, 0, 4};
1564 const int rand2
[] = {4, 5, 6, 7, 4};
1565 const int rand3
[] = {5, 5, 1, 6, 1};
1566 const int rand4
[] = {1, 5, 2, 7, 6, 1, 4, 2, 3, 2};
1567 const int rand5
[] = {7, 8, 5, 6, 7, 2, 1, 9, 10, 10};
1568 const int rand6
[] = {2, 8, 3, 4, 0};
1570 const int ids1
[] = {3, 0, 2, 1, 4};
1571 const int ord1
[] = {0, 1, 2, 3, 4};
1572 const int ids2
[] = {3, 9, 7, 0, 2, 1, 4, 8, 6, 5};
1573 const int ord2
[] = {0, 4, 7, 1, 2, 3, 9, 8, 6, 5};
1574 const int ord3
[] = {0, 3, 9, 2, 1, 8, 7, 6, 5, 4};
1575 const int ids4
[] = {9, 0, 1, 8, 6};
1576 const int ord4
[] = {1, 0, 4, 3, 2};
1582 hWndHeader
= create_header_control();
1584 ZeroMemory(&hdi
, sizeof(HDITEMA
));
1585 hdi
.mask
= HDI_TEXT
| HDI_LPARAM
;
1586 hdi
.pszText
= buffer
;
1587 strcpy(buffer
, "test");
1589 for (i
= 0; i
< 5; i
++)
1592 SendMessageA(hWndHeader
, HDM_INSERTITEMA
, rand1
[i
], (LPARAM
)&hdi
);
1594 check_order(ids1
, ord1
, 5, "insert without iOrder");
1596 hdi
.mask
|= HDI_ORDER
;
1597 for (i
= 0; i
< 5; i
++)
1600 hdi
.iOrder
= rand2
[i
];
1601 SendMessageA(hWndHeader
, HDM_INSERTITEMA
, rand3
[i
], (LPARAM
)&hdi
);
1603 check_order(ids2
, ord2
, 10, "insert with order");
1605 hdi
.mask
= HDI_ORDER
;
1606 for (i
=0; i
<10; i
++)
1608 hdi
.iOrder
= rand5
[i
];
1609 SendMessageA(hWndHeader
, HDM_SETITEMA
, rand4
[i
], (LPARAM
)&hdi
);
1611 check_order(ids2
, ord3
, 10, "setitems changing order");
1614 SendMessageA(hWndHeader
, HDM_DELETEITEM
, rand6
[i
], 0);
1615 check_order(ids4
, ord4
, 5, "deleteitem");
1617 DestroyWindow(hWndHeader
);
1620 static LRESULT CALLBACK
HeaderTestWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1627 NMHEADERA
*hdr
= (NMHEADERA
*)lParam
;
1628 EXPECTEDNOTIFY
*expected
;
1631 if (hdr
->hdr
.code
== NM_CUSTOMDRAW
)
1632 if (g_CustomDrawProc
)
1633 return g_CustomDrawProc(g_CustomDrawCount
++, (NMCUSTOMDRAW
*)hdr
);
1635 for (i
=0; i
<nUnexpectedNotify
; i
++)
1636 ok(hdr
->hdr
.code
!= unexpectedNotify
[i
], "Received invalid notify %d\n", hdr
->hdr
.code
);
1638 if (nReceivedNotify
>= nExpectedNotify
|| hdr
->hdr
.hwndFrom
!= hWndHeader
)
1641 expected
= &expectedNotify
[nReceivedNotify
];
1642 if (hdr
->hdr
.code
!= expected
->iCode
)
1646 compare_items(hdr
->hdr
.code
, &expected
->hdItem
, hdr
->pitem
, expected
->fUnicode
);
1651 di
= (DRAWITEMSTRUCT
*)lParam
;
1652 ok(g_DrawItem
.CtlType
!= 0, "Unexpected WM_DRAWITEM\n");
1653 if (g_DrawItem
.CtlType
== 0) return 0;
1654 g_DrawItemReceived
= TRUE
;
1655 compare(di
->CtlType
, g_DrawItem
.CtlType
, "%d");
1656 compare(di
->CtlID
, g_DrawItem
.CtlID
, "%d");
1657 compare(di
->hwndItem
, g_DrawItem
.hwndItem
, "%p");
1658 compare(di
->itemID
, g_DrawItem
.itemID
, "%d");
1659 compare(di
->itemState
, g_DrawItem
.itemState
, "%d");
1660 compare(di
->rcItem
.left
, g_DrawItem
.rcItem
.left
, "%ld");
1661 compare(di
->rcItem
.top
, g_DrawItem
.rcItem
.top
, "%ld");
1662 compare(di
->rcItem
.right
, g_DrawItem
.rcItem
.right
, "%ld");
1663 compare(di
->rcItem
.bottom
, g_DrawItem
.rcItem
.bottom
, "%ld");
1671 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
1677 static void init_functions(void)
1679 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
1681 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
1682 X(ImageList_Create
);
1683 X(ImageList_Destroy
);
1687 static BOOL
init(void)
1694 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1697 wc
.hInstance
= GetModuleHandleA(NULL
);
1699 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
1700 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
1701 wc
.lpszMenuName
= NULL
;
1702 wc
.lpszClassName
= "HeaderTestClass";
1703 wc
.lpfnWndProc
= HeaderTestWndProc
;
1704 RegisterClassA(&wc
);
1706 /* The height of the header control depends on the height of the system font.
1707 The height of the system font is dpi dependent */
1709 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
1710 GetTextMetricsA(hdc
, &tm
);
1711 /* 2 dot extra space are needed for the border */
1712 g_customheight
= tm
.tmHeight
+ 2;
1713 trace("customdraw height: %ld (dpi: %d)\n", g_customheight
, GetDeviceCaps(hdc
, LOGPIXELSY
));
1714 SelectObject(hdc
, hOldFont
);
1717 hHeaderParentWnd
= CreateWindowExA(0, "HeaderTestClass", "Header test", WS_OVERLAPPEDWINDOW
,
1718 CW_USEDEFAULT
, CW_USEDEFAULT
, 672+2*GetSystemMetrics(SM_CXSIZEFRAME
),
1719 226+GetSystemMetrics(SM_CYCAPTION
)+2*GetSystemMetrics(SM_CYSIZEFRAME
),
1720 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1721 ok(hHeaderParentWnd
!= NULL
, "failed to create parent wnd\n");
1723 ShowWindow(hHeaderParentWnd
, SW_SHOW
);
1724 return hHeaderParentWnd
!= NULL
;
1727 /* maximum 8 items allowed */
1728 static void check_orderarray(HWND hwnd
, DWORD start
, DWORD set
, DWORD expected
,
1729 BOOL todo
, int line
)
1733 DWORD ret
, array
= 0;
1735 count
= SendMessageA(hwnd
, HDM_GETITEMCOUNT
, 0, 0);
1738 for(i
= 1; i
<=count
; i
++)
1739 order
[i
-1] = start
>>(4*(count
-i
)) & 0xf;
1741 ret
= SendMessageA(hwnd
, HDM_SETORDERARRAY
, count
, (LPARAM
)order
);
1742 ok_(__FILE__
, line
)(ret
, "Expected HDM_SETORDERARRAY to succeed, got %ld\n", ret
);
1745 for(i
= 1; i
<=count
; i
++)
1746 order
[i
-1] = set
>>(4*(count
-i
)) & 0xf;
1747 ret
= SendMessageA(hwnd
, HDM_SETORDERARRAY
, count
, (LPARAM
)order
);
1748 ok_(__FILE__
, line
)(ret
, "Expected HDM_SETORDERARRAY to succeed, got %ld\n", ret
);
1750 /* check actual order */
1751 ret
= SendMessageA(hwnd
, HDM_GETORDERARRAY
, count
, (LPARAM
)order
);
1752 ok_(__FILE__
, line
)(ret
, "Expected HDM_GETORDERARRAY to succeed, got %ld\n", ret
);
1753 for(i
= 1; i
<=count
; i
++)
1754 array
|= order
[i
-1]<<(4*(count
-i
));
1757 ok_(__FILE__
, line
)(array
== expected
, "Expected %lx, got %lx\n", expected
, array
);
1760 static void test_hdm_orderarray(void)
1766 hwnd
= create_header_control();
1769 addItem(hwnd
, 0, NULL
);
1770 addItem(hwnd
, 1, NULL
);
1771 addItem(hwnd
, 2, NULL
);
1773 ret
= SendMessageA(hwnd
, HDM_GETORDERARRAY
, 3, (LPARAM
)order
);
1776 win_skip("HDM_GETORDERARRAY not implemented.\n");
1777 DestroyWindow(hwnd
);
1781 expect(0, order
[0]);
1782 expect(1, order
[1]);
1783 expect(2, order
[2]);
1787 /* null pointer, crashes native */
1788 ret
= SendMessageA(hwnd
, HDM_SETORDERARRAY
, 3, 0);
1791 /* count out of limits */
1792 ret
= SendMessageA(hwnd
, HDM_SETORDERARRAY
, 5, (LPARAM
)order
);
1794 /* count out of limits */
1795 ret
= SendMessageA(hwnd
, HDM_SETORDERARRAY
, 2, (LPARAM
)order
);
1798 /* try with out of range item index */
1799 /* (0,1,2)->(1,0,3) => (1,0,2) */
1800 check_orderarray(hwnd
, 0x120, 0x103, 0x102, FALSE
, __LINE__
);
1801 /* (1,0,2)->(3,0,1) => (0,2,1) */
1802 check_orderarray(hwnd
, 0x102, 0x301, 0x021, TRUE
, __LINE__
);
1803 /* (0,2,1)->(2,3,1) => (2,0,1) */
1804 check_orderarray(hwnd
, 0x021, 0x231, 0x201, FALSE
, __LINE__
);
1806 /* (0,1,2)->(0,2,2) => (0,1,2) */
1807 check_orderarray(hwnd
, 0x012, 0x022, 0x012, FALSE
, __LINE__
);
1809 addItem(hwnd
, 3, NULL
);
1811 /* (0,1,2,3)->(0,1,2,2) => (0,1,3,2) */
1812 check_orderarray(hwnd
, 0x0123, 0x0122, 0x0132, FALSE
, __LINE__
);
1813 /* (0,1,2,3)->(0,1,3,3) => (0,1,2,3) */
1814 check_orderarray(hwnd
, 0x0123, 0x0133, 0x0123, FALSE
, __LINE__
);
1815 /* (0,1,2,3)->(0,4,2,3) => (0,1,2,3) */
1816 check_orderarray(hwnd
, 0x0123, 0x0423, 0x0123, FALSE
, __LINE__
);
1817 /* (0,1,2,3)->(4,0,1,2) => (0,1,3,2) */
1818 check_orderarray(hwnd
, 0x0123, 0x4012, 0x0132, TRUE
, __LINE__
);
1819 /* (0,1,3,2)->(4,0,1,4) => (0,3,1,2) */
1820 check_orderarray(hwnd
, 0x0132, 0x4014, 0x0312, TRUE
, __LINE__
);
1821 /* (0,1,2,3)->(4,1,0,2) => (1,0,3,2) */
1822 check_orderarray(hwnd
, 0x0123, 0x4102, 0x1032, TRUE
, __LINE__
);
1823 /* (0,1,2,3)->(0,1,4,2) => (0,1,2,3) */
1824 check_orderarray(hwnd
, 0x0123, 0x0142, 0x0132, FALSE
, __LINE__
);
1825 /* (0,1,2,3)->(4,4,4,4) => (0,1,2,3) */
1826 check_orderarray(hwnd
, 0x0123, 0x4444, 0x0123, FALSE
, __LINE__
);
1827 /* (0,1,2,3)->(4,4,1,2) => (0,1,3,2) */
1828 check_orderarray(hwnd
, 0x0123, 0x4412, 0x0132, TRUE
, __LINE__
);
1829 /* (0,1,2,3)->(4,4,4,1) => (0,2,3,1) */
1830 check_orderarray(hwnd
, 0x0123, 0x4441, 0x0231, TRUE
, __LINE__
);
1831 /* (0,1,2,3)->(1,4,4,4) => (1,0,2,3) */
1832 check_orderarray(hwnd
, 0x0123, 0x1444, 0x1023, FALSE
, __LINE__
);
1833 /* (0,1,2,3)->(4,2,4,1) => (0,2,3,1) */
1834 check_orderarray(hwnd
, 0x0123, 0x4241, 0x0231, FALSE
, __LINE__
);
1835 /* (0,1,2,3)->(4,2,0,1) => (2,0,3,1) */
1836 check_orderarray(hwnd
, 0x0123, 0x4201, 0x2031, TRUE
, __LINE__
);
1837 /* (3,2,1,0)->(4,2,0,1) => (3,2,0,1) */
1838 check_orderarray(hwnd
, 0x3210, 0x4201, 0x3201, FALSE
, __LINE__
);
1840 DestroyWindow(hwnd
);
1846 ULONG_PTR ctx_cookie
;
1850 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1855 test_header_control();
1856 test_item_auto_format(hHeaderParentWnd
);
1857 test_header_order();
1858 test_hdm_orderarray();
1861 DestroyWindow(hHeaderParentWnd
);
1863 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1864 parent_hwnd
= create_custom_parent_window();
1865 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent windows", FALSE
);
1867 test_hdm_index_messages(parent_hwnd
);
1868 test_hdm_getitemrect(parent_hwnd
);
1869 test_hdm_hittest(parent_hwnd
);
1870 test_hdm_layout(parent_hwnd
);
1871 test_hdm_ordertoindex(parent_hwnd
);
1872 test_hdm_sethotdivider(parent_hwnd
);
1873 test_hdm_imageMessages(parent_hwnd
);
1874 test_hdm_filterMessages(parent_hwnd
);
1875 test_hdm_unicodeformatMessages(parent_hwnd
);
1876 test_hdm_bitmapmarginMessages(parent_hwnd
);
1878 if (!load_v6_module(&ctx_cookie
, &hCtx
))
1880 DestroyWindow(parent_hwnd
);
1886 /* comctl32 version 6 tests start here */
1887 test_hdf_fixedwidth(parent_hwnd
);
1888 test_hds_nosizing(parent_hwnd
);
1889 test_item_auto_format(parent_hwnd
);
1890 test_hdm_layout(parent_hwnd
);
1892 unload_v6_module(ctx_cookie
, hCtx
);
1894 DestroyWindow(parent_hwnd
);