一、簡介:
象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擴展屬性
BOOL SetLayeredWindowAttributes(HWND hwnd,COLORREF crKey,BYTE bAlpha,DWORD dwFlags);
SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
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下編譯調試成功。
本文配套源碼