画面上のウィンドウをグリッドスタイルで配置するアプリを開発しています。これをWindows 10で実行すると、ウィンドウ間に大きなギャップがあります。さらなる調査の結果、GetWindowRect
は目に見えない境界線を含む予期しない値を返していることがわかりましたが、境界線が見える実際の値を返すことはできません。
1) このスレッド はこれが仕様によるものであり、winver = 6とリンクすることで「修正」できることを示唆しています。私の環境ではこれは許可されていませんが、影響なしでPE MajorOperatingSystemVersion
およびMajorSubsystemVersion
を6に変更しようとしました
2)同じスレッドは、DwmGetWindowAttribute
をDWMWA_EXTENDED_FRAME_BOUNDS
とともに使用してDWMから実際の座標を取得することも推奨していますが、これは機能しますが、ウィンドウ座標を取得するすべての場所を変更することを意味します。また、値を設定することもできません。ウィンドウサイズを設定できるように、プロセスを逆にする必要があります。
3) この質問 は、プロセスにおけるDPI認識の欠如を示唆しています。マニフェストにDPI認識フラグを設定することも、SetProcessDpiAwareness
を呼び出すことも、結果にはなりませんでした。
4)気まぐれに、Windows Vista、7、8、8.1、および10の互換性フラグも追加しようとしましたが、Windowsテーマは変更なしで表示されます。
このウィンドウは0x0、1280x1024に移動され、おそらく画面全体に表示されます。座標を照会すると、同じ値が返されます。ただし、ウィンドウの実際の幅は14ピクセル狭くなっています。これは、古いバージョンのWindowsの境界を考慮するためです。
実際のウィンドウ座標で作業するようにWindowsを説得するにはどうすればよいですか?
Windows 10の左、右、下には目に見えない薄い境界線があり、サイズ変更のためにマウスをつかむために使用されます。境界は次のようになります。7,0,7,7
(左、上、右、下)
SetWindowPos
を呼び出して、ウィンドウをこの座標に配置すると、次のようになります。0, 0, 1280, 1024
ウィンドウはそれらの正確な座標を選択し、GetWindowRect
は同じ座標を返します。しかし視覚的には、ウィンドウは次のように見えます。7, 0, 1273, 1017
ウィンドウをだまして、代わりにここに移動するように指示できます。-7, 0, 1287, 1031
そのために、Windows 10の境界線の太さを取得します。
RECT rect, frame;
GetWindowRect(hwnd, &rect);
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT));
//rect should be `0, 0, 1280, 1024`
//frame should be `7, 0, 1273, 1017`
RECT border;
border.left = frame.left - rect.left;
border.top = frame.top - rect.top;
border.right = rect.right - frame.right;
border.bottom = rect.bottom - frame.bottom;
//border should be `7, 0, 7, 7`
次に、長方形を次のようにオフセットします。
rect.left -= border.left;
rect.top -= border.top;
rect.right += border.left + border.right;
rect.bottom += border.top + border.bottom;
//new rect should be `-7, 0, 1287, 1031`
より簡単な解決策がない限り!
どうすれば実際のウィンドウ座標で作業できるようにWindowsを説得できますか?
あなたはすでに実際の座標で作業しています。 Windows10は単に境界線を目から隠すことを選択しました。しかし、それでも彼らはまだそこにいます。ウィンドウの端を通過すると、カーソルがサイズ変更カーソルに変わります。つまり、実際にはまだウィンドウ上にあります。
Windowsが伝えていることと目を一致させたい場合は、Aero Liteテーマを使用して、これらの境界線を表示して、再び見えるようにすることができます。
http://winaero.com/blog/enable-the-hidden-aero-lite-theme-in-windows-10/
AdjustWindowRectEx
(またはWindows 10以降 AdjustWindowRectExForDpi
)が役立つ場合があります。これらの関数は、クライアントの長方形をウィンドウサイズに変換します。
境界線を重ねたくないと思うので、これはおそらく完全な解決策ではありません-しかし、それは解決策の一部であり、この質問に出くわした他の人々にとって役立つかもしれません。
これが私のコードベースの簡単なスニペットです。これらを使用してウィンドウサイズを設定し、目的のクライアントサイズを取得しました。エラー処理マクロはご容赦ください。
DWORD window_style = (DWORD)GetWindowLong(global_context->window, GWL_STYLE);
CHECK_CODE(window_style);
CHECK(window_style != WS_OVERLAPPED); // Required by AdjustWindowRectEx
DWORD window_style_ex = (DWORD)GetWindowLong(global_context->window, GWL_EXSTYLE);
CHECK_CODE(window_style_ex);
// XXX: Use DPI aware version?
RECT requested_size = {};
requested_size.right = width;
requested_size.bottom = height;
AdjustWindowRectEx(
&requested_size,
window_style,
false, // XXX: Why always false here?
window_style_ex
);
UINT set_window_pos_flags = SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
CHECK_CODE(SetWindowPos(
global_context->window,
nullptr,
0,
0,
requested_size.right - requested_size.left,
requested_size.bottom - requested_size.top,
set_window_pos_flags
));
上記の使用例には、まだ2つのあいまいさが存在します。