将军英文怎么发音:VC对话框隐藏运行 (四)悬浮窗

来源:百度文库 编辑:中财网 时间:2024/05/09 16:16:31

VC对话框隐藏运行 (四)悬浮窗

发表时间:2010-7-10  阅读数:544  网友评论:0条Windows的菜单一层一层的,有时操作起来不方便,就想自己写个工具直接调用。对迅雷的悬浮窗垂涎好久了,哈,正好趁这个机会搞一搞。在悬浮窗上用快捷菜单不是很方便吗?在VC知识库中找到了一篇介绍悬浮窗实现的例子,很好,拿来就用,又做了些增强功能,呵呵,特此Show一下。知识库文章地址:点这里。要实现悬浮窗,就得弄明白悬浮窗是什么,有什么行为和作用。悬浮窗其实是一个无边框可以拖动的窗口,再有就是它上面铺满一张图,当然也可以是空白,可以设置透明度,双击可实现主窗口的显示和隐藏,右键有菜单,可以实现快捷操作;还有一点就是它在任务栏中不显示。好了,明白了原理就开始找资料动手了。我的习惯是先攻克所有的技术点,然后再动手写程序。在资源文件中插入一个Dialog,给它添加一个类CFloatWnd。首先是无边框,这个容易,将窗口的Border设为None就可以了。无边框窗口的拖动也很容易,重写OnNcHitTest就可以了。原理就是当用户点击了窗口客户区后,把它当成标题栏来传给操作系统,这样就实现了拖动。代码如下:
  1. LRESULT CFloatWnd::OnNcHitTest(CPoint point)   
  2. {   
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值   
  4.     LRESULT nHitTest = CDialog::OnNcHitTest(point);   
  5.   
  6.     if (nHitTest == HTCLIENT && GetAsyncKeyState(MK_LBUTTON) < 0 )  //如果是客户区//如果鼠标左键按下,GetAsyncKeyState函数的返回值小于0   
  7.         nHitTest = HTCAPTION;                       //则把它当成标题栏   
  8.   
  9.     return nHitTest;   
  10.     //return CDialog::OnNcHitTest(point);   
  11. }   
不要认为GetAsyncKeyState没有用,这样做的目的是点击左键拖动,而点击右键则不能拖动且要弹出右键菜单。 好了,现在窗口能拖动了,但是是空白窗口,不好看。那好,加个位图,首先添加资源文件Logo.bmp,资源ID设为IDB_BITMAP_Logo,然后在窗口上放个Picture Control,Type指定为Bitmap,image设为IDB_BITMAP_Logo就可以了。至于图片位置和窗口大小就写程序控制好了。给图片添加变量m_Logo。在OnInitDialog中添加如下代码:
  1. // 让窗体和Logo相符   
  2. //mfc里的Attach和Detach函数主要用于对mfc类对象跟sdk句柄   
  3. //之间关联的处理,attach将mfc类对象与句柄关联起来   
  4. //对该对象的操作都会施加在相应的句柄身上   
  5. //detach则消除这种关联关系   
  6. CBitmap m_Bitmap;   
  7. HBITMAP hBitmap = m_Logo.GetBitmap();   
  8. ASSERT(hBitmap);   
  9. m_Bitmap.Attach(hBitmap);//关联   
  10. BITMAP bmp;   
  11. m_Bitmap.GetBitmap(&bmp);   
  12.   
  13. int nX = bmp.bmWidth;   
  14. int nY = bmp.bmHeight;   
  15. MoveWindow(0,0,nX,nY);              //窗口移到左上角并设置宽高   
  16. m_Logo.MoveWindow(0,0,nX,nY);       //图片移到窗口的左上角   
  17. CenterWindow();                                         //窗口居中   
  18. ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);//窗口置顶   
  19. m_Bitmap.Detach();      //释放关联   
做完这些以后在主窗口CMainAppDlg中添加成员变量CFloatWnd m_FloatWnd; 然后在CMainAppDlg的OnInitDialog中添加如下代码,来显示我们的悬浮窗。
  1. //显示   
  2. m_FloatWnd.Create(CFloatWnd::IDD,this);//注意父窗口为this   
  3. m_FloatWnd.ShowWindow(SW_SHOW);   
还有,别忘记在MainAppDlg.h 中添加这个:#include "FloatWnd.h"好了,现在运行。感觉上挺不错了,但是双击不能显示主窗口,也没有右键菜单。嗯,继续做吧。添加成员函数afx_msg void OnShowHide(); //显示隐藏具体代码如下:
  1. //显示的时候隐藏,隐藏的时候显示   
  2. void CFloatWnd::OnShowHide()    
  3. {   
  4.     CWnd *pParent = GetParent();    //得到父窗口,即主窗口   
  5.     ASSERT(pParent);   
  6.     if(pParent->IsWindowVisible())      //如果显示   
  7.         pParent->ShowWindow(SW_HIDE);       //则隐藏   
  8.     else                                    //否则显示   
  9.         pParent->ShowWindow(SW_SHOW);   
  10. }   
  11. //在窗口双击事件中调用   
  12. void CFloatWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)   
  13. {   
  14.     // TODO: 在此添加消息处理程序代码和/或调用默认值   
  15.     OnShowHide();   
  16.     CDialog::OnNcLButtonDblClk(nHitTest, point);   
  17. }   
运行一下,双击能够显示和隐藏,效果还是不错的。下一步添加右键菜单。在资源文件里添加个新菜单,ID设为IDR_MENU_FloatWnd,然后添加两个子菜单项:1、Caption为显示/隐藏主窗口(&S) ,ID为ID_ShowHide;2、Caption为退出(&E) ,ID为ID_Exit。给CFloatWnd添加菜单成员变量:CMenu m_Right; //右键菜单在OnInitDialog中加载:
  1. //加载右键菜单   
  2. m_Right.LoadMenu(IDR_MENU_FloatWnd);   
  3. //加载好了就要在OnRButtonUp中显示了:   
  4. //鼠标右键显示弹出菜单   
  5. void CFloatWnd::OnRButtonUp(UINT nFlags, CPoint point)   
  6. {   
  7.     // TODO: 在此添加消息处理程序代码和/或调用默认值   
  8.     CMenu *pSub = m_Right.GetSubMenu(0);            //取第一个子菜单   
  9.     ClientToScreen(&point);                         //转换坐标为窗口坐标   
  10.     pSub->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this,NULL);//显示   
  11.     CDialog::OnRButtonUp(nFlags, point);   
  12. }   
  13. //显示是显示了,可没有功能,嗯,那就做消息映射写代码喽:   
  14. ON_COMMAND(ID_Exit, OnExit)             //右键退出   
  15. ON_COMMAND(ID_ShowHide, OnShowHide)     //右键显示/隐藏   
  16. //OnShowHide的代码有了,下面是OnExit:   
  17. //退出   
  18. void CFloatWnd::OnExit()    
  19. {   
  20.     CWnd *pParent = GetParent();   
  21.     this->DestroyWindow();          //销毁自己   
  22.     pParent->DestroyWindow();       //销毁主窗口   
  23. }   
运行一下,效果很棒。但还没有透明度设置。在主窗口上放一个Slider Control,给它添加变量m_Slider,最大值设为255,最小值设为0。然后重写窗口的OnHScroll事件,在事件中根据滑动条的值来设置窗口的透明度。关于窗口的透明度,在VC2005中可以直接用SetLayeredWindowAttributes来设置,在VC6中要用LoadLibrary("User32.DLL")来实现。好了,完整代码如下:
  1. //在CMainAppDlg::OnInitDialog()中   
  2. //设定滑动条最大值和最小值   
  3. m_Slider.SetRangeMax(255,TRUE);   
  4. m_Slider.SetRangeMin(1,TRUE);   
  5. //鼠标单击时一次滚动个单位   
  6. m_Slider.SetPageSize(10);   
  7. //设置透明度函数   
  8. void CFloatWnd::OnUpdateTransparent(int iTransparent)   
  9. {   
  10.     SetLayeredWindowAttributes(0,iTransparent,2);   
  11.     //在VC6中请用如下代码   
  12.     //HINSTANCE hInst = LoadLibrary("User32.DLL");   
  13.     //if(hInst)   
  14.     //{   
  15.     //  typedef BOOL (WINAPI *SLWA)(HWND,COLORREF,BYTE,DWORD);   
  16.     //  SLWA pFun = NULL;   
  17.     //  //取得SetLayeredWindowAttributes函数指针   
  18.     //  pFun = (SLWA)GetProcAddress(hInst,"SetLayeredWindowAttributes");   
  19.     //  if(pFun)   
  20.     //  {   
  21.     //      pFun(m_hWnd,0,iTransparent,2);   
  22.     //  }   
  23.     //  FreeLibrary(hInst);    
  24.     //}   
  25. }   
  26. //在CFloatWnd::OnInitDialog()中给窗体加入扩展属性,否则无法设置透明度   
  27.     //加入WS_EX_LAYERED扩展属性   
  28. SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);   
  29.     //默认不透明   
  30.     OnUpdateTransparent(255);