前言
很多文章示範了使用Windows 2000/XP的層次特性來實現視窗的透明化。本文可以通過該特性使任意視窗透明化,即使你沒有該程式的原始碼。
使用 "WinTrans" 程式你可以選擇任意正在啟動並執行程式,用滑鼠左鍵拖拽左上方框內的棒並將它壓在該程式的標題列上,然後放開,則該程式就可以變成透明。你可以調整滑動條的位置來控制透明度。"WinTrans" 有一個非常象 SPY 的介面,還可以示範Win32 APIs的如下用法:用滑鼠指標錨定視窗,擷取例如類名、標題等視窗資訊。
用法
在Windows 2000/XP中,User32.dll增加了一個新函數SetLayeredWindowAttributes。要使用該函數,我們必須在產生視窗或使用SetWindowLong函數中設定視窗風格WS_EX_LAYERED (0x00080000)。該風格一旦被設定,我們就可以調用該函數來透明化視窗。該函數所需參數如下:
HWND hWnd: 視窗控制代碼
COLORREF col: 透明化顏色
BYTE bAlpha: =0:整個視窗透明, =255 完全不透明
DWORD dwFlags: =1:僅顏色 col 透明, =2 :視窗按照bAlpha變數進行透明處理。
代碼
首先定義對話方塊的成員變數(WinTransDlg.h)。
bool m_bTracking; // 當滑鼠被捕捉時設定為TRUE
HWND m_hCurrWnd; // 滑鼠所在視窗的控制代碼
HCURSOR m_hCursor; // 棒型游標控制代碼
同時定義一個指向SetLayeredWindowAttributes函數的指標。該函數在User32.dll中定義。// 全域變數
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr,
BYTE bAlpha, DWORD dwFlags);
lpfn g_pSetLayeredWindowAttributes;
在OnInitDialog事件中擷取SetLayeredWindowAttributes函數的指標並且儲存在全域變數g_pSetLayeredWindowAttributes中。BOOL CWinTransDlg::OnInitDialog()
{
....
// 擷取函數 SetLayeredWindowAttributes 在User32.dll中的指標
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32,
"SetLayeredWindowAttributes");
if (g_pSetLayeredWindowAttributes == NULL)
AfxMessageBox (
"Layering is not supported in this version of Windows",
MB_ICONEXCLAMATION);
// 裝入棒形游標
HINSTANCE hInstResource = AfxFindResourceHandle(
MAKEINTRESOURCE(IDC_WAND), RT_GROUP_CURSOR);
m_hCursor = ::LoadCursor( hInstResource, MAKEINTRESOURCE(IDC_WAND) );
...
}
然後定義事件 WM_LBUTTONDOWN, WM_LBUTTONUP 和 WM_MOUSEMOVE 的觸發函數. M_LBUTTONDOWN 事件代碼如下: void CWinTransDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
...
SetCapture(); //滑鼠捕獲設定到指定的視窗。在滑鼠按鍵按下的時候,這個視窗會為//當前應用程式或整個系統接收所有滑鼠輸入
m_hCurrWnd = NULL; //現在還沒有視窗透明
m_bTracking = true; // 設定track標誌
::SetCursor(m_hCursor); // 將游標改為棒形
}
WM_MOUSEMOVE事件處理函數: void CWinTransDlg::OnMouseMove(UINT nFlags, CPoint point)
{
...
if (m_bTracking)
{
...
// 擷取滑鼠位置
ClientToScreen(&point);
...
// 擷取滑鼠下面所在的視窗控制代碼
m_hCurrWnd = ::WindowFromPoint(point);
...
// 顯示該視窗的類、標題等資訊…
...
}
...
}
一旦用滑鼠左鍵在視窗內點擊並且不釋放,滑鼠的指標將變為棒形,並且該視窗的資訊將顯示在WinTrans視窗上。當滑鼠左鍵被釋放後,事件WM_LBUTTONUP處理函數就被調用。
void CWinTransDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
...
//釋放滑鼠捕獲
ReleaseCapture();
m_bTracking = false;
//如果滑鼠下面的視窗不是本程式WinTrans,我們就要設定層次樣式並且通過設定滑動條來實現透明化。
if (g_pSetLayeredWindowAttributes && m_hCurrWnd != m_hWnd)
{
::SetWindowLong(m_hCurrWnd, GWL_EXSTYLE,
GetWindowLong(m_hCurrWnd,
GWL_EXSTYLE) ^ WS_EX_LAYERED);
g_pSetLayeredWindowAttributes(m_hCurrWnd, 0,
(BYTE)m_slider.GetPos(), LWA_ALPHA);
::RedrawWindow(m_hCurrWnd, NULL, NULL,
RDW_ERASE | RDW_INVALIDATE |
RDW_FRAME | RDW_ALLCHILDREN);
}
...
}