Windows的菜單一層一層的,有時(shí)操作起來不方便,就想自己寫個(gè)工具直接調(diào)用。對迅雷的懸浮窗垂涎好久了,哈,正好趁這個(gè)機(jī)會(huì)搞一搞。在懸浮窗上用快捷菜單不是很方便嗎?
在VC知識(shí)庫中找到了一篇介紹懸浮窗實(shí)現(xiàn)的例子,很好,拿來就用,又做了些增強(qiáng)功能,呵呵,特此Show一下。知識(shí)庫文章地址:
點(diǎn)這里。要實(shí)現(xiàn)懸浮窗,就得弄明白懸浮窗是什么,有什么行為和作用。懸浮窗其實(shí)是一個(gè)無邊框可以拖動(dòng)的窗口,再有就是它上面鋪滿一張圖,當(dāng)然也可以是空白,可以設(shè)置透明度,雙擊可實(shí)現(xiàn)主窗口的顯示和隱藏,右鍵有菜單,可以實(shí)現(xiàn)快捷操作;還有一點(diǎn)就是它在任務(wù)欄中不顯示。好了,明白了原理就開始找資料動(dòng)手了。
我的習(xí)慣是先攻克所有的技術(shù)點(diǎn),然后再動(dòng)手寫程序。在資源文件中插入一個(gè)Dialog,給它添加一個(gè)類CFloatWnd。首先是無邊框,這個(gè)容易,將窗口的Border設(shè)為None就可以了。無邊框窗口的拖動(dòng)也很容易,重寫OnNcHitTest就可以了。原理就是當(dāng)用戶點(diǎn)擊了窗口客戶區(qū)后,把它當(dāng)成標(biāo)題欄來傳給操作系統(tǒng),這樣就實(shí)現(xiàn)了拖動(dòng)。代碼如下:
- LRESULT CFloatWnd::OnNcHitTest(CPoint point)
- {
-
- LRESULT nHitTest = CDialog::OnNcHitTest(point);
-
- if (nHitTest == HTCLIENT && GetAsyncKeyState(MK_LBUTTON) < 0 )
- nHitTest = HTCAPTION;
-
- return nHitTest;
-
- }
不要認(rèn)為GetAsyncKeyState沒有用,這樣做的目的是點(diǎn)擊左鍵拖動(dòng),而點(diǎn)擊右鍵則不能拖動(dòng)且要彈出右鍵菜單。
好了,現(xiàn)在窗口能拖動(dòng)了,但是是空白窗口,不好看。那好,加個(gè)位圖,首先添加資源文件Logo.bmp,資源ID設(shè)為IDB_BITMAP_Logo,然后在窗口上放個(gè)Picture Control,Type指定為Bitmap,image設(shè)為IDB_BITMAP_Logo就可以了。至于圖片位置和窗口大小就寫程序控制好了。給圖片添加變量m_Logo。在OnInitDialog中添加如下代碼:
-
-
-
-
-
- CBitmap m_Bitmap;
- HBITMAP hBitmap = m_Logo.GetBitmap();
- ASSERT(hBitmap);
- m_Bitmap.Attach(hBitmap);
- BITMAP bmp;
- m_Bitmap.GetBitmap(&bmp);
-
- int nX = bmp.bmWidth;
- int nY = bmp.bmHeight;
- MoveWindow(0,0,nX,nY);
- m_Logo.MoveWindow(0,0,nX,nY);
- CenterWindow();
- ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
- m_Bitmap.Detach();
做完這些以后在主窗口CMainAppDlg中添加成員變量CFloatWnd m_FloatWnd; 然后在CMainAppDlg的OnInitDialog中添加如下代碼,來顯示我們的懸浮窗。
-
- m_FloatWnd.Create(CFloatWnd::IDD,this);
- m_FloatWnd.ShowWindow(SW_SHOW);
還有,別忘記在MainAppDlg.h 中添加這個(gè):#include "FloatWnd.h"
好了,現(xiàn)在運(yùn)行。感覺上挺不錯(cuò)了,但是雙擊不能顯示主窗口,也沒有右鍵菜單。嗯,繼續(xù)做吧。添加成員函數(shù)afx_msg void OnShowHide(); //顯示隱藏具體代碼如下:
-
- void CFloatWnd::OnShowHide()
- {
- CWnd *pParent = GetParent();
- ASSERT(pParent);
- if(pParent->IsWindowVisible())
- pParent->ShowWindow(SW_HIDE);
- else
- pParent->ShowWindow(SW_SHOW);
- }
-
- void CFloatWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
- {
-
- OnShowHide();
- CDialog::OnNcLButtonDblClk(nHitTest, point);
- }
運(yùn)行一下,雙擊能夠顯示和隱藏,效果還是不錯(cuò)的。下一步添加右鍵菜單。在資源文件里添加個(gè)新菜單,ID設(shè)為IDR_MENU_FloatWnd,然后添加兩個(gè)子菜單項(xiàng):1、Caption為顯示/隱藏主窗口(&S) ,ID為ID_ShowHide;2、Caption為退出(&E) ,ID為ID_Exit。給CFloatWnd添加菜單成員變量:CMenu m_Right; //右鍵菜單在OnInitDialog中加載:
-
- m_Right.LoadMenu(IDR_MENU_FloatWnd);
-
-
- void CFloatWnd::OnRButtonUp(UINT nFlags, CPoint point)
- {
-
- CMenu *pSub = m_Right.GetSubMenu(0);
- ClientToScreen(&point);
- pSub->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this,NULL);
- CDialog::OnRButtonUp(nFlags, point);
- }
-
- ON_COMMAND(ID_Exit, OnExit)
- ON_COMMAND(ID_ShowHide, OnShowHide)
-
-
- void CFloatWnd::OnExit()
- {
- CWnd *pParent = GetParent();
- this->DestroyWindow();
- pParent->DestroyWindow();
- }
運(yùn)行一下,效果很棒。但還沒有透明度設(shè)置。
在主窗口上放一個(gè)Slider Control,給它添加變量m_Slider,最大值設(shè)為255,最小值設(shè)為0。然后重寫窗口的OnHScroll事件,在事件中根據(jù)滑動(dòng)條的值來設(shè)置窗口的透明度。關(guān)于窗口的透明度,在VC2005中可以直接用SetLayeredWindowAttributes來設(shè)置,在VC6中要用LoadLibrary("User32.DLL")來實(shí)現(xiàn)。好了,完整代碼如下:
-
-
- m_Slider.SetRangeMax(255,TRUE);
- m_Slider.SetRangeMin(1,TRUE);
-
- m_Slider.SetPageSize(10);
-
- void CFloatWnd::OnUpdateTransparent(int iTransparent)
- {
- SetLayeredWindowAttributes(0,iTransparent,2);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
-
-
- SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
-
- OnUpdateTransparent(255);