Всплывающая подсказка для отслеживания в Win32 C

#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» тоже.