|
[図10-1] :
ただし,ここで問題があります.WM_SIZEの処理中にMoveWindow()やSetWindowPos()といったウィンドウサイズを変えるAPIを呼ぶと,MoveWindow()した後にまたWM_SIZEが発生してしまい,WM_SIZEの処理内でMoveWindow()して,またWM_SIZEが発生して...と,永久ループに陥ってしまう可能性があるということです.
MoveWindow()で,変更前と変更後のサイズをぴったり同じサイズにサイズ変更すると,WM_SIZEは発生しないので,とりあえずこの方法でも問題はおきません.
しかし,一応念のために,永久ループに陥らないように対処はしておくべきです.リスト10-1では,WM_SIZE処理中にWM_SIZEが発生する場合は,static変数にフラグを立てておき,フラグが立っている場合はWM_SIZEの処理はしないようにしています.これで安全になります.
[リスト10-1] :
#include <windows.h> #define XRAITO 16 #define YRAITO 9 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_CREATE: break; case WM_DESTROY : PostQuitMessage(0); return 0; case WM_PAINT :{ HDC hdc; PAINTSTRUCT ps; RECT rc; hdc = BeginPaint( hwnd ,&ps ); GetClientRect (hwnd , &rc ); char sz[256]; wsprintf( sz, "%d x %d", rc.right - rc.left, rc.bottom - rc.top ); DrawText( hdc , sz ,-1 ,&rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER ); EndPaint(hwnd ,&ps ); return 0; } case WM_SIZE:{ static BOOL fProcessing = FALSE; if( !fProcessing ) { static int cxOld = 1; static int cyOld = 1; RECT rc; GetClientRect( hwnd, &rc ); int cx = rc.right - rc.left; int cy = rc.bottom - rc.top; BOOL f = FALSE; if( (cx * 100 / cxOld) > (cy * 100 / cyOld) ) { f = TRUE; } if( cx == cxOld && cy != cyOld ) { f = FALSE; } else if( cy == cyOld && cx != cxOld ) { f = TRUE; } if( f ) { cy = ( cx / XRAITO ) * YRAITO; } else { cx = ( cy / YRAITO ) * XRAITO; } rc.right = rc.left + cx; rc.bottom = rc.top + cy; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); if( cx != cxOld || cy != cyOld ) { fProcessing = TRUE; SetWindowPos( hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOMOVE ); } cxOld = cx; cyOld = cy; } else { fProcessing = FALSE; } return 0; } } return DefWindowProc(hwnd , message ,wParam ,lParam); } int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { static char szAppName[] = "HelloWin" ; HWND hwnd; MSG msg; WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = (WNDPROC)WndProc ; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance ; wc.hIcon = LoadIcon ( NULL , IDI_HAND ); wc.hCursor = LoadCursor ( NULL , IDC_ARROW ); wc.hbrBackground= GetStockObject ( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName=szAppName; RegisterClass( &wc ); // hwnd = CreateWindowEx ( WS_EX_CLIENTEDGE, szAppName, hwnd = CreateWindowEx ( NULL, szAppName, "つきの", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd , nCmdShow ); UpdateWindow( hwnd ); while( GetMessage(&msg , NULL ,0 ,0 ) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); }(2)は,問題もなく簡単にできるはずなので,こちらのほうがいいかもしれません(図10-2).
[図10-2] :