[COMCTL32_WINETEST]
[reactos.git] / rostests / winetests / comctl32 / tooltips.c
index 2b4f43f..8ca3f7b 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "wine/test.h"
 
+#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
+
 static void test_create_tooltip(void)
 {
     HWND parent, hwnd;
@@ -42,7 +44,8 @@ static void test_create_tooltip(void)
     trace("style = %08x\n", style);
     exp_style = 0x7fffffff | WS_POPUP;
     exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME);
-    ok(style == exp_style,"wrong style %08x/%08x\n", style, exp_style);
+    ok(style == exp_style || broken(style == (exp_style | WS_BORDER)), /* nt4 */
+       "wrong style %08x/%08x\n", style, exp_style);
 
     DestroyWindow(hwnd);
 
@@ -142,7 +145,6 @@ static void test_customdraw(void) {
         /* Invalid notification responses */
         {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
         {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
-        {CDRF_NOTIFYSUBITEMDRAW, TEST_CDDS_PREPAINT},
         {CDRF_NEWFONT, TEST_CDDS_PREPAINT}
     };
 
@@ -168,6 +170,7 @@ static void test_customdraw(void) {
         iterationNumber++) {
 
        HWND parent, hwndTip;
+       RECT rect;
        TOOLINFO toolInfo = { 0 };
 
        /* Create a main window */
@@ -201,7 +204,7 @@ static void test_customdraw(void) {
              SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
 
        /* Create a tool */
-       toolInfo.cbSize = sizeof(TOOLINFO);
+       toolInfo.cbSize = TTTOOLINFO_V1_SIZE;
        toolInfo.hwnd = parent;
        toolInfo.hinst = GetModuleHandleA(NULL);
        toolInfo.uFlags = TTF_SUBCLASS;
@@ -216,13 +219,18 @@ static void test_customdraw(void) {
        SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
 
        /* Put cursor inside window, tooltip will appear immediately */
-       SetCursorPos(100, 100);
+       GetWindowRect( parent, &rect );
+       SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
        flush_events(200);
 
-       /* Check CustomDraw results */
-       ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls,
-          "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
-          expectedResults[iterationNumber].ExpectedCalls);
+       if (CD_Stages)
+       {
+           /* Check CustomDraw results */
+           ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls ||
+              broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */
+              "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
+              expectedResults[iterationNumber].ExpectedCalls);
+       }
 
        /* Clean up */
        DestroyWindow(hwndTip);
@@ -232,14 +240,63 @@ static void test_customdraw(void) {
 
 }
 
+static const CHAR testcallbackA[]  = "callback";
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    if (message == WM_NOTIFY && lParam)
+    {
+        NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
+
+        if (ttnmdi->hdr.code == TTN_GETDISPINFOA)
+            lstrcpy(ttnmdi->lpszText, testcallbackA);
+    }
+
+    return DefWindowProcA(hwnd, message, wParam, lParam);
+}
+
+static BOOL register_parent_wnd_class(void)
+{
+    WNDCLASSA cls;
+
+    cls.style = 0;
+    cls.lpfnWndProc = parent_wnd_proc;
+    cls.cbClsExtra = 0;
+    cls.cbWndExtra = 0;
+    cls.hInstance = GetModuleHandleA(NULL);
+    cls.hIcon = 0;
+    cls.hCursor = LoadCursorA(0, IDC_ARROW);
+    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+    cls.lpszMenuName = NULL;
+    cls.lpszClassName = "Tooltips test parent class";
+    return RegisterClassA(&cls);
+}
+
+static HWND create_parent_window(void)
+{
+    if (!register_parent_wnd_class())
+        return NULL;
+
+    return CreateWindowEx(0, "Tooltips test parent class",
+                          "Tooltips test parent window",
+                          WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+                          WS_MAXIMIZEBOX | WS_VISIBLE,
+                          0, 0, 100, 100,
+                          GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
+}
+
 static void test_gettext(void)
 {
-    HWND hwnd;
+    HWND hwnd, notify;
     TTTOOLINFOA toolinfoA;
     TTTOOLINFOW toolinfoW;
     LRESULT r;
-    char bufA[10] = "";
+    CHAR bufA[10] = "";
     WCHAR bufW[10] = { 0 };
+    static const CHAR testtipA[] = "testtip";
+
+    notify = create_parent_window();
+    ok(notify != NULL, "Expected notification window to be created\n");
 
     /* For bug 14790 - lpszText is NULL */
     hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
@@ -247,6 +304,8 @@ static void test_gettext(void)
                            NULL, NULL, NULL, 0);
     assert(hwnd);
 
+    /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
+    /* otherwise it crashes on the NULL lpszText */
     toolinfoA.cbSize = sizeof(TTTOOLINFOA);
     toolinfoA.hwnd = NULL;
     toolinfoA.hinst = GetModuleHandleA(NULL);
@@ -256,7 +315,6 @@ static void test_gettext(void)
     toolinfoA.lParam = 0xdeadbeef;
     GetClientRect(hwnd, &toolinfoA.rect);
     r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
-    ok(r, "Adding the tool to the tooltip failed\n");
     if (r)
     {
         toolinfoA.hwnd = NULL;
@@ -265,8 +323,65 @@ static void test_gettext(void)
         SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
         ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
     }
+    else
+    {
+        win_skip( "Old comctl32, not testing NULL text\n" );
+        DestroyWindow( hwnd );
+        return;
+    }
+
+    /* add another tool with text */
+    toolinfoA.cbSize = sizeof(TTTOOLINFOA);
+    toolinfoA.hwnd = NULL;
+    toolinfoA.hinst = GetModuleHandleA(NULL);
+    toolinfoA.uFlags = 0;
+    toolinfoA.uId = 0x1235ABCD;
+    strcpy(bufA, testtipA);
+    toolinfoA.lpszText = bufA;
+    toolinfoA.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &toolinfoA.rect);
+    r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    if (r)
+    {
+        DWORD length;
+
+        length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
+        ok(length == 0, "Expected 0, got %d\n", length);
+
+        toolinfoA.hwnd = NULL;
+        toolinfoA.uId = 0x1235ABCD;
+        toolinfoA.lpszText = bufA;
+        SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
+        ok(strcmp(toolinfoA.lpszText, testtipA) == 0, "lpszText should be an empty string\n");
+
+        length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
+        ok(length == 0, "Expected 0, got %d\n", length);
+    }
+
+    /* add another with callback text */
+    toolinfoA.cbSize = sizeof(TTTOOLINFOA);
+    toolinfoA.hwnd = notify;
+    toolinfoA.hinst = GetModuleHandleA(NULL);
+    toolinfoA.uFlags = 0;
+    toolinfoA.uId = 0x1236ABCD;
+    toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
+    toolinfoA.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &toolinfoA.rect);
+    r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    if (r)
+    {
+        toolinfoA.hwnd = notify;
+        toolinfoA.uId = 0x1236ABCD;
+        toolinfoA.lpszText = bufA;
+        SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
+        ok(strcmp(toolinfoA.lpszText, testcallbackA) == 0,
+           "lpszText should be an (%s) string\n", testcallbackA);
+    }
 
     DestroyWindow(hwnd);
+    DestroyWindow(notify);
 
     SetLastError(0xdeadbeef);
     hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
@@ -303,6 +418,208 @@ static void test_gettext(void)
     DestroyWindow(hwnd);
 }
 
+static void test_ttm_gettoolinfo(void)
+{
+    TTTOOLINFOA ti;
+    TTTOOLINFOW tiW;
+    HWND hwnd;
+    DWORD r;
+
+    hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
+                           10, 10, 300, 100,
+                           NULL, NULL, NULL, 0);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE;
+    ti.hwnd = NULL;
+    ti.hinst = GetModuleHandleA(NULL);
+    ti.uFlags = 0;
+    ti.uId = 0x1234ABCD;
+    ti.lpszText = NULL;
+    ti.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &ti.rect);
+    r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
+    ok(r, "Adding the tool to the tooltip failed\n");
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE;
+    ti.lParam = 0xaaaaaaaa;
+    r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
+    ok(r, "Getting tooltip info failed\n");
+    ok(0xdeadbeef == ti.lParam ||
+       broken(0xdeadbeef != ti.lParam), /* comctl32 < 5.81 */
+       "Expected 0xdeadbeef, got %lx\n", ti.lParam);
+
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE;
+    tiW.hwnd = NULL;
+    tiW.uId = 0x1234ABCD;
+    tiW.lParam = 0xaaaaaaaa;
+    r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
+    ok(r, "Getting tooltip info failed\n");
+    ok(0xdeadbeef == tiW.lParam ||
+       broken(0xdeadbeef != tiW.lParam), /* comctl32 < 5.81 */
+       "Expected 0xdeadbeef, got %lx\n", tiW.lParam);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE;
+    ti.uId = 0x1234ABCD;
+    ti.lParam = 0xaaaaaaaa;
+    SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE;
+    ti.lParam = 0xdeadbeef;
+    r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
+    ok(r, "Getting tooltip info failed\n");
+    ok(0xaaaaaaaa == ti.lParam ||
+       broken(0xaaaaaaaa != ti.lParam), /* comctl32 < 5.81 */
+       "Expected 0xaaaaaaaa, got %lx\n", ti.lParam);
+
+    DestroyWindow(hwnd);
+
+    /* 1. test size parameter validation rules (ansi messages) */
+    hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
+                           10, 10, 300, 100,
+                           NULL, NULL, NULL, 0);
+
+    ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
+    ti.hwnd = NULL;
+    ti.hinst = GetModuleHandleA(NULL);
+    ti.uFlags = 0;
+    ti.uId = 0x1234ABCD;
+    ti.lpszText = NULL;
+    ti.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &ti.rect);
+    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
+    ti.hwnd = NULL;
+    ti.uId = 0x1234ABCD;
+    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
+    ti.hwnd = NULL;
+    ti.hinst = GetModuleHandleA(NULL);
+    ti.uFlags = 0;
+    ti.uId = 0x1234ABCD;
+    ti.lpszText = NULL;
+    ti.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &ti.rect);
+    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
+    ti.hwnd = NULL;
+    ti.uId = 0x1234ABCD;
+    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
+    ti.hwnd = NULL;
+    ti.hinst = GetModuleHandleA(NULL);
+    ti.uFlags = 0;
+    ti.uId = 0x1234ABCD;
+    ti.lpszText = NULL;
+    ti.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &ti.rect);
+    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
+    ti.hwnd = NULL;
+    ti.uId = 0x1234ABCD;
+    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
+    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    DestroyWindow(hwnd);
+
+    /* 2. test size parameter validation rules (w-messages) */
+    hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
+                           10, 10, 300, 100,
+                           NULL, NULL, NULL, 0);
+    if(!hwnd)
+    {
+        win_skip("CreateWindowExW() not supported. Skipping.\n");
+        return;
+    }
+
+    tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
+    tiW.hwnd = NULL;
+    tiW.hinst = GetModuleHandleA(NULL);
+    tiW.uFlags = 0;
+    tiW.uId = 0x1234ABCD;
+    tiW.lpszText = NULL;
+    tiW.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &tiW.rect);
+    r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
+    tiW.hwnd = NULL;
+    tiW.uId = 0x1234ABCD;
+    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
+    tiW.hwnd = NULL;
+    tiW.hinst = GetModuleHandleA(NULL);
+    tiW.uFlags = 0;
+    tiW.uId = 0x1234ABCD;
+    tiW.lpszText = NULL;
+    tiW.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &tiW.rect);
+    r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
+    tiW.hwnd = NULL;
+    tiW.uId = 0x1234ABCD;
+    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
+    tiW.hwnd = NULL;
+    tiW.hinst = GetModuleHandleA(NULL);
+    tiW.uFlags = 0;
+    tiW.uId = 0x1234ABCD;
+    tiW.lpszText = NULL;
+    tiW.lParam = 0xdeadbeef;
+    GetClientRect(hwnd, &tiW.rect);
+    r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
+    ok(r, "Adding the tool to the tooltip failed\n");
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+    /* looks like TTM_DELTOOLW doesn't work with invalid size */
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
+    tiW.hwnd = NULL;
+    tiW.uId = 0x1234ABCD;
+    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(1, r);
+
+    tiW.cbSize = TTTOOLINFOW_V2_SIZE;
+    tiW.hwnd = NULL;
+    tiW.uId = 0x1234ABCD;
+    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
+    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
+    expect(0, r);
+
+    DestroyWindow(hwnd);
+}
+
 START_TEST(tooltips)
 {
     InitCommonControls();
@@ -310,4 +627,5 @@ START_TEST(tooltips)
     test_create_tooltip();
     test_customdraw();
     test_gettext();
+    test_ttm_gettoolinfo();
 }