+ /* message isn't forwarded to header */
+ subclass_header(hwnd);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ expect(0, ret);
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
+ "WM_SETREDRAW: not forwarded to header", FALSE);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_hittest(void)
+{
+ HWND hwnd;
+ DWORD r;
+ RECT bounds;
+ LVITEMA item;
+ static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
+ POINT pos;
+ INT x, y;
+ HIMAGELIST himl, himl2;
+ HBITMAP hbmp;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ /* LVS_REPORT with a single subitem (2 columns) */
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+ insert_item(hwnd, 0);
+
+ item.iSubItem = 0;
+ /* the only purpose of that line is to be as long as a half item rect */
+ item.pszText = text;
+ r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
+ expect(TRUE, r);
+
+ memset(&bounds, 0, sizeof(bounds));
+ bounds.left = LVIR_BOUNDS;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
+ ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
+ ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
+ expect(TRUE, r);
+
+ /* LVS_EX_FULLROWSELECT not set, no icons attached */
+
+ /* outside columns by x position - valid is [0, 199] */
+ x = -1;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TOLEFT, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+
+ x = pos.x + 50; /* column half width */
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ x = pos.x + 150; /* outside column */
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ /* outside possible client rectangle (to right) */
+ x = pos.x + 500;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
+ test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+ /* subitem returned with -1 item too */
+ x = pos.x + 150;
+ y = -10;
+ test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+ /* parent client area is 100x100 by default */
+ MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
+ x = pos.x + 150; /* outside column */
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ /* the same with LVS_EX_FULLROWSELECT */
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
+ x = pos.x + 150; /* outside column */
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
+ x = pos.x + 150; /* outside column */
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
+ /* outside possible client rectangle (to right) */
+ x = pos.x + 500;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
+ test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
+ /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
+ himl = ImageList_Create(16, 16, 0, 4, 4);
+ ok(himl != NULL, "failed to create imagelist\n");
+ hbmp = CreateBitmap(16, 16, 1, 1, NULL);
+ ok(hbmp != NULL, "failed to create bitmap\n");
+ r = ImageList_Add(himl, hbmp, 0);
+ ok(r == 0, "should be zero\n");
+ hbmp = CreateBitmap(16, 16, 1, 1, NULL);
+ ok(hbmp != NULL, "failed to create bitmap\n");
+ r = ImageList_Add(himl, hbmp, 0);
+ ok(r == 1, "should be one\n");
+
+ r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
+ ok(r == 0, "should return zero\n");
+
+ item.mask = LVIF_IMAGE;
+ item.iImage = 0;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+ /* on state icon */
+ x = pos.x + 8;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
+
+ /* state icons indices are 1 based, check with valid index */
+ item.mask = LVIF_STATE;
+ item.state = INDEXTOSTATEIMAGEMASK(1);
+ item.stateMask = LVIS_STATEIMAGEMASK;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+ /* on state icon */
+ x = pos.x + 8;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
+
+ himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
+ ok(himl2 == himl, "should return handle\n");
+
+ r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
+ ok(r == 0, "should return zero\n");
+ /* on item icon */
+ x = pos.x + 8;
+ y = pos.y + (bounds.bottom - bounds.top) / 2;
+ test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE);
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
+ y = (bounds.bottom - bounds.top) / 2;
+ test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_getviewrect(void)
+{
+ HWND hwnd;
+ DWORD r;
+ RECT rect;
+ LVITEMA item;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ /* empty */
+ r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+
+ memset(&item, 0, sizeof(item));
+ item.iItem = 0;
+ item.iSubItem = 0;
+ SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+
+ r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
+ expect(TRUE, r);
+
+ rect.left = rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* left is set to (2e31-1) - XP SP2 */
+ expect(0, rect.right);
+ expect(0, rect.top);
+ expect(0, rect.bottom);
+
+ /* switch to LVS_ICON */
+ SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
+
+ rect.left = rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ expect(0, rect.left);
+ expect(0, rect.top);
+ /* precise value differs for 2k, XP and Vista */
+ ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
+ ok(rect.right > 0, "Expected positive right value, got %d\n", rect.right);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_getitemposition(void)
+{
+ HWND hwnd, header;
+ DWORD r;
+ POINT pt;
+ RECT rect;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = subclass_header(hwnd);
+
+ /* LVS_REPORT, single item, no columns added */
+ insert_item(hwnd, 0);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ pt.x = pt.y = -1;
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
+ expect(TRUE, r);
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
+
+ /* LVS_REPORT, single item, single column */
+ insert_column(hwnd, 0);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ pt.x = pt.y = -1;
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
+ expect(TRUE, r);
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
+
+ memset(&rect, 0, sizeof(rect));
+ SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
+ /* some padding? */
+ expect(2, pt.x);
+ /* offset by header height */
+ expect(rect.bottom - rect.top, pt.y);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_columnscreation(void)
+{
+ HWND hwnd, header;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ insert_item(hwnd, 0);
+
+ /* headers columns aren't created automatically */
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header handle\n");
+ r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
+ expect(0, r);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_getitemrect(void)
+{
+ HWND hwnd;
+ HIMAGELIST himl;
+ HBITMAP hbm;
+ RECT rect;
+ DWORD r;
+ LVITEMA item;
+ LVCOLUMNA col;
+ INT order[2];
+ POINT pt;
+
+ /* rectangle isn't empty for empty text items */
+ hwnd = create_listview_control(LVS_LIST);
+ memset(&item, 0, sizeof(item));
+ item.mask = 0;
+ item.iItem = 0;
+ r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ expect(0, r);
+ rect.left = LVIR_LABEL;
+ SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(0, rect.left);
+ expect(0, rect.top);
+ todo_wine expect(96, rect.right);
+ DestroyWindow(hwnd);
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ /* empty item */
+ memset(&item, 0, sizeof(item));
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ expect(0, r);
+
+ rect.left = LVIR_BOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+
+ /* zero width rectangle with no padding */
+ expect(0, rect.left);
+ expect(0, rect.right);
+
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+
+ col.mask = LVCF_WIDTH;
+ col.cx = 50;
+ r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
+ expect(TRUE, r);
+
+ col.mask = LVCF_WIDTH;
+ col.cx = 100;
+ r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
+ expect(TRUE, r);
+
+ rect.left = LVIR_BOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+
+ /* still no left padding */
+ expect(0, rect.left);
+ expect(150, rect.right);
+
+ rect.left = LVIR_SELECTBOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding */
+ expect(2, rect.left);
+
+ rect.left = LVIR_LABEL;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding, column width */
+ expect(2, rect.left);
+ expect(50, rect.right);
+
+ /* no icons attached */
+ rect.left = LVIR_ICON;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding */
+ expect(2, rect.left);
+ expect(2, rect.right);
+
+ /* change order */
+ order[0] = 1; order[1] = 0;
+ r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
+ expect(TRUE, r);
+ pt.x = -1;
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
+ expect(TRUE, r);
+ /* 1 indexed column width + padding */
+ expect(102, pt.x);
+ /* rect is at zero too */
+ rect.left = LVIR_BOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ expect(0, rect.left);
+ /* just width sum */
+ expect(150, rect.right);
+
+ rect.left = LVIR_SELECTBOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* column width + padding */
+ expect(102, rect.left);
+
+ /* back to initial order */
+ order[0] = 0; order[1] = 1;
+ r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
+ expect(TRUE, r);
+
+ /* state icons */
+ himl = ImageList_Create(16, 16, 0, 2, 2);
+ ok(himl != NULL, "failed to create imagelist\n");
+ hbm = CreateBitmap(16, 16, 1, 1, NULL);
+ ok(hbm != NULL, "failed to create bitmap\n");
+ r = ImageList_Add(himl, hbm, 0);
+ ok(r == 0, "should be zero\n");
+ hbm = CreateBitmap(16, 16, 1, 1, NULL);
+ ok(hbm != NULL, "failed to create bitmap\n");
+ r = ImageList_Add(himl, hbm, 0);
+ ok(r == 1, "should be one\n");
+
+ r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
+ ok(r == 0, "should return zero\n");
+
+ item.mask = LVIF_STATE;
+ item.state = INDEXTOSTATEIMAGEMASK(1);
+ item.stateMask = LVIS_STATEIMAGEMASK;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ /* icon bounds */
+ rect.left = LVIR_ICON;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + stateicon width */
+ expect(18, rect.left);
+ expect(18, rect.right);
+ /* label bounds */
+ rect.left = LVIR_LABEL;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + stateicon width -> column width */
+ expect(18, rect.left);
+ expect(50, rect.right);
+
+ r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
+ ok(r != 0, "should return current list handle\n");
+
+ r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
+ ok(r == 0, "should return zero\n");
+
+ item.mask = LVIF_STATE | LVIF_IMAGE;
+ item.iImage = 1;
+ item.state = 0;
+ item.stateMask = ~0;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ /* icon bounds */
+ rect.left = LVIR_ICON;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding, icon width */
+ expect(2, rect.left);
+ expect(18, rect.right);
+ /* label bounds */
+ rect.left = LVIR_LABEL;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + icon width -> column width */
+ expect(18, rect.left);
+ expect(50, rect.right);
+
+ /* select bounds */
+ rect.left = LVIR_SELECTBOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding, column width */
+ expect(2, rect.left);
+ expect(50, rect.right);
+
+ /* try with indentation */
+ item.mask = LVIF_INDENT;
+ item.iIndent = 1;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ /* bounds */
+ rect.left = LVIR_BOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + 1 icon width, column width */
+ expect(0, rect.left);
+ expect(150, rect.right);
+
+ /* select bounds */
+ rect.left = LVIR_SELECTBOUNDS;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + 1 icon width, column width */
+ expect(2 + 16, rect.left);
+ expect(50, rect.right);
+
+ /* label bounds */
+ rect.left = LVIR_LABEL;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + 2 icon widths, column width */
+ expect(2 + 16*2, rect.left);
+ expect(50, rect.right);
+
+ /* icon bounds */
+ rect.left = LVIR_ICON;
+ rect.right = rect.top = rect.bottom = -1;
+ r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
+ expect(TRUE, r);
+ /* padding + 1 icon width indentation, icon width */
+ expect(2 + 16, rect.left);
+ expect(34, rect.right);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_editbox(void)
+{
+ static CHAR testitemA[] = "testitem";
+ static CHAR testitem1A[] = "testitem_quitelongname";
+ static CHAR buffer[25];
+ HWND hwnd, hwndedit, hwndedit2, header;
+ LVITEMA item;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ insert_column(hwnd, 0);
+
+ memset(&item, 0, sizeof(item));
+ item.mask = LVIF_TEXT;
+ item.pszText = testitemA;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ expect(0, r);
+
+ /* test notifications without edit created */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)0xdeadbeef);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
+ "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE);
+ /* same thing but with valid window */
+ hwndedit = CreateWindowA("Edit", "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20,
+ 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
+ "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE);
+ DestroyWindow(hwndedit);
+
+ /* setting focus is necessary */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+
+ /* test children Z-order after Edit box created */
+ header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header to be created\n");
+ ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
+ ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
+
+ /* modify initial string */
+ r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
+ expect(TRUE, r);
+
+ /* edit window is resized and repositioned,
+ check again for Z-order - it should be preserved */
+ ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
+ ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
+
+ /* return focus to listview */
+ SetFocus(hwnd);
+
+ memset(&item, 0, sizeof(item));
+ item.mask = LVIF_TEXT;
+ item.pszText = buffer;
+ item.cchTextMax = sizeof(buffer);
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
+
+ /* send LVM_EDITLABEL on already created edit */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ /* focus will be set to edit */
+ ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
+ hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
+
+ /* creating label disabled when control isn't focused */
+ SetFocus(0);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
+
+ /* check EN_KILLFOCUS handling */
+ memset(&item, 0, sizeof(item));
+ item.pszText = testitemA;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ /* modify edit and notify control that it lost focus */
+ r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
+ expect(TRUE, r);
+ r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
+ expect(0, r);
+ memset(&item, 0, sizeof(item));
+ item.pszText = buffer;
+ item.cchTextMax = sizeof(buffer);
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
+ expect(lstrlen(item.pszText), r);
+ ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
+ ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
+ /* end edit without saving */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
+ "edit box - end edit, no change, escape", TRUE);
+ /* end edit with saving */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
+ "edit box - end edit, no change, return", TRUE);
+
+ memset(&item, 0, sizeof(item));
+ item.pszText = buffer;
+ item.cchTextMax = sizeof(buffer);
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
+ expect(lstrlen(item.pszText), r);
+ ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
+
+ /* LVM_EDITLABEL with -1 destroys current edit */
+ hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
+ ok(hwndedit == NULL, "Expected Edit window not to be created\n");
+ /* no edit present */
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
+ ok(hwndedit == NULL, "Expected Edit window not to be created\n");
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ /* edit present */
+ ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
+ hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
+ ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
+ ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
+ ok(GetFocus() == hwnd, "Expected List to be focused\n");
+ /* check another negative value */
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
+ hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
+ ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
+ ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
+ ok(GetFocus() == hwnd, "Expected List to be focused\n");
+ /* and value greater than max item index */
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
+ ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
+ ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
+ ok(GetFocus() == hwnd, "Expected List to be focused\n");
+
+ /* messaging tests */
+ SetFocus(hwnd);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ blockEdit = FALSE;
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ /* testing only sizing messages */
+ ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
+ "edit box create - sizing", FALSE);
+
+ /* WM_COMMAND with EN_KILLFOCUS isn't forwared to parent */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
+ "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_notifyformat(void)
+{
+ HWND hwnd, header;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
+ CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
+ /* set */
+ r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
+ expect(0, r);
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ if (r == 1)
+ {
+ r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ }
+ else
+ {
+ win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ DestroyWindow(hwnd);
+
+ /* test failure in parent WM_NOTIFYFORMAT */
+ notifyFormat = 0;
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
+ r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
+ ok(r != 0, "Expected valid format\n");
+
+ notifyFormat = NFR_UNICODE;
+ r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
+ expect(NFR_UNICODE, r);
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
+
+ notifyFormat = NFR_ANSI;
+ r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
+ expect(NFR_ANSI, r);
+ r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
+
+ DestroyWindow(hwnd);
+
+ /* try different unicode window combination and defaults */
+ if (!GetModuleHandleW(NULL))
+ {
+ win_skip("Additional notify format tests are incompatible with Win9x\n");
+ return;
+ }
+
+ hwndparentW = create_parent_window(TRUE);
+ ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
+ if (!IsWindow(hwndparentW)) return;
+
+ notifyFormat = -1;
+ hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ DestroyWindow(hwnd);
+ /* receiving error code defaulting to ansi */
+ notifyFormat = 0;
+ hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ DestroyWindow(hwnd);
+ /* receiving ansi code from unicode window, use it */
+ notifyFormat = NFR_ANSI;
+ hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ DestroyWindow(hwnd);
+ /* unicode listview with ansi parent window */
+ notifyFormat = -1;
+ hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ DestroyWindow(hwnd);
+ /* unicode listview with ansi parent window, return error code */
+ notifyFormat = 0;
+ hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "expected header to be created\n");
+ r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
+ expect(0, r);
+ r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, r);
+ DestroyWindow(hwnd);
+
+ DestroyWindow(hwndparentW);
+}
+
+static void test_indentation(void)
+{
+ HWND hwnd;
+ LVITEMA item;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ memset(&item, 0, sizeof(item));
+ item.mask = LVIF_INDENT;
+ item.iItem = 0;
+ item.iIndent = I_INDENTCALLBACK;
+ r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ expect(0, r);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ item.iItem = 0;
+ item.mask = LVIF_INDENT;
+ r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
+ expect(TRUE, r);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
+ "get indent dispinfo", FALSE);
+
+ DestroyWindow(hwnd);
+}
+
+static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
+{
+ return 0;
+}
+
+static BOOL is_below_comctl_5(void)
+{
+ HWND hwnd;
+ BOOL ret;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ insert_item(hwnd, 0);
+
+ ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
+
+ DestroyWindow(hwnd);
+
+ return !ret;
+}
+
+static void test_get_set_view(void)
+{
+ HWND hwnd;
+ DWORD ret;
+ DWORD_PTR style;
+
+ /* test style->view mapping */
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
+ expect(LV_VIEW_DETAILS, ret);
+
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ /* LVS_ICON == 0 */
+ SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
+ ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
+ expect(LV_VIEW_ICON, ret);
+
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
+ ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
+ expect(LV_VIEW_SMALLICON, ret);
+
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
+ ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
+ expect(LV_VIEW_LIST, ret);
+
+ /* switching view doesn't touch window style */
+ ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
+ expect(1, ret);
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ ok(style & LVS_LIST, "Expected style to be preserved\n");
+ ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
+ expect(1, ret);
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ ok(style & LVS_LIST, "Expected style to be preserved\n");
+ ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
+ expect(1, ret);
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ ok(style & LVS_LIST, "Expected style to be preserved\n");
+
+ DestroyWindow(hwnd);
+}
+
+static void test_canceleditlabel(void)
+{
+ HWND hwnd, hwndedit;
+ DWORD ret;
+ CHAR buff[10];
+ LVITEMA itema;
+ static CHAR test[] = "test";
+ static const CHAR test1[] = "test1";
+
+ hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ insert_item(hwnd, 0);
+
+ /* try without edit created */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
+ expect(TRUE, ret);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
+ "cancel edit label without edit", FALSE);
+
+ /* cancel without data change */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected edit control to be created\n");
+ ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
+ expect(TRUE, ret);
+ ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
+
+ /* cancel after data change */
+ memset(&itema, 0, sizeof(itema));
+ itema.pszText = test;
+ ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
+ expect(TRUE, ret);
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
+ ok(IsWindow(hwndedit), "Expected edit control to be created\n");
+ ret = SetWindowText(hwndedit, test1);
+ ok(ret != 0, "Expected edit text to change\n");
+ ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
+ expect(TRUE, ret);
+ ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
+ memset(&itema, 0, sizeof(itema));
+ itema.pszText = buff;
+ itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
+ expect(5, ret);
+ ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
+
+ DestroyWindow(hwnd);
+}
+
+static void test_mapidindex(void)
+{
+ HWND hwnd;
+ DWORD ret;
+
+ /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
+ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+ insert_item(hwnd, 0);
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
+ expect(-1, ret);
+ DestroyWindow(hwnd);
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ /* LVM_MAPINDEXTOID with invalid index */
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
+ expect(-1, ret);
+
+ insert_item(hwnd, 0);
+ insert_item(hwnd, 1);
+
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
+ expect(-1, ret);
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
+ expect(-1, ret);
+
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
+ expect(1, ret);
+ /* remove 0 indexed item, id retained */
+ SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
+ expect(1, ret);
+ /* new id starts from previous value */
+ insert_item(hwnd, 1);
+ ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
+ expect(2, ret);
+
+ /* get index by id */
+ ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
+ expect(-1, ret);
+ ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
+ expect(-1, ret);
+ ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
+ expect(1, ret);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_getitemspacing(void)
+{
+ HWND hwnd;
+ DWORD ret;
+ INT cx, cy;
+ HIMAGELIST himl;
+ HBITMAP hbmp;
+ LVITEMA itema;
+
+ cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
+ cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
+
+ /* LVS_ICON */
+ hwnd = create_listview_control(LVS_ICON);
+ ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
+todo_wine {
+ expect(cx, LOWORD(ret));
+ expect(cy, HIWORD(ret));
+}
+ /* now try with icons */
+ himl = ImageList_Create(40, 40, 0, 4, 4);
+ ok(himl != NULL, "failed to create imagelist\n");
+ hbmp = CreateBitmap(40, 40, 1, 1, NULL);
+ ok(hbmp != NULL, "failed to create bitmap\n");
+ ret = ImageList_Add(himl, hbmp, 0);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
+ expect(0, ret);
+
+ itema.mask = LVIF_IMAGE;
+ itema.iImage = 0;
+ itema.iItem = 0;
+ itema.iSubItem = 0;
+ ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
+todo_wine {
+ /* spacing + icon size returned */
+ expect(cx + 40, LOWORD(ret));
+ expect(cy + 40, HIWORD(ret));
+}
+ DestroyWindow(hwnd);
+ /* LVS_SMALLICON */
+ hwnd = create_listview_control(LVS_SMALLICON);
+ ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
+todo_wine {
+ expect(cx, LOWORD(ret));
+ expect(cy, HIWORD(ret));
+}
+ DestroyWindow(hwnd);
+ /* LVS_REPORT */
+ hwnd = create_listview_control(LVS_REPORT);
+ ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
+todo_wine {
+ expect(cx, LOWORD(ret));
+ expect(cy, HIWORD(ret));
+}
+ DestroyWindow(hwnd);
+ /* LVS_LIST */
+ hwnd = create_listview_control(LVS_LIST);
+ ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
+todo_wine {
+ expect(cx, LOWORD(ret));
+ expect(cy, HIWORD(ret));
+}
+ DestroyWindow(hwnd);
+}
+
+static void test_getcolumnwidth(void)
+{
+ HWND hwnd;
+ DWORD ret;
+ DWORD_PTR style;
+ LVCOLUMNA col;
+ LVITEMA itema;
+
+ /* default column width */
+ hwnd = create_listview_control(LVS_ICON);
+ ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+ expect(0, ret);
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
+ ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+ todo_wine expect(8, ret);
+ style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
+ SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
+ col.mask = 0;
+ ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+ expect(10, ret);
+ DestroyWindow(hwnd);
+
+ /* default column width with item added */
+ hwnd = create_listview_control(LVS_LIST);
+ memset(&itema, 0, sizeof(itema));
+ SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
+ ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+ todo_wine expect(96, ret);
+ DestroyWindow(hwnd);
+}
+
+static void test_scrollnotify(void)
+{
+ HWND hwnd;
+ DWORD ret;
+
+ hwnd = create_listview_control(LVS_REPORT);
+
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+ insert_item(hwnd, 0);
+
+ /* make it scrollable - resize */
+ ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
+ expect(TRUE, ret);
+ ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
+ expect(TRUE, ret);
+
+ /* try with dummy call */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
+ expect(TRUE, ret);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
+ "scroll notify 1", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
+ expect(TRUE, ret);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
+ "scroll notify 2", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
+ expect(TRUE, ret);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
+ "scroll notify 3", TRUE);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_LVS_EX_TRANSPARENTBKGND(void)
+{
+ HWND hwnd;
+ DWORD ret;
+ HDC hdc;
+
+ hwnd = create_listview_control(LVS_REPORT);
+
+ ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
+ expect(TRUE, ret);
+
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
+ LVS_EX_TRANSPARENTBKGND);
+
+ ret = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
+ if (ret != CLR_NONE)
+ {
+ win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ /* try to set some back color and check this style bit */
+ ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
+ expect(TRUE, ret);
+ ret = SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+ ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
+
+ /* now test what this style actually does */
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
+ LVS_EX_TRANSPARENTBKGND);
+
+ hdc = GetWindowDC(hwndparent);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
+ "LVS_EX_TRANSPARENTBKGND parent", FALSE);
+
+ ReleaseDC(hwndparent, hdc);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_approximate_viewrect(void)
+{
+ HWND hwnd;
+ DWORD ret;
+ HIMAGELIST himl;
+ HBITMAP hbmp;
+ LVITEMA itema;
+ static CHAR test[] = "abracadabra, a very long item label";
+
+ hwnd = create_listview_control(LVS_ICON);
+ himl = ImageList_Create(40, 40, 0, 4, 4);
+ ok(himl != NULL, "failed to create imagelist\n");
+ hbmp = CreateBitmap(40, 40, 1, 1, NULL);
+ ok(hbmp != NULL, "failed to create bitmap\n");
+ ret = ImageList_Add(himl, hbmp, 0);
+ expect(0, ret);
+ ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
+ expect(0, ret);
+
+ itema.mask = LVIF_IMAGE;
+ itema.iImage = 0;
+ itema.iItem = 0;
+ itema.iSubItem = 0;
+ ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
+ expect(0, ret);
+
+ ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75));
+ if (ret == 0)
+ {
+ /* version 4.0 */
+ win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
+ return;
+ }
+
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
+ ok(MAKELONG(77,827)==ret,"Incorrect Approximate rect\n");
+
+ ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50));
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
+ ok(MAKELONG(102,302)==ret,"Incorrect Approximate rect\n");
+
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
+ ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
+
+ itema.pszText = test;
+ ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
+ expect(TRUE, ret);
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
+ ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
+
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100));
+ ok(MAKELONG(52,2)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100));
+ ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100));
+ ok(MAKELONG(102,52)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100));
+ ok(MAKELONG(102,102)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100));
+ ok(MAKELONG(102,102)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100));
+ ok(MAKELONG(102,152)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100));
+ ok(MAKELONG(102,152)==ret,"Incorrect Approximate rect\n");
+ ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100));
+ ok(MAKELONG(152,152)==ret,"Incorrect Approximate rect\n");
+
+ DestroyWindow(hwnd);
+}
+
+static void test_finditem(void)
+{
+ LVFINDINFOA fi;
+ static char f[5];
+ HWND hwnd;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ insert_item(hwnd, 0);
+
+ memset(&fi, 0, sizeof(fi));
+
+ /* full string search, inserted text was "foo" */
+ strcpy(f, "foo");
+ fi.flags = LVFI_STRING;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(0, r);
+ /* partial string search, inserted text was "foo" */
+ strcpy(f, "fo");
+ fi.flags = LVFI_STRING | LVFI_PARTIAL;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(0, r);
+ /* partial string search, part after start char */
+ strcpy(f, "oo");
+ fi.flags = LVFI_STRING | LVFI_PARTIAL;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(-1, r);
+
+ /* try with LVFI_SUBSTRING */
+ strcpy(f, "fo");
+ fi.flags = LVFI_SUBSTRING;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ if (r == -1)
+ {
+ win_skip("LVFI_SUBSTRING not supported\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+ expect(0, r);
+ strcpy(f, "f");
+ fi.flags = LVFI_SUBSTRING;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(0, r);
+ strcpy(f, "o");
+ fi.flags = LVFI_SUBSTRING;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(-1, r);
+
+ strcpy(f, "f");
+ fi.flags = LVFI_SUBSTRING | LVFI_STRING;
+ fi.psz = f;
+ r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
+ expect(0, r);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_LVS_EX_HEADERINALLVIEWS(void)
+{
+ HWND hwnd, header;
+ DWORD style;
+
+ hwnd = create_listview_control(LVS_ICON);
+
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
+ LVS_EX_HEADERINALLVIEWS);
+
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ if (!IsWindow(header))
+ {
+ win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ /* LVS_NOCOLUMNHEADER works as before */
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER);
+ style = GetWindowLongA(header, GWL_STYLE);
+ ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n");
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER);
+ style = GetWindowLongA(header, GWL_STYLE);
+ ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n");
+
+ /* try to remove style */
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0);
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header to be created\n");
+ style = GetWindowLongA(header, GWL_STYLE);
+ ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n");
+
+ DestroyWindow(hwnd);
+
+ /* check other styles */
+ hwnd = create_listview_control(LVS_LIST);
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
+ LVS_EX_HEADERINALLVIEWS);
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header to be created\n");
+ DestroyWindow(hwnd);
+
+ hwnd = create_listview_control(LVS_SMALLICON);
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
+ LVS_EX_HEADERINALLVIEWS);
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header to be created\n");
+ DestroyWindow(hwnd);
+
+ hwnd = create_listview_control(LVS_REPORT);
+ SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
+ LVS_EX_HEADERINALLVIEWS);
+ header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(header), "Expected header to be created\n");
+ DestroyWindow(hwnd);
+}
+
+static void test_hover(void)
+{
+ HWND hwnd;
+ DWORD r;
+
+ hwnd = create_listview_control(LVS_ICON);
+
+ /* test WM_MOUSEHOVER forwarding */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwnd, WM_MOUSEHOVER, 0, 0);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER allow test", TRUE);
+ g_block_hover = TRUE;
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ r = SendMessage(hwnd, WM_MOUSEHOVER, 0, 0);
+ expect(0, r);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER block test", TRUE);
+ g_block_hover = FALSE;
+
+ r = SendMessage(hwnd, LVM_SETHOVERTIME, 0, 500);
+ expect(HOVER_DEFAULT, r);
+ r = SendMessage(hwnd, LVM_GETHOVERTIME, 0, 0);
+ expect(500, r);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_destroynotify(void)
+{
+ HWND hwnd;
+
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create listview window\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+ ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_destroy, "check destroy order", FALSE);
+}
+
+static void test_header_notification(void)
+{
+ HWND list, header;
+ HDITEMA item;
+ NMHEADER nmh;
+ LVCOLUMNA col;
+ LRESULT ret;
+
+ list = create_listview_control(LVS_REPORT);
+ ok(list != 0, "failed to create listview window\n");
+
+ memset(&col, 0, sizeof(col));
+ col.mask = LVCF_WIDTH;
+ col.cx = 100;
+ ret = SendMessage(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
+ ok(!ret, "expected 0, got %ld\n", ret);
+
+ header = subclass_header(list);
+
+ ret = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
+ ok(ret == 1, "expected header item count 1, got %ld\n", ret);
+
+ memset(&item, 0, sizeof(item));
+ item.mask = HDI_WIDTH;
+ ret = SendMessage(header, HDM_GETITEMA, 0, (LPARAM)&item);
+ ok(ret, "HDM_GETITEM failed\n");
+ ok(item.cxy == 100, "expected 100, got %d\n", item.cxy);
+
+ nmh.hdr.hwndFrom = header;
+ nmh.hdr.idFrom = GetWindowLongPtr(header, GWLP_ID);
+ nmh.hdr.code = HDN_ITEMCHANGEDA;
+ nmh.iItem = 0;
+ nmh.iButton = 0;
+ item.mask = HDI_WIDTH;
+ item.cxy = 50;
+ nmh.pitem = &item;
+ ret = SendMessage(list, WM_NOTIFY, 0, (LPARAM)&nmh);
+ ok(!ret, "WM_NOTIFY/HDN_ITEMCHANGED failed\n");
+
+ DestroyWindow(list);
+}
+
+static void test_createdragimage(void)
+{
+ HIMAGELIST himl;
+ POINT pt;
+ HWND list;
+
+ list = create_listview_control(LVS_ICON);
+ ok(list != 0, "failed to create listview window\n");
+
+ insert_item(list, 0);
+
+ /* NULL point */
+ himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, 0);
+ ok(himl == NULL, "got %p\n", himl);
+
+ himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt);
+ ok(himl != NULL, "got %p\n", himl);
+ ImageList_Destroy(himl);
+
+ DestroyWindow(list);
+}
+
+START_TEST(listview)
+{
+ HMODULE hComctl32;
+ BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
+
+ ULONG_PTR ctx_cookie;
+ HANDLE hCtx;
+ HWND hwnd;
+
+ hComctl32 = GetModuleHandleA("comctl32.dll");
+ pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
+ if (pInitCommonControlsEx)
+ {
+ INITCOMMONCONTROLSEX iccex;
+ iccex.dwSize = sizeof(iccex);
+ iccex.dwICC = ICC_LISTVIEW_CLASSES;
+ pInitCommonControlsEx(&iccex);
+ }
+ else
+ InitCommonControls();
+
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ hwndparent = create_parent_window(FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ g_is_below_5 = is_below_comctl_5();
+
+ test_header_notification();
+ test_images();
+ test_checkboxes();
+ test_items();
+ test_create();