WinAPI C ++:重新编程窗口调整大小 [英] WinAPI C++: Reprogramming Window Resize
问题描述
我有一个窗口,我想实现边框调整边框,像任何其他窗口。接受评论和答案的建议,我重写了我的代码。对于WM_GETMINMAXINFO,我有:
I have a window, and I want to implement the borders as resizing borders, like any other window. Taking in suggestions from comments and answers, I have rewritten my code. For WM_GETMINMAXINFO I have:
MINMAXINFO *min_max = reinterpret_cast<MINMAXINFO *>(lparam);
min_max->ptMinTrackSize.x = MINX;
min_max->ptMinTrackSize.y = MINY;
MINX和MINY是我想要的窗口的最小尺寸。对于WM_NCHITTEST,我有:
MINX and MINY are the minimum size I want the window to be. For WM_NCHITTEST I have:
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;
这些变量是不言自明的。这段代码给了我一个边框,我可以拖动来调整窗口大小。它工作得很好,当我拖动右下,底部和右边框。与其他边界,窗口的右下角似乎仍然来回移动,当我试图拖动它们。这是类似的是,在谷歌浏览器或Visual Studio 2012与同组的边界看到,但我不认为这在Windows资源管理器。
The variables are pretty self-explanatory. This code gives me a border that I can drag to resize the window. It works well when I drag the bottom-right, bottom, and right borders. With the other borders, the bottom-right corner of the window still seems to move back and forth when I try to drag them. It's similar to what is seen in Google Chrome or Visual Studio 2012 with the same set of borders, but I don't see this in Windows Explorer.
有没有办法使右下角不是蠕动来回我调整顶部或左侧边框,就像在Windows资源管理器?
Is there a way to make the bottom-right corner not "wriggle" back and forth as I'm resizing the top or left borders, like in Windows Explorer?
推荐答案
我知道这有点晚了,但我想我已经找到一个方法来调整大小,没有扭动(内部窗口绘图滞后将仍然存在)。
I know it is a little late, but I think I have found a way to resize without "wriggle" (inside window drawing lag will still remain).
与manuell所说的不同, WM_NCCALCSIZE
是所有邪恶的根源。此外,此方法应使用任何窗口样式(使用 WS_POPUP
和 WS_OVERLAPPEDWINDOW
测试)
,同时保留了它们的功能,所以我是时候关闭并发布代码与评论:
Unlike what manuell has said, WM_NCCALCSIZE
is the root of all evil. Also this method should work with any window style (tested with WS_POPUP
and WS_OVERLAPPEDWINDOW
)
while preserving their functionality, so it's time for me to shut up and post the code with commentary:
//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;
}
这篇关于WinAPI C ++:重新编程窗口调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!