#c #tooltip
#c #всплывающая подсказка
Вопрос:
Мы пытаемся создать динамические всплывающие подсказки, в которых всплывающая подсказка изменяется в зависимости от выбранного пользователем языка. (64-разрядное приложение C win api, внешние библиотеки не используются)
Однако мы не можем заставить это работать. Всплывающая подсказка отображает только первую букву текста. Снипет кода:
wchar_t* ws = new wchar_t[200];
swprintf(ws, 200, L"Hello");
TTTOOLINFOW toolInfoW = { 0 };
toolInfoW.cbSize = sizeof(toolInfoW);
toolInfoW.hwnd = hDlg;
toolInfoW.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfoW.uId = (UINT_PTR)hwndTool;
toolInfoW.lpszText = ws;
Даже если мы жестко закодируем «Привет», отображается только первая буква
TTTOOLINFOW toolInfoW = { 0 };
toolInfoW.cbSize = sizeof(toolInfoW);
toolInfoW.hwnd = hDlg;
toolInfoW.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfoW.uId = (UINT_PTR)hwndTool;
toolInfoW.lpszText = L"Hello";
Должно быть, мы упускаем что-то чрезвычайно очевидное, потому что заставить это работать не может быть так сложно.
Заранее спасибо за любые советы.
Комментарии:
1. Вероятно, вам нужно убедиться, что более новая версия общей библиотеки элементов управления (comctl32.dll ) используется путем указания манифеста. Например, добавьте в свой код следующую директиву:
#pragma comment(linker, ""/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"")
2. Кроме того, у вас есть
UNICODE
и_UNICODE
определено?3. Спасибо за советы — у нас уже были реализованы оба из них. Все еще нет радости.
Ответ №1:
Из любопытства я попробовал это, и следующий код действительно работал при компиляции для x64 с использованием MSVC 2019 в Windows 10. Он создает простое окно с кнопкой в нем, и при наведении курсора мыши на эту кнопку отображается всплывающая подсказка с текстом This works! ☺
(содержащим символ смайлика в Юникоде).
Обязательно скомпилируйте этот пример с включенным C 17, иначе буфер, возвращаемый с помощью data()
, будет иметь тип const wchar_t*
и, следовательно, будет несовместим с lpszText
(членом TTTOOLINFOW
структуры), который имеет тип LPWSTR
, т.е. Просто wchar_t*
.
#pragma comment(linker, ""/manifestdependency:type='win32'
name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
processorArchitecture='*' publicKeyToken='6595b64144ccf1df'
language='*'"")
#pragma comment(lib, "comctl32.lib")
#define _WIN32_WINNT _WIN32_WINNT_WIN10
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <SDKDDKVer.h>
#include <windows.h>
#include <commctrl.h>
#include <string>
HINSTANCE g_hInstance{ nullptr };
HWND CreateMyButton(HINSTANCE hInstance, HWND hWndApp)
{
return ::CreateWindowExW(0UL, L"BUTTON", L"Hover over this button",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 45, 10, 200, 35,
hWndApp, nullptr, hInstance, nullptr);
}
void CreateMyTooltip(HWND hWndParent, HWND hWndControl)
{
HWND hWndTip{ ::CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW,
nullptr, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 0, 0, 0, 0,
hWndParent, nullptr, nullptr, nullptr) };
::SetWindowPos(hWndTip, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
std::wstring wsTooltipText{ L"This works! u263A" };
TTTOOLINFOW ti{};
ti.cbSize = sizeof ti;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.hwnd = hWndParent;
ti.uId = reinterpret_cast<UINT_PTR>(hWndControl);
ti.lpszText = wsTooltipText.data();
::SendMessageW(hWndTip, TTM_ADDTOOL, 0U, reinterpret_cast<LPARAM>(amp;ti));
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
CreateMyTooltip(hWnd, CreateMyButton(g_hInstance, hWnd));
break;
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
break;
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}
int WINAPI wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int)
{
g_hInstance = hInstance;
const INITCOMMONCONTROLSEX initControls
{
sizeof(INITCOMMONCONTROLSEX),
ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES
};
::InitCommonControlsEx(amp;initControls);
WNDCLASSW wc{};
wc.lpfnWndProc = MyWndProc;
wc.hInstance = hInstance;
wc.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
wc.hbrBackground = ::GetSysColorBrush(COLOR_3DFACE);
wc.lpszClassName = L"Tooltip";
::RegisterClassW(amp;wc);
::CreateWindowExW(0UL, wc.lpszClassName, L"Tooltip Example",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
300, 100, nullptr, nullptr, hInstance, nullptr);
MSG msg{};
while (::GetMessageW(amp;msg, nullptr, 0U, 0U))
{
::TranslateMessage(amp;msg);
::DispatchMessageW(amp;msg);
}
return static_cast<int>(msg.wParam);
}