MFC 无边框窗体实现用鼠标拖动窗体边缘实现窗体大小变化

无边框窗体如何实现用鼠标拖动窗体边缘实现窗体大小变动呢?下面介绍一种方法,通过以下几个步骤即可实现:

1.实现WM_NCHITTEST消息,实现四条边框的模拟

2.实现WM_NCLBUTTONDOWN,发送窗体拖曳变化的消息

具体阐述如下:

1.实现WM_NCHITTEST消息,实现四条边框的模拟

参考代码如下:

LRESULT CUserForm::OnNcHitTest(CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值    
    CRect rect;
    GetWindowRect(&rect);
    CRect rect1 = rect;
    rect1.DeflateRect(10, 10, -10, -10);//缩小矩形
    rect1.NormalizeRect();//规范化矩形确保非0或负
    if (point.x <= rect.left+3)
        return HTLEFT;
    else if (point.x >= rect.right-3)
        return HTRIGHT;
    else if (point.y <= rect.top+3)
        return HTTOP;
    else if (point.y >= rect.bottom-3)
        return HTBOTTOM;
    else if (point.x <= rect.left+10 && point.y <= rect.top+10)
        return HTTOPLEFT;
    else if (point.x >= rect.right-10 && point.y <= rect.top+10)
        return HTTOPRIGHT;
    else if (point.x <= rect.left+10 && point.y >= rect.bottom-10)
        return HTBOTTOMLEFT;
    else if (point.x >= rect.right-10 && point.y >= rect.bottom-10)
        return HTBOTTOMRIGHT;
    else if (!rect.IsRectEmpty())
    {
        LRESULT uRet = CWnd::OnNcHitTest(point);
        uRet = (uRet == HTCLIENT) ? HTCAPTION : uRet;//客户区转换成非客户区
        return uRet;
    }
    else
    {
        return CWnd::OnNcHitTest(point);
    }
    return 0;
}

2.实现WM_NCLBUTTONDOWN,发送窗体拖曳变化的消息

void CUserForm::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if (nHitTest == HTTOP)
    {        
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));
    }
    else if (nHitTest == HTBOTTOM)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOM, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTLEFT)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_LEFT, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTRIGHT)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_RIGHT, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTTOPLEFT)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPLEFT, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTTOPRIGHT)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPRIGHT, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTBOTTOMLEFT)
        SendMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMLEFT, MAKELPARAM(point.x, point.y));
    else if (nHitTest == HTBOTTOMRIGHT)
        SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMRIGHT, MAKELPARAM(point.x, point.y));
    else if (nHitTest==HTCAPTION)
        SendMessage(WM_SYSCOMMAND, SC_MOVE | 4, MAKELPARAM(point.x, point.y));
}

通常,使用上述的代码即可实现要求。

我们进行一下扩展。在窗体大小发生变化时,有两种表现形式:一种是出现虚线框,一种没有。这个选择依赖于操作系统,你可以右击桌面/属性/外观/效果中通过选择或取消“拖动时显示窗口内容”来表现这两种形式。那么如何在程序中实现而不依赖于当前机器的设置呢

if(nHitTest == HTTOP)
{        
    SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);
    SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));
    SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, 0);
}

 

WM_SYSCOMMAND
 
当用户从 窗口菜单选择一个命令或当用户选择最大化按钮,最小化按钮,复原按钮或关闭按钮时,一个窗口将会接收该消息
Syntax
WM_SYSCOMMAND
WPARAM wParam
LPARAM lParam;
 
参数
wParam
指定系统命令的类型。该参数可以是下列值之一:
SC_CLOSE
关闭窗口
SC_CONTEXTHELP
将光标改为一个问题标识样式。如果用户之后点击了对话框中的一个控件,该控件会收到一个WM_HELP消息。
SC_DEFAULT
当用户双击 窗口菜单时,选择默认的条目。
SC_HOTKEY
以应用程序指定的热键激活窗口。lParam参数标识了所要激活的窗口。
SC_HSCROLL
水平滚动。
SC_KEYMENU
键盘的敲击返回 窗口菜单
SC_MAXIMIZE
最大化窗口
SC_MINIMIZE
最小化窗口
SC_MONITORPOWER
设置显示状态。该命令支持具有节电特性的设备,如电池供电的个人电脑。
lParam参数可以具有下列值:
-1 - 显示设备打开
1 - 显示设备将要进入节电模式。
2 - 显示设备将要被关闭
SC_MOUSEMENU
鼠标单击返回 窗口菜单
SC_MOVE
移动窗口
SC_NEXTWINDOW
移到下一个窗口
SC_PREVWINDOW
移到前一个窗口
SC_RESTORE
将窗口复原到原始的位置和大小。
SC_SCREENSAVE
执行System.ini文件里[boot]部分指定的屏幕保护程序。
SC_SIZE
改变窗口大小。
SC_TASKLIST
激活【开始】菜单。
SC_VSCROLL
垂直滚动。
lParam
如果一个窗口命令被鼠标选中,低位字指定光标的水平位置。否则该参数不被使用。
如果一个窗口命令被鼠标选中,高位字指定光标的垂直位置。如果使用 系统加速键选择的命令,则该参数为-1,如果使用 助记符的话,则该参数为0.
返回值
如果成功处理该消息,则返回值为0.
备注
获得屏幕坐标系下的位置坐标,可以使用下面的代码:
xPos = GET_X_LPARAM(lParam); // horizontal position
yPos = GET_Y_LPARAM(lParam); // vertical position

 

参考文章:http://blog.csdn.net/zjtchow/article/details/6122320

参考文章:http://baike.baidu.com/link?url=mwSXzuAO5-zjQ7Oyhgr8WfVNGsEkIdLCNJtdlHxd32JXRj_JydBjcIEq3vy-kUw3mZ8aa9c6W6ESwk-xmgX0t_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值