zoukankan      html  css  js  c++  java
  • Duilib改进窗口拖动,使整个窗口都能拖动两种方法(转载)

    转载:http://www.cnblogs.com/XiHua/articles/3490490.html

    转载:http://blog.csdn.net/lostspeed/article/details/19275249

     知识回顾:

      当鼠标在窗口内移动,点击或者释放时都会产生WM_NCHITTEST消息,响应函数OnNcHitTest会返回一个枚举值,系统会根据这个枚举值进行相应的处理。 当返回值为HTCAPTION时,系统会认为此时鼠标位于标题栏上,因而当鼠标按下并移动时就会执行拖动操作。我们需要做的就是响应这个消息,然后根据自己的需要,返回HTCAPTION参数即可!

         所以Duilib在客户区设置标题栏能让用户拖动窗口,其实就是当鼠标按下时在OnNcHitTest消息响应里面返回HTCAPTION,让系统默认为此时鼠标位于标题栏,原理就这么简单。

    这种方法不修改Duilib库的源码,需要的话直接在你自己的窗口类中添加两个方法实现,不需要的话,还使用原来的方法。

     方法一:

    MyWnd

    .h文件

    1 virtual LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);  
    2    
    3 BOOL IsInStaticControl(CControlUI * pControl); 

    .cpp文件

    加入头文件 

    1 #include <algorithm>
     1 LRESULT MyWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     2 {
     3     POINT           pt;  
     4     RECT            rcClient;  
     5     RECT            rcCaption;  
     6     CControlUI *    pControl = NULL;  
     7 
     8     rcCaption = m_PaintManager.GetCaptionRect();  
     9     GetClientRect(m_PaintManager.GetPaintWindow(), &rcClient);  
    10     pt.x = GET_X_LPARAM(lParam);  
    11     pt.y = GET_Y_LPARAM(lParam);  
    12     ::ScreenToClient(m_PaintManager.GetPaintWindow(), &pt);  
    13 
    14     if (-1 == rcCaption.bottom) ///< xml中描述bottom为-1时,整个窗口区域都可以拖动  
    15     {  
    16         rcCaption.bottom = rcClient.bottom;  
    17     }  
    18 
    19     if ((pt.x >= rcClient.left)  
    20         && (pt.x < rcClient.right)  
    21         && (pt.y >= rcCaption.top)   
    22         && (pt.y < rcCaption.bottom))   
    23     {  
    24         pControl = m_PaintManager.FindControl(pt);  
    25         if (IsInStaticControl(pControl))  
    26         {  
    27             return HTCAPTION;  
    28         }  
    29     }  
    30 
    31     return __super::OnNcHitTest(uMsg, wParam, lParam, bHandled); 
    32 }
    33 
    34 BOOL MyWnd::IsInStaticControl(CControlUI * pControl)
    35 {
    36     CDuiString strClassName;  
    37     std::vector<CDuiString> vctStaticName;  
    38     std::vector<CDuiString>::iterator it;  
    39 
    40     if (NULL == pControl)  
    41         return FALSE;  
    42 
    43     strClassName = pControl->GetClassName();  
    44     strClassName.MakeLower();  
    45     vctStaticName.push_back(L"controlui");  
    46     vctStaticName.push_back(L"textui");  
    47     vctStaticName.push_back(L"labelui");  
    48     vctStaticName.push_back(L"containerui");  
    49     vctStaticName.push_back(L"horizontallayoutui");  
    50     vctStaticName.push_back(L"verticallayoutui");  
    51     vctStaticName.push_back(L"tablayoutui");  
    52     vctStaticName.push_back(L"childlayoutui");  
    53     vctStaticName.push_back(L"dialoglayoutui");  
    54 
    //可以指定那些控件在响应 WM_NCHITTEST 消息 不返回 HTCAPTION
    55 it = std::find(vctStaticName.begin(), vctStaticName.end(), strClassName); 56 return (it != vctStaticName.end()); 57 }

    最后在窗口xml中指定caption="0,0,0,-1",不管窗口大小如何变,都可以整个窗口拖动啦~

    效果图:

    方法二:

    这种方法是纯Win32的函数调用,首先我们要理清楚拖动窗口任意位置移动的原理:

     其实在移动过程中会产生WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP这三个消息,其过程就是鼠标左键按下---->拖动窗口移动--->鼠标左键弹起   窗口移动完成。因此我们可以在自己的窗口处理函数中对这三个消息进行处理。

    首先在.h文件中定义三个窗口的成员变量以及三个消息函数响应的声明:

    private:
    
    Crect m_startRect;     //窗口的初始位置所在的矩形 
      
    bool m_isMouseDown;    //鼠标是否按下   初始化为false 
    
    CPoint m_startPoint;   //鼠标按下的位置  
    
    ................
    
    
    public:
    
    LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
    LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
    LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
    ..............

    .cpp中进行响应的处理

    LRESULT CxxxWnd::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        isMouseDown = true;//记录鼠标按下
    
            //鼠标按下时的坐标
        m_startPoint.x = GET_X_LPARAM(lParam);  
        m_startPoint.y = GET_Y_LPARAM(lParam);
    
            //鼠标按下时窗口的位置
        GetWindowRect(this->GetHWND(),&startRect);
    
        return 0;
    }
    LRESULT CLoginWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        if(isMouseDown == true)  
        {  
    
            POINT point;
     
            //获取当前鼠标的位置
                    
            //第一种获取位置方法
            //point.x = GET_X_LPARAM(lParam); 
            //point.y = GET_Y_LPARAM(lParam);
            
                    //第二种获取位置方法
            ::GetCursorPos(&point);
    
            ::ScreenToClient(m_PaintManager.GetPaintWindow(), &point);
    
    
            int Dx = point.x - startPoint.x;  
            int Dy = point.y - startPoint.y;  
            startRect.left += Dx;  
            startRect.right += Dx;  
            startRect.top +=Dy;  
            startRect.bottom +=Dy;             //获取新的位置  
            SetWindowPos(this->GetHWND(),NULL,startRect.left,startRect.top,0,0,SWP_NOSIZE);     //将窗口移到新的位置  
        }  
    
        return 0;
    }
    LRESULT CLoginWnd::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
            //左键弹起,改变鼠标状态
        isMouseDown = false;
        return 0;
    }    

    运行效果:

    参考:http://blog.csdn.net/luanwujian/article/details/9059861

    可惜这样修改后有一个bug,当你拖动窗口一直到任务栏,然后松开鼠标左键,这时窗口自动跟着鼠标移动,暂时没找到这个bug,所以暂时采用响应WM_NCHITTEST消息方式,

    在消息响应函数里面直接返回 HTCAPTION

    1 LRESULT CLoginWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    2 {
    3     return HTCAPTION;
    4 }
  • 相关阅读:
    JAVA获取昨天、今天、明天等日期
    IDEA设置调用方法时提示方法上的注释
    Hibernate使用distinct返回不重复的数据,使用group by 进行分组
    SpringBoot 自定义注解
    tailwindcss 使用总结
    nodejs nvm 包管理
    macos NPM 全局安装解决方案
    git 遇到修改github密码导致本地push失败解决方案
    Jupyter 快捷方式设置
    Vue indent eslint缩进webstorm冲突解决
  • 原文地址:https://www.cnblogs.com/chechen/p/6105556.html
Copyright © 2011-2022 走看看