zoukankan      html  css  js  c++  java
  • (收藏)VC 实现无标题窗口的拖拽

    到底我们怎样来欺骗Windows呢?

    我们主动来响应WM_NCHITTEST消息。

    ClassWizard添加WM_NCHITTEST的消息响应函数。

    注:用ClassWizard添加消息响应函数时候,在右下角的“Filter for message available to”选择“Windows”。否则你找不到WM_NCHITTEST消息。

    编写代码如下:

    UINT CTestDlg::OnNcHitTest(CPoint point) 

    {

        //得到鼠标点击的窗口的部位

        UINT nHitTest = CDialog::OnNcHitTest(point);

     

        // 如果鼠标点击的是客户区,则返回HTCAPTIONWindows

        if (nHitTest == HTCLIENT)

        {

           return HTCAPTION;

        }

        else

           return nHitTest;

    }

    Windows会根据紧接着发送的WM_NCLBUTTONDOWN消息的wParam的内容来决定是否启用拖拽状态。实际上,就是根据OnNcHitTest的返回值来确定是否启用。如果返回值是HTCAPTION,就启用。我们正是利用这个特性来欺骗了Windows

    你可能觉得这样处理会有问题,因为我们虽然欺骗了Windows,但鼠标确实不在标题栏上。试想鼠标拖动的时候,Windows必须使窗口和鼠标同步移动。此刻Windows误以为我们的鼠标就在标题栏上,要实现同步移动Windows会一下子把标题栏移动到鼠标当前位置。

    你的担心是多余的,Windows移动窗口的时候是根据鼠标位置的改变量来改变窗口坐标的。它不是以鼠标的实际坐标来直接确定窗口坐标的。

     

    另外一个更简单的处理方法是,是在OnLButtonDown中加上一句话。如下:

    void CTsDlg::OnLButtonDown(UINT nFlags, CPoint point) 

    {

        SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));

     

        CDialog::OnLButtonDown(nFlags, point);

    }

    上面已经说过,Windows先向窗口发送WM_NCHITTEST消息以确定鼠标点击的部位,如果点击的是非客户区,则又会发送WM_NCLBUTTONDOWN消息。我们现在伪造了一条WM_NCLBUTTONDOWN消息来欺骗Windows,这样更加直接。






    ========================================================================






    从微软的站点看到一个简单的方法实现,不必计算RECT,不必处理鼠标消息的细节和窗口绘制,就能轻松实现没有标题栏的窗口移动的问题,就是使用OnNcHitTest消息。

      手工增加该消息映射:

    用classwizard是无法增加该消息的,在BEGIN_MESSAGE_MAP中加入消息ON_WM_NCHITTEST(),然后在头文件中加入



      afx_msg UINT OnNcHitTest(CPoint point);


    在实现文件中,加入LBUTTONDOWN消息函数


      void CClyzDlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
    CTranDialog::OnLButtonDown(nFlags, point);//把CTranDialog改成你的基类
    PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));
    }

      加入NCHITTEST消息函数


      UINT CClyzDlg::OnNcHitTest(CPoint point)
    {
    UINT nHitTest = CTranDialog::OnNcHitTest( point );//把CTranDialog改成你的基类
    return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
    }

      编译运行,没有出错就完成了,前后不到十行代码。

      我用基于对话框的应用程序,在vc6.0,winnt4.0下编译,运行良好。



    ==================================================================




    WM_LButtonDown 消息响应处理 // 鼠标左键

    void CDlgDlg::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));
    CDialog::OnLButtonDown(nFlags, point);
    }

    按窗体任何位置都可移动窗体!-------------------------------------------

    -----在无标题栏的窗体上右键功能实现:↓↓

    WM_RButtonDown 消息响应处理 // 鼠标右键

    void CDlgDlg::OnRButtonDown(UINT nFlags, CPoint point) 
    {
    CMenu menu,*sub;
    menu.LoadMenu(IDR_MENU1);  ////加载菜单
    sub=menu.GetSubMenu(0);
    ClientToScreen(&point);
    sub->TrackPopupMenu(TPM_RIGHTBUTTON,point.x,point.y,this);
    CDialog::OnRButtonDown(nFlags, point);
    }

    -----------------------------------------------------------------------------------------------------------------

    对于无标题栏的对话框,用鼠标移动它的简单方法为:对消息WM_NCHITTEST进行处理,然后做鼠标位置的判断,如果鼠标位置在要移动窗口的客户区,则返回为鼠标在标题栏的信号,也就是欺骗windows,让它误认为你在点击标题栏,于是,你就可以正常拖动窗口了。

    WM_NCHITTEST  消息响应处理

    让窗口部分区域起移动功能的作用!

    函数GetWindowPlacement得到当前窗口在屏幕上的位置.

    这个函数的参数类型为WINDOWPLACEMENT结构。原型为
    typedef struct tagWINDOWPLACEMENT {     /* wndpl */
    UINT  length;
    UINT  flags;
    UINT  showCmd;
    POINT ptMinPosition;
    POINT ptMaxPosition;
    RECT  rcNormalPosition;
    } WINDOWPLACEMENT;
    其中,第六个变量rcNormalPosition为窗口正常显示时的位置

    UINT CTimeWakeDlg::OnNcHitTest(CPoint point)
    {
    UINT hit=CDialog::OnNcHitTest(point);
    if(hit==HTCLIENT)
    {
    WINDOWPLACEMENT winplace;
    GetWindowPlacement(&winplace);
    int xp=winplace.rcNormalPosition.left;
    int yp=winplace.rcNormalPosition.top;

    if((point.x>xp)&&(point.x<xp+50)&&(point.y>yp)&&(point.y<yp+30))
    return HTCAPTION;
    else 
    return hit;
    }
    else
    return hit;
    }       

    好了,再在左上角画个图之类的,就更明显漂亮喽

  • 相关阅读:
    The network connection was lost 文件下载错误提示
    ThinkPHP第一课 环境搭建
    Docs-.NET-C#-指南-语言参考-关键字-值类型:内置数值转换
    Docs-.NET-C#-指南-语言参考-关键字-值类型-:浮点数值类型
    Docs-.NET-C#-指南-语言参考-关键字-内置类型-值类型:整型数值类型
    Docs-.NET-C#-指南-语言参考-关键字-内置类型-值类型:值类型的功能
    Docs-.NET-C#-指南-语言参考-关键字:C# 关键字
    Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma checksum(C# 参考)
    Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma warning(C# 参考)
    Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma(C# 参考)
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1791874.html
Copyright © 2011-2022 走看看