Create custom window border disappears on resize

Pretty much what the title says.

I am trying to make my own border, for example visual studio 2015. Once the border is working for me, I have to add a child window which is the main window for my program, the border will be the parent. I will also try adding an outer glow as soon as I get it working.

But the problem im having right now is when I drag my border to resize to shrink it. Right or bottom start getting thinner depending on how fast I drag the mouse.

Is there a better way to do this or is there a simple step I can take to fix it.

#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);
}

      

+3


source to share


1 answer


If you only want a rectangular frame, a simpler solution can be achieved like this:

  • The window style should be such that the entire frame is usually displayed ( WS_CAPTION|WS_POPUP

    works well for me).
  • Call DwmExtendFrameIntoClientArea()

    with MARGINS{0,0,0,1}

    .
  • Call SetWindowPos(nullptr, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED)

    for recalculation of the NC area.
  • Returns 0 from WM_NCCALCSIZE

    if wParam TRUE

    . This expands the client area to the size of the window, including the frame. The border of the regular window will be removed, but the shadow will still be drawn by the DWM (see also the WM_NCCALCSIZE notes section ).
  • In WM_PAINT

    draw your frame and content area as you wish, but remember to set an opaque alpha channel for the box defined by the call DwmExtendFrameIntoClientArea()

    . Otherwise, part of the regular frame will be visible in this area. You can use GDI + for this, since most normal GDI functions ignore the alpha channel.


You can place child controls in this window as usual. Just make sure the child controls do not overlap the border defined by the call DwmExtendFrameIntoClientArea()

, because most GDI controls ignore the alpha channel.

0


source







All Articles