一、簡介:
象flashget、迅雷、BT等都有浮動視窗,能詳細地顯示下載的詳細資料,該類型的視窗有一下幾個特點:1、視窗無標題列,視窗的大小跟位元影像一樣大。2、最上層顯示。3、在客戶區內按下滑鼠左鍵可以隨意拖動視窗的位置。4、可以改變視窗的透明度。5、雙擊可以將主視窗啟用,並顯示。下面就該類型視窗的各個功能實現予以說明。
二、代碼的詳細說明:
1、視窗無標題列,視窗的大小跟位元影像一樣大。建立一個對話方塊資源,設定為POPUP類型,並取消Title Bar屬性。在上面插入一個圖片控制項,設定為匯入的位元影像。
//得到位元影像 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();
2、最上層顯示。
//通過SetWindowsPos函數將視窗最上層顯示。 ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
3、在客戶區內按下滑鼠左鍵可以隨意拖動視窗的位置。響應WM_HITTEST函數,當滑鼠左鍵按下並在客戶區內,返回HTCAPTION,欺騙Windows,達到跟在標題列拖動視窗一樣的效果。
UINT CFloatWnd::OnNcHitTest(CPoint pt){ UINT nHitTest = CDialog::OnNcHitTest(pt); if (nHitTest == HTCLIENT && ::GetAsyncKeyState(MK_LBUTTON) < 0) // 如果滑鼠左鍵按下,GetAsyncKeyState函數的傳回值小於0 nHitTest = HTCAPTION; return nHitTest;}
4、改變視窗的透明度。將視窗樣式設定為WS_EX_LAYERED,並調用SetLayeredWindowAttributes函數來改變視窗的透明度。WS_EX_LAYERED可能沒定義,我們可以直接取值0x80000。
//加入WS_EX_LAYERED擴充屬性 SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
BOOL SetLayeredWindowAttributes(HWND hwnd,COLORREF crKey,BYTE bAlpha,DWORD dwFlags);
hwnd是要改變的視窗,當dwFlags為LWA_ALPHA(0x2)時,crKey參數沒用,bAlpha為透明度,取值在0~255之間。該函數要從User.dll中載入。
//更新視窗透明度的代碼,其中iTransparent為透明度。void CFloatWnd::OnUpdateTransparent(int iTransparent){ HINSTANCE hInst = LoadLibrary("User32.DLL"); if(hInst) { typedef BOOL (WINAPI *SLWA)(HWND,COLORREF,BYTE,DWORD); SLWA pFun = NULL; //取得SetLayeredWindowAttributes函數指標 pFun = (SLWA)GetProcAddress(hInst,"SetLayeredWindowAttributes"); if(pFun) { pFun(m_hWnd,0,iTransparent,2); } FreeLibrary(hInst); }}
5、雙擊可以將主視窗啟用並顯示。由於WM_HITTEST訊息的影響,我們雙擊滑鼠的時候產生的是WM_NCLBUTTONDBLCLK訊息,而不是WM_LBUTTONDBLCLK訊息。
void CFloatWnd::OnNcLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CWnd *pParent = GetParent(); ASSERT(pParent); //顯示視窗 if(!pParent->IsWindowVisible()) pParent->ShowWindow(SW_SHOW); //置視窗到最前面 pParent->SetForegroundWindow(); CDialog::OnNcLButtonDblClk(nFlags, point);}
關於調節透明度的Slider使用,也寫了一些代碼,一併貼出來,供大家參考。
void CMainDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default //得到Slider的位置 int iCurPos = m_Slider.GetPos(); //得到最大值、最小值,及頁大小 int nMax = m_Slider.GetRangeMax(); int nMin = m_Slider.GetRangeMin(); int nPageSize = m_Slider.GetPageSize(); switch(nSBCode) { case SB_LINELEFT: if(iCurPos > nMin) iCurPos --; break; case SB_LINERIGHT: if(iCurPos < nMax) iCurPos ++; break; case SB_PAGELEFT: if(iCurPos > nMin) iCurPos = max(nMin,iCurPos - nPageSize); break; case SB_PAGERIGHT: if(iCurPos < nMax) iCurPos = min(nMax,iCurPos + nPageSize); break; case SB_THUMBTRACK: iCurPos = nPos; break; case SB_THUMBPOSITION: iCurPos = nPos; break; } //設定Slider位置 m_Slider.SetPos(iCurPos); //更新透明度 pFloatWnd->OnUpdateTransparent(iCurPos); CDialog::OnHScroll(nSBCode, nPos, pScrollBar);}
至於該視窗的右鍵菜單,視窗的顯示與隱藏,程式的退出等簡單代碼我就不多介紹了。
三、該程式在Windows xp sp2和Visual C++6.0下編譯調試成功。
原始碼下載!
摘自:VC知識庫