打开网易邮箱可以发现,网易邮箱的边框是没有的,貌似现在的采用自绘的客户终端大多都是没有边框和标题栏,同时非最大化的时候还可以实现自动拖拽功能,那么今天就想把制作客户端遇到的问题进行分析。
流程:
- 创建窗口
- 重载最大化最小换 GETMINMAXINFO
- 重载 NCCALCSIZE 重新绘制标题栏,解决出现边框的问题
问题:
:发现 WM_NCCALCSIZE 和 WM_GETMINMAXINFO两个消息连续使用,没有实现取消边框。
开始:
0,先创建一个对话框
看到在window8.1 操作系统中,清晰的可以发现有一圈黄色的边框,这个边框不是我们所想要的,但是我们应该如何去除这层边框,但是去除边框的同时,这个对话框同时具有拖拽放大客户区域的功能。
1,在InitDialog 中设置窗口样式
// 这一层设置窗口样式对于我们这个主题来说没有太大关联
::SetWindowLong(m_hWnd, GWL_STYLE,
WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPED | WS_THICKFRAME | 0x00008000);
::SetWindowLong(m_hWnd, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_WINDOWEDGE);
// 设置窗口全屏
ShowWindow(SW_MAXIMIZE);
2,重载最大化最小换 GETMINMAXINFO
void xxxDlg::OnGetMinMaxInfo(MINMAXINFO* pMMI)
{
//最大化对话框
int iWidth = GetSystemMetrics(SM_CXSCREEN);
int iHeight = GetSystemMetrics(SM_CYSCREEN);
CRect rt;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rt, 0); // 获取客户区大小
int y = ::GetSystemMetrics(SM_CYSCREEN) - rt.Height(); // 任务高度
pMMI->ptMaxPosition.x = 0; // 设置窗口最大化时x坐标
pMMI->ptMaxPosition.y = 0; // 设置窗口最大化时y坐标
pMMI->ptMaxSize.x = iWidth ;
pMMI->ptMaxSize.y = iHeight - y; // 防止挡住任务栏
}
// 1,这一层主要使用来设置最大化最小化时候窗口的高度,哎,说道最大化,最小化的按钮怎么不见了。这个下一节再去自绘定义,不想使用微软自带的。
// 2,边框问题需要解决
// 那么先看下效果
那么我们是否可以在这里就罢了边框给干掉了,先把代码贴出来
//最大化对话框
int iWidth = GetSystemMetrics(SM_CXSCREEN);
int iHeight = GetSystemMetrics(SM_CYSCREEN);
CRect rt;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rt, 0); // 获取客户区大小
int y = ::GetSystemMetrics(SM_CYSCREEN) - rt.Height(); // 任务高度
const int iBorderWidth = 10;
pMMI->ptMaxPosition.x = 0 - iBorderWidth;// 设置窗口最大化时x坐标
pMMI->ptMaxPosition.y = 0 - ::GetSystemMetrics(SM_CYCAPTION) - iBorderWidth;// 设置窗口最大化时y坐标
pMMI->ptMaxSize.x = iWidth + iBorderWidth*2;// 设置窗口最大化时候的宽度
pMMI->ptMaxSize.y = iHeight - y + ::GetSystemMetrics(SM_CYCAPTION) + iBorderWidth;// 设置窗口最大化时候的高度
– 不是存在标题吗,那我就从最上面在 + 一个标题的宽度开始绘画,这个客户去显示的就是正常的。横向的我也是这样认为的,但是这样就早造成两个问题,虽然右上角的问题能够解决,但是右下角就不能正常的解决。我认为是一块画布,网左上角拉扯,但是不能解决右下角的问题。这样的全屏不好。接下来我想去验证我这个想法。
我在这里只是把标题栏给干掉了,但是右下方的边框无法解决
验证:
pMMI->ptMaxSize.x = 10; // 设置窗口最大化时候的宽度
pMMI->ptMaxSize.y = iHeight - y + ::GetSystemMetrics(SM_CYCAPTION) + iBorderWidth;// 设置窗口最大化时候的高度
// 我改变了宽度,但是边框还是出现了,所以这个逻辑被我否认了。
![FAILED](https://img-blog.csdn.net/20170222234518020?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXdlX090aXM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
3,所以接下来我就考虑使用专门为边框设计的【NCCALCSIZE】
代码先贴上了:
/// 响应最大化事件,这里不锁死x,y的初始点
void xxxDlg::OnGetMinMaxInfo(MINMAXINFO* pMMI)
{
//最大化对话框
int iWidth = GetSystemMetrics(SM_CXSCREEN);
int iHeight = GetSystemMetrics(SM_CYSCREEN);
CRect rt;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rt, 0); // 获取客户区大小
int y = ::GetSystemMetrics(SM_CYSCREEN) - rt.Height(); // 任务高度
pMMI->ptMaxSize.y -= y // 设置窗口最大化时的高度-下方任务栏的高度
//pMMI->ptMaxPosition.x = 0; // 设置窗口最大化时x坐标
//pMMI->ptMaxPosition.y = 0; // 设置窗口最大化时y坐标
}
// 响应重载 NCCALCSIZE 重新绘制标题栏,解决出现边框的问题
void xxxDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
if (lpncsp != NULL && GetWindowLong(GetSafeHwnd(), GWL_STYLE)) // & WS_MAXIMIZE
{
CRect& rc = (CRect&)lpncsp->rgrc[0];//get the client rectangle
{
rc.top += 0 - GetSystemMetrics(SM_CYCAPTION);
rc.bottom += 0 + 10;
}
}
CDialogEx::OnNcCalcSize(bCalcValidRects, lpncsp);
}