WIN32 API 中 WM_MOUSEHOVER 上的弹出窗口 - 如何关闭它?
Posted
技术标签:
【中文标题】WIN32 API 中 WM_MOUSEHOVER 上的弹出窗口 - 如何关闭它?【英文标题】:POPUP Window on WM_MOUSEHOVER in WIN32 API - how to close it? 【发布时间】:2014-12-03 13:27:59 【问题描述】:我是 WIN32 API 的新手,下面显示的代码有问题,这是来自我的 WinProc 函数:当鼠标光标在我的窗口中停留一段时间时,我使用带有 TME_HOVER 的 TrackMouseEvent 来获取 WM_MOUSEHOVER。如果我在每个 WM_MOUSEMOVE 上调用 TrackMouseEvent,这可行,但如果我只在其他地方调用一次,则不行。为什么? (这是第一个问题)
当我收到 WM_MOUSEHOVER 时,我创建了一个可以看到的 POPUP 窗口,然后再次为 TME_LEAVE 调用 TrackMouseEvent。这有效,当鼠标光标离开我的窗口时我收到 WM_MOUSELEAVE,然后我想隐藏并销毁弹出窗口(我存储在静态变量中的 HWND)但这不起作用,弹出窗口留在那里。为什么? (这是第二个问题)
谁能给我一个示例或链接到一个显示 TrackMouseEvent 和 PopUp 窗口的简单示例?非常感谢。
case WM_MOUSEMOVE:
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER;
tme.hwndTrack = hSBox;
TrackMouseEvent(&tme);
break;
case WM_MOUSEHOVER:
hPop = CreateWindowEx(WS_EX_STATICEDGE, //WS_EX_CLIENTEDGE,
TEXT("STATIC"),
TEXT("pop-up"),
WS_POPUP | WS_BORDER,
100, 100, 100, 100,
hWnd, (HMENU)0, hInstance, NULL);
ShowWindow(hPop, SW_SHOW);
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hSBox;
TrackMouseEvent(&tme);
return 0;
case WM_MOUSELEAVE:
ShowWindow(hPop, SW_HIDE);
DestroyWindow(hPop);
return 0;
【问题讨论】:
为什么不只创建一次窗口,并在悬停时显示/在离开时隐藏? 有趣的反对意见,我猜这意味着使用 TOOLTIPS_CLASS?尽管如此,使用此处显示的代码,您可能对显示的文本有更多的控制权,并且可以更好地改变它吗?我不知道。 好吧,更好的说法是,你的评论显然是正确的。 【参考方案1】:对了,我也发现我想做的,用windows TOOLTIPS_CLASS也可以做到。
我为此找到的最值得推荐的链接是:
http://winapi.foosyerdoos.org.uk/info/common_cntrls.php#CreateTooltip
https://github.com/wine-mirror/wine/blob/master/dlls/comctl32/tooltips.c
Unicode tooltips not showing up
【讨论】:
【参考方案2】:我可以看到两个问题:
TME_HOVER
的问题是因为您没有初始化 dwHoverTime
成员;您应该将其设置为HOVER_DEFAULT
。否则,悬停超时将设置为堆栈上的任何随机值。
您的第二个问题是对TrackMouseEvent
的每次调用都会覆盖前一次调用。因为您在每条WM_MOUSEMOVE
消息上都调用TrackMouseEvent
,所以TME_LEAVE
调用很快就会被您的下一个TME_HOVER
调用覆盖。
解决方案是在WM_MOUSEMOVE
处理程序中使用某种标志,这样当鼠标第一次进入您的窗口时,您只需调用一次TrackMouseEvent
。当您收到 WM_MOUSEHOVER
和 WM_MOUSELEAVE
消息时,跟踪将被取消,因此在这些点您将重置标志,以便下次收到 WM_MOUSEMOVE
时,您可以在必要时重新启动它。
// note: BOOL g_fMouseTracking needs to be declared in the same place
// hPop is
case WM_MOUSEMOVE:
if (!g_fMouseTracking && !hPop)
// start tracking if we aren't already
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = hSBox;
tme.dwHoverTime = HOVER_DEFAULT;
g_fMouseTracking = TrackMouseEvent(&tme);
break;
case WM_MOUSEHOVER:
g_fMouseTracking = FALSE; // tracking now cancelled
if (!hPop)
hPop = CreateWindowEx(WS_EX_STATICEDGE, //WS_EX_CLIENTEDGE,
TEXT("STATIC"),
TEXT("pop-up"),
WS_POPUP | WS_BORDER,
100, 100, 100, 100,
hWnd, (HMENU)0, hInstance, NULL);
ShowWindow(hPop, SW_SHOW);
// set up leave tracking
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hSBox;
g_fMouseTracking = TrackMouseEvent(&tme);
return 0;
case WM_MOUSELEAVE:
g_fMouseTracking = FALSE; // tracking now cancelled
if (hPop)
// close popup if it's open
ShowWindow(hPop, SW_HIDE);
DestroyWindow(hPop);
hPop = NULL;
return 0;
【讨论】:
谢谢,您修改后的代码运行良好!不是 HOVER_DEFAULT 是我的问题(我有它,虽然不在我粘贴在这里的代码中)但缺少检查“if (!g_fMouseTracking && !hPop)”是我的问题。 也感谢这个例子说明如何更好地注释源代码以上是关于WIN32 API 中 WM_MOUSEHOVER 上的弹出窗口 - 如何关闭它?的主要内容,如果未能解决你的问题,请参考以下文章