DLL自定义窗口类
2011-1-9
目的是模拟Windows在DLL中注册窗口类,然后在其它模块中调用。代码如下:
调用模块:
#include <windows.h> #pragma comment (lib, "F://MyClass//debug//MyClassDLL.lib") HWND MyCreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ); int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { HWND hwnd = ::MyCreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "myClass", "自定义窗口类", WS_VISIBLE|WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400,200,//相同窗口成等差数列排列 NULL, NULL, hInstance, NULL); if ( hwnd == NULL ) { ::MessageBox(NULL, "创建窗口失败!", "", MB_OK); return 0; } MSG msg; while ( GetMessage(&msg, NULL, 0, 0) ) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } MessageBox(NULL, "", "", MB_OK); return 0; }
DLL模块:
#include <windows.h> LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_CLOSE: ::DestroyWindow(hwnd); ::PostQuitMessage(0); break; } return ::DefWindowProc(hwnd, uMsg, wParam, lParam); } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch ( ul_reason_for_call) { case DLL_PROCESS_ATTACH: { WNDCLASSEX wc; wc.cbSize = sizeof(wc); wc.style = CS_VREDRAW | CS_HREDRAW;//可为赋值为0,但不能不赋值! wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ::GetModuleHandle(NULL); wc.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = ::CreateSolidBrush(RGB(255,255,255)); wc.lpszMenuName = NULL; wc.lpszClassName = "myClass"; wc.hIconSm = NULL; ::RegisterClassEx(&wc); } case DLL_THREAD_ATTACH: case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH: break; } return TRUE; } HWND MyCreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ) { return ::CreateWindowEx( dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam ); }
def文件
LIBRARY "MyClassDLL" EXPORTS MyCreateWindowEx
总结:
1. 解决方案会生成一个Debug文件夹(当然在Release模式下生成Release文件夹),用于统一存放各工程的输出(DLL、LIB或 EXE)。
2. 如果模块中没有调用DLL中的任何函数,那么DLL不好被加载。也就是说此时删除DLL,也不会影响程序正常执行。所以要为DLL加载(以便注册自定义窗口类),就得调用其中的函数。DLL中,将user32.dll中的CreateWindowEx封装成为MyCreateWindowEx,目的是让调用模块在CreateWindow的同时也加载了DLL的代码,这样就对自定义的窗口类进行了注册。个人推测,在用户调用user32.dll中的CreateWindowEx时,在user32.dll初始代码中对”button”这样的系统窗口类已经进行了注册。