NOTIFYICON_VERSION和NOTIFYICON_VERSION_4之间的差异在NOTIFYICONDATA结构中使用?

问题描述 投票:-1回答:3

当添加从Windows系统托盘图标有API的两个版本,我们可以通过通过Shell_NotifyIcon()结构NOTIFYICONDATA。有两种API之间的细微差别,而这些都不是MSDN上的任何地方上市。我花了一些努力,找出一些差异,我现在要分享。改进/增加的答案总是受欢迎的。

PS:这个问题纯粹是为了分享什么我已经在过去几天与Windows DPI缩放实验的经验教训。

windows winapi system-tray trayicon shell32.dll
3个回答
1
投票

@萨赫勒 - 辛格你是对的吧,我与其他人,你的应用程序应该是DPI感知同意,但是当这是不是在这里一个点。

我也有类似的问题,即我的应用程序是(仍然)不知道DPI和GET_X_LPARAM(wParam参数)将返回非虚坐标。这个值传递给TrackPopupMenu()后,我得到的屏幕上错误的位置。

最好的办法是使用GetMessagePos()而不是wParam中。在这种情况下,Windows会为您提供与虚拟坐标新的DWORD,然后使用GET_X_LPARAM / GET_Y_LPARAM让你可以传递给TrackPopupMenu一个值()。


0
投票

这似乎(2年后在2019年)是documented on MSDN:

NOTIFYICONDATAA structure

uCallbackMessage

类型:UINT

当uVersion构件是0或NOTIFYICON_VERSION,该消息的wParam参数包含在任务栏图标中发生事件的标识符。这个标识符可以是长度为32个比特。 lParam参数保存与事件相关联的鼠标或键盘消息。例如,当在任务栏图标的指针移动,lParam的被设置为WM_MOUSEMOVE

当uVersion构件是NOTIFYICON_VERSION_4,应用程序继续接收在通过uCallbackMessage构件应用程序定义的消息的形式通知事件,但该消息的wParam和lParam参数的解释如下改变:

  • LOWORD(lParam)包含通知事件,如NIN_BALLOONSHOW,NIN_POPUPOPEN,或WM_CONTEXTMENU。
  • HIWORD(lParam)包含图标ID。图标ID被限制为16个比特的长度。
  • GET_X_LPARAM(wParam)返回X坐标锚通知事件NIN_POPUPOPEN,NIN_SELECT,NIN_KEYSELECT,和WM_MOUSEFIRST和WM_MOUSELAST之间所有的鼠标消息。如果任何这些消息是由键盘产生的wParam被设定为目标图标的左上角。对于其他所有消息,wParam为不确定。
  • GET_Y_LPARAM(wParam)返回在Y坐标锚通知事件和消息作为X锚定义。

-1
投票

uVersion结构的NOTIFYICONDATA构件可以有3个可能的值,表示用于创建任务栏图标的API的版本。

  • 0使用事先到Windows 2000设计的Windows版本应用此值。
  • NOTIFYICON_VERSION使用Windows 2000的行为。使用了专为Windows 2000及更高版本的应用该值。
  • NOTIFYICON_VERSION_4使用当前的行为。使用了专为Windows Vista和更高版本的应用该值。

当涉及到消息处理程序托盘图标,所述wParamuParam具有如下面的图像中示出的不同之处。

NOTIFYICON_VERSION vs NOTIFYICON_VERSION_4

请注意,在NOTIFYICON_VERSION_4的wParam中给出了X,和各种事件的Y坐标,但没有规定获取坐标NOTIFYICON_VERSION。这就产生了一个有趣的现象(这是一个BUG,我试图解决的一个原因)。如果您使用NOTIFYICON_VERSION,然后调用托盘图标,然后将鼠标光标,只要当你调用的菜单可能的上下文菜单中,得到正确的托盘图标的中心放置。即使你的调用图标的上下文菜单使用键盘(WINDOWS + B),鼠标指针仍然移动到图标。

这可能不是特别感兴趣的是你的,直到你看看这个特殊的BUG我想在Pico torrent应用程序来解决。

下面是这种情况。

  • 操作系统:Windows 10
  • 应用程序是不是每个监视器DPI知道,但系统级DPI意识。
  • 有桌面缩放组的初始值,比方说150%,当用户登录英寸
  • 微微洪流正在运行。
  • DPI缩放值改变,比方说125%
  • 微微洪流的上下文菜单中调用上下文菜单将不会在适当的位置被显示出来,并会被移动了一点,呈现出偏差。

请参阅下面的图片来了解发生了什么。

DPI scaling level : 150 % DPI scaling level : 125 %

问题是,虽然MSDNGET_X_LPARAM(wParam)GET_Y_LPARAM(wParam)应在托盘图标的处理程序给予正确的价值观,但它没有,在DPI缩放(即在DPI缩放变化的存在而不做登出并在)。在另一方面GetCursorPos()返回鼠标光标的坐标的正确值的API。注意随着NOTIFYICON_VERSION_4将只工作,不GetCursorPos(),因为上下文菜单中可以使用键盘,在该鼠标光标可以在屏幕(S)上的任何地方被调用。

那么,如何结合所有的知识刚刚学会正确显示托盘图标的上下文菜单时DPI缩放在上面的方式完成,无需让你的应用程序每监视器DPI感知(每监视器DPI感知应用程序GET_X_LPARAM(wParam)GET_Y_LPARAM(wParam)总是返回正确的值)?

使用NOTIFYICON_VERSION代替NOTIFYICON_VERSION_4,这将在托盘图标上的鼠标光标调用上下文菜单时,然后用GetCursorPos()获取鼠标光标的位置。显示使用TrackPopupMenu()与坐标的上下文菜单。

PS:在DPI缩放值上面的例子中是从150%变化到125%。当DPI缩放从一个更大的价值做了一个小的值,当你的托盘图标区位于屏幕的右下方的上下文菜单偏差更加明显。这是因为当DPI缩放完成,窗口放大这是不是每个显示器意识到,使用DPI虚拟化,那么事情向右移动,病房,和下病房的UI元素。例如。如果在应用程序中的窗口矩形(0,0,100,100)(屏幕坐标),然后放大到150%后,可能变得(0,0,150,150)。现在对于托盘图标的菜单,如果你指定的位于超出屏幕的右下角坐标,那么OS仍然会显示在其位于屏幕内侧的右下角位置,并确保菜单正常显示。例如。如果屏幕是1920×1080,和TrackPopupMenu()is给出(10000,10000)为菜单,菜单仍然为1920×1080的屏幕矩形内显示。因此,增加DPI缩放不会任何进一步的移动上下文菜单中,如果它已经达到了右最低位置。

© www.soinside.com 2019 - 2024. All rights reserved.