为什么父窗口的剪切矩形与子窗口的大小相同?

时间:2016-10-08 07:22:52

标签: c winapi

我有一个具有父窗口和制表符控件子窗口的应用程序。选项卡控件具有CS_HREDRAWCS_VREDRAW类样式。当我调整父窗口的大小时,WM_PAINT中父级的剪切矩形与选项卡控件的大小相同。对于没有CS_HREDRAWCS_VREDRAW类样式的子窗口,不会发生这种情况。通常,当您调整父窗口的大小时,父窗口的剪切矩形等于父窗口的未覆盖部分。为什么会这样?

编辑:为什么父窗口的剪切矩形是父窗口的整个客户区域的大小?我没有为父类指定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;
}

1 个答案:

答案 0 :(得分:2)

问题是你的WM_SIZE处理程序太晚了,主窗口的部分已经标记为脏。在调用DefWindowProc()之前,您必须在WM_SIZING时间之前完成此操作。哪个工作正常,但有一个棘手的问题,很难从建议的新窗口大小计算客户区。

简单的解决方法是将子控件占用的窗口部分标记为已验证:

if (! inputFile.exists()) {
    window = new Stage();
    window.initModality(Modality.APPLICATION_MODAL);
    window.initStyle(StageStyle.UNDECORATED);
    window.setTitle("File was not found.");
    window.setMinWidth(250);
    window.setMaxHeight(100);

    //form
    TextField fileInput = new TextField();
    Button inputButton = new Button("Upload File");
    inputButton.disableProperty().bind(Bindings.createBooleanBinding(
        () -> ! new File(fileInput.getText()).exists(), 
        fileInput.textProperty()));
    inputButton.setOnAction(e -> {
        inputFile = new File(fileInput.getText());
        window.close();
    });


    //Layout
    VBox layout = new VBox(10);
    layout.setPadding(new Insets(20, 20, 20, 20));
    layout.getChildren().addAll(fileInput, inputButton);

    //Set scene and show in window.
    Scene scene = new Scene(layout, 300, 100);
    window.setScene(scene);
    window.showAndWait();
}