2016-10-08 3 views
1

У меня есть приложение с родительским окном и дочерним окном управления вкладкой. Элемент управления вкладками имеет стили классов CS_HREDRAW и CS_VREDRAW. Когда я изменяю размер родительского окна, обрезающий прямоугольник родителя в WM_PAINT совпадает с размером элемента управления вкладки. Этого не происходит с дочерними окнами, у которых нет стилей классов CS_HREDRAW и CS_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

@Inpectable Точно! Я попросил, чтобы родительское окно не перерисовывало себя, не указывая «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 слишком поздно, части основного окна уже отмечены грязными. Вы должны сделать это раньше, в WM_SIZING время, перед вызовом DefWindowProc(). Это прекрасно работает, но с серьезной проблемой трудно вычислить область клиента из предложенного размера нового окна.

Простой обходной путь, чтобы пометить часть окна, занимаемого дочерний элемент управления, как подтверждено:

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; 
Смежные вопросы