本來今天平安夜,我是要來寫點東西的,結果發現上回的文章(Desktop控制第一部分)沒有人注意,
也沒有人有留言, 故信心大減.
但我還是把: Desktop背景圖設置整理一下.
另外再講一下: Hook Desktop 後的方便, 以及Hook Desktop 的實現原理.
1. Desktop背景圖設置
由於上一篇文章沒有講的很細緻, 這回補充說明一下.
下面的代碼是基於VC6 MFC的. 額外使用類: CDVReg 設置註冊表健值, 這個大家可以自己實現. 這裏不再提供.
{
if( !lpszImage || 0 == lstrlen( lpszImage ) )
return TRUE;
CString strSubKey = "";
// 下面代碼找到當前用戶的KEY值, 如: S-1-5-21-329068152-1788223648-839522115-500
HKEY keyUsers = NULL;
for( int i = 0; i < 24; i ++ )
{
DWORD dwRet = RegEnumKey( HKEY_USERS,
i,
strSubKey.GetBuffer( 256 ),
256 );
strSubKey.ReleaseBuffer();
if( ERROR_SUCCESS == dwRet )
{
CString strCheck = strSubKey + "/Software/Microsoft/Internet Explorer/Desktop/General";
HKEY hKeySub = NULL;
if( ERROR_SUCCESS == RegOpenKey( HKEY_USERS, strCheck, &hKeySub ) )
{
RegCloseKey( hKeySub );
break;
}
}
else
{
strSubKey = "";
break;
}
strSubKey = "";
}
if( strSubKey.IsEmpty() )
return FALSE;
CString strWallPaper = lpszImage;
CString WallpaperStyle = "2"; // 風格
// 1.
CString strPath = "Control Panel/Desktop";
CString strField = "Wallpaper";
CString strWallpaperStyle = "WallpaperStyle";
// a.
BOOL bSet = CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
// b.
strField = "BackupWallpaper";
bSet = CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
// c.
CDVReg::RegString( REG_SET_CURRENT, strPath, strWallpaperStyle, &WallpaperStyle );
// 2.
strPath = "Software/Microsoft/Internet Explorer/Desktop/General";
// a.
strField = "Wallpaper";
CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
// b.
strField = "BackupWallpaper";
CDVReg::RegString( REG_SET_CURRENT, strPath, strField, &strWallPaper );
// c.
CDVReg::RegString( REG_SET_CURRENT, strPath, strWallpaperStyle, &WallpaperStyle );
// 4.
strPath = strSubKey + "/Control Panel/Desktop";
// a.
strField = "Wallpaper";
CDVReg::RegString( REG_SET_USERS, strPath, strField, &strWallPaper );
// b.
strField = "BackupWallpaper";
CDVReg::RegString( REG_SET_USERS, strPath, strField, &strWallPaper );
// c.
CDVReg::RegString( REG_SET_USERS, strPath, strWallpaperStyle, &WallpaperStyle );
// 5.
strPath = strSubKey + "/Software/Microsoft/Internet Explorer/Desktop/General";
// a.
strField = "Wallpaper";
CDVReg::RegString( REG_SET_USERS, strPath, strField, &strWallPaper );
// b.
strField = "BackupWallpaper";
CDVReg::RegString( REG_SET_USERS, strPath, strField, &strWallPaper );
// c
CDVReg::RegString( REG_SET_USERS, strPath, strWallpaperStyle, &WallpaperStyle );
BOOL b = SystemParametersInfo( 0x0014,
NULL,
(PVOID)lpszImage,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
ASSERT( b );
// SPIF_UPDATEINIFILE, SPIF_SENDCHANGE 兩個參數不再說明.
// 請參考網上其他人的說明以及MSDN.
return TRUE;
}
2. HOOK Desktop
A. 爲什麼要Hook desktop
因爲有這樣的情況: desktop上設置了背景圖, 背景圖上有個太陽.
而點太陽, 要做一些事, 比如: 彈出一個網頁之類的.
當然上面只是一種情況, 還有其他的情況也都可以使用HOOK Desktop實現.
或者是使用遠程線程叉入實現.
也可以兩種方式都使用.
B. 如何實現Hook Desktop
最好的方法當然是使用explorer 內部的線程實現hook.
這裏我就不再說明這些細節, 因爲Hook 其實是非常容易使用的.
如果不知道, 請查MSDN: SetWindowsHookEx
我的實現代碼:
頭文件:
#define _WNDPROC_HOOKER_H_
/////////////////////////////////////////////////////////////
#include <windows.h>
typedef HHOOK (WINAPI* SetWindowsHookExAProc)(int,HOOKPROC,HINSTANCE,DWORD);
typedef LRESULT (WINAPI* CallNextHookExProc)(HHOOK,int,WPARAM,LPARAM);
typedef BOOL (WINAPI* UnhookWindowsHookExProc)(HHOOK);
class CHooker
{
CHooker();
public:
static void OnMouseUp( PMSG p );
static void InitHook(HWND hWnd);
static void UnHook();
static void OnMouseMove( PMSG p );
};
/////////////////////////////////////////////////////////////
#endif
實現文件:
HHOOK g_hHookMessage = NULL;
static LRESULT WINAPI GetMsgProc( int code, WPARAM wParam, LPARAM lParam )
{
PMSG p = (PMSG)lParam;
if( code == HC_ACTION && p && wParam == PM_REMOVE )
{
if( WM_MOUSEMOVE == p->message )
{
CHooker::OnMouseMove( p );
}
else if( WM_LBUTTONUP == p->message )
{
CHooker::OnMouseUp( p );
}
}
NextHook:
if( code == HC_ACTION && p && wParam == PM_REMOVE )
{
return TRUE;
}
else
{
// return CallNextHookEx( g_hMessage, code, wParam, lParam );
return g_ptrCallNextHookEx( NULL, code, wParam, lParam );
}
}
void CHooker::InitHook(HWND hWnd)
{
if( !g_hHookMessage )
{
DWORD dwThreadID = GetWindowThreadProcessId( hWnd, NULL );
HINSTANCE hModule = (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE);
SetWindowsHookExAProc ptrSetWindowsHookExA = (SetWindowsHookExAProc)::GetProcAddress( LoadLibrary( "User32.dll" ), "SetWindowsHookExA" );
if( ptrSetWindowsHookExA &&
dwThreadID &&
hModule )
{
g_hHookMessage = ptrSetWindowsHookExA( WH_GETMESSAGE, GetMsgProc, hModule, dwThreadID );
}
}
}
void CHooker::UnHook()
{
if( !g_hHookMessage )
{
UnhookWindowsHookExProc ptrUnhookWindowsHookEx =
(UnhookWindowsHookExProc)::GetProcAddress( LoadLibrary( "User32.dll" ), "UnhookWindowsHookEx" );
if( ptrUnhookWindowsHookEx )
{
ptrUnhookWindowsHookEx( g_hHookMessage );
}
g_hHookMessage = NULL;
}
}
至於:
void CHooker::OnMouseUp(PMSG p)
void CHooker::OnMouseMove(PMSG p)
的實現, 就隨心所欲了. 想怎麼樣就怎麼樣.
3. 關於遠程線程的叉入
這裏不再說明, 事實網上實例很多.
那麼是否能在遠程線程內部實現一個Web browser 對象呢?
是可以的. 不過稍微複雜一些.
如果你有這方面問題請留言,或者加入下面的VC技術羣提問.
4. 關於Hook explorer 裏面的文件目錄
並顯示圖像.
事實非常容易, 直接使用Hook 就可以. 至於找wnd, 當然是必須要的.
下篇一內容, 有可能我會做個實例並公開給大家.
如果你有這方面問題請留言,或者加入下面的VC技術羣提問.
VC技術羣: 30107096