uVersion
NOTIFYICONDATA
構造体のメンバには、タスクバーアイコンの作成に使用されているAPIのバージョンを表す3つの値を指定できます。
- のバージョンのWindows用に設計されたアプリケーションのための使用は、この値を以前のWindows 2000へ
- NOTIFYICON_VERSION Windows 2000の動作を使用してください。この値は、Windows 2000以降用に設計されたアプリケーションに使用します。
- NOTIFYICON_VERSION_4現在の動作を使用します。 Windows Vista以降用に設計されたアプリケーションには、この値を使用します。
トレイアイコンのメッセージハンドラについては、wParam
とuParam
の違いは次のとおりです。

NOTIFYICON_VERSION_4
にwParamには、Xを与え、様々なイベントのY座標が、NOTIFYICON_VERSION
の座標を取得するための規定がないことに注意してください。これは面白い振る舞いを引き起こします(私が解決しようとしていたバグの原因でした)。 NOTIFYICON_VERSION
を使用してトレイアイコンのコンテキストメニューを呼び出すと、マウスカーソルは、メニューを呼び出している間はどこでもトレイアイコンの中央に置かれます。アイコンのコンテキストメニューを呼び出すためにキーボード(WINDOWS + B)を使用しても、マウスカーソルはアイコンに移動します。
私がPico torrentアプリケーションで解決しようとしているこの特定のバグを見るまで、これは特に興味深いことではありません。
ここにシナリオがあります。
- OS:Windowsの10
- アプリケーションごとのモニターDPIは認識していないが、システムレベルDPIは認識しています。
- ユーザがログインしたときにデスクトップスケーリングの初期値が設定されています(たとえば150%)。
- ピコトレントが実行されています。
- DPIスケーリング値は125%
- ピコの急流のコンテキストメニューは、コンテキストメニューは、その適切な場所に表示されません 呼び出され、逸脱を示す、少しずれることになると言う、に変更されます。
何が起きているのかを理解するには、次のイメージを参照してください。

問題はあるがMSDNはGET_X_LPARAM(wParam)
、およびGET_Y_LPARAM(wParam)
は、トレイアイコンのハンドラで正しい値を与えるべきであると述べているが、それは、DPIの存在にするために、すなわち(スケーリングしないということですサインアウトやサインインをせずにDPIスケーリングを変更する)。一方、API GetCursorPos()
はマウスカーソル座標の正しい値を返します。画面上のどこにでもマウスカーソルを置くことができるキーボードを使用してコンテキストメニューを呼び出すことができるので、NOTIFYICON_VERSION_4
とGetCursorPos()
は機能しません。
DPIスケーリングが上記のように行われたときにトレイアイコンのコンテキストメニューを正しく表示するために学んだ知識を、どのように組み合わせて、アプリケーションごとにDPI対応アプリケーションを作成する必要はありませんGET_X_LPARAM(wParam)
、GET_Y_LPARAM(wParam)
は常に正しい値を返します)。
NOTIFYICON_VERSION_4
の代わりにNOTIFYICON_VERSION
を使用すると、コンテキストメニューが呼び出されたときにトレイアイコンにマウスカーソルが移動し、GetCursorPos()
を使用してマウスカーソルの位置を取得します。座標を使用してTrackPopupMenu()
を使用してコンテキストメニューを表示します。
PS:上記の例では、DPIスケーリング値が150%から125%に変更されています。トレイアイコン領域が画面の右下にある場合、DPIスケーリングが大きい値から小さい値に設定されると、コンテキストメニューの偏差がより顕著になります。これは、DPIスケーリングが実行され、DPI仮想化を使用してモニタごとに認識されないUI要素を拡大すると、物事が右肩上がり、下り坂に移動するためです。例えば。アプリケーションでウィンドウの矩形が(0,0,100,100)(画面座標)の場合、倍率150%の後に(0,0,150,150)になることがあります。今トレイアイコンのメニューの場合、画面の右下を越える座標を指定すると、OSは画面内の右下の位置に表示され、メニューが正しく表示されます。例えば。画面が1920x1080で、メニューがTrackPopupMenu()
(10000,10000)の場合、メニューは1920x1080画面の四角形内に表示されます。したがって、DPIスケーリングが増加するとコンテキストメニューがさらに右に移動することはありません。
問題の正しい解決方法は、プログラムをDPIに対応させることです。実行時に必要に応じて 'SetProcessDpiAwareness()'を動的にロードしてください。 – andlabs
また、トレイアイコンのポップアップがキーボードから呼び出されているときは、['Shell_NotifyIconGetRect()'](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378426 vs.85).aspx)を使用して、GetCursorPos()を使用してマウスの現在の画面位置を取得する代わりに、アイコン自体の現在のスクリーン位置を取得します。 –
@andlabsいいえ、そうではありません。モニタごとにDPIを認識させると、すべてのUI要素のスケーリングを自分で処理する必要があるためです。多くの開発者は、DPI仮想化をある程度使いたいと思っています。さらに、アプリケーションがUI要素を作成するサードパーティ製のバイナリを使用する場合、コードを持たないため、DPIスケーリングを処理することはできません。これは、MicrosoftがWIndows 10 Aniversary Update、SetThreadDpiAwarenessContext()で新しいAPIを導入する主な理由でした。 –