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;
    }       

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

  • 相关阅读:
    每日日报2020.12.1
    每日日报2020.11.30
    981. Time Based Key-Value Store
    1146. Snapshot Array
    565. Array Nesting
    79. Word Search
    43. Multiply Strings
    Largest value of the expression
    1014. Best Sightseeing Pair
    562. Longest Line of Consecutive One in Matrix
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1791874.html
Copyright © 2011-2022 走看看