發佈《 .NET Windows Form 改變窗體類名(Class Name)有多難?》轉眼大半年過去了,要不是在前幾天有園友對這篇文章進行評論,基本上已經不多關注它了,畢竟那只是一個解惑的研究,在開發中沒什麼實際的用處。可是因爲Squares園友的評論,結合最近本身相關的工做,靈感一現,卻真的找到了解決之法,不得不感慨一下,「問題老是會有解決辦法的,只是本身能力不夠或一時沒想到而已」。好了,前奏寫完,進入正題。css
最近一段時間,從新拾起之前比較熟悉的界面UI開發,因爲須要,瞭解了一些 HOOK API 的知識。HOOK API C++ 已經有比較好的開源資源,MHook 和 MinHook。而 HOOK API 就是解決 「Windows Form 改變窗體類名(Class Name)」的關鍵。html
還記得上一篇文章裏提到爲何不能改變Windows Form窗體類名的緣由嗎?就是微軟的代碼裏只認系統註冊的 ClassName,只要咱們在 CreateParams 屬性裏設置的 ClassName 不是系統註冊的 ClassName,就會報錯。因此,設置本身喜歡的 ClassName,只能按照窗口建立的過程,本身實現一個窗口。而實現一個窗口的過程也很簡單:git
過程很是簡單,Winform 的窗口也脫離不了這個過程。那這樣, HOOK API 不就有隙可乘了嗎?只要咱們 HOOK RegisterClass 和 CreateWindowEx,在 Winform 註冊窗口時,把它使用的類名改成咱們須要的類名;建立窗口的時候,也一樣。固然,在實際處理過程當中,UnregisterClass,GetClassInfo 也是須要 HOOK 進行處理的。github
很少說,很是簡單,一切以代碼說話。 app
1 #include "ClassNameManager.h" 2 #include <Windows.h> 3 #include <tchar.h> 4 #include <assert.h> 5 #include "../MinHook/include/MinHook.h" 6 7 #ifdef _M_X64 8 #pragma comment(lib, "../lib/MinHook/MinHook.x64.lib") 9 #else 10 #pragma comment(lib,"../lib/MinHook/MinHook.x86.lib") 11 #endif 12 13 namespace Starts2000 { 14 namespace Window { 15 namespace Forms { 16 17 #define FORM_CLASS_NAME L"WindowsForms10.Window.8.app" 18 #define FORM_CUSTOM_CLASS_NAME L"Starts2000.Window" 19 20 typedef ATOM (WINAPI * TrueRegisterClassW)(_In_ CONST WNDCLASSW *); 21 typedef BOOL (WINAPI * TrueUnregisterClassW)(_In_ LPCWSTR, _In_opt_ HINSTANCE); 22 typedef BOOL (WINAPI * TrueGetClassInfoW)( 23 _In_opt_ HINSTANCE, 24 _In_ LPCWSTR, 25 _Out_ LPWNDCLASSW); 26 typedef HWND (WINAPI * TrueCreateWindowExW)( 27 _In_ DWORD, 28 _In_opt_ LPCWSTR, 29 _In_opt_ LPCWSTR, 30 _In_ DWORD, 31 _In_ int, 32 _In_ int, 33 _In_ int, 34 _In_ int, 35 _In_opt_ HWND, 36 _In_opt_ HMENU, 37 _In_opt_ HINSTANCE, 38 _In_opt_ LPVOID); 39 40 TrueRegisterClassW _registerClassW = NULL; 41 TrueUnregisterClassW _unregisterClassW = NULL; 42 TrueGetClassInfoW _getClassInfoW = NULL; 43 TrueCreateWindowExW _createWindowExW = NULL; 44 45 ATOM WINAPI RegisterClassWD(_In_ CONST WNDCLASSW *lpWndClass) { 46 if (_tcsstr(lpWndClass->lpszClassName, FORM_CLASS_NAME)) { 47 WNDCLASSW wndClass; 48 memcpy(&wndClass, lpWndClass, sizeof(WNDCLASSW)); 49 wndClass.lpszClassName = FORM_CUSTOM_CLASS_NAME; 50 auto ret = _registerClassW(&wndClass); 51 return ret; 52 } 53 54 return _registerClassW(lpWndClass); 55 } 56 57 BOOL WINAPI UnregisterClassWD(_In_ LPCWSTR lpClassName, _In_opt_ HINSTANCE hInstance) { 58 if (_tcsstr(lpClassName, FORM_CLASS_NAME)) { 59 return _unregisterClassW(FORM_CUSTOM_CLASS_NAME, hInstance); 60 } 61 62 return _unregisterClassW(lpClassName, hInstance); 63 } 64 65 BOOL WINAPI GetClassInfoWD(_In_opt_ HINSTANCE hInstance, 66 _In_ LPCWSTR lpClassName, 67 _Out_ LPWNDCLASSW lpWndClass) { 68 if (_tcsstr(lpClassName, FORM_CLASS_NAME)) { 69 return _getClassInfoW(hInstance, FORM_CUSTOM_CLASS_NAME, lpWndClass); 70 } 71 72 return _getClassInfoW(hInstance, lpClassName, lpWndClass); 73 } 74 75 HWND WINAPI CreateWindowExWD( 76 _In_ DWORD dwExStyle, 77 _In_opt_ LPCWSTR lpClassName, 78 _In_opt_ LPCWSTR lpWindowName, 79 _In_ DWORD dwStyle, 80 _In_ int X, 81 _In_ int Y, 82 _In_ int nWidth, 83 _In_ int nHeight, 84 _In_opt_ HWND hWndParent, 85 _In_opt_ HMENU hMenu, 86 _In_opt_ HINSTANCE hInstance, 87 _In_opt_ LPVOID lpParam) { 88 if (_tcsstr(lpClassName, FORM_CLASS_NAME)) { 89 auto hwnd = _createWindowExW(dwExStyle, FORM_CUSTOM_CLASS_NAME, lpWindowName, dwStyle, 90 X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); 91 assert(hwnd); 92 return hwnd; 93 } 94 95 return _createWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, 96 X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); 97 } 98 99 ClassNameManager::ClassNameManager() { 100 auto ret = MH_Initialize(); 101 assert(ret == MH_STATUS::MH_OK); 102 103 ret = MH_CreateHookApi(L"User32.dll", 104 "RegisterClassW", &RegisterClassWD, reinterpret_cast<LPVOID*>(&_registerClassW)); 105 assert(ret == MH_STATUS::MH_OK); 106 107 ret = MH_CreateHookApi(L"User32.dll", 108 "UnregisterClassW", &UnregisterClassWD, reinterpret_cast<LPVOID*>(&_unregisterClassW)); 109 assert(ret == MH_STATUS::MH_OK); 110 111 ret = MH_CreateHookApi(L"User32.dll", 112 "GetClassInfoW", &GetClassInfoWD, reinterpret_cast<LPVOID*>(&_getClassInfoW)); 113 assert(ret == MH_STATUS::MH_OK); 114 115 ret = MH_CreateHookApi(L"User32.dll", 116 "CreateWindowExW", &CreateWindowExWD, reinterpret_cast<LPVOID*>(&_createWindowExW)); 117 assert(ret == MH_STATUS::MH_OK); 118 119 ret = MH_EnableHook(MH_ALL_HOOKS); 120 assert(ret == MH_STATUS::MH_OK); 121 } 122 123 ClassNameManager::~ClassNameManager() { 124 } 125 126 ClassNameManager::!ClassNameManager() { 127 auto ret = MH_Uninitialize(); 128 assert(ret == MH_STATUS::MH_OK); 129 } 130 } 131 } 132 }
源碼是要上的,下載項目源代碼。函數