这两天学习动态库的练习,分享下方法
实例.封装窗口类的两种状态.
1.自定义窗口类QWnd
2.资源模板窗口对话框类
下面是dll的头文件,类的声明
#pragma once #ifndef _CLASSDLL_H_ #define _CLASSDLL_H_ #include <windows.h> #include <assert.h> //定义导入与导出类的宏标识 //在动态库的.cpp文件中定义DLLCLASS_EXPORTS表示导出类函数 #ifdef DLLCLASS_EXPORTS #define EXT_CLASS _declspec(dllexport) //定义导出类 #else #define EXT_CLASS _declspec(dllimport) //定义导入类 #endif /* * QWnd Class */ class EXT_CLASS QWnd { public: QWnd(); public://成员函数 //创建窗口 //参数说明: // 1.lpClassName: .窗口类名 // 2.lpWndName:....窗口标题 // 3.dwStyle: .....窗口风格样式 // 4.x,y,nWidth,nHegiht: ...窗口位置和宽高 // 5.hParent: .....父窗口句柄 // 6.meunID: ......菜单句柄(子窗口为子窗口ID) BOOL CreateWindowX(LPCTSTR lpClassName, LPCTSTR lpWndName, UINT dwStyle, int x, int y, int nWidth, int nHegiht, HWND hParent, HMENU menuID, HINSTANCE hInstance); /****** 静态消息回调函数 */ static LRESULT CALLBACK lpWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //实际的消息回调处理函数 virtual LRESULT MyWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); //显示窗口 BOOL ShowWindow(int nCmdShow); //更新窗口 BOOL UpdateWindow()const; //消息循环 BOOL RunMsg()const; public: //成员变量 HWND m_hWnd; //窗口句柄 HINSTANCE m_hInstance; //程序实例句柄 LPVOID m_lpVoid; //窗口附加数据,用于窗口间传递数据 public: //msg消息处理函数 virtual LRESULT OnDestroy(WPARAM wParam, LPARAM lParam); //窗口销毁消息 virtual LRESULT OnCreate(WPARAM wParam, LPARAM lParam); //窗口创建消息 virtual LRESULT OnClose(WPARAM wParam, LPARAM lParam); //窗口关闭消息 virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam); //响应按键消息 virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); //子窗口通知消息 virtual LRESULT OnPaint(WPARAM wParam, LPARAM lParam); //窗口重绘消息 virtual LRESULT OnLButtonDBlclk(WPARAM wParam, LPARAM lParam); //鼠标左键双击消息 virtual LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam); //鼠标左键按下消息 virtual LRESULT OnLButtonUp(WPARAM wParam, LPARAM lParam); //鼠标左键弹起消息 virtual LRESULT OnRButtonDBlclk(WPARAM wParam, LPARAM lParam); //鼠标右键双击消息 virtual LRESULT OnRButtonDown(WPARAM wParam, LPARAM lParam); //鼠标右键按下消息 virtual LRESULT OnRButtonUp(WPARAM wParam, LPARAM lParam); //鼠标右键弹起消息 virtual LRESULT onm ouseMove(WPARAM wParam, LPARAM lParam); //鼠标移动消息 virtual LRESULT onm ouseLeave(WPARAM wParam, LPARAM lParam); // virtual LRESULT onm ouseWheel(WPARAM wParam, LPARAM lParam); //鼠标滚轮消息 virtual LRESULT onm ouseLast(WPARAM wParam, LPARAM lParam); // virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam); //系统按钮消息 }; /* * QDialogEx Class */ class EXT_CLASS QDialogEx:public QWnd { public: QDialogEx(QWnd* pPrent = NULL, DWORD dlgIDD = 0); static INT_PTR CALLBACK lpDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); virtual INT_PTR MyDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); //创建模板资源对话框 // 参数说明: // 1.hInstance: ..程序实例句柄 // 2.dlgIDD: .....对话框资源ID号 // 3.hParent: ....父窗口句柄 BOOL CreateDialogX(HINSTANCE hInstance, UINT dlgIDD, HWND hParent = NULL); //模态对话框(父窗口类的对象) INT_PTR DoModul(QWnd* pParent); public://msg virtual INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); //初始化对话框消息 virtual LRESULT OnClose(WPARAM wParam, LPARAM lParam); //关闭消息 virtual LRESULT OnDestroy(WPARAM wParam, LPARAM lParam); //销毁窗口消息 virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam); public: BOOL m_IsModul; //是否是模态窗口 UINT m_IDD; //对话框的资源ID LPARAM m_lParam;//窗口附加数据,用于数据的传进与传出 }; #endif
弄了好久才弄好,途中错误连连,不过也学到不少东西.
下面是dll.cpp文件
#define DLLCLASS_EXPORTS #include "Classdll.h" #pragma region 窗口类QWnd QWnd::QWnd() { m_hInstance = 0; m_hWnd = 0; m_lpVoid = 0; } BOOL QWnd::CreateWindowX(LPCTSTR lpClassName, LPCTSTR lpWndName, UINT dwStyle, int x, int y, int nWidth, int nHegiht, HWND hParent, HMENU menuID, HINSTANCE hInstance) { m_hInstance = hInstance; //设计自定义窗口类 WNDCLASSEX wcx = { 0 }; wcx.cbSize = sizeof(WNDCLASSEX); if (!GetClassInfoEx(hInstance, lpClassName, &wcx)) { wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.lpfnWndProc = lpWindowProc; wcx.lpszClassName = lpClassName; wcx.lpszMenuName = NULL; wcx.hbrBackground = (HBRUSH)(COLOR_3DFACE); wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW); wcx.hIcon = ::LoadIcon(NULL, IDI_WINLOGO); wcx.hIconSm = ::LoadIcon(NULL, IDI_WINLOGO); wcx.hInstance = hInstance; wcx.style = CS_VREDRAW | CS_HREDRAW; //注册窗口类 if (!RegisterClassEx(&wcx)) { OutputDebugString(TEXT("窗口类注册失败!!!")); return FALSE; } } //创建窗口 m_hWnd = ::CreateWindowEx(0, lpClassName, lpWndName, dwStyle,x,y,nWidth,nHegiht, hParent, menuID, hInstance,this); if (NULL == m_hWnd) { OutputDebugString(TEXT("窗口创建失败!!!!")); return FALSE; } return TRUE; } LRESULT CALLBACK QWnd::lpWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (WM_CREATE == uMsg) { QWnd* pWnd = (QWnd*)((CREATESTRUCT*)lParam)->lpCreateParams; if (pWnd) { pWnd->m_hWnd = hWnd; SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG)pWnd); return pWnd->MyWndProc(uMsg, wParam, lParam); } } QWnd* pWnd = (QWnd*)GetWindowLongPtr(hWnd, GWL_USERDATA); if (pWnd) { return pWnd->MyWndProc(uMsg, wParam, lParam); } return DefWindowProc(hWnd, uMsg, wParam, lParam); } LRESULT QWnd::MyWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: return OnDestroy(wParam, lParam); case WM_CREATE: return OnCreate(wParam, lParam); case WM_CLOSE: return OnClose(wParam, lParam); case WM_COMMAND: return OnCommand(wParam, lParam); case WM_SYSCOMMAND: OnSysCommand(wParam, lParam); break; case WM_NOTIFY: return OnNotify(wParam, lParam); case WM_PAINT: OnPaint(wParam, lParam); break; case WM_LBUTTONDBLCLK: return OnLButtonDBlclk(wParam, lParam); case WM_LBUTTONDOWN: return OnLButtonDown(wParam, lParam); case WM_LBUTTONUP: return OnLButtonUp(wParam, lParam); case WM_RBUTTONDBLCLK: return OnRButtonDBlclk(wParam, lParam); case WM_RBUTTONDOWN: return OnRButtonDown(wParam, lParam); case WM_RBUTTONUP: return OnRButtonUp(wParam, lParam); case WM_MOUSEMOVE: return onm ouseMove(wParam, lParam); case WM_MOUSELEAVE: return onm ouseLeave(wParam, lParam); case WM_MOUSEWHEEL: return onm ouseWheel(wParam, lParam); case WM_MOUSELAST: return onm ouseLast(wParam, lParam); } return DefWindowProc(m_hWnd, uMsg, wParam, lParam); } BOOL QWnd::ShowWindow(int nCmdShow) { assert(m_hWnd); return ::ShowWindow(m_hWnd, nCmdShow); } BOOL QWnd::UpdateWindow() const { assert(m_hWnd); return ::UpdateWindow(m_hWnd); } BOOL QWnd::RunMsg() const { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } #pragma region 虚函数 LRESULT QWnd::OnDestroy(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnCreate(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnClose(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnCommand(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnNotify(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnPaint(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnLButtonDBlclk(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnRButtonDBlclk(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnRButtonUp(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnMouseMove(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnMouseLeave(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnMouseLast(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QWnd::OnSysCommand(WPARAM wParam, LPARAM lParam) { return 0; } #pragma endregion #pragma endregion 窗口类 #pragma region 对话框类QDialogEx QDialogEx::QDialogEx(QWnd * pPrent, DWORD dlgIDD) { m_IsModul = FALSE; m_IDD = (dlgIDD != 0) ? dlgIDD : 0; } INT_PTR CALLBACK QDialogEx::lpDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (WM_INITDIALOG == uMsg) { QDialogEx* pDlg = (QDialogEx*)lParam; if (pDlg) { pDlg->m_hWnd = hWnd; SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG)pDlg); return pDlg->MyDlgProc(uMsg, wParam, lParam); } } QDialogEx* pDlg = (QDialogEx*)GetWindowLongPtr(hWnd, GWL_USERDATA); if (pDlg) { return pDlg->MyDlgProc(uMsg, wParam, lParam); } return 0; } INT_PTR QDialogEx::MyDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: return OnInitDialog(wParam, lParam); case WM_COMMAND: return OnCommand(wParam, lParam); case WM_NOTIFY: return OnNotify(wParam, lParam); case WM_CLOSE: return OnClose(wParam, lParam); case WM_DESTROY: return OnDestroy(wParam, lParam); } return INT_PTR(); } BOOL QDialogEx::CreateDialogX(HINSTANCE hInstance, UINT dlgIDD, HWND hParent /*= NULL*/) { m_hInstance = hInstance; m_hWnd = ::CreateDialogParam(hInstance, MAKEINTRESOURCE(dlgIDD), hParent,lpDialogProc, (LPARAM)this); if (NULL == m_hWnd) { OutputDebugString(TEXT("创建对话框资源窗口失败!!!")); return FALSE; } return TRUE; } INT_PTR QDialogEx::DoModul(QWnd* pParent) { assert(pParent); m_IsModul = TRUE; return ::DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(m_IDD), pParent->m_hWnd,lpDialogProc,(LPARAM)this); } INT_PTR QDialogEx::OnInitDialog(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QDialogEx::OnClose(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QDialogEx::OnDestroy(WPARAM wParam, LPARAM lParam) { return 0; } LRESULT QDialogEx::OnCommand(WPARAM wParam, LPARAM lParam) { return 0; } #pragma endregion 对话框类QDialogEx
本想弄到一个消息处理函数中,但是冲途好多,就弄了两个处理消息函数,以后弄明白再说吧.现在能用就OK
用法:
1.将生成的.dll .lib .h三个文件拷到要用的工程目录下,
2.在工程中声明
#include "../Classdll/Classdll.h" //这是声明动态库的头文件,你放在什么地方就写什么地方
#pragma comment(lib,"../Debug/Classdll.lib") //这是引入动态库.dll,和上面一样,放在什么地方就写什么地方
测试:
int main() { #if 0 //定位内存漏泄所在代码位置 _CrtSetBreakAlloc(13); #endif HINSTANCE hInstance=GetModuleHandle(NULL); MyDialog dlg; dlg.CreateDialogX(hInstance, IDD_DIALOG1, NULL); dlg.ShowWindow(SW_SHOW); dlg.UpdateWindow(); dlg.RunMsg(); #ifdef _DEBUG _CrtDumpMemoryLeaks(); //检查内存漏泄 #endif return 0; }
效果:
因是在控制台测试的,所以有控制台的黑窗口