MSFlexGrid 控件在 ATL 复合控件上






4.89/5 (6投票s)
如何在 ATL 复合控件上使用 MSFlexGrid 控件
引言
在 ATL 项目中使用 MSFlexGrid 控件有点棘手(我花了大量时间研究 MSDN 和网络),因为
- MSFlexGrid 控件是一个 Visual Basic 控件
- MSFlexGrid 控件需要运行时控制许可证。
要检查问题,您可以执行以下操作
- 创建 ATL Server Dll
- 添加 ATL 复合控件
- 右键单击并插入 MSFlexGrid 控件
- 右键单击并添加事件,并公开一些事件。
- 构建 Dll。
- 将其与MSFlex.ocx和其他支持库一起部署在测试机器上。请注意,它在开发机器(安装了 Visual Studio 的机器)上运行良好,因为当您安装 Visual Studio 时,它默认会为当前系统提供设计时和运行时许可证。
查看详细信息:
- http://support.microsoft.com/default.aspx?scid=kb;en-us;Q151771
- http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q151804&LN=EN-US&SD=gn&FR=0&qry=Q151804&rnk=1&src=DHCS_MSPSS_gn_SRCH&SPR=CHS
结果
它在测试机器(仅安装了 OS 的机器)上不起作用。 如果您使用 Visual Basic 作为客户端,它将在控件的位置显示找不到页面的 HTML 页面。如何使用MSFlexGrid
?
- 创建 ATL Server Dll。
- 添加 ATL 复合控件。
- 在控件头文件中导入msflxgrd.ocx。
#import "C:\WINNT\System32\msflxgrd.ocx" raw_interfaces_only, raw_native_types, no_namespace, named_guids
- 在
#import "...msflxgrid.ocx..."
之前添加#pragma warning(disable:4146)
,否则会给出警告。 - 现在的问题是:在创建控件时,您需要获取 MSFlexGrid 控件的运行时许可证。 我做了一个函数来做到这一点
// Create Control void CreateObject() { CComPtr
pUnkCont; ComQIPtr spPerStm; CComPtr pCF; // Add CLSID of MSFlexGrid for Runtime license CComBSTR bstrLicKey = "72E67120-5959-11cf-91F6-C2863C385E30"; HRESULT hr = CoGetClassObject(CLSID_MSFlexGrid, CLSCTX_ALL, NULL, IID_IClassFactory2, reinterpret_cast<void**>(&pCF) ); // Call CreateInstanceLic to create instance of control // with runtime license if( !FAILED( hr ) ) hr =pCF->CreateInstanceLic(NULL,NULL,IID_IUnknown,bstrLicKey, reinterpret_cast<void**>(&pUnk)); spPerStm=pUnk; spPerStm->InitNew(); wnd.Attach(m_hWnd); wnd.AttachControl(pUnk, &pUnkCont); m_VarGrid = pUnk; // Start event connection DispEventAdvise(pUnk); } - 添加以下成员变量。 我已将以下成员变量添加为公共变量。
CAxWindow wnd; IUnknownPtr pUnk; IMSFlexGridPtr m_Grid;
- 下一步是捕获 flxgrid 控件的事件,这可以通过在类声明中添加以下行来完成
public IDispEventImpl < ID_VAR_GRID,CAuthorVar,&DIID_DMSFlexGridEvents, &LIBID_MSFlexGridLib,1,0 >
- 添加 Sink Entry(我感觉很懒,只使用单击事件,如果您愿意,您可以根据您的要求使用任意数量的事件)
BEGIN_SINK_MAP(CFlxCtrl) //Make sure the Event Handlers have __stdcall calling convention SINK_ENTRY_EX(ID_GRID,DIID_DMSFlexGridEvents, DISPID_CLICK, OnClick_grid) END_SINK_MAP()
- 在Resource.h文件中添加
#define ID_GRID 201
或您喜欢的任何 ID。 - 添加事件处理程序
VOID __stdcall Click_grid() { AfxMessageBox("Clicked"); }
- 您还可以添加一个方法来初始化网格,例如:
void InitGrid() { CString Cols[5]={"Name","Phone No","MailID"}; m_VarGrid->put_FixedRows(1); m_VarGrid->put_FixedCols(0); m_VarGrid->put_Rows(2); m_VarGrid->put_Cols(3); for(int i = 0;i!=3;i++) { m_VarGrid->put_TextMatrix(0,i,(_bstr_t)Cols[i]); m_VarGrid->put_ColWidth(i,1260); } }
- 在
OnInitDialog
中调用CreateObject()
函数和InitGrid()
。 - 向接口添加一个方法,例如:
STDMETHODIMP CAuthorVar::Stop() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) if(pUnk) { HRESULT hr= DispEventUnadvise(pUnk);// } m_Grid.Release(); return S_OK; }
- 在 ActiveX 控件测试容器中测试该控件,并且不要忘记在关闭之前调用 stop 方法。
我还注意到了另一个问题,那就是
每次都需要调用DispEventUnadvise(pUnk)/DispEventAdvise(pUnk)
方法,并且它不会处理来自容器窗口或放置在那里的其他控件的任何消息。 我发现最简单的解决方案是将您的第一个控件包装到另一个复合控件中,这将使您的生活更轻松。
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Licenses\72E67120-5959-11cf-91F6-C2863C385E30]
@="ibcbbbebqbdbciebmcobmbhifcmciibblgmf"
并感到高兴,但我不推荐它。 所以,祝你使用 MSFlexGrid 和 ATL 复合控件玩得开心。