场景
-
在开发无边框的窗口时,没有了系统自带的边框后,也需要我们自己对界面进行编码拉伸. 如何实现?
-
如果想保留系统自带的边框,不想自己编码实现界面拉伸如何做?
说明
- 如果需要自带系统的边框,那么在创建窗口时加上
WS_SIZEBOX
if(wndMain.CreateEx(NULL,NULL,WS_SIZEBOX|WS_CLIPCHILDREN | WS_CLIPSIBLINGS|WS_POPUP) == NULL)
- 创建无边框窗口,
WS_POPUP
是关键
if(wndMain.CreateEx(NULL,NULL,WS_CLIPCHILDREN | WS_CLIPSIBLINGS|WS_POPUP) == NULL)
- 创建无边框窗口后,其实需要自己响应几个鼠标操作:
- 鼠标移动到窗口的边界时,鼠标能边为箭头;
- 鼠标左键按下后移动鼠标,界面随着鼠标移动的方向拉伸改变大小,并且鼠标的箭头不变。
- 无边框窗口拉伸后,标题栏的按钮能随着拉伸后改变位置。
- 实现拉伸的方式应该不止一种,我这里列举的是其中一种方法.
- 实现3个消息映射
WM_NCHITTEST
,WM_SETCURSOR
,WM_NCLBUTTONDOWN
BEGIN_MSG_MAP_EX(CMainFrame)
MSG_WM_NCHITTEST(OnNcHitTest)
MSG_WM_SETCURSOR(OnSetCursor)
MSG_WM_NCLBUTTONDOWN(OnNcLButtonDown)
CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
END_MSG_MAP()
#define RESIZE_REGION_SIZE 5
UINT CMainFrame::OnNcHitTest(CPoint pt)
{
RECT rcWindow;
::GetWindowRect(m_hWnd, &rcWindow);
// 最好将四个角的判断放在前面
if (pt.x <= rcWindow.left + RESIZE_REGION_SIZE && pt.y <= rcWindow.top + RESIZE_REGION_SIZE)
return HTTOPLEFT;
else if (pt.x >= rcWindow.right - RESIZE_REGION_SIZE && pt.y <= rcWindow.top + RESIZE_REGION_SIZE)
return HTTOPRIGHT;
else if (pt.x <= rcWindow.left + RESIZE_REGION_SIZE && pt.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
return HTBOTTOMLEFT;
else if (pt.x >= rcWindow.right - RESIZE_REGION_SIZE && pt.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
return HTBOTTOMRIGHT;
else if (pt.x <= rcWindow.left + RESIZE_REGION_SIZE)
return HTLEFT;
else if (pt.x >= rcWindow.right - RESIZE_REGION_SIZE)
return HTRIGHT;
else if (pt.y <= rcWindow.top + RESIZE_REGION_SIZE)
return HTTOP;
else if (pt.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
return HTBOTTOM;
return HTCAPTION;
}
BOOL CMainFrame::OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
{
switch (nHitTest)
{
case HTTOP:
case HTBOTTOM:
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS)));
return TRUE;
case HTLEFT:
case HTRIGHT:
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
return TRUE;
case HTTOPLEFT:
case HTBOTTOMRIGHT:
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
return TRUE;
case HTTOPRIGHT:
case HTBOTTOMLEFT:
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
return TRUE;
default:
return FALSE;
}
}
void CMainFrame::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
switch (nHitTest)
{
case HTTOP:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));
break;
case HTBOTTOM:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOM, MAKELPARAM(point.x, point.y));
break;
case HTLEFT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_LEFT, MAKELPARAM(point.x, point.y));
break;
case HTRIGHT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_RIGHT, MAKELPARAM(point.x, point.y));
break;
case HTTOPLEFT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPLEFT, MAKELPARAM(point.x, point.y));
break;
case HTTOPRIGHT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPRIGHT, MAKELPARAM(point.x, point.y));
break;
case HTBOTTOMLEFT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMLEFT, MAKELPARAM(point.x, point.y));
break;
case HTBOTTOMRIGHT:
SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMRIGHT, MAKELPARAM(point.x, point.y));
break;
default:
SetMsgHandled(FALSE);
break;
}
}
图示
项目下载
WTL-MFC-Win32无边框窗口.zip
test-WTL10.zip无边框的About窗口