#c #winapi #tooltip
#c #winapi #всплывающая подсказка
Вопрос:
В приложении Win32 / C , работающем под 64-разрядной Windows 7, с использованием Visual Studio 16.7.7, я хочу реализовать всплывающие подсказки для отслеживания в главном (и единственном) окне. Следуя примерам в документации Microsoft SDK, отслеживание, похоже, работает, но само окно всплывающей подсказки не отображается.
Я проверил, используя отладчик, что всплывающая подсказка активирована и деактивирована, что происходит ожидаемое отслеживание мыши, что координаты экрана в TTM_TRACKPOSITION
сообщении правильные, а текст в порядке. Приложение работает в формате Unicode, и я проверил, что структуры являются версиями Unicode, а общие элементы управления инициализированы и что текущая версия библиотеки общих элементов управления связана. Окно всплывающей подсказки имеет WS_EX_TOPMOST
WS_EX_TOOLWINDOW
стили и extended для Spy .
Какие изменения необходимы, чтобы всплывающая подсказка отображалась?
Вот код, который я использую:
Глобальные переменные:
HINSTANCE hInst;
HWND hWnd;
HWND hwndTT;
WCHAR ttText[12];
TOOLINFO toolTipInfo;
BOOL trackingMouse;
Инициализация:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
// Set up for mouse tracking (tooltips)
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_BAR_CLASSES;
BOOL ok=InitCommonControlsEx(amp;icc);
trackingMouse = FALSE;//
WCHAR nullString[15] = { L"After create" };
hwndTT = CreateTrackingToolTip(0 /*toolID*/, hWnd, nullString);
...
HWND CreateTrackingToolTip(int toolID, HWND hWndParent, WCHAR* pText)
{
// Create a tooltip.
HWND h = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWndParent, NULL, hInst, NULL);
if(!h)
{
return NULL;
}
// Set up the tool information. In this case, the "tool" is the entire parent window.
memset(amp;toolTipInfo, 0, sizeof(TOOLINFO));
toolTipInfo.cbSize = sizeof(TOOLINFO);
toolTipInfo.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
toolTipInfo.hwnd = hWndParent;
toolTipInfo.hinst = hInst;
toolTipInfo.lpszText = pText;
toolTipInfo.uId = (UINT_PTR)hWndParent;
GetClientRect(hWndParent, amp;toolTipInfo.rect);
// Associate the tooltip with the tool window.
SendMessage(h, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)amp;toolTipInfo);
return h;
}
Оконная процедура:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MOUSELEAVE: // The mouse pointer has left our window. Deactivate the tooltip.
SendMessage(hwndTT, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)amp;toolTipInfo);
trackingMouse = FALSE;
TRACE(L"nDeactivate tooltip");
return FALSE;
case WM_MOUSEMOVE:
static int oldX, oldY;
int newX, newY;
if(!trackingMouse) // The mouse has just entered the window.
{ // Request notification when the mouse leaves.
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = hWnd;
tme.dwFlags = TME_LEAVE;
BOOL ok=TrackMouseEvent(amp;tme);
// Activate the tooltip.
SendMessage(hwndTT, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)amp;toolTipInfo);
trackingMouse = TRUE;
TRACE(L"nActivate tooltip");
}
newX = GET_X_LPARAM(lParam); newY = GET_Y_LPARAM(lParam);
// Make sure the mouse has actually moved. The presence of the tooltip
// causes Windows to send the message continuously.
if((newX != oldX) || (newY != oldY))
{
oldX = newX; oldY = newY;
// Update the text.
swprintf_s(ttText, ARRAYSIZE(ttText), L"%d, %d", newX, newY);
toolTipInfo.lpszText = ttText;
SendMessage(hwndTT, TTM_SETTOOLINFO, 0, (LPARAM)amp;toolTipInfo);
// Position the tooltip. The coordinates are adjusted so that the tooltip does not overlap the mouse pointer.
POINT pt = { newX, newY };
ClientToScreen(hWnd, amp;pt);
SendMessage(hwndTT, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(pt.x 10, pt.y - 20));
}
return FALSE;
...
Комментарии:
1. Попробуйте включить элемент управления, сначала отправив ему
TTM_ACTIVATE
сообщение (сwParam
установленным значениемTRUE
).2. @Jonathan Potter: отправка TTM_ACTIVATE после TTM_ADDTOOL ничего не меняет. Всплывающие подсказки по-прежнему не отображаются.
3. Странное решение; всплывающие подсказки для отслеживания — это не просто функция comctrl v6, насколько я знаю.
Ответ №1:
Требуется следующая строка:
#pragma comment(linker,"/manifestdependency:"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"")
Более подробную информацию см. в разделе «Использование манифестов или директив для обеспечения возможности применения визуальных стилей к приложениям«.
Комментарии:
1. Рита Хан — Добавление этой строки действительно заставляет ее работать. Я думал, что об этом позаботится манифест (компоновщик / МАНИФЕСТ). Компоновщик показал «Поиск C:Program Files (x86) Windows Kits 10 lib 10.0.18362.0 um x64 Comctl32.lib» тоже.