在多文档编程框架中,要显示多个视图,如何将视图类封装到DLL中?运行时将其创建此视图,并嵌入到到主框架中,以此实现模块编程呢?步骤如下:

(1)创建一个MFC的扩展DLL工程,在资源中添加一个FormView窗口,并创建相应的类CDeviceManageView。添加导出函数如下:

在stdafx.h文件中定义全局变量
//全局变量
extern CWnd * g_pParentWnd   ;
extern BOOL   g_bIsCloseView ;
//在dllmain.cpp中声明
CWnd * g_pParentWnd = NULL;
BOOL   g_bIsCloseView = FALSE;

extern "C" AFX_EXT_API UINT Create(CRuntimeClass * * view,CWnd * p)
{
        new CDynLinkLibrary(Scale3DCDeviceManageDLL);
	g_pParentWnd = p;
	*view = RUNTIME_CLASS(CScale3DCDeviceManageView);
	g_bIsCloseView = TRUE;
	return(0);
}

extern "C"  AFX_EXT_API  BOOL  GetVisual()
{//视图是否可见
	return g_bIsCloseView;
}

(2)主框架中调用DLL函数创建视图

HINSTANCE hDllInst = AfxLoadLibrary(CScale3DCGlobal::GetApplicationPath() 
                     + _T("\\DeviceManage.DLL"));
if (hDllInst)
{
	typedef UINT(*MYFUNC)(CRuntimeClass**,CWnd *parent);
	MYFUNC CreateViewUI = NULL;
	CreateViewUI = (MYFUNC)GetProcAddress(hDllInst, "Create");
	if (CreateViewUI)
	{
		CRuntimeClass* pNewViewClass;
		CreateViewUI(&pNewViewClass,AfxGetMainWnd());
		ASSERT(pNewViewClass);

		CCreateContext context;
		context.m_pNewViewClass = pNewViewClass;
		pChildFrame = new CScale3DCChildFrame;//测试工程中的子框架窗口
		if (!pChildFrame->LoadFrame(32000,//与DLL中的资源ID一致
			WS_OVERLAPPEDWINDOW | FWS_PREFIXTITLE, AfxGetMainWnd(), &context))
			return;
			pChildFrame->SetWindowText(_T("通信连接"));
			pChildFrame->InitialUpdateFrame(NULL, TRUE);
		}
		//FreeLibrary(hDllInst);
	}
}

编译器相关设置,如下:
1.png

2.png

3.png

(2)设置视图的标签页标题

#include <afxMDIChildWndEx.h>
void CScale3DCScaleWeightView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	CMDIChildWndEx * pFrame = (CMDIChildWndEx*)this->GetParentFrame();
	//CScale3DCChildFrame * pMidFrame = (CScale3DCChildFrame*)pFrame;

	pFrame->SetWindowText(_T("称重数据区"));
	// TODO: 在此添加专用代码和/或调用基类
}

(3)设置视图窗口的背景颜色

BOOL CScale3DCScaleWeightView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect   rt;
	GetClientRect(&rt);
	CBrush   brush;
	brush.CreateSolidBrush(RGB(224, 241, 251));
	CBrush * pOldBrush = pDC->SelectObject(&brush);
	pDC->FillRect(&rt, &brush);

	pDC->SelectObject(pOldBrush);

	return TRUE;
	//return CFormView::OnEraseBkgnd(pDC);
}
(4)在FormView中添加消息处理如下:
void CScale3DCUserManageView::OnNcDestroy()
{
	CFormView::OnNcDestroy();
	g_bIsCloseView = FALSE;
	// TODO: 在此处添加消息处理程序代码
}

(5)为DLL中的视图窗口,设置唯一的ID(即相对于所有的DLL包含的视图)。

(6)控件产生提示

.h文件中添加提示控件
CToolTipCtrl  m_tip;
void CScale3DCWeightView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
 	m_tip.Create(this);
 	m_tip.AddTool(GetDlgItem(IDC_ADD_SCALE), _T("称重界面"));
}

BOOL CScale3DCDeviceManageView::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_MOUSEMOVE)
		m_Mytip.RelayEvent(pMsg);

	return CFormView::PreTranslateMessage(pMsg);
}

(7)窗口静态标签控件透明

HBRUSH CScale3DCWeightView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何特性
	if (nCtlColor == CTLCOLOR_STATIC)
	{
		pDC->SetBkMode(TRANSPARENT); //设备背景透明模式
		return (HBRUSH)GetStockObject(NULL_BRUSH);
	}
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

(8)显示滚动条

SetScrollSizes(MM_TEXT, CSize(800, 170*4));//设置滚动条范围

(9)在子框架中给主框架发消息

void CScale3DCWeightView::OnNcDestroy()
{//通知主视图,关闭相关面板
	g_bIsCloseView = FALSE;
	CMDIChildWndEx * pFrame = (CMDIChildWndEx*)this->GetParentFrame();
	CWnd * pMainFrame = pFrame->GetParentFrame();
	if(pMainFrame)
		::SendMessage(pMainFrame->m_hWnd, WM_APP + 301, 0, 0);

	CFormView::OnNcDestroy();//放到最后一句
}

(10)CImage类加载DLL中的资源

VOID CScale3DCYiBiaoData::SetImage(INT id)
{
	m_nImgID = id;
	HINSTANCE temp = AfxGetResourceHandle();//保存旧的句柄
	//设置当前DLL资源环境句柄
	AfxSetResourceHandle(GetModuleHandle(_T("Scale3DCDeviceManage")));//DLL名称
	m_img.Destroy();//为了多次加载
	m_img.LoadFromResource(AfxGetResourceHandle(), id);
	AfxSetResourceHandle(temp);//恢复原先句柄
}

从资源中加载字符串,则不必,直接LoadString(id)即可