我有一个窗口,我想将边框实现为调整边框大小,就像任何其他窗口一样。从评论和答案中吸取建议,我重写了我的代码。对于 WM_GETMINMAXINFO,我有:
MINMAXINFO *min_max = reinterpret_cast<MINMAXINFO *>(lparam);
min_max->ptMinTrackSize.x = MINX;
min_max->ptMinTrackSize.y = MINY;
MINX 和 MINY 是我希望窗口的最小尺寸。对于 WM_NCHITTEST,我有:
RECT wnd_rect;
int x, y;
GetWindowRect (window, &wnd_rect);
x = GET_X_LPARAM (lparam) - wnd_rect.left;
y = GET_Y_LPARAM (lparam) - wnd_rect.top;
if (x >= BORDERWIDTH && x <= wnd_rect.right - wnd_rect.left - >BORDERWIDTH && y >= BORDERWIDTH && y <= TITLEBARWIDTH)
return HTCAPTION;
else if (x < BORDERWIDTH && y < BORDERWIDTH)
return HTTOPLEFT;
else if (x > wnd_rect.right - wnd_rect.left - BORDERWIDTH && y < BORDERWIDTH)
return HTTOPRIGHT;
else if (x > wnd_rect.right - wnd_rect.left - BORDERWIDTH && y > wnd_rect.bottom - wnd_rect.top - BORDERWIDTH)
return HTBOTTOMRIGHT;
else if (x < BORDERWIDTH && y > wnd_rect.bottom - wnd_rect.top - BORDERWIDTH)
return HTBOTTOMLEFT;
else if (x < BORDERWIDTH)
return HTLEFT;
else if (y < BORDERWIDTH)
return HTTOP;
else if (x > wnd_rect.right - wnd_rect.left - BORDERWIDTH)
return HTRIGHT;
else if (y > wnd_rect.bottom - wnd_rect.top - BORDERWIDTH)
return HTBOTTOM;
return HTCLIENT;
变量是不言自明的。此代码为我提供了一个边框,我可以拖动它来调整窗口大小。当我拖动右下角、底部和右边框时效果很好。对于其他边框,当我尝试拖动它们时,窗口的右下角似乎仍然来回移动。它类似于在具有相同边框集的 Google Chrome 或 Visual Studio 2012 中看到的内容,但我在 Windows 资源管理器中看不到这一点。
有没有办法让右下角在我调整顶部或左侧边框大小时不会像在 Windows 资源管理器中那样来回“摆动”?
最佳答案
我知道有点晚了,但我想我已经找到了一种无需“扭动”即可调整大小的方法(窗口内绘图延迟仍然存在)。
与 manuell 所说的不同,WM_NCCALCSIZE
是万恶之源。此方法也应该适用于任何窗口样式(使用WS_POPUP
和WS_OVERLAPPEDWINDOW
测试)
在保留其功能的同时,我该闭嘴并发布带有评论的代码了:
//some sizing border definitions
#define MINX 200
#define MINY 200
#define BORDERWIDTH 5
#define TITLEBARWIDTH 30
//................
HWND TempHwnd = Create(NULL, TEXT("CUSTOM BORDER"), TEXT("CUSTOM BORDER"),
WS_POPUP | WS_VISIBLE,
100, 100, 400, 400, NULL, NULL,
GetModuleHandle(NULL), NULL);
//...............
LRESULT CALLBACK WinMsgHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZING: // I use this message to redraw window on sizing (o rly?)
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
case WM_PAINT: // Used to draw borders and stuff to test WM_NCHITTEST
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
RECT ClientRect;
GetClientRect(hWnd, &ClientRect);
RECT BorderRect = { BORDERWIDTH, BORDERWIDTH, ClientRect.right - BORDERWIDTH - BORDERWIDTH, ClientRect.bottom - BORDERWIDTH - BORDERWIDTH },
TitleRect = { BORDERWIDTH, BORDERWIDTH, ClientRect.right - BORDERWIDTH - BORDERWIDTH, TITLEBARWIDTH };
HBRUSH BorderBrush = CreateSolidBrush(0x0000ff);
FillRect(ps.hdc, &ClientRect, BorderBrush);
FillRect(ps.hdc, &BorderRect, GetSysColorBrush(2));
FillRect(ps.hdc, &TitleRect, GetSysColorBrush(1));
DeleteObject(BorderBrush);
EndPaint(hWnd, &ps);
}
break;
case WM_GETMINMAXINFO: // It is used to restrict WS_POPUP window size
{ // I don't know if this works on others
MINMAXINFO *min_max = reinterpret_cast<MINMAXINFO *>(lParam);
min_max->ptMinTrackSize.x = MINX;
min_max->ptMinTrackSize.y = MINY;
}
break;
case WM_CREATE: // In this message we use MoveWindow to invoke
{ //WM_NCCALCSIZE msg to remove border
CREATESTRUCT *WindowInfo = reinterpret_cast<CREATESTRUCT *>(lParam);
MoveWindow(hWnd, WindowInfo->x, WindowInfo->y, WindowInfo->cx - BORDERWIDTH, WindowInfo->cy - BORDERWIDTH, TRUE);
//Notice that "- BORDERWIDTH" is recommended on every manually called resize function,
//Because we will add BORDERWIDTH value in WM_NCCALCSIZE message
}
break;
case WM_NCCALCSIZE:
{ // Microsoft mentioned that if wParam is true, returning 0 should be enough, but after MoveWindow or similar functions it would begin to "wriggle"
if (wParam)
{
NCCALCSIZE_PARAMS *Params = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam);
Params->rgrc[0].bottom += BORDERWIDTH; // rgrc[0] is what makes this work, don't know what others (rgrc[1], rgrc[2]) do, but why not change them all?
Params->rgrc[0].right += BORDERWIDTH;
Params->rgrc[1].bottom += BORDERWIDTH;
Params->rgrc[1].right += BORDERWIDTH;
Params->rgrc[2].bottom += BORDERWIDTH;
Params->rgrc[2].right += BORDERWIDTH;
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
break;
case WM_NCHITTEST:
{
RECT WindowRect;
int x, y;
GetWindowRect(hWnd, &WindowRect);
x = GET_X_LPARAM(lParam) - WindowRect.left;
y = GET_Y_LPARAM(lParam) - WindowRect.top;
if (x >= BORDERWIDTH && x <= WindowRect.right - WindowRect.left - BORDERWIDTH && y >= BORDERWIDTH && y <= TITLEBARWIDTH)
return HTCAPTION;
else if (x < BORDERWIDTH && y < BORDERWIDTH)
return HTTOPLEFT;
else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH && y < BORDERWIDTH)
return HTTOPRIGHT;
else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH && y > WindowRect.bottom - WindowRect.top - BORDERWIDTH)
return HTBOTTOMRIGHT;
else if (x < BORDERWIDTH && y > WindowRect.bottom - WindowRect.top - BORDERWIDTH)
return HTBOTTOMLEFT;
else if (x < BORDERWIDTH)
return HTLEFT;
else if (y < BORDERWIDTH)
return HTTOP;
else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH)
return HTRIGHT;
else if (y > WindowRect.bottom - WindowRect.top - BORDERWIDTH)
return HTBOTTOM;
else
return HTCLIENT;
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
关于c++ - WinAPI C++ : Reprogramming Window Resize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19106047/