Reputation: 27
I'm trying to create a borderless, captionless, and resizeable without using the WS_THICKFRAME
, WS_BORDER
and WS_SIZEBOX
styles.
I don't want to use these styles because they create a border but more importantly, when I use the SetWindowCompositionAttribute
function to enable an acrylic blur behind on the window, the blur goes past the window for some reason .
I checked out this repo and I'm currently using their hit testing logic.
So essentially I believe I need to implement my own resizing ability but I don't know where to really start.
Upvotes: 0
Views: 846
Reputation: 9545
There is a lot of nuance to exactly replicating all standard window resizing behavior but the main thing you need to do is implement your own handler of WM_NCHITTEST, which basically tells Windows which part of the window a given point is in.
Here's an example that will allow dragging via a custom title bar area and resizing via dragging the left, right, and bottom of the window.
#include <windows.h>
#include <tuple>
#include "windowsx.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = L"customwindowresizing";
if (!RegisterClass(&wc))
return 1;
if (!CreateWindow(wc.lpszClassName,
L"",
WS_POPUP | WS_VISIBLE,
0, 0, 640, 480, 0, 0, hInstance, NULL))
return 2;
while (GetMessage(&msg, NULL, 0, 0) > 0)
DispatchMessage(&msg);
return 0;
}
LRESULT HandleNonclientHitTest(HWND wnd, LPARAM lparam, int title_bar_hgt, int resizing_border_wd)
{
RECT wnd_rect;
GetWindowRect(wnd, &wnd_rect);
int wd = wnd_rect.right - wnd_rect.left;
int hgt = wnd_rect.bottom - wnd_rect.top;
RECT title_bar = { 0,0, wd, title_bar_hgt };
RECT left = { 0, title_bar_hgt , resizing_border_wd , hgt - title_bar_hgt - resizing_border_wd };
RECT right = {wd - resizing_border_wd , title_bar_hgt , wd, hgt - title_bar_hgt - resizing_border_wd };
RECT bottom = { 0, hgt - resizing_border_wd, wd, hgt };
std::tuple<RECT, LRESULT> rects[] = {
{title_bar, HTCAPTION},
{left, HTLEFT},
{right, HTRIGHT},
{bottom, HTBOTTOM}
};
POINT pt = { GET_X_LPARAM(lparam) - wnd_rect.left, GET_Y_LPARAM(lparam) - wnd_rect.top };
for (const auto& [r, code] : rects) {
if (PtInRect(&r, pt))
return code;
}
return HTCLIENT;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_NCHITTEST:
return HandleNonclientHitTest(hWnd, lParam, 25, 10);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Upvotes: 3
Reputation: 25398
So essentially I believe I need to implement my own resizing ability
Actually, you don't. If you only want to resize via the bottom-right hand corner of the window, just catch WM_NCHITTEST
and return HTGROWBOX
when the mouse is in the area of the window that you consider to be your resizing handle.
Other, more complex, return values from WM_NCHITTEST
are possible (including making it possible for the user to drag the window around on the screen), but you get the idea.
Upvotes: 1