• 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_

  • 相关阅读:
    【CF-148E】Porcelain DP
    【CF-687C】The Values You Can Make 01背包变形
    【CF-269】B. Greenhouse Effect 最公共子序列
    【CF-1345】C.Hilbert's Hotel 数论
    【CF-607B】Zuma 经典区间DP
    【【模板】三分法】
    【CF-1355 E.Restorer Distance】三分,贪心
    【CF-1355 BCount Triangles】枚举
    【CF-1355 Sequence with Digits】
    触发器的类型有哪三种?
  • 原文地址:https://www.cnblogs.com/mqxs/p/3483797.html
Copyright © 2020-2023  润新知