调整大小的大小时,会创建自定义的Windows边框边缘消失



标题所说的几乎是。

我试图像Visual Studio 2015那样建立自己的边界。一旦我将边框工作如它的工作,我将添加一个子窗口,该窗口是我程序的主窗口,边框将是父母。一旦我工作起来,也会尝试添加外部光芒。

但是,我现在遇到的问题是,当我将边框拖动以使其大小以使其更小时,正确或底部开始变得更薄,具体取决于我拖动鼠标的速度。

有更好的方法来做到这一点,还是可以采取简单的步骤来修复它。

#include <windows.h>
LPTSTR className_ = TEXT("BorderWindow");
BOOL WINAPI Init(HINSTANCE hInstance, INT cmdShow);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow) {
    MSG msg;
    if (!Init(hInstance, nCmdShow)) {
        return FALSE;
    }
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (INT)msg.wParam;
}

BOOL WINAPI Init(HINSTANCE hInstance, INT cmdShow)
{
    WNDCLASSEX wcex{ 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = 0;
    wcex.lpfnWndProc = (WNDPROC)WndProc;
    wcex.hInstance = hInstance;
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT + 1);
    wcex.lpszClassName = className_;
    wcex.hIconSm = NULL;
    if (!RegisterClassEx(&wcex)) {
        return FALSE;
    }
    HWND hwnd_ = CreateWindow(className_, className_, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, 200, 500, nullptr, nullptr, hInstance, nullptr);
    if (!hwnd_)
        return FALSE;
    ShowWindow(hwnd_, cmdShow);
    UpdateWindow(hwnd_);
    return TRUE;
}

void CreateHole(HWND hWnd)
{
    HRGN WindowRgn;
    HRGN HoleRgn;
    //Get the window region:
    RECT windowrect;
    GetWindowRect(hWnd, &windowrect);
    int width = windowrect.right - windowrect.left;
    int height = windowrect.bottom - windowrect.top;
    WindowRgn = CreateRectRgn(0, 0, width, height);
    //Create the hole region:
    HoleRgn = CreateRectRgn(2, 2, width - 2, height - 2);
    CombineRgn(WindowRgn, WindowRgn, HoleRgn, RGN_DIFF);
    SetWindowRgn(hWnd, WindowRgn, TRUE);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_SIZE:
        CreateHole(hwnd);
        return 0;
    case WM_NCCALCSIZE:
        // remove default borders
        return 0;
    case WM_NCHITTEST:
    {
        RECT rc;
        GetClientRect(hwnd, &rc);
        POINT pt = { LOWORD(lparam), HIWORD(lparam) };
        ScreenToClient(hwnd, &pt);
        if (pt.y > (rc.bottom - 5))
        {
            if (pt.x > (rc.right - 5))
            {
                return HTBOTTOMRIGHT;
            }
        }
        return HTBORDER;
    }
    }
    return DefWindowProc(hwnd, message, wparam, lparam);
}

如果您只需要矩形框架,则可以实现更轻松的解决方案,如下所示:

  • 窗口样式应该通常显示整个帧(WS_CAPTION|WS_POPUP对我来说效果很好(。
  • MARGINS{0,0,0,1}致电DwmExtendFrameIntoClientArea()
  • 致电SetWindowPos(nullptr, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED)重新计算NC区域。
  • 如果WPARAM为TRUE,则从WM_NCCALCSIZE返回0。这具有将客户区域扩展到窗口大小在内的效果。常规的窗框将被删除,但DWM仍将绘制阴影(另请参见WM_NCCALCSIZE的注释部分(。
  • WM_PAINT中,按照您的要求绘制框架和内容区域,但请确保为DwmExtendFrameIntoClientArea()调用定义的空白设置不透明的Alpha通道。否则,常规框架的一部分将在该区域可见。您可以使用GDI 为此,因为大多数常规的GDI函数都忽略了alpha频道。

您可以像正常一样将子控制器放入此窗口。只需确保子控制器不会重叠由DwmExtendFrameIntoClientArea()调用定义的余量,因为大多数GDI控制都会忽略Alpha通道。

最新更新