标题所说的几乎是。
我试图像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通道。