关于鼠标弹出右键菜单的问题?

screen12 2014-08-12 08:51:17
我的一个输入法,我在程序中设置了:在它的窗口范围内击一下鼠标右键,会弹出右键菜单。

但是由于输入法的窗口都有CS_IME风格,所以它是收不到鼠标消息的,作为替代,我是处理WM_SETCURSOR消息,然后再用GetCursorPos获取当前鼠标位置,我是这样写的:

case WM_SETCURSOR:
if(HIWORD(lParam) == WM_LBUTTONDOWN)
{
goto LButtonDown;
}
else if(HIWORD(lParam) == WM_MOUSEMOVE)
{
goto LButtonMove;
}
else if(HIWORD(lParam) == WM_LBUTTONUP)
{
goto LButtonUp;
}
else if(HIWORD(lParam) == WM_RBUTTONDOWN)//鼠标右键
{
GetCursorPos(&ptScreen);
TrackPopupMenu(hMenuSet, TPM_BOTTOMALIGN, ptScreen.x, ptScreen.y, 0, hWnd, NULL);
}


可是我发现:如果设置TPM_BOTTOMALIGN,让菜单在鼠标右上方弹出,会出现一个奇怪的现象:就是一点击右键,菜单确实会出现,但闪烁不止,就好象一直不断的弹出一样。

如果不设这个参数,让它默认在右下方弹出,通常情况下一切正常,菜单可以正常弹出。但是当位置位于屏幕下方,这时下方的位置已经不够弹出菜单的,这时windows会自己将菜单移到右上方,这时又会出现上面所说的闪烁不止的现象。

调试发现:出现闪烁的时候,不断收到WM_SETCURSOR消息,且HIWORD(lParam) == WM_RBUTTONDOWN,这当然会导致菜单不断弹出了。可是为什么菜单在右上方弹出的时候,会不断收到WM_SETCURSOR消息呢?

求解。
...全文
362 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
llf10811020205 2015-11-17
  • 打赏
  • 举报
回复
想请问一下楼主,输入法窗口中点击左键,窗口却隐藏了,这个怎么处理的
Eleven 2014-08-13
  • 打赏
  • 举报
回复
你能否HOOK WH_MOUSE_LL判断鼠标鼠标右键是否点在你输入法窗口上PtInRect() ?
screen12 2014-08-13
  • 打赏
  • 举报
回复
引用 5 楼 VisualEleven 的回复:
你能否HOOK WH_MOUSE_LL判断鼠标鼠标右键是否点在你输入法窗口上PtInRect() ?
鼠标肯定点击在输入法的窗口上,问题是:弹出菜单在哪里弹出?我发现如果在右下方弹出,就正常,如果在右上方弹出,就会出现那种情况。 我自己的理解是:比如菜单的矩形上方坐标为100,下方坐标为300,如果鼠标纵坐标为100,大概系统认为是在菜单以内,如果为300,系统大概以为不在菜单以内。 所以就造成了菜单在右下方弹出,会正常(此时鼠标纵坐标等于菜单上方坐标),菜单在右上方弹出(此时鼠标纵坐标等于菜单底部坐标),就不正常。 按照我的这个理解,我觉得菜单如果在鼠标的左上方、左下方弹出,都会出现那种闪烁的情况,结果一试验,果然如此。 但是我不知道造成这种现象的原因。我的窗口是带CS_IME风格的输入法窗口。它是收不到鼠标消息的,但是能收到WM_SETCURSOR消息,据说(只是据说而已,不知道这种处理方法是否规范)输入法都是这样处理鼠标消息的。 但我估计正常窗口,能收到WM_RBUTTONDOW消息的,恐怕不会出现这种情况。输入法是小众软件,做的人不多。
screen12 2014-08-12
  • 打赏
  • 举报
回复
渐渐的找出发生这种现象的规律了,那就是:弹出菜单的时候,如果鼠标位于菜单之内,那就正常,如果鼠标位于菜单之外,就会出现这种不断收到WM_SETCURSOR消息,从而导致菜单不断被弹出而引起的闪烁不止的现象。 如果是这样的语句: TrackPopupMenu(hMenuSet, 0, ptScreen.x, ptScreen.y, 0, hWnd, NULL); 菜单默认是从鼠标位置的右下方弹出,也就是说,鼠标位置位于菜单左上角,这时大概系统会认为位于菜单内部,所以弹出正常,不会出现闪烁现象。 但是这种情况下,如果鼠标点击的位置位于屏幕下方,在右下方已经不够弹出菜单了,这时系统会自动把菜单移到右上角。这时,鼠标位置相当于位于菜单底部,这时系统大概认为这不属于菜单内部,也不知怎么回事,就不断的发WM_SETCURSOR消息从而造成菜单不断弹出而引起闪烁现象。当然这种情况下,用户是无法操作的。 如果用这样的语句: TrackPopupMenu(hMenuSet, TPM_BOTTOMALIGN, ptScreen.x, ptScreen.y, 0, hWnd, NULL); 那么好象在通常情况下,就会出现闪烁现象,因为它默认是在右上角弹出菜单。 可是这个问题是产生的?又怎么解决呢?
screen12 2014-08-12
  • 打赏
  • 举报
回复
引用 2 楼 wozhaolala 的回复:
有个退一步的蠢方法:WM_SETCURSOR消息响应函数内判断菜单是否弹出
这个怎么判断菜单是否已弹出呢? 我已经采用了这样一个不是办法的办法: SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rcwork, 0); if(rcwork.bottom - ptScreen.y < 170) TrackPopupMenu(hMenuSet, TPM_BOTTOMALIGN, ptScreen.x, ptScreen.y+1, 0, hWnd, NULL); else TrackPopupMenu(hMenuSet, 0, ptScreen.x, ptScreen.y, 0, hWnd, NULL); 就是先取得工作区的矩形坐标,然后判断当前鼠标点击处与屏幕下方距离是否大于170(我的菜单高度约为170),如果不小于,正常弹出(会弹出在右下方),如果小于,就让它以TPM_BOTTOMALIGN的方式弹出在右上方,但是我把此时的纵坐标设为ptScreen.y + 1,这样一来,菜单会向下移一个像素,结果鼠标位置就位于菜单以内了,就不会出现那种情况了。 但这个办法显然不是很好的办法,如果将来加菜单项怎么办?高度一变,170这个数值就得修改。还担心在不同的系统上,菜单的高度不同,万一XP系统里高度不是170怎么办? 我看了一个别的输入法,它们的右键菜单可以正常弹出。而且我仔细看了一下,并不是象我这样往下移一个像素的。他们不知是如何做到的。
悟迟 2014-08-12
  • 打赏
  • 举报
回复
有个退一步的蠢方法:WM_SETCURSOR消息响应函数内判断菜单是否弹出

16,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧