不靠谱的tooltip

typedef struct tagTOOLINFOA {
    UINT cbSize;
    UINT uFlags;
    HWND hwnd;
    UINT_PTR uId;
    RECT rect;
    HINSTANCE hinst;
    LPSTR lpszText;
#if (_WIN32_IE >= 0x0300)
    LParaM lParam;
#endif
#if (_WIN32_WINNT >= 0x0501)
    void *lpReserved;
#endif
} TTTOOLINFOA,NEAR *PTOOLINFOA,*LPTTTOOLINFOA;

如果#define _WIN32_WINNT 0x0500,那么tooltip一切正常
当有一天#define _WIN32_WINNT 0x0501了,
这时设置tooltip.cbSize = sizeof(TOOLINFO)的时候就让人崩溃了。
编译调试不显示任何错误,但是tooltip就是显示不出来了。。。(they were just failing silently without kNowing why)
因为系统认加载comctl 5.82,这个版本里面的tooltip的size根本没有sizeof(TOOLINFO),里面没有void *lpReserved;
所以cbSize设大了,出错了。。。
这时需要写成 tooltip.cbSize = TTTOOLINFOA_V2_SIZE;
或者强制指定comctl 6.0
#pragma comment(linker,"\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'\"")

ps:  指定#define _WIN32_WINNT 0x0501将导致程序只能运行在xp及以上系统。

测试程序:
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"comctl32.Lib")
#pragma comment(lib,"gdi32.Lib")

int count;
TCHAR str[1000];

HWND g_hwndTrackingTT;
TOOLINFO g_toolItem;
HINSTANCE g_hInst;
BOOL g_TrackingMouse = FALSE;

LRESULT CALLBACK WindowFunc(HWND,UINT,WParaM,LParaM);

HWND CreateTrackingToolTip(int toolID,HWND hDlg,char *pText);

TCHAR szWinName[] = TEXT("MyWin");

int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst,LPSTR lpszArgs,int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wcl;
INITCOMMONCONTROLSEX ic;
BOOL ret;

g_hInst = hThisInst;
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = 0x00004000;//ICC_STANDARD_CLASSES|ICC_BAR_CLASSES;
ret = InitCommonControlsEx(&ic);
wcl.cbSize = sizeof(WNDCLASSEX);
wcl.hInstance = hThisInst;
wcl.lpszClassName = szWinName;
wcl.lpfnWndProc = WindowFunc;
wcl.style = CS_HREDRAW|CS_VREDRAW;
wcl.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wcl.hIconSm = NULL;
wcl.hCursor = LoadCursor(NULL,IDC_ARROW);
wcl.lpszMenuName = NULL;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hbrBackground = (HBrush) GetStockObject(WHITE_Brush);
if(!RegisterClassEx(&wcl)) return 0;
hwnd = CreateWindowEx(
WS_EX_WINDOWEDGE,
szWinName,
TEXT("Window Title"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
hThisInst,
NULL
);
ShowWindow(hwnd,nWinMode);
UpdateWindow(hwnd);

while(GetMessage(&msg,NULL,0))
{
TranslateMessage(&msg);
dispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hwnd,UINT message,WParaM
wParam,LParaM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static int cxClient = 0,cyClient = 0,oldX,oldY;
int newX,newY;
char coords[12];
POINT pt;

switch(message){
case WM_CREATE:
g_hwndTrackingTT = CreateTrackingToolTip(456,hwnd,"");
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return 0;
case WM_MOUSELEAVE:
// The mouse pointer has left our window.
// Deactivate the ToolTip.
SendMessage(g_hwndTrackingTT,TTM_TRACKACTIVATE,(WParaM)
FALSE,(LParaM)&g_toolItem);
g_TrackingMouse = FALSE;
return FALSE;
case WM_MOUSEMOVE:
if (!g_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;
TrackMouseEvent(&tme);

// Activate the ToolTip.
SendMessage(g_hwndTrackingTT,
(WParaM)TRUE,(LParaM)&g_toolItem);
g_TrackingMouse = TRUE;
}

newX = LOWORD(lParam);
newY = HIWORD(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.
sprintf(coords,"%d,%d",newX,newY);
g_toolItem.lpszText = coords;
SendMessage(g_hwndTrackingTT,TTM_SETTOOLINFO,(LParaM)
&g_toolItem);

// Position the ToolTip.
// The coordinates are adjusted so that the ToolTip does not
// overlap the mouse pointer.
pt.x = newX;
pt.y = newY;
ClientToScreen(hwnd,&pt);
SendMessage(g_hwndTrackingTT,TTM_TRACKPOSITION,
0,(LParaM)MAKELONG(pt.x + 10,pt.y - 20));
}
return FALSE;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}

HWND CreateTrackingToolTip(int toolID,char *pText)
{
// Create a ToolTip.
HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST,
TOOLTIPS_CLASS,
WS_POPUP | TTS_nopREFIX | TTS_ALWAYSTIP,CW_USEDEFAULT,
hDlg,g_hInst,NULL);
if (!hwndTT)
{
return NULL;
}
// Set up tool information.
// In this case,the "tool" is the entire parent window.
g_toolItem.cbSize = sizeof(TOOLINFO);
//g_toolItem.cbSize = TTTOOLINFOA_V2_SIZE;
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,(LParaM) (LPTOOLINFO)&g_toolItem);
return hwndTT;
}

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...