sa.PtrOfIndex(lindex, (void**)&prect); m_cells[i-llb1][j-llb2].m_rect = prect; } }
sa.Unlock();
InvalidateControl(); SetModifiedFlag(); }
其实只要将Texts属性的代码拷贝过来,稍微修改一下就可以了,这里的 GUID_Lib和GUID_Rect定义在LiteGridCtrl.cpp中,如下: const GUID GUID_Lib =
{ 0x191618F9, 0xEBF9, 0x4538, { 0x9E, 0x10, 0xD9, 0xC5, 0x62, 0x7E, 0xAE, 0xA9 } }; const GUID GUID_Rect =
{ 0x6BF5EE0C, 0x373A, 0x4893, { 0x89, 0xEB, 0x2C, 0x02, 0x08, 0xD3, 0xD4, 0xEB } };
3.在VB的Form_Load中添加如下代码 Private Sub Form_Load()
Dim str(0 To 9, 0 To 9) As String Dim stro() As String Dim i As Integer Dim j As Integer For i = 0 To 9 For j = 0 To 9
str(i, j) = i & \ Next Next
LiteGrid1.Texts = str stro = LiteGrid1.Texts Dim v() As Rect Dim x As Integer Dim y As Integer x = 0 y = 0
v = LiteGrid1.Rects
For i = LBound(v) To UBound(v) y = 0
For j = LBound(v, 2) To UBound(v, 2) v(i, j).Left = x v(i, j).Top = y
v(i, j).Right = x + 40 v(i, j).bottom = y + 16 y = y + 20 Next x = x + 50
Next
LiteGrid1.Rects = v End Sub
前面的一段是上一步中的内容,也给列了出来,运行一下会发现框框没有并在一起了,分开了些,证明Rect属性的Get和Set都是调用成功了。 所以,其实还是蛮简单的
本来是想要用SafeArrayAllocDescriptor和SafeArrayAllocData来模拟 SafeArrayCreateEx的,而且事实上好象也不会出错的,SAFEARRAY的各个成员的值两种方法得到的都一样,如下: SAFEARRAY* psa = NULL;
SafeArrayAllocDescriptor(2, &psa); psa->rgsabound[0].lLbound = 0; psa->rgsabound[0].cElements = 10; psa->rgsabound[1].lLbound = 0; psa->rgsabound[1].cElements = 10; psa->cbElements = sizeof(RECT); psa->fFeatures = FADF_RECORD;
HRESULT hresult = SafeArrayAllocData(psa); if(FAILED(hresult)){
SafeArrayDestroyDescriptor(psa); return vaResult; }
可是,意外的是竟然GetRects和SetRects全都没有正确执行 然后在后面加上
SafeArraySetRecordInfo(psa, pRecInfo);
就OK了。
所以看起来似乎这个 IRecordInfo是隐藏在SAFEARRAY结构中的,具体放哪里,就不去管它了,研究这个好象也没什么意义的,如果哪位朋友碰巧熟悉这个,烦情告知一下,感谢。 差点忘了,因为这里还是用COleSafeArray来解析的,所以没用到SafeArrayGetVartype,这个函数好象也是msdn 中没有的,可以用它来判断是否是你所需要的VARTYPE,应该是比较有用的。 VARTYPE vt;
SafeArrayGetVarType(psa, &vt);
这里psa为SAFEARRAY*。
这一步很需要一些COM基础,因为没有这个基础的话,可能会有为什么要做这个,有必要吗,之类的疑问的。这回我们要看看双接口,为MFC设计的控件添加双接口(双接口是什么就不解释了)。
这里参考了msdn中的例子acdual,并且应用了例子里面的一些宏,这个例子可以直接搜索 msdn找到,还有TN065: Dual-Interface Support for OLE Automation Servers参考。 老是用一个例子,也有些腻了,咱新来一例子,TDual控件 好,开始:
1.新建MFC控件工程,这里添加了一个属性 Hello(在控件上显示Hello属性对应的字符串),一个方法SayHello,弹出一消息框,显示方法参数中的字符串。
2.改造接口, 添加第二个接口
[ uuid(C3180013-EB23-4e8f-924C-38F5A201D3D8), helpstring(\ oleautomation, dual ]
interface ITDual : IDispatch {
[propput, id(1)] HRESULT Hello([in] BSTR newText); [propget, id(1)] HRESULT Hello([out, retval] BSTR* ret); [id(2)] HRESULT SayHello(BSTR strHello); }
双接口的接口描述中必须有oleautomation和dual属性,而且接口必须派生自 IDispatch。 这里的接口定义很象ATL中的IDL定义,如果用ATL设计过控件的话,应该不陌生的,具体的规则就不罗嗦了,如果不清楚的话,请自行查找资料了,大家可以和MFC中原来的接口定义对照一下: properties:
// NOTE - ClassWizard will maintain property information here. // Use extreme caution when editing this section. //{{AFX_ODL_PROP(CTDualCtrl) [id(1)] BSTR Hello; //}}AFX_ODL_PROP methods:
// NOTE - ClassWizard will maintain method information here. // Use extreme caution when editing this section. //{{AFX_ODL_METHOD(CTDualCtrl) [id(2)] void SayHello(BSTR strHello); //}}AFX_ODL_METHOD
定义好了新的接口后,需要在coclass描述中添加新接口的一个引用,如下: [ uuid(A1E75855-8561-4416-BE49-97B4D9A228E2), helpstring(\ coclass TDual {
// [default] dispinterface _DTDual;
// [default, source] dispinterface _DTDualEvents; [default] interface ITDual;
[default, source] dispinterface _DTDualEvents; dispinterface _DTDual; };
这里将缺省的接口设置为了ITDual而不是原来的dispinterface _DTDual。
3.改造好了接口后,就要实现这个新的接口了。MFC使用嵌套类来实现一个接口,得到嵌套类的方法是使用 BEGIN_INTERFACE_PART/END_INTERFACE_PART宏对,接着具体实现嵌套类的相应接口函数(包括IUnknown和 IDispatch的接口函数)就可以了。
这里用了acdul例子中定义的BEGIN_DUAL_INTERFACE_PART和 END_DUAL_INTERFACE_PART宏对和DELEGATE_DUAL_INTERFACE宏来简化实现IUnknown和 IDispatch中的接口函数。这些宏的定义将在最后列出。
在TDualCtl.h中,#include \添加新接口PART,如下: // Event maps
//{{AFX_EVENT(CTDualCtrl) //}}AFX_EVENT
DECLARE_EVENT_MAP()
//此处为添加部分 public:
///////////////////////////////////////////////////////////////////////////// // Double Interface Part
DECLARE_INTERFACE_MAP()
BEGIN_DUAL_INTERFACE_PART(TDual, ITDual)
STDMETHOD(put_Hello)(THIS_ BSTR newText); STDMETHOD(get_Hello)(THIS_ BSTR FAR* ret); STDMETHOD(SayHello)(THIS_ BSTR strHello); END_DUAL_INTERFACE_PART(TDual)
在TDualCtl.cpp中
///////////////////////////////////////////////////////////////////////////// // Control type information
static const DWORD BASED_CODE _dwTDualOleMisc = OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST | OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE | OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CTDualCtrl, IDS_TDUAL, _dwTDualOleMisc)
//添加AddRef,QueryInterface等通用函数的实现 DELEGATE_DUAL_INTERFACE(CTDualCtrl, TDual) ......
//这两个函数是原来Dispatch接口分发时要用到的Hello属性和SayHello方法函数 void CTDualCtrl::OnHelloChanged() {
// TODO: Add notification handler code InvalidateControl(); SetModifiedFlag(); }
void CTDualCtrl::SayHello(LPCTSTR strHello) {
// TODO: Add your dispatch handler code here AfxMessageBox(strHello);
相关推荐: