[2/2] comctl32/tooltips: Fix callback tip text retrieval

Nikolay Sivov bunglehead at gmail.com
Wed May 27 14:43:08 CDT 2009


http://bugs.winehq.org/show_bug.cgi?id=17563

Changelog:
    - Fix callback tip text retrieval

>From ee116430df2d83aec1ce80214bf4ab7bf9c90d72 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Wed, 27 May 2009 23:01:51 +0400
Subject: Fix callback tip text retrieval

---
 dlls/comctl32/tests/tooltips.c |  104 +++++++++++++++++++++++++++++++++++++++-
 dlls/comctl32/tooltips.c       |   64 +++++++++++++-----------
 2 files changed, 136 insertions(+), 32 deletions(-)

diff --git a/dlls/comctl32/tests/tooltips.c b/dlls/comctl32/tests/tooltips.c
index 2b4f43f..6a927aa 100644
--- a/dlls/comctl32/tests/tooltips.c
+++ b/dlls/comctl32/tests/tooltips.c
@@ -232,14 +232,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,
@@ -266,7 +315,58 @@ static void test_gettext(void)
         ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
     }
 
+    /* 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,
diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c
index ee2700f..9d7c327 100644
--- a/dlls/comctl32/tooltips.c
+++ b/dlls/comctl32/tooltips.c
@@ -359,7 +359,7 @@ TOOLTIPS_Refresh (const TOOLTIPS_INFO *infoPtr, HDC hdc)
         DeleteObject(hRgn);
 }
 
-static void TOOLTIPS_GetDispInfoA(TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
+static void TOOLTIPS_GetDispInfoA(const TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr, WCHAR *buffer)
 {
     NMTTDISPINFOA ttnmdi;
 
@@ -377,45 +377,45 @@ static void TOOLTIPS_GetDispInfoA(TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
 
     if (IS_INTRESOURCE(ttnmdi.lpszText)) {
         LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
-               infoPtr->szTipText, INFOTIPSIZE);
+               buffer, INFOTIPSIZE);
         if (ttnmdi.uFlags & TTF_DI_SETITEM) {
             toolPtr->hinst = ttnmdi.hinst;
             toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText;
         }
     }
     else if (ttnmdi.lpszText == 0) {
-        infoPtr->szTipText[0] = '\0';
+        buffer[0] = '\0';
     }
     else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
-        Str_GetPtrAtoW(ttnmdi.lpszText, infoPtr->szTipText, INFOTIPSIZE);
+        Str_GetPtrAtoW(ttnmdi.lpszText, buffer, INFOTIPSIZE);
         if (ttnmdi.uFlags & TTF_DI_SETITEM) {
             toolPtr->hinst = 0;
             toolPtr->lpszText = NULL;
-            Str_SetPtrW(&toolPtr->lpszText, infoPtr->szTipText);
+            Str_SetPtrW(&toolPtr->lpszText, buffer);
         }
     }
     else {
         ERR("recursive text callback!\n");
-        infoPtr->szTipText[0] = '\0';
+        buffer[0] = '\0';
     }
 
     /* no text available - try calling parent instead as per native */
     /* FIXME: Unsure if SETITEM should save the value or not        */
-    if (infoPtr->szTipText[0] == 0x00) {
+    if (buffer[0] == 0x00) {
 
         SendMessageW(GetParent(toolPtr->hwnd), WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi);
 
         if (IS_INTRESOURCE(ttnmdi.lpszText)) {
             LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
-                   infoPtr->szTipText, INFOTIPSIZE);
+                   buffer, INFOTIPSIZE);
         } else if (ttnmdi.lpszText &&
                    ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
-            Str_GetPtrAtoW(ttnmdi.lpszText, infoPtr->szTipText, INFOTIPSIZE);
+            Str_GetPtrAtoW(ttnmdi.lpszText, buffer, INFOTIPSIZE);
         }
     }
 }
 
-static void TOOLTIPS_GetDispInfoW(TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
+static void TOOLTIPS_GetDispInfoW(const TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr, WCHAR *buffer)
 {
     NMTTDISPINFOW ttnmdi;
 
@@ -433,47 +433,47 @@ static void TOOLTIPS_GetDispInfoW(TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
 
     if (IS_INTRESOURCE(ttnmdi.lpszText)) {
         LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
-               infoPtr->szTipText, INFOTIPSIZE);
+               buffer, INFOTIPSIZE);
         if (ttnmdi.uFlags & TTF_DI_SETITEM) {
             toolPtr->hinst = ttnmdi.hinst;
             toolPtr->lpszText = ttnmdi.lpszText;
         }
     }
     else if (ttnmdi.lpszText == 0) {
-        infoPtr->szTipText[0] = '\0';
+        buffer[0] = '\0';
     }
     else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) {
-        Str_GetPtrW(ttnmdi.lpszText, infoPtr->szTipText, INFOTIPSIZE);
+        Str_GetPtrW(ttnmdi.lpszText, buffer, INFOTIPSIZE);
         if (ttnmdi.uFlags & TTF_DI_SETITEM) {
             toolPtr->hinst = 0;
             toolPtr->lpszText = NULL;
-            Str_SetPtrW(&toolPtr->lpszText, infoPtr->szTipText);
+            Str_SetPtrW(&toolPtr->lpszText, buffer);
         }
     }
     else {
         ERR("recursive text callback!\n");
-        infoPtr->szTipText[0] = '\0';
+        buffer[0] = '\0';
     }
 
     /* no text available - try calling parent instead as per native */
     /* FIXME: Unsure if SETITEM should save the value or not        */
-    if (infoPtr->szTipText[0] == 0x00) {
+    if (buffer[0] == 0x00) {
 
         SendMessageW(GetParent(toolPtr->hwnd), WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi);
 
         if (IS_INTRESOURCE(ttnmdi.lpszText)) {
             LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
-                   infoPtr->szTipText, INFOTIPSIZE);
+                   buffer, INFOTIPSIZE);
         } else if (ttnmdi.lpszText &&
                    ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) {
-            Str_GetPtrW(ttnmdi.lpszText, infoPtr->szTipText, INFOTIPSIZE);
+            Str_GetPtrW(ttnmdi.lpszText, buffer, INFOTIPSIZE);
         }
     }
 
 }
 
 static void
-TOOLTIPS_GetTipText (TOOLTIPS_INFO *infoPtr, INT nTool)
+TOOLTIPS_GetTipText (const TOOLTIPS_INFO *infoPtr, INT nTool, WCHAR *buffer)
 {
     TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
 
@@ -482,26 +482,26 @@ TOOLTIPS_GetTipText (TOOLTIPS_INFO *infoPtr, INT nTool)
 	TRACE("load res string %p %x\n",
 	       toolPtr->hinst, LOWORD(toolPtr->lpszText));
 	LoadStringW (toolPtr->hinst, LOWORD(toolPtr->lpszText),
-		       infoPtr->szTipText, INFOTIPSIZE);
+		       buffer, INFOTIPSIZE);
     }
     else if (toolPtr->lpszText) {
 	if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
 	    if (toolPtr->bNotifyUnicode)
-		TOOLTIPS_GetDispInfoW(infoPtr, toolPtr);
+		TOOLTIPS_GetDispInfoW(infoPtr, toolPtr, buffer);
 	    else
-		TOOLTIPS_GetDispInfoA(infoPtr, toolPtr);
+		TOOLTIPS_GetDispInfoA(infoPtr, toolPtr, buffer);
 	}
 	else {
 	    /* the item is a usual (unicode) text */
-	    lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
+	    lstrcpynW (buffer, toolPtr->lpszText, INFOTIPSIZE);
 	}
     }
     else {
 	/* no text available */
-        infoPtr->szTipText[0] = '\0';
+        buffer[0] = '\0';
     }
 
-    TRACE("%s\n", debugstr_w(infoPtr->szTipText));
+    TRACE("%s\n", debugstr_w(buffer));
 }
 

@@ -597,7 +597,7 @@ TOOLTIPS_Show (TOOLTIPS_INFO *infoPtr, BOOL track_activate)
 
     TRACE("Show tooltip pre %d! (%p)\n", nTool, infoPtr->hwndSelf);
 
-    TOOLTIPS_GetTipText (infoPtr, nTool);
+    TOOLTIPS_GetTipText (infoPtr, nTool, infoPtr->szTipText);
 
     if (infoPtr->szTipText[0] == '\0')
         return;
@@ -1506,6 +1506,7 @@ TOOLTIPS_GetMaxTipWidth (const TOOLTIPS_INFO *infoPtr)
 static LRESULT
 TOOLTIPS_GetTextA (const TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
 {
+    WCHAR buffer[INFOTIPSIZE];
     INT nTool;
 
     if (lpToolInfo == NULL)
@@ -1520,8 +1521,10 @@ TOOLTIPS_GetTextA (const TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
        what size buffer it requires nor a way to specify how long the
        one it supplies is.  We'll assume it's up to INFOTIPSIZE */
 
-    WideCharToMultiByte(CP_ACP, 0, infoPtr->tools[nTool].lpszText, -1,
-			lpToolInfo->lpszText, INFOTIPSIZE, NULL, NULL);
+    buffer[0] = '\0';
+    TOOLTIPS_GetTipText(infoPtr, nTool, buffer);
+    WideCharToMultiByte(CP_ACP, 0, buffer, -1, lpToolInfo->lpszText,
+                                               INFOTIPSIZE, NULL, NULL);
 
     return 0;
 }
@@ -1543,7 +1546,8 @@ TOOLTIPS_GetTextW (const TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
     if (infoPtr->tools[nTool].lpszText == NULL)
 	return 0;
 
-    strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
+    lpToolInfo->lpszText[0] = '\0';
+    TOOLTIPS_GetTipText(infoPtr, nTool, lpToolInfo->lpszText);
 
     return 0;
 }
@@ -2073,7 +2077,7 @@ TOOLTIPS_SetToolInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
 
     if (infoPtr->nCurrentTool == nTool)
     {
-        TOOLTIPS_GetTipText (infoPtr, infoPtr->nCurrentTool);
+        TOOLTIPS_GetTipText (infoPtr, infoPtr->nCurrentTool, infoPtr->szTipText);
 
         if (infoPtr->szTipText[0] == 0)
             TOOLTIPS_Hide(infoPtr);
-- 
1.5.6.5





More information about the wine-patches mailing list