Hi.
Trying without success to show tooltips for a tabcontrol, I found the following problems in the source code. Notice, that my skills in C++ are poor, so it is very possible the following is a false alarm.
I am quote https://github.com/wine-mirror/wine/blob/master/dlls/comctl32/tab.c (hope it is the proper source code)
This seems to be a bug: WM_LBUTTONDOWN is relayed in the WM_MOUSEMOVE handler. But WM_LBUTTONDOWN will always hide the tooltip. WM_MOUSEMOVE instead will set the timer for showing the tooltip.
static LRESULT TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { int redrawLeave; int redrawEnter;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
/* Determine which tab to highlight. Redraw tabs which change highlight ** status. */ TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter);
hottrack_refresh (infoPtr, redrawLeave); hottrack_refresh (infoPtr, redrawEnter);
return 0; }
The WM_LBUTTONDOWN is relayed twice? Why? It is not exactly a bug, but sub-optimal.
static LRESULT TAB_LButtonDown (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { POINT pt; INT newItem; UINT dummy;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
if (!(infoPtr->dwStyle & TCS_FOCUSNEVER)) { SetFocus (infoPtr->hwnd); }
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
So, the continuation of my story, how I fixed the tooltips for tab control and what problems and differences with Windows I found. (It does not seems to be the bestseller of the year, but still can help someone)
At the end I was able to fix the missing tooltips by the following code:
.ti TOOLINFO
invoke SendMessageW, [hEditorsHost], TCM_GETTOOLTIPS, 0, 0 mov esi, eax
mov [.ti.cbSize], sizeof.TOOLINFO mov [.ti.uFlags], TTF_SUBCLASS or TTF_IDISHWND ; it does not work with the tab ctrl ID
mov eax, [hTabControl] mov [.ti.uId], eax
mov eax, [.hParent] ; it handles the TTN_NEEDTEXTW mov [.ti.hwnd], eax
mov [.ti.lpszText], LPSTR_TEXTCALLBACK
lea eax, [.ti] invoke SendMessageW, esi, TTM_ADDTOOLW, 0, eax
Now I got TTN_NEEDTEXTW notifications and everything seemed to work ok, but when testing on Windows it didn't work at all. After some investigation, I found out that the content of the NMHDR structure passed is different in WINE and Windows.
The differences are in the .idFrom field:
WINE puts there the handle of the tab control window (maybe because of the above TTF_IFISHWND). Windows always puts there the index of the tab hovered.
(NB: Actually, the WINE approach of passing the handle of the tab control in .idFrom field is much better and natural, because it gives an easy way to identify which control have to provide the tooltip text)
In attempt to make the same behavior in WINE and Windows, I tried to remove the TTF_IDISHWND flag from the above code and to put in [.ti.uId] the unique ID of the tab control, but then the tooltips stopped to appear in WINE at all.
As a result, in order to have the same behavior in Windows and WINE, one should never use .idFrom field, but instead, identify the hovered tab, by using TCM_HITTEST:
lea ebx, [.pnt] invoke GetCursorPos, ebx
mov ecx, [.pnt.x] mov edx, [.pnt.y] mov [.tchi.pt.x], ecx mov [.tchi.pt.y], edx
lea ebx, [.tchi] invoke ScreenToClient, esi, ebx invoke SendMessageW, esi, TCM_HITTEST, 0, ebx
On Fri, 30 Sep 2016 00:49:14 +0300 John Found johnfound@asm32.info wrote:
Hi.
Trying without success to show tooltips for a tabcontrol, I found the following problems in the source code. Notice, that my skills in C++ are poor, so it is very possible the following is a false alarm.
I am quote https://github.com/wine-mirror/wine/blob/master/dlls/comctl32/tab.c (hope it is the proper source code)
This seems to be a bug: WM_LBUTTONDOWN is relayed in the WM_MOUSEMOVE handler. But WM_LBUTTONDOWN will always hide the tooltip. WM_MOUSEMOVE instead will set the timer for showing the tooltip.
static LRESULT TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { int redrawLeave; int redrawEnter;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
/* Determine which tab to highlight. Redraw tabs which change highlight ** status. */ TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter);
hottrack_refresh (infoPtr, redrawLeave); hottrack_refresh (infoPtr, redrawEnter);
return 0; }
The WM_LBUTTONDOWN is relayed twice? Why? It is not exactly a bug, but sub-optimal.
static LRESULT TAB_LButtonDown (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { POINT pt; INT newItem; UINT dummy;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
if (!(infoPtr->dwStyle & TCS_FOCUSNEVER)) { SetFocus (infoPtr->hwnd); }
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
Am 29.09.2016 um 23:49 schrieb John Found:
Hi.
Trying without success to show tooltips for a tabcontrol, I found the following problems in the source code. Notice, that my skills in C++ are poor, so it is very possible the following is a false alarm.
I am quote https://github.com/wine-mirror/wine/blob/master/dlls/comctl32/tab.c (hope it is the proper source code)
This seems to be a bug: WM_LBUTTONDOWN is relayed in the WM_MOUSEMOVE handler. But WM_LBUTTONDOWN will always hide the tooltip. WM_MOUSEMOVE instead will set the timer for showing the tooltip.
static LRESULT TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { int redrawLeave; int redrawEnter;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
/* Determine which tab to highlight. Redraw tabs which change highlight ** status. */ TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter);
hottrack_refresh (infoPtr, redrawLeave); hottrack_refresh (infoPtr, redrawEnter);
return 0; }
The WM_LBUTTONDOWN is relayed twice? Why? It is not exactly a bug, but sub-optimal.
static LRESULT TAB_LButtonDown (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { POINT pt; INT newItem; UINT dummy;
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
if (!(infoPtr->dwStyle & TCS_FOCUSNEVER)) { SetFocus (infoPtr->hwnd); }
if (infoPtr->hwndToolTip) TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam);
Hi, what you found here looks like a copy&paste error to me, what happens to your problem if you make your suggested change?
On Wed, 5 Oct 2016 21:11:14 +0200 André Hentschel nerv@dawncrow.de wrote:
Hi, what you found here looks like a copy&paste error to me, what happens to your problem if you make your suggested change?
I am not sure I can clone wine, edit and then compile and have working product at the end. I am programming in assembly language and using Fossil version control. The world of C/C++ and git is very, very orthogonal to what I can do. :(