Как настроить управление подсказками Win32 с помощью динамического текста в Юникоде? - PullRequest
0 голосов
/ 14 июня 2009

У меня возникли проблемы с предоставлением элемента управления всплывающих подсказок Win32 с динамическим текстом в формате Unicode. Я использую следующий код для настройки элемента управления:

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);

Это прекрасно работает, пока я предоставляю текст подсказки в ti.lpszText. Однако я хочу, чтобы текст был динамическим, поэтому вместо этого я устанавливаю ti.lpszText на LPSTR_TEXTCALLBACKW и обрабатываю обратный вызов в моем WindowProc (), например:

...
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;
...

Что не работает, так как я никогда не получаю сообщение TTN_GETDISPINOW. (Примечание: это работает, если вместо этого я обработаю TTN_GETDISPINFO и использую NMTTDISPINFO для предоставления массива символов, но тогда поддержка юникода не будет ...)

Я предполагаю, что я что-то не так делаю в моей настройке или обработке сообщений здесь? Любые предложения о том, как это сделать правильно?

Обновление
Также обратите внимание, что мой проект не скомпилирован в уникальном режиме (то есть _UNICODE не определен, и проект настроен на использование многобайтовой кодировки). Это сделано намеренно, и я хотел бы сохранить его таким, поскольку у меня нет желания переписывать все приложение, чтобы оно поддерживало юникод (по крайней мере, пока). Поскольку определение _UNICODE используется для выбора * W версий различных функций и структур данных, я надеялся, что смогу достичь того же результата, явно используя их в своем коде, как показано выше.

Ответы [ 3 ]

3 голосов
/ 14 июня 2009

Тот факт, что вы получаете код уведомления TTN_GETDISPINFO, но не TTN_GETDISPINFOW, указывает на то, что ваш проект настроен на «Использование многобайтового набора символов».

Проверьте страницы свойств проектов: «Свойства конфигурации» -> «Общие» -> «Набор символов»
Для этого свойства должно быть установлено значение «Использовать набор символов Юникода».

3 голосов
/ 15 июня 2009

Спасибо за ссылку Роберта Скотта. Я нашел способ решить это сейчас.

Короче говоря, хитрость заключалась в том, чтобы убедиться, что окно получения было окном Unicode, и зарегистрировать процедуру окна Unicode для него.

Проблема заключалась в том, что у меня не было Unicode WindowProc() для моего родительского окна, обрабатывающего уведомление TTN_GETDISPINFOW. Так как это окно (класс) было создано с RegisterClassEx()<code>/<code>CreateWindowEx(), а не RegisterClassExW()<code>/<code>CreateWindowExW(), в нем не было зарегистрированной процедуры окна для сообщений Unicode.

Чтобы обойти проблему, я изменил ti.hwnd с hwnd_main на hwnd_control при отправке TTM_ADDTOOLW , в результате чего оконная процедура элемента управления получает уведомления вместо его родителя. Чтобы перехватить события Unicode, которые теперь отправляются в оконную процедуру элемента управления, я разделил его на подклассы, используя SetWindowLongW (hwnd_control, GWL_WNDPROC, (LONG) NewControlWndProc) .

Обратите внимание, что hwnd_control является стандартным окном "LISTBOX", созданным с помощью CreateWindowExW () , и поэтому учитывает юникод, поскольку все встроенные классы Windows автоматически регистрируются системой как в Unicode, так и в версии ANSI. .

1 голос
/ 14 июня 2009

Использует ли все ваше приложение юникод? В противном случае вы можете прочитать эту «статью Microsoft» . В особенности раздел «Двенадцать шагов к включению Unicode» .

Или попробуй как этот парень

Подсказки Роберта Скотта по Unicode

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...