kernel32: Implement GetShortPathName16.
[wine] / dlls / comctl32 / tests / toolbar.c
index 5e619ee..02601cf 100644 (file)
@@ -1,4 +1,4 @@
-/* Unit tests for treeview.
+/* Unit tests for toolbar.
  *
  * Copyright 2005 Krzysztof Foltman
  * Copyright 2007 Mikolaj Zalewski
@@ -40,6 +40,8 @@ static BOOL g_fExpectedHotItemOld;
 static BOOL g_fExpectedHotItemNew;
 static DWORD g_dwExpectedDispInfoMask;
 
+#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
+
 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
     val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
     val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
@@ -112,7 +114,7 @@ static void basic_test(void)
         WS_VISIBLE | WS_CLIPCHILDREN | CCS_TOP |
         WS_CHILD | TBSTYLE_LIST,
         100,
-        0, NULL, (UINT)0,
+        0, NULL, 0,
         buttons, sizeof(buttons)/sizeof(buttons[0]),
         0, 0, 20, 16, sizeof(TBBUTTON));
     ok(hToolbar != NULL, "Toolbar creation\n");
@@ -166,7 +168,7 @@ static void rebuild_toolbar(HWND *hToolbar)
     *hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
         hMainWnd, (HMENU)5, GetModuleHandle(NULL), NULL);
     ok(*hToolbar != NULL, "Toolbar creation problem\n");
-    ok(SendMessage(*hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
+    ok(SendMessage(*hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
     ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
     ok(SendMessage(*hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
 }
@@ -201,6 +203,13 @@ static void rebuild_toolbar_with_buttons(HWND *hToolbar)
     ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
 }
 
+static void add_128x15_bitmap(HWND hToolbar, int nCmds)
+{
+    TBADDBITMAP bmp128;
+    bmp128.hInst = GetModuleHandle(NULL);
+    bmp128.nID = IDB_BITMAP_128x15;
+    ok(SendMessageA(hToolbar, TB_ADDBITMAP, nCmds, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+}
 
 #define CHECK_IMAGELIST(count, dx, dy) { \
     int cx, cy; \
@@ -709,6 +718,18 @@ static tbsize_result_t tbsize_results[] =
     {  0,   0, 163,  38}, {163,   0, 326,  38}, {326,   0, 489,  38},
     {489,   0, 652,  38}, {652,   0, 819,  38}, {819,   0, 850,  38},
   }, },
+  { {0, 0, 672, 100}, {239, 102}, 3, {
+    {  0,   2, 100,  102}, {100,   2, 139,  102}, {139, 2, 239,  102},
+  }, },
+  { {0, 0, 672, 42}, {185, 40}, 3, {
+      {  0,   2,  75,  40}, {75,   2, 118, 40}, {118, 2, 185, 40},
+  }, },
+  { {0, 0, 672, 42}, {67, 40}, 1, {
+      {  0,   2,  67,  40},
+  }, },
+  { {0, 0, 672, 42}, {67, 41}, 2, {
+      {  0,   2,  672,  41}, {  0,   41,  672,  80},
+  }, },
 };
 
 static int tbsize_numtests = 0;
@@ -757,6 +778,7 @@ static void test_sizes(void)
 {
     HWND hToolbar = NULL;
     HIMAGELIST himl;
+    TBBUTTONINFO tbinfo;
     int style;
     int i;
 
@@ -852,6 +874,18 @@ static void test_sizes(void)
     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 15));
     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 21), "Unexpected button size\n");
+    /* -1 in TB_SETBITMAPSIZE is a special code meaning that the coordinate shouldn't be changed */
+    add_128x15_bitmap(hToolbar, 16);
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(14, -1)), "TB_SETBITMAPSIZE failed\n");
+    compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(21, 21), "%x");
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(-1, 12)), "TB_SETBITMAPSIZE failed\n");
+    compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(21, 18), "%x");
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(-1, -1)), "TB_SETBITMAPSIZE failed\n");
+    compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(21, 18), "%x");
+    /* check the imagelist */
+    InvalidateRect(hToolbar, NULL, TRUE);
+    UpdateWindow(hToolbar);
+    CHECK_IMAGELIST(16, 14, 12);
 
     rebuild_toolbar(&hToolbar);
     SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
@@ -922,6 +956,148 @@ static void test_sizes(void)
     SendMessageA(hToolbar, TB_DELETEBUTTON, 0, 0);
     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
 
+    rebuild_toolbar(&hToolbar);
+
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(32, 32)) == 1, "TB_SETBITMAPSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(100, 100)) == 1, "TB_SETBUTTONSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons2[0]) == 1, "TB_ADDBUTTONS failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[2]) == 1, "TB_ADDBUTTONS failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[0]) == 1, "TB_ADDBUTTONS failed\n");
+    SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
+    check_sizes();
+
+    rebuild_toolbar(&hToolbar);
+    SetWindowLong(hToolbar, GWL_STYLE, TBSTYLE_LIST | GetWindowLong(hToolbar, GWL_STYLE));
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(32, 32)) == 1, "TB_SETBITMAPSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(100, 100)) == 1, "TB_SETBUTTONSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons2[0]) == 1, "TB_ADDBUTTONS failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[2]) == 1, "TB_ADDBUTTONS failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]) == 1, "TB_ADDBUTTONS failed\n");
+    SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
+    check_sizes_todo(0xff);
+
+    rebuild_toolbar(&hToolbar);
+    SetWindowLong(hToolbar, GWL_STYLE, TBSTYLE_LIST | GetWindowLong(hToolbar, GWL_STYLE));
+    ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(32, 32)) == 1, "TB_SETBITMAPSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(100, 100)) == 1, "TB_SETBUTTONSIZE failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]) == 1, "TB_ADDBUTTONS failed\n");
+    SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0 );
+    check_sizes();
+
+    rebuild_toolbar(&hToolbar);
+    SetWindowLong(hToolbar, GWL_STYLE, TBSTYLE_WRAPABLE | GetWindowLong(hToolbar, GWL_STYLE));
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]) == 1, "TB_ADDBUTTONS failed\n");
+    ok(SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]) == 1, "TB_ADDBUTTONS failed\n");
+    tbinfo.cx = 672;
+    tbinfo.cbSize = sizeof(TBBUTTONINFO);
+    tbinfo.dwMask = TBIF_SIZE | TBIF_BYINDEX;
+    ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 0, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
+    ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
+    SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
+    check_sizes();
+
+    DestroyWindow(hToolbar);
+}
+
+/* Toolbar control has two ways of reacting to a change. We call them a
+ * relayout and recalc. A recalc forces a recompute of values like button size
+ * and top margin (the latter in comctl32 <v6), while a relayout uses the cached
+ * values. This functions creates a flat toolbar with a top margin of a non-flat
+ * toolbar. We will notice a recalc, as it will recompte the top margin and
+ * change it to zero*/
+static void prepare_recalc_test(HWND *phToolbar)
+{
+    RECT rect;
+    rebuild_toolbar_with_buttons(phToolbar);
+    SetWindowLong(*phToolbar, GWL_STYLE,
+        GetWindowLong(*phToolbar, GWL_STYLE) | TBSTYLE_FLAT);
+    SendMessage(*phToolbar, TB_GETITEMRECT, 1, (LPARAM)&rect);
+    ok(rect.top == 2, "Test will make no sense because initial top is %d instead of 2\n",
+        rect.top);
+}
+
+static BOOL did_recalc(HWND hToolbar)
+{
+    RECT rect;
+    SendMessage(hToolbar, TB_GETITEMRECT, 1, (LPARAM)&rect);
+    ok(rect.top == 2 || rect.top == 0, "Unexpected top margin %d in recalc test\n",
+        rect.top);
+    return (rect.top == 0);
+}
+
+/* call after a recalc did happen to return to an unstable state */
+static void restore_recalc_state(HWND hToolbar)
+{
+    RECT rect;
+    /* return to style with a 2px top margin */
+    SetWindowLong(hToolbar, GWL_STYLE,
+        GetWindowLong(hToolbar, GWL_STYLE) & ~TBSTYLE_FLAT);
+    /* recalc */
+    SendMessage(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]);
+    /* top margin will be 0px if a recalc occurs */
+    SetWindowLong(hToolbar, GWL_STYLE,
+        GetWindowLong(hToolbar, GWL_STYLE) | TBSTYLE_FLAT);
+    /* safety check */
+    SendMessage(hToolbar, TB_GETITEMRECT, 1, (LPARAM)&rect);
+    ok(rect.top == 2, "Test will make no sense because initial top is %d instead of 2\n",
+        rect.top);
+}
+
+static void test_recalc(void)
+{
+    HWND hToolbar;
+    TBBUTTONINFO bi;
+    CHAR test[] = "Test";
+    const int EX_STYLES_COUNT = 5;
+    int i;
+
+    /* Like TB_ADDBUTTONS tested in test_sized, inserting a button without text
+     * results in a relayout, while adding one with text forces a recalc */
+    prepare_recalc_test(&hToolbar);
+    SendMessage(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons3[0]);
+    ok(!did_recalc(hToolbar), "Unexpected recalc - adding button without text\n");
+
+    prepare_recalc_test(&hToolbar);
+    SendMessage(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons3[3]);
+    ok(did_recalc(hToolbar), "Expected a recalc - adding button with text\n");
+
+    /* TB_SETBUTTONINFO, even when adding a text, results only in a relayout */
+    prepare_recalc_test(&hToolbar);
+    bi.cbSize = sizeof(bi);
+    bi.dwMask = TBIF_TEXT;
+    bi.pszText = test;
+    SendMessage(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&bi);
+    ok(!did_recalc(hToolbar), "Unexpected recalc - setting a button text\n");
+
+    /* most extended styled doesn't force a recalc (testing all the bits gives
+     * the same results, but prints some ERRs while testing) */
+    for (i = 0; i < EX_STYLES_COUNT; i++)
+    {
+        if (i == 1 || i == 3)  /* an undoc style and TBSTYLE_EX_MIXEDBUTTONS */
+            continue;
+        prepare_recalc_test(&hToolbar);
+        expect(0, (int)SendMessage(hToolbar, TB_GETEXTENDEDSTYLE, 0, 0));
+        SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, (1 << i));
+        ok(!did_recalc(hToolbar), "Unexpected recalc - setting bit %d\n", i);
+        SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, 0);
+        ok(!did_recalc(hToolbar), "Unexpected recalc - clearing bit %d\n", i);
+        expect(0, (int)SendMessage(hToolbar, TB_GETEXTENDEDSTYLE, 0, 0));
+    }
+
+    /* TBSTYLE_EX_MIXEDBUTTONS does a recalc on change */
+    prepare_recalc_test(&hToolbar);
+    SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
+    ok(did_recalc(hToolbar), "Expected a recalc - setting TBSTYLE_EX_MIXEDBUTTONS\n");
+    restore_recalc_state(hToolbar);
+    SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
+    ok(!did_recalc(hToolbar), "Unexpected recalc - setting TBSTYLE_EX_MIXEDBUTTONS again\n");
+    restore_recalc_state(hToolbar);
+    SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, 0);
+    ok(did_recalc(hToolbar), "Expected a recalc - clearing TBSTYLE_EX_MIXEDBUTTONS\n");
+
+    /* undocumented exstyle 0x2 seems to changes the top margin, what
+     * interferes with these tests */
+
     DestroyWindow(hToolbar);
 }
 
@@ -948,7 +1124,7 @@ static void test_getbuttoninfo(void)
     DestroyWindow(hToolbar);
 }
 
-static void test_createtoolbarex()
+static void test_createtoolbarex(void)
 {
     HWND hToolbar;
     TBBUTTON btns[3];
@@ -1063,7 +1239,7 @@ static void test_setrows(void)
         WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD | CCS_NORESIZE | CCS_NOPARENTALIGN
         | CCS_NOMOVEY | CCS_TOP,
         0,
-        0, NULL, (UINT)0,
+        0, NULL, 0,
         buttons, sizeof(buttons)/sizeof(buttons[0]),
         20, 20, 0, 0, sizeof(TBBUTTON));
     ok(hToolbar != NULL, "Toolbar creation\n");
@@ -1077,7 +1253,7 @@ static void test_setrows(void)
         memset(&rc, 0xCC, sizeof(rc));
         SendMessageA(hToolbar, TB_SETROWS,
                      MAKELONG(tbrows_results[i].nRows, tbrows_results[i].bLarger),
-                     (LONG) &rc);
+                     (LPARAM) &rc);
 
         rows = SendMessageA(hToolbar, TB_GETROWS, MAKELONG(0,0), MAKELONG(0,0));
         ok(rows == tbrows_results[i].expectedRows,
@@ -1088,6 +1264,38 @@ static void test_setrows(void)
     DestroyWindow(hToolbar);
 }
 
+static void test_getstring(void)
+{
+    HWND hToolbar = NULL;
+    char str[10];
+    WCHAR strW[10];
+    static const char answer[] = "STR";
+    static const WCHAR answerW[] = { 'S','T','R',0 };
+    INT r;
+
+    hToolbar = CreateWindowExA(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hMainWnd, (HMENU)5, GetModuleHandle(NULL), NULL);
+    ok(hToolbar != NULL, "Toolbar creation problem\n");
+
+    r = SendMessage(hToolbar, TB_GETSTRING, MAKEWPARAM(0, 0), 0);
+    expect(-1, r);
+    r = SendMessage(hToolbar, TB_GETSTRINGW, MAKEWPARAM(0, 0), 0);
+    expect(-1, r);
+    r = SendMessage(hToolbar, TB_ADDSTRING, 0, (LPARAM)answer);
+    expect(0, r);
+    r = SendMessage(hToolbar, TB_GETSTRING, MAKEWPARAM(0, 0), 0);
+    expect(lstrlenA(answer), r);
+    r = SendMessage(hToolbar, TB_GETSTRINGW, MAKEWPARAM(0, 0), 0);
+    expect(lstrlenA(answer), r);
+    r = SendMessage(hToolbar, TB_GETSTRING, MAKEWPARAM(sizeof(str), 0), (LPARAM)str);
+    expect(lstrlenA(answer), r);
+    expect(0, lstrcmp(answer, str));
+    r = SendMessage(hToolbar, TB_GETSTRINGW, MAKEWPARAM(sizeof(strW), 0), (LPARAM)strW);
+    expect(lstrlenA(answer), r);
+    expect(0, lstrcmpW(answerW, strW));
+
+    DestroyWindow(hToolbar);
+}
+
 START_TEST(toolbar)
 {
     WNDCLASSA wc;
@@ -1101,7 +1309,7 @@ START_TEST(toolbar)
     wc.cbWndExtra = 0;
     wc.hInstance = GetModuleHandleA(NULL);
     wc.hIcon = NULL;
-    wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
+    wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
     wc.lpszMenuName = NULL;
     wc.lpszClassName = "MyTestWnd";
@@ -1118,10 +1326,12 @@ START_TEST(toolbar)
     test_add_string();
     test_hotitem();
     test_sizes();
+    test_recalc();
     test_getbuttoninfo();
     test_createtoolbarex();
     test_dispinfo();
     test_setrows();
+    test_getstring();
 
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {