2016-10-08 2 views
1

私は、親ウィンドウとタブコントロールの子ウィンドウを持つアプリケーションを持っています。タブコントロールには、CS_HREDRAWCS_VREDRAWのクラススタイルがあります。親ウィンドウのサイズを変更すると、WM_PAINTの親のクリッピング矩形はタブコントロールのサイズと同じになります。これは、CS_HREDRAWCS_VREDRAWクラススタイルを持たない子ウィンドウでは発生しません。通常、親ウィンドウのサイズを変更すると、親ウィンドウのクリッピング矩形は親ウィンドウの覆われていない部分と等しくなります。なぜこれが起こるのですか?親ウィンドウのクリッピング矩形が子ウィンドウのサイズと同じであるのはなぜですか?

EDIT:親ウィンドウのクリッピング矩形が親のクライアントエリア全体のサイズの理由はなぜですか?親クラスにCS_HREDRAW/CS_VREDRAWを指定していません。親ウィンドウのクリッピング矩形を、サイズを変更したときに覆われていない領域だけにしたい。親ウィンドウにこれらのクラススタイルがある場合、子ウィンドウはCS_HREDRAW/CS_VREDRAWを継承します。ドキュメンテーションは、親が子供のスタイルを継承しているとは言いません。親ウインドウにクラススタイルがCS_HREDRAW/CS_VREDRAWではないが、子がそうである場合、親はそのスタイルを子から継承しますか?

#include <windows.h> 
#include <commctrl.h> 

#pragma comment(lib, "comctl32.lib") 
HINSTANCE g_hInst; 

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    static HWND hTab; 
    static RECT rc; 

    switch(msg) 
    { 
    case WM_CREATE: 
     hTab = CreateWindowEx(0, WC_TABCONTROL, 0, WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, hwnd, 0, g_hInst, 0); 
     break; 

    case WM_PAINT: 
     { 
      HDC hdc; 
      PAINTSTRUCT ps; 
      WCHAR text[70]; 

      hdc = BeginPaint(hwnd, &ps); 
      wsprintf(text, L"%d, %d, %d, %d", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); 
      SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)text); 
      EndPaint(hwnd, &ps); 
     } 
     break; 

    case WM_SIZE: 
     GetClientRect(hwnd, &rc); 
     SetWindowPos(hTab, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER); 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 

    default: 
     return DefWindowProc(hwnd, msg, wParam, lParam); 
    } 
    return 0; 
} 


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 
{ 
    const TCHAR szClassName[] = L"Appppppppppppp"; 
    WNDCLASSEX wc = { 0 }; 
    HWND hwnd; 
    MSG msg; 

    wc.cbSize  = sizeof(WNDCLASSEX); 
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 
    wc.hCursor  = LoadCursor(0, IDC_ARROW); 
    wc.hIcon   = LoadIcon(0, IDI_APPLICATION); 
    wc.hInstance  = hInstance; 
    wc.lpfnWndProc = WndProc; 
    wc.lpszClassName = szClassName; 
    if(!RegisterClassEx(&wc)) return 0; 

    g_hInst = hInstance; 
    InitCommonControls(); 
    hwnd = CreateWindowEx(0, szClassName, L"App", WS_OVERLAPPEDWINDOW, 40, 40, 420, 200, 0, 0, hInstance, 0); 
    if(!hwnd) return 0; 

    ShowWindow(hwnd, nCmdShow); 
    UpdateWindow(hwnd); 

    while(GetMessage(&msg, 0, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return (int)msg.wParam; 
} 
+0

あなたの親ウィンドウが '' CS_HREDRAW'またはCS_VREDRAW'クラスのスタイルを持っていません。サイズを変更すると、クリッピング矩形がウィンドウ全体を囲むのはなぜと思いますか?あなたのクラス登録が要求されました、あなたはそうしたくありません。 – IInspectable

+0

@IInspectableまさに!私は、親ウィンドウが 'CS_HREDRAW'と' CS_VREDRAW'を指定しないことでそれ自身を再描画しないように要求しましたが、サイズを変更するたびに再描画します。私は、タブコントロールに 'CS_HREDRAW'と' CS_VREDRAW'スタイルがあるという事実と関係があると思います。サイズを変更するたびに親ウィンドウが再描画されないようにするにはどうすればよいですか? – Mike32ab

+0

本当に気になりますか?または、[WS_CLIPCHILDREN](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600.aspx)ウィンドウスタイルが欠落していますか? – IInspectable

答えて

2

問題は、WM_SIZEハンドラが遅すぎて、メインウィンドウの一部が既にダーティとマークされていることです。 DefWindowProc()を呼び出す前に、WM_SIZING時に早く行う必要があります。これはうまくいきますが、提案された新しいウィンドウサイズからクライアント領域を計算するのは難しいという問題があります。

簡単な回避策は、検証として、子コントロールによって占有ウィンドウの一部をマークすることです:

case WM_SIZE: 
    GetClientRect(hwnd, &rc); 
    SetWindowPos(hTab, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER); 
    ValidateRect(hwnd, &rc);  // <== added 
    break; 
関連する問題