// 01 Dll插件Dlg.h : 头文件 // #pragma once #include <vector> using std::vector; #include "Shape.h" typedef struct _SHAPE { CPoint Begin; CPoint End; }SHAPE; // CMy01Dll插件Dlg 对话框 class CMy01Dll插件Dlg : public CDialogEx { // 构造 public: CMy01Dll插件Dlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_MY01DLL_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 void OnMenuCommand(UINT id); // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButton1(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); CPoint m_Begin; BOOL m_bIsPush; CPoint m_End; vector<SHAPE> m_vecPoint; CShape* m_CurrentShape; vector<CShape*> m_Shape; };
// 01 Dll插件Dlg.cpp : 实现文件 // #include "stdafx.h" #include "01 Dll插件.h" #include "01 Dll插件Dlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CMy01Dll插件Dlg 对话框 CMy01Dll插件Dlg::CMy01Dll插件Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMy01Dll插件Dlg::IDD, pParent), m_CurrentShape(NULL) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMy01Dll插件Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMy01Dll插件Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CMy01Dll插件Dlg::OnBnClickedButton1) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_COMMAND_RANGE(10001, 10100, OnMenuCommand) END_MESSAGE_MAP() // CMy01Dll插件Dlg 消息处理程序 void CMy01Dll插件Dlg::OnMenuCommand(UINT id) { m_CurrentShape = m_Shape[id - 10001]; } BOOL CMy01Dll插件Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 //1 遍历指定目录下的dll文件 WIN32_FIND_DATA wfd = {0}; HANDLE hFile = FindFirstFile(L"..\debug\*.dll", &wfd); CMenu * menu = GetMenu(); CMenu * SubMenu = menu->GetSubMenu(0); if (hFile!=INVALID_HANDLE_VALUE) { do { //2 载入dll文件 HMODULE hMoudle = LoadLibrary(wfd.cFileName); //3 查看是否是插件-通过导出函数来判断 typedef WCHAR* (*NAMEFUN)(); NAMEFUN GetName = NULL; GetName = (NAMEFUN)GetProcAddress(hMoudle, "GetName"); WCHAR* szName = GetName(); if (szName==NULL) { FreeLibrary(hMoudle); continue; } //4 获取出插件名字,并将其添加到菜单中 SubMenu->AppendMenu(0, 10001, szName); //5 将绘图产品存储到本程序中 typedef CShape*(* SHAPEFUN)(); SHAPEFUN CreateShape = (SHAPEFUN)GetProcAddress(hMoudle, "CreateShape"); m_Shape.push_back(CreateShape()); } while (FindNextFile(hFile, &wfd)); } SubMenu->DeleteMenu(0, MF_BYPOSITION); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CMy01Dll插件Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CMy01Dll插件Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CMy01Dll插件Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMy01Dll插件Dlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 } void CMy01Dll插件Dlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_bIsPush = TRUE; m_Begin = point; CDialogEx::OnLButtonDown(nFlags, point); } void CMy01Dll插件Dlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_bIsPush = FALSE; m_End = point; SHAPE Temp = { m_Begin, m_End }; m_vecPoint.push_back(Temp); CDialogEx::OnLButtonUp(nFlags, point); } void CMy01Dll插件Dlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (m_bIsPush == TRUE) { CDC* dc = GetDC(); CDC memDc; memDc.CreateCompatibleDC(dc); CRect rt; GetClientRect(rt); CBitmap bit; //注意:双缓冲的易忽略点,需要给BitMap创建一个兼容BitMap; bit.CreateCompatibleBitmap(&memDc, rt.Width(),rt.Height()); //内存DC需要有一个位图 memDc.SelectObject(bit); HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255)); memDc.FillRect(rt, CBrush::FromHandle(hBrush)); for (int i = 0; i < m_vecPoint.size();i++) { memDc.MoveTo(m_vecPoint[i].Begin.x, m_vecPoint[i].Begin.y); memDc.LineTo(m_vecPoint[i].End.x, m_vecPoint[i].End.y); } if (m_CurrentShape!=NULL) { m_CurrentShape->Draw(&memDc, m_Begin, point); } else { memDc.MoveTo(m_Begin.x, m_Begin.y); memDc.LineTo(point.x, point.y); } dc->BitBlt(0, 0, rt.Width(), rt.Height(), &memDc, 0, 0, SRCCOPY); } CDialogEx::OnMouseMove(nFlags, point); }
#pragma once #include "afxwin.h" class CShape { public: CShape(); ~CShape(); public: virtual void Draw(CDC* dc, CPoint Begin, CPoint End) = 0; };
#pragma once #include "Shape.h" class CDrawRect:public CShape { public: CDrawRect(); ~CDrawRect(); void Draw(CDC* dc,CPoint Begin,CPoint End) { CRect rt = { Begin, End }; dc->Rectangle(rt); } };
// 01 画方块的插件.cpp : 定义 DLL 的初始化例程。 // #include "stdafx.h" #include "01 画方块的插件.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // //TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的, // 则从此 DLL 导出的任何调入 // MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到 // 该函数的最前面。 // // 例如: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // 此处为普通函数体 // } // // 此宏先于任何 MFC 调用 // 出现在每个函数中十分重要。 这意味着 // 它必须作为函数中的第一个语句 // 出现,甚至先于所有对象变量声明, // 这是因为它们的构造函数可能生成 MFC // DLL 调用。 // // 有关其他详细信息, // 请参阅 MFC 技术说明 33 和 58。 // // CMy01画方块的插件App BEGIN_MESSAGE_MAP(CMy01画方块的插件App, CWinApp) END_MESSAGE_MAP() // CMy01画方块的插件App 构造 CMy01画方块的插件App::CMy01画方块的插件App() { // TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中 } // 唯一的一个 CMy01画方块的插件App 对象 CMy01画方块的插件App theApp; // CMy01画方块的插件App 初始化 BOOL CMy01画方块的插件App::InitInstance() { CWinApp::InitInstance(); return TRUE; } #include "DrawRect.h" extern "C" _declspec(dllexport) CShape * CreateShape() { return new CDrawRect; } extern "C" _declspec(dllexport) WCHAR* GetName() { return L"画方块"; }
; 01 画方块的插件.def : 声明 DLL 的模块参数。 LIBRARY EXPORTS ; 此处可以是显式导出