仿QQ悬挂窗口的实现封装

该博客介绍了如何基于MFC实现仿QQ的悬挂窗口功能。作者在调试基础上进行了DLL封装,使得在实际编程中能更方便地调用。同时,文章提到了使用CButtonST库来创建按钮,并通过添加全局鼠标钩子WM_MOUSE,结合窗口坐标判断和SetWindowPos函数,实现了平滑的悬挂动画效果。

1 参考仿QQ悬挂窗口的实现 作者: 郑瑜。 在调试基础上,对悬挂功能[Docking]进行封装处理。非常方便实际编程中的直接调用。再次感谢郑瑜,通过他的文章而产生的灵感。

2 按钮,用CButtonST实现 参考www.codeproject.com  , 详细参考:
CButtonST v3.9 (MFC Flat buttons)
By Davide Calabro

方便应用程序使用:

代码思想:

1 添加WM_MOUSE的全局钩子[dll]

2 通过对mouse当前坐标、Wnd的ClientRect判断,进行不同的slide

   利用SetWindowPo, sleep(30)模拟动态悬挂效果。

 

核心代码:

 

  1. void Docking::TranslateMessage()
  2. {
  3.     //减少常变量析构; 加快程序效率
  4.     static const int Span = 5; //对此单位元素就进行Docking
  5.     POINT pt;
  6.     CRect rcWindow;
  7.     ::GetCursorPos(&pt);
  8.     m_Wnd->GetWindowRect(&rcWindow);
  9.     //如果pt在窗体中, 直接返回
  10.     if ((rcWindow.PtInRect(pt) && rcWindow.Width() > SpanValue) 
  11.         && (rcWindow.PtInRect(pt) && rcWindow.Height() > SpanValue))
  12.         return ;
  13.     if (rcWindow.Width() > Span && rcWindow.left < Span)//Left -> Hide
  14.     {
  15.         SliderWindow(LEFT, false);
  16.     }
  17.     else if(rcWindow.Width() < Span && pt.x < SpanValue + 1 && 
  18.         (pt.y > rcWindow.top && pt.y < rcWindow.bottom) ) //Left -> Show
  19.     {
  20.         SliderWindow(LEFT, true);
  21.     }
  22.     else if(rcWindow.Width() > Span && rcWindow.right > this->ScreeWidth - Span && pt.x < ScreeWidth - Span)//Right -> Hide
  23.     {
  24.         SliderWindow(RIGHT, false);
  25.     }
  26.     else if(rcWindow.Width() < Span && pt.x >= ScreeWidth - Span && 
  27.         (pt.y > rcWindow.top && pt.y < rcWindow.bottom)) //Right -> Show
  28.     {
  29.         SliderWindow(RIGHT, true);
  30.     }
  31.     else if(rcWindow.Height() > SpanValue && rcWindow.top < Span)//Top -> Hide
  32.     {
  33.         SliderWindow(TOP, false);
  34.     }
  35.     else if(rcWindow.Height() < SpanValue + 1 && pt.y < Span 
  36.         && (pt.x > rcWindow.left && pt.x < rcWindow.right))//Top -> Show
  37.     {
  38.         SliderWindow(TOP, true);
  39.     }
  40.     else if(rcWindow.Height() > 0 && rcWindow.bottom > ScreeHeigth - Span)//Bottom -> Hide
  41.     {
  42.         SliderWindow(BOTTOM, false);
  43.     }
  44.     else if(rcWindow.Height() < 1 && pt.y > ScreeHeigth - Span
  45.         && (pt.x > rcWindow.left && pt.x < rcWindow.right))//Bottom -> Show
  46.     {
  47.         SliderWindow(BOTTOM, true);
  48.     }
  49. }
  50. void Docking::SliderWindow(int nPos, bool bShow)
  51. {
  52.     //提高效率
  53.     if (m_oldDockingState.first == nPos && m_oldDockingState.second == bShow)
  54.         return;
  55.     m_oldDockingState.first = nPos;
  56.     m_oldDockingState.second = bShow;
  57.     CRect rc;
  58.     m_Wnd->GetWindowRect(rc);
  59.     if (!bShow) //Docking前,先记录一下原始大小
  60.     {
  61.         m_ClientRect.left = rc.left; 
  62.         m_ClientRect.right = rc.right;
  63.         m_ClientRect.top = rc.top;
  64.         m_ClientRect.bottom =  rc.bottom;
  65.     }
  66.     switch(nPos)
  67.     {
  68.     case LEFT:
  69.         {
  70.             long W = m_ClientRect.Width();
  71.             long step = W / 10;
  72.             if(bShow)
  73.             {
  74.                 for(int i=0; i<=10; i++)
  75.                 {
  76.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, 0, rc.top, i*step, rc.Height(), SWP_SHOWWINDOW);
  77.                     Sleep(30);
  78.                 }
  79.             }
  80.             else
  81.             {
  82.                 for(int i=0; i<=10; i++)
  83.                 {
  84.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, 0, rc.top, W-step*i , rc.Height(), SWP_SHOWWINDOW);
  85.                     Sleep(30);
  86.                 }
  87.                 m_Wnd->SetWindowPos(&CWnd::wndTopMost, 0, rc.top, SpanValue , rc.Height(), SWP_SHOWWINDOW);
  88.             }
  89.         }
  90.         break;
  91.     case RIGHT:
  92.         {
  93.             long W = m_ClientRect.Width();
  94.             long step = W / 10;
  95.             if(bShow)
  96.             {
  97.                 for(int i=0; i<=10; i++)
  98.                 {
  99.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left - i * step, rc.top, i*step, rc.Height(), SWP_SHOWWINDOW);
  100.                     Sleep(30);
  101.                 }
  102.             }
  103.             else
  104.             {
  105.                 for(int i=0; i<=10; i++)
  106.                 {
  107.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left + i * step, rc.top, W-step*i, rc.Height(), SWP_SHOWWINDOW);
  108.                     Sleep(30);
  109.                 }
  110.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, ScreeWidth - SpanValue, rc.top, SpanValue, rc.Height(), SWP_SHOWWINDOW);
  111.             }
  112.         }
  113.         break;
  114.     case TOP:
  115.         {
  116.             int H = m_ClientRect.Height();
  117.             int step = H / 10;
  118.             if (bShow)
  119.             {
  120.                 for(int i = 0; i <= 10; i++)
  121.                 {
  122.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left, 0, rc.Width(), i * step, SWP_SHOWWINDOW);
  123.                     Sleep(30);
  124.                 }
  125.             }
  126.             else
  127.             {
  128.                 for(int i = 0; i <= 10; i++)
  129.                 {
  130.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left, 0, rc.Width(), H- i*step, SWP_SHOWWINDOW);
  131.                     Sleep(30);
  132.                 }
  133.                 m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left, 0, rc.Width(), SpanValue, SWP_SHOWWINDOW);
  134.             }
  135.         }
  136.         break;
  137.     case BOTTOM:
  138.         {
  139.             int H = m_ClientRect.Height();
  140.             int step = H / 10;
  141.             if (bShow)
  142.             {
  143.                 for(int i = 0; i <= 10; i++)
  144.                 {
  145.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left, rc.top - step*i, rc.Width(), i * step, SWP_SHOWWINDOW);
  146.                     Sleep(30);
  147.                 }
  148.             }
  149.             else
  150.             {
  151.                 for(int i = 0; i <= 10; i++)
  152.                 {
  153.                     m_Wnd->SetWindowPos(&CWnd::wndTopMost, rc.left, rc.top + step*i, rc.Width(), H- i*step, SWP_SHOWWINDOW);
  154.                     Sleep(30);
  155.                 }
  156.             }
  157.         }
  158.         break;
  159.     default:
  160.         break;
  161.     }   
  162. }

运行效果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sxbluebird

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值