无边框窗口

前面我们已经提到了,利用桌面管理器DWM可以实现无边框窗口,让整个窗口成为客户区。并且还提供了别的方法,可以处理如利用当前主题自己绘制标题栏,窗口大小改变等,就和普通窗口的功能一样。但是如果我们不利用DWM的方法呢,也可以实现窗口无边框,这个呢就是在WM_NCCALCSIZE消息,其中wParam参数呢,是一个bool值,如果为TRUE,确定程序应该说明客户区的哪个部分包含了有效信息,系统就会复制有效信息到新客户区的指定区域。如果是FALSE,说明程序不必说明客户区的有效部分,lParam参数指向了一个结构体,它的值根据wParam参数来确定,如果wParam参数为TRUE,那么它就指向的是一个NCCALCSIZE_PARAMS结构体,包含了一些信息,程序用来计算新的客户区矩形的大小和位置。如果wParam为FALSE,lParam参数就是指向的RECT结构体,包含了推荐的窗口矩形大小。在程序退出的时候,包含了窗口客户区的屏幕坐标。当然这些参数的意思看不明白不要紧,因为我们基本不需要,因为默认情况下是传递给默认窗口过程处理的。而在这里,我们要实现我们的无边框窗口,同时保留单击任务栏图标可以最小化和窗口恢复。在这里呢,很简单,我们应该这么做
检查wParam的值,如果是TRUE,那么我们就不要传递给默认窗口过程函数了,直接返回,这么一来,就没有了边框,在sdk中呢,这个很简单:
case WM_NCCALCSIZE:
if(wParam==TRUE)
{
return 0;////////////////不再做别的处理
}
else
{
return DefWindowProc(........);//////////////////////具体就不写了,就是普通的默认窗口过程
}
如果在MFC中呢,我们来看
void CdlgtestDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if( bCalcValidRects!=1)
	{
	    CDialogEx::OnNcCalcSize(bCalcValidRects, lpncsp);
	}
}
和SDK有点不同,这个是通过处理基类的函数来传递给默认的窗口过程的,那么我们在这里,如果是TRUE,我们就不调用基类的函数了,就达到效果了
好了,现在还剩下一个问题,那就是当窗口第一次创建的时候,不会调用这个函数,也就是说,虽然我们这么做了,但是窗口第一次出来的时候,还是有边框,那么我必须强制让窗口第一次创建的时候,就调用这个函数,我们呢,可以调用SetWindowPos函数来做到:
RECT rcClient;
        GetWindowRect(hWnd, &rcClient);

        // Inform application of the frame change.
        SetWindowPos(hWnd, 
                     NULL, 
                     rcClient.left, rcClient.top,
                     RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
                     SWP_FRAMECHANGED);
这个地方,我们可以在WM_CREATE中调用,那么这样一来,就ok了。我们仍然保留了点击任务栏图标,最小化,恢复窗口,激活窗口的操作,也实现了无边框。
////////////////////////////////////////////////////////////////////////////////////////
附:为什么我们需要这样的窗口呢,下面解释一下:
1诸如酷狗,迅雷这样的窗口没有明显的标题栏,客户区与非客户区的明显界限,那么我们在设计程序的UI的时候,可以完全不受默认窗口边框这样的标准框架的限制,设计我们的程序界面,如最大化,最小化,关闭的按钮,我们都可以自己设计,然后发送WM_SYSCOMMAND消息去执行,就可以了,所以,这样一来就有利于我们的界面设置,当然,我不确定酷狗和迅雷是不是这么做的,我只是举个例子。
2在我们使用Layered窗口,也就是创建半透明和不规则窗口的时候,我们要自己绘制界面,这里就有一个界面绘制的坐标是以整个窗口的左上角为原点,但是我们在设置鼠标响应区的时候,使用的是客户区坐标,这样一来就有一个坐标差,给我们带来了很大的麻烦。如果这么做,就没有这种情况了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值