Reputation: 20986
I am having some trouble provding a Win32 tooltips control with dynamic text in unicode format. I use the following code to set up the control:
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);
HWND hwnd_tip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hinst, NULL
);
SetWindowPos(hwnd_tip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
TOOLINFOW ti;
memset(&ti, 0, sizeof(TOOLINFOW));
ti.cbSize = sizeof(TOOLINFOW);
ti.hwnd = hwnd_main;
ti.uId = (UINT) hwnd_control;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.lpszText = L"This tip is shown correctly, including unicode characters.";
SendMessageW(hwnd_tip, TTM_ADDTOOLW, 0, (LPARAM) &ti);
This works fine as long as I provide the tooltip text in ti.lpszText
. However, I want the text to be dynamic, so instead I set ti.lpszText
to LPSTR_TEXTCALLBACKW
and handle the callback in my WindowProc(), like this:
...
case WM_NOTIFY:
{
NMHDR *nm = (NMHDR *) lParam;
switch (nm->code)
{
case TTN_GETDISPINFOW:
{
static std::wstring tip_string = L"Some random unicode string.";
NMTTDISPINFOW *nmtdi = (NMTTDISPINFOW *) lParam;
nmtdi->lpszText = (LPWSTR) tip_string.c_str();
}
break;
}
}
break;
...
Which does not work, as I never receive the TTN_GETDISPINOW
message. (Note: It works if I handle TTN_GETDISPINFO
instead and use NMTTDISPINFO
to provide a char array, but then no unicode support...)
I'm guessing I'm doing something wrong in my setup or message handling here? Any suggestions on how to do it properly?
Update
Also note that my project is not compiled in unicoe mode (i.e. _UNICODE is not defined and the project is set to use multi-byte character set). This is intentional and I would like to keep it like that as, I have no desire to rewrite the entire application to be unicode-aware (at least not yet). Since the _UNICODE define is used to select *W versions of various functions and data structures I was hoping I could achieve the same result by using these explicitly in my code, as shown above.
Upvotes: 1
Views: 4439
Reputation: 20986
Thanks for the Robert Scott link. I found a way to solve it now.
In short, the trick was to make sure the receiving window was a unicode window and register a unicode window procedure for it.
The problem was that I did not have a unicode WindowProc()
for my parent window handling the TTN_GETDISPINFOW
notification message. Since this window (class) was created with RegisterClassEx()
/
CreateWindowEx()
and not RegisterClassExW()
/
CreateWindowExW()
, it did not have registered window procedure for unicode messages.
To get around the problem I changed ti.hwnd
from hwnd_main
to hwnd_control
when sending TTM_ADDTOOLW, resulting in the control's window procedure receving the notifications instead of its parent. In order to intercept the unicode events now sent to the control's window procedure, I subclassed it using SetWindowLongW(hwnd_control, GWL_WNDPROC, (LONG) NewControlWndProc).
Note that hwnd_control is a standard "LISTBOX" window created with CreateWindowExW() and is therefore unicode-aware, since all buildt-in Windows classes are automatically registered in both unicode and ANSI version by the system.
Upvotes: 3
Reputation: 5573
The fact that you get the TTN_GETDISPINFO notification code but not TTN_GETDISPINFOW indicates that your project is setup to "Use Multi-Byte Character Set".
Check the projects property pages: "Configuration Properties" -> "General" -> "Character Set"
This property should be set to "Use Unicode Character Set".
Upvotes: 3
Reputation: 54605
Is your whole application using unicode? Else you might read this "Microsoft article". Especially the "Twelve steps to Unicode-enabling" section.
Or try like this guy did
Upvotes: 1