私の開発スタンスはとりあえずやりたいことをやって、中途半端に実装して違うことしだすんで一向に完成しません…。おかずだけ食べてごはんが残るような状態です。なので最近は1機能を面倒でもしっかり作りんこんでから次に行くようにしました。一通りタブの実装が終わったんで、次はやりたくは無いんですが、ポップアップメニューを仕上げようとしています。
あとやらないといけないのは2つあって、1つはポップアップメニューが縦に長くなった時に表示される↑↓ボタンを表示するのと、画面の端っこの方でポップアップメニューが表示された場合の表示位置の調整です。どちらの実装もディスプレイの情報が必要になります。
ポップアップメニューの↑↓ボタンって?
メニューの上下に表示される↑↓です。私が実装しちゃったので、少ないメニューでも表示されていますが、本当はメニューの数が多くなってディスプレイに表示できなくなると自動的に表示されます。
マルチディスプレイを考慮してディスプレイ情報を取得する方法
やっと本題。これでよさそう。monitor_info が rcMonitor ならディスプレイ全体の領域で rcWork ならタスクバーを除いた領域を取得できるようです。メモ帳のポップアップメニューはタスクバーの上にも表示されるので、rcMonitor でよさそう。
仮にウィンドウがどのディスプレイモニターとも交差しない場合、ウィンドウに最も近いディスプレイモニターへのハンドルを返してもらうために MonitorFromWindow の第2引数には MONITOR_DEFAULTTONEAREST を設定します。
ただ、実際にマルチディスプレイ環境で試せるといいのですが、私の開発環境は接続端子が無くて試せないんです…。もしかして1 枚のディスプレイでも試せる方法ってあるんですかね?
ディスプレイ全体の情報を取得する
指定したウィンドウが存在するディスプレイ全体の領域を取得するサンプルです。
static inline void GetMonitorRect(HWND hWnd, RECT& rect) {
// ウィンドウが表示されているディスプレイ情報を取得する
HMONITOR monitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor_info{};
monitor_info.cbSize = sizeof(monitor_info);
::GetMonitorInfo(monitor, &monitor_info));
rect = monitor_info.rcMonitor;
}
タスクバーを除いたディスプレイ情報を取得
指定したウィンドウが存在するディスプレイからタスクバーを除いた作業領域を取得するサンプルです。
static inline void GetMonitorRect(HWND hWnd, RECT& rect) {
// ウィンドウが表示されているディスプレイ情報を取得する
HMONITOR monitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor_info{};
monitor_info.cbSize = sizeof(monitor_info);
::GetMonitorInfo(monitor, &monitor_info));
rect = monitor_info.rcWork;
}
おわりに
あと、確かメモ帳のポップアップメニューは表示しているディスプレイ内で完結しようとするけど、.NETのポップアップメニューは表示しきれなくなると別ディスプレイに表示する違いがあったような…。これも今すぐ確認できないんですよね。つらいですね。
コメント