Windows ToolTips简要介绍(转)

Posted ~小小鸟~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows ToolTips简要介绍(转)相关的知识,希望对你有一定的参考价值。

原文转自 https://blog.csdn.net/sesiria/article/details/77450151

 

Windows 标准控件ToolTips简要介绍

参考文档 MSDN

https://msdn.microsoft.com/en-us/library/ff486072(v=vs.85).aspx

 

一,什么是ToolTips

ToolTips 就是一个类似于一个悬浮的文本框,在鼠标指针移动上去能显示特定的文本。

各种ToolTips样式。

二,创建ToolTips

HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            hwndParent, NULL, hinstMyDll,
                            NULL);

SetWindowPos(hwndTip, HWND_TOPMOST,0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

此后ToolTips的窗口函数自动维护Tooltips的尺寸,位置和显示隐藏状态等。 ToolTips的高度基于所设置的字体的高度。

 

1.激活ToolTips

Tooltips可以处于激活和未激活的状态。激活状态下ToolTips会显示文本。 当ToolTips未激活,其文本讲不被显示。即使鼠标指针放在一个Tools上发送TTM_ACTIVE可以激活和关闭激活一个ToolTips的状态。

 

2.将ToolTips关联Tools

创建一个TOOLINFO的结构体对象,设置uID为关联工具的ID

设置uFlags为  TTF_IDISHWND

并发送TTM_ADDTOOL消息给ToolTips的句柄。后面的完整的例子。

 

3.显示文本

默认使用TOOLINFO的  lpszText为显示问题。 可以发送TTM_UPDATETIPTEXT消息来更新显示值。

如果将lpszText 设置为 LPSTR_TEXTCALLBACK ToolTips需要显示文本时候,会Call之前注册的父窗口句柄的窗口函数并发送 TTN_GETDISPINFO通知码,

该消息包含了指向NMTTDISPINFO 结构的指针用于修改相应的文本,以供后续显示使用。

 

4.消息和通知

windows默认只发送消息给包含鼠标指针的窗口,并不会发送消息给ToolTips。因此需要关联ToolTips和其对应的父窗口活控件ID来控制其显示(恰当的位置和恰当的时间)。

ToolTips会自动处理一下的消息。

1.通过TOOLINFO绑定过的控件或者父窗口的矩形区域。

2.绑定ToolTip的父窗口在同一个线程内。

满足以上两个条件 将TOOLINFO的uFlags设置为 TTF_SUBCLASS  然后发送TTM_ADDTOOL消息给Tooltip的句柄。  但是ToolTips和关联的窗口必须有直接的消息通路。也就是父窗口和子窗口的关系。 如果你关联了别的进程的窗口,还是收不到消息的。可能要使用HOOK。此时你应该发送TTM_RELAYEVENT消息给tooltip 参考Tracking Tooltip

 

当Tooltip要显示的时候会发送给其拥有者窗口TTN_SHOW通知码。 TTN_POP表明Tooltip即将要隐藏。  通过WM_NOTIFY消息发送。

 

三,ToolTips应用

 

1.一个简单的ToolTips的例子

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#pragma comment(lib, "comctl32.lib")

LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;
HWND hTTWnd;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
    g_hInst = hInstance;
    INITCOMMONCONTROLSEX cx = { sizeof(INITCOMMONCONTROLSEX), ICC_BAR_CLASSES };
    BOOL ret = InitCommonControlsEx(&cx);
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MyDlgProc);
}


// Description:
//   Creates a tooltip for an item in a dialog box. 
// Parameters:
//   idTool - identifier of an dialog box item.
//   nDlg - window handle of the dialog box.
//   pszText - string to use as the tooltip text.
// Returns:
//   The handle to the tooltip.
//
HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText)
{
    if (!toolID || !hDlg || !pszText)
    {
        return FALSE;
    }
    // Get the window of the tool.
    HWND hwndTool = GetDlgItem(hDlg, toolID);

    // Create the tooltip. g_hInst is the global instance handle.
    HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        hDlg, NULL,
        g_hInst, NULL);

    if (!hwndTool || !hwndTip)
    {
        return (HWND)NULL;
    }

    // Associate the tooltip with the tool.
    TOOLINFO toolInfo = { 0 };
    toolInfo.cbSize = sizeof(toolInfo);
    toolInfo.hwnd = hDlg;
    toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
    toolInfo.uId = (UINT_PTR)hwndTool;
    toolInfo.lpszText = pszText;
    SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);

    return hwndTip;
}

void CreateToolTipForRect(HWND hwndParent)
{
    // Create a tooltip.
    HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        hwndParent, NULL, g_hInst, NULL);

    SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0,
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

    // Set up "tool" information. In this case, the "tool" is the entire parent window.

    TOOLINFO ti = { 0 };
    ti.cbSize = sizeof(TOOLINFO);
    ti.uFlags = TTF_SUBCLASS;
    ti.hwnd = hwndParent;
    ti.hinst = g_hInst;
    ti.lpszText = TEXT("This is your tooltip string.");

    GetClientRect(hwndParent, &ti.rect);

    // Associate the tooltip with the "tool" window.
    SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
}

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        CreateToolTipForRect(hDlg);

        break;
    }
    case WM_CLOSE:
        EndDialog(hDlg, FALSE);
        break;
    }
    return FALSE;
}

这个代码很简单就是在Windows对话框上显示ToolTips。可是编译以后死活不显示,初始化InitCommonControlsEx的调用也没有问题。观察到自己创建的对话框风格非常复古。

 

后来查阅相关资料。这是由于项目缺少了Manifest定义。在网上找了一个Manifest的定义文件在项目加载此文件就解决了此问题。关于Manifest文件的定义参考此文章

 

MSDN: Enable Visual Style in your program.

 

https://msdn.microsoft.com/en-us/library/windows/desktop/bb773175(v=vs.85).aspx#no_extensions

 

Windows.Manifest定义如下

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity 
  name="Microsoft.Windows.XXXX" 
  processorArchitecture="x86" 
  version="5.1.0.0" 
  type="win32"/> 
  <description>Windows Shell</description> 
  <dependency> 
  <dependentAssembly> 
  <assemblyIdentity 
  type="win32" 
  name="Microsoft.Windows.Common-Controls" 
  version="6.0.0.0" 
  processorArchitecture="x86" 
  publicKeyToken="6595b64144ccf1df" 
  language="*" 
   /> 
  </dependentAssembly> 
  </dependency> 
  </assembly>

运行结果如下。

关于这个问题深入研究发现,是调用TOOLINFOW类的时候如果程序加载Common Control 6.0以下的版本,这个结构体的定义的实际size比6.0少4个字节。

而ANSI版本无此问题。如果使用Unicode版本必须加入manifest强制让应用程序加载common Control 6.0才能使用sizeof(TOOLINFOW)的返回值。

否则就要将此值减去4

参考此文章:  https://stackoverflow.com/questions/2545682/unicode-tooltips-not-showing-up/15173051

 

2. 一个指定位置显示Tooltip的例子 同时显示2个Tooltip并且自己定位Toolpis的位置。

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#pragma comment(lib, "comctl32.lib")

LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;
HWND hTTWnd;
HWND g_hwndTrackingTT;
HWND g_hwndTrackingTT1;
TOOLINFO g_toolItem;
BOOL g_TrackingMouse;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
    g_hInst = hInstance;
    INITCOMMONCONTROLSEX cx = { sizeof(INITCOMMONCONTROLSEX), ICC_BAR_CLASSES };
    BOOL ret = InitCommonControlsEx(&cx);
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MyDlgProc);
}


// Description:
//   Creates a tooltip for an item in a dialog box. 
// Parameters:
//   idTool - identifier of an dialog box item.
//   nDlg - window handle of the dialog box.
//   pszText - string to use as the tooltip text.
// Returns:
//   The handle to the tooltip.
//
HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText)
{
    if (!toolID || !hDlg || !pszText)
    {
        return FALSE;
    }
    // Get the window of the tool.
    HWND hwndTool = GetDlgItem(hDlg, toolID);

    // Create the tooltip. g_hInst is the global instance handle.
    HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        hDlg, NULL,
        g_hInst, NULL);

    if (!hwndTool || !hwndTip)
    {
        return (HWND)NULL;
    }

    // Associate the tooltip with the tool.
    TOOLINFO toolInfo = { 0 };
    toolInfo.cbSize = sizeof(toolInfo);
    toolInfo.hwnd = hDlg;
    toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
    toolInfo.uId = (UINT_PTR)hwndTool;
    toolInfo.lpszText = pszText;
    SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);

    return hwndTip;
}

void CreateToolTipForRect(HWND hwndParent)
{
    // Create a tooltip.
    HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        hwndParent, NULL, g_hInst, NULL);

    SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0,
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

    // Set up "tool" information. In this case, the "tool" is the entire parent window.

    TOOLINFO ti = { 0 };
    ti.cbSize = sizeof(TOOLINFO);
    ti.uFlags = TTF_SUBCLASS;
    ti.hwnd = hwndParent;
    ti.hinst = g_hInst;
    ti.lpszText = TEXT("This is your tooltip string.");

    GetClientRect(hwndParent, &ti.rect);

    // Associate the tooltip with the "tool" window.
    SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
}

HWND CreateTrackingToolTip(int toolID, HWND hDlg, WCHAR* pText)
{
    // Create a tooltip.
    HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        hDlg, NULL, g_hInst, NULL);

    if (!hwndTT)
    {
        return NULL;
    }

    // Set up the tool information. In this case, the "tool" is the entire parent window.

    g_toolItem.cbSize = sizeof(TOOLINFO);
    g_toolItem.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
    g_toolItem.hwnd = hDlg;
    g_toolItem.hinst = g_hInst;
    g_toolItem.lpszText = pText;
    g_toolItem.uId = (UINT_PTR)hDlg;

    GetClientRect(hDlg, &g_toolItem.rect);

    // Associate the tooltip with the tool window.

    SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&g_toolItem);

    return hwndTT;
}

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        g_hwndTrackingTT = CreateTrackingToolTip(0, hDlg, L"");
        g_hwndTrackingTT1 = CreateTrackingToolTip(0, hDlg, L"");
        break;
    }

    case WM_MOUSELEAVE:
        SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&g_toolItem);
        SendMessage(g_hwndTrackingTT1, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&g_toolItem);
        g_TrackingMouse = FALSE;
        return FALSE;

    case WM_MOUSEMOVE:
        static int oldX, oldY;
        int newX, newY;

        if (!g_TrackingMouse)   // The mouse has just entered the window.
        {                       // Request notification when the mouse leaves.

            TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
            tme.hwndTrack = hDlg;
            tme.dwFlags = TME_LEAVE;

            TrackMouseEvent(&tme);

            // Activate the tooltip.
            SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&g_toolItem);
            SendMessage(g_hwndTrackingTT1, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&g_toolItem);

            g_TrackingMouse = TRUE;
        }

        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.
            WCHAR coords[12];
            wsprintf(coords, TEXT("%d, %d"), newX, newY);

            g_toolItem.lpszText = coords;
            SendMessage(g_hwndTrackingTT, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);
            SendMessage(g_hwndTrackingTT1, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);

            // Position the tooltip. The coordinates are adjusted so that the tooltip does not overlap the mouse pointer.

            //POINT pt = { newX, newY };
            POINT pt = { 50, 50 };
            ClientToScreen(hDlg, &pt);
            SendMessage(g_hwndTrackingTT, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(pt.x + 10, pt.y - 20));
            SendMessage(g_hwndTrackingTT1, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(pt.x + 100, pt.y - 20));
        }
        return FALSE;
    case WM_CLOSE:
        EndDialog(hDlg, FALSE);
        break;
    }
    return FALSE;
}

转Android进程间通信(IPC)机制Binder简要介绍和学习计划

WCF入门教程1——WCF简要介绍

Nginx windows下搭建过程

Nginx windows下搭建过程

WPF 与 StringFormat 的绑定在 ToolTips 上不起作用

求wpf代码,鼠标移上列表某列单元格时,用tooltips展示与该单元格数据相关的一个列表(数据是个一集合)