@EDIT: Windows 7 と VS 2012 でクラシック ビューと Aero ビューの両方を試してみたところ、Windows 8 RC の問題であることがわかりました。@Werner Henze と @Ven Boigt のフィードバックに感謝します
EDIT 2:これはベータ版であったため、Windows のバグであり、新しいリビジョンで修正されたので、もう心配する必要はありません。とにかくフィードバックをありがとう。
以前は、800*600 のクライアント領域のウィンドウを作成するために次のことを行っていました。
dwStyle = WS_OVERLAPPED | WS_THICKFRAME | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX;
hWindowHandle = CreateWindow( L"CGFramework", wszWndCaption,
pWindowData->dwStyle, pWindowData->nPositionX, pWindowData->nPositionY,
800 + GetSystemMetrics( SM_CXSIZEFRAME )*2,
600 + GetSystemMetrics( SM_CYSIZEFRAME ) *2
+ GetSystemMetrics( SM_CYCAPTION ),
0, 0, hInstance, 0
);
その後、GetClientRect を使用してクライアント rect をクエリすると、以前は 800*600 を取得していましたが、Visual Studio 2008 プロジェクトを VS2012 にアップグレードしたところ、GetClientRect() 関数が代わりに 792*592 を返すようになりました。
その上、作成されるウィンドウの実際のサイズは 804*629 です。サイズ変更可能なフレーム (WS_THICKFRAME から) は明らかに両側で 2 ピクセルよりも大きいため、理由はわかりません。
これは Windows 8 の Aero 動作の問題だと思っていましたが、これは VS2012 ビルドでのみ発生し、VS2008 ビルドでは発生しないことに気付きました。Aero またはクラシック スタイルで実行しても違いはありません。動作は VS2012 ビルドにのみ適用されます。なんで?この恐ろしい動作を修正するために、VS2012 プロジェクト構成を変更できるものはありますか?
プロジェクト構成の「DPI認識」設定を変更してみましたが、違いはありません。また、同じ構成ページでマニフェストの使用を削除しましたが、結果のウィンドウにはまだ変化が見られません。
これは私のテストコードです:
#include <Windows.h>
#include <cstdio>
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
// WM_DESTROY is sent when the window is being destroyed.
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd )
{
WNDCLASS wc;
wc.style = NULL; // CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
wc.lpszMenuName = 0;
wc.lpszClassName = L"CGFramework";
DWORD dwStyle = WS_OVERLAPPED | WS_THICKFRAME | WS_BORDER |
WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX; // WS_DLGFRAME |
if( !RegisterClass(&wc) )
{
MessageBox(0, L"RegisterClass FAILED", 0, 0);
return E_FAIL;
}
RECT r;
//r.left = 100;
//r.top = 100;
//r.right = 800;
//r.bottom = 600;
////-----------------------------
r.left = 100;
r.top = 100;
r.right = 900;
r.bottom = 700;
////-----------------------------
//r.left = 100;
//r.top = 100;
//r.right = 800+GetSystemMetrics( SM_CXFRAME )*2;
//r.bottom = 600+GetSystemMetrics( SM_CYFRAME )*2+GetSystemMetrics( SM_CYCAPTION );
BOOL result = AdjustWindowRect( &r, dwStyle, FALSE );
HWND hWindowHandle = CreateWindow( L"CGFramework", L"testWindow", dwStyle,
r.left, r.top, r.right-r.left, r.bottom-r.top,
// r.left, r.top, r.right, r.bottom,
0, 0, hInstance, 0 );
if( 0 == hWindowHandle )
{
MessageBox(0, L"CreateWindow FAILED", 0, 0);
UnregisterClass( wc.lpszClassName, hInstance );
return 0;
}
char buffer[512]; // for outing test message
GetClientRect( hWindowHandle, &r );
sprintf( &buffer[0], "left=%i, top=%i, right=%i, bottom=%i", r.left, r.top, r.right, r.bottom );
MessageBoxA(0, buffer, 0, 0); // print rect values before ShowWindow
ShowWindow( hWindowHandle, SW_SHOW );
GetClientRect( hWindowHandle, &r );
sprintf( &buffer[0], "left=%i, top=%i, right=%i, bottom=%i", r.left, r.top, r.right, r.bottom );
MessageBoxA(0, buffer, 0, 0); // print rect values after ShowWindow
// main window loop
MSG msg;
ZeroMemory( &msg, sizeof( MSG ) );
while( msg.message != WM_QUIT )
{
while( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
if( GetAsyncKeyState( VK_ESCAPE ) )
DestroyWindow( hWindowHandle );
}
UnregisterClass( wc.lpszClassName, hInstance );
return 0;
}
回答する前にコードを注意深く見てください。私がすでに試したことに回答してしまう可能性があるためです (すべての選択肢を無駄にしたため、この質問を投稿しています)。
Windows 8 RC (MS Windows 6.2.8400) と VS2012 RC (11.0.50706.0 QRELRC July 2012) を使用してこの奇妙な動作を取得していますが、この問題に対処できる回答はありませんでした。このコードはさまざまな方法でテストされていますが、微妙な違いがあり、最終的には改善されませんでした。