这段代码是msdn例子,我也看过,但我还是不明白,同样是调用COM,
为什么不用你在
http://www.csdn.net/expert/topic/624/624448.xml?temp=4.009426E-03发那种方法呢
为什么不用你在
http://www.csdn.net/expert/topic/624/624448.xml?temp=4.009426E-03发那种方法呢
解决方案 »
- 界面花屏了,怎么办?
- 帮我看看程序哪里出错了!!谢谢。。
- 创建空的Win32 Application,新增一个main.c文件,写上main(long nPipe),出错
- 求《visual c++ 程序开发范例宝典》电子书与源码,谢谢
- 都说windows网络技术这本书好,一看到是...京京的...顿时吓了一跳
- 请问一个关于对话框的简单问题
- 关于END_MESSAGE_MAP的嵌套定义问题
- 关于END_COM_MAP,子类里为什么还能存在纯虚函数,感觉没看懂
- 关于DirectShow中ISampleGrabber抓图实现拍照功能
- MFC中Slider控件垂直放置时使它的大端在上小端在下?
- 请问如何得到其他程序中窗口的字体(如:button,edit……)?
- 如何改变group box的背景色?
Have you noticed that VB developers can create almost any COM object and call its methods at run-time, and VC++ developers have to use compile-time generated wrapper classes? Anyone understands COM will say that we can do the same thing in C++, but we don't want to bother with writing so much low-level com code to accomplish this. My goal is to derive a utility class from COleDispatchDriver so that we can write code like the following in VC++ without generating any wrapper class at compile-time: // declare a utility object
MyUtilityClass utility;
// create a com object with prog id "MyComObj1"
utility.CreateObject("MyComObj1");
// call the method "GetData" (no argument) in the com object
CString strData = utility.CallMethod("GetData");
// create another com object with prog id "MyComObj2"
utility.CreateObject("MyComOb2");
// call the method "GetMsgCount" with one argument
long nUserID = 3;
long nCount = utitilty.CallMethod("GetMsgCount", nUserID);
As you can see later, I came pretty close to achieving this goal. If someone flames me for damaging a developer's brain with VB-style code, then my job is done :-). Please note that this is not meant to replace other existing methods of creating and using a com object. I would like to thank Chris Losinger and Aaron Schaefer for answering my "anonymous" programming questions. XYDispDriver
XYDispDriver is the name of my utility class. The source code project will build a library XYDispDriver.dll which exports the XYDispDriver class. As usual, you may use and modify the source code anyway you wish, I would appreciate some acknowledgment for my contribution (if possible). Here is the header file of my class. #include <afxdisp.h>class XYDispDriver: public COleDispatchDriver
{
// an internal array to store type information
CPtrArray m_arrayDispInfo;
// an internal function to get index to stored type information
int FindDispInfo(const CString strName, const WORD wFlag = DISPATCH_METHOD);
// clear internal storage
void Clear();
// these 3 functions are here to hide functions with the same names in the base class
BOOL CreateDispatch(REFCLSID clsid, COleException* pError = NULL) { return FALSE; }
void AttachDispatch(LPDISPATCH lpDispatch, BOOL bAutoRelease = TRUE ) {}
LPDISPATCH DetachDispatch( ) { return NULL; }
public:
XYDispDriver();
~XYDispDriver();
// create a com object with given prog id, this function
// hide the function with the same name in the base class
BOOL CreateDispatch(LPCTSTR lpszProgID);
// get the type of a property
VARTYPE GetPropertyType(const CString strPropertyName);
// get the property value
void* GetProperty(const CString strPropertyName);
// set the property value
void SetProperty(const CString strPropertyName, ...);
// get return type of a method
VARTYPE GetReturnType(const CString strMethodName);
// get number of parameters in a method
int GetParamCount(const CString strMethodName);
// get the type of a parameter in a method
VARTYPE GetParamType(const CString strMethodName, const int nParamIndex);
// invoke a method
void* InvokeMethod(const CString strMethodName, ...);
};
To use the XYDispDriver class, you first need to declare an instance of this class and call the CreateDispatch member function passing the prog id of a com object. This method not only creates an IDispatch pointer, it also retrieves and stores all the necessary type information using the ITypeInfo interface. Then you can call other member functions to either invoke a method in the com object or get/set a property value. Please note that GetProperty and InvokeMethod both return a void pointer. To access the return data, you need to cast the pointer to the appropriate data type and then dereference it. Also, the return data will be over-ridden by the next call to the same method. I know this is cumbersome and un-OO like, but who said the world is perfect? :-) Please also note that methods of XYDispDriver may throw exceptions of type COleException, an MFC class. Sample code
Here is a sample program that creates an XYMailClient object described in my other article and sends/receives e-mail messages. The code can be written and executed without using any type library at compile-time. /*************** Test.cpp ***********************/#include "XYDispDriver.h"void main()
{
XYDispDriver disp;
try
{
if(disp.CreateDispatch("XYMailClient.1"))
{
if(*(BOOL*)disp.InvokeMethod("InitSession","MyProfile","")==FALSE)
{
printf("Failed to call InitSession\n");
return;
}
if(!*(BOOL*)disp.InvokeMethod("SendMsg","[email protected]",
"","","Hello","This is a test",""))
{
printf("Failed to call SendMsg\n");
}
long nCount = *(long*)disp.InvokeMethod("FetchMsg");
printf("Total messages = %d\n",nCount);
for(int i=0;i<nCount;i++)
{
printf("Message %d: %s\n",i,*(CString*)disp.InvokeMethod("GetMsg",i));
}
disp.InvokeMethod("DeleteMsg",0);
disp.InvokeMethod("EndSession");
}
else
{
printf("Failed to create com obj\n");
}
}
catch(COleException* e)
{
printf("Ole exception\n");
TCHAR buf[251];
e->GetErrorMessage(buf,250);
printf("%s\n",buf);
e->Delete();
}
printf("Done\n");
}
/**************** End of Test.cpp ****************/
Using XYDispDriver in your own program
XYDispDriver is implemented with VC++ 5.0 and MFC.
To use XYDispDriver, you need only to add the source files to your project or use it as a dll. You should always use the CString class for string data, although you can pass literal strings as input parameters. I have not done extensive testing with various data types except for strings and numbers. Please let me know if you found or fixed a bug.