📄 auto.html.primary
字号:
<font color="#cc0066"><b>~DispObject</b></font> ()
{
if (_iDisp)
_iDisp->Release ();
}
operator bool () const { return _iDisp != 0; }
bool operator ! () const { return _iDisp == 0; }
DISPID <font color="#cc0066"><b>GetDispId</b></font> (WCHAR * funName)
{
DISPID dispid;
HRESULT hr = _iDisp->GetIDsOfNames (
IID_NULL,
&funName,
1,
GetUserDefaultLCID (),
&dispid);
return dispid;
}
void <font color="#cc0066"><b>GetProperty</b></font> (DISPID propId, VARIANT & result)
{
// In parameters
DISPPARAMS args = { 0, 0, 0, 0 };
EXCEPINFO except;
UINT argErr;
HRESULT hr = _iDisp->Invoke (propId,
IID_NULL,
GetUserDefaultLCID (),
DISPATCH_PROPERTYGET,
&args,
&result,
&except,
&argErr);
if (FAILED (hr))
throw HEx (hr, "Couldn't get property");
}
void * <font color="#cc0066"><b>AcquireInterface</b></font> (IID const & iid)
{
void * p = 0;
HRESULT hr = _iDisp->QueryInterface (iid, &p);
if (FAILED (hr))
{
if (hr == E_NOINTERFACE)
throw "No such interface";
else
throw HEx (hr, "Couldn't query interface");
}
return p;
}
protected:
DispObject (IDispatch * iDisp) : _iDisp (iDisp) {}
DispObject () : _iDisp (0) {}
protected:
IDispatch * _iDisp;
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
Below is a small illustration of dynamic dispatching. Of course, the same result could have been obtained directly by calling the method <i>get_Name</i> of the <i>IGenericDocument</i> interface. We'll use this direct (vtable) method in a moment to obtain the full path of the document.
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
// Use docObj as a dispatch interface
<font color="#009966">DISPID</font> pid = docObj.<b>GetDispId</b> (L"Name");
<font color="#009966">VARIANT</font> varResult ;
::<font color="#000099"><b>VariantInit</b></font>(& varResult) ;
docObj.<b>GetProperty</b> (pid, varResult);
BString bName (varResult);
CString cName (bName);
canvas.Text (20, y, "Name:");
canvas.Text (200, y, cName);
</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
And this is how you obtain the path, the vtable way.
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
<font color="#cc0066"><b>SObjFace</b></font><IGenericDocument, &IID_IGenericDocument> doc (docObj);
<font color="#cc0066"><b>BString</b></font> bPath;
doc->get_FullName (bPath.GetPointer ());
</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
Now you shouldn't have any problems understanding the code that retrieves the line number of the line where the user positioned the cursor.
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
BString bType;
doc->get_Type (bType.GetPointer ());
if (type.IsEqual ("Text"))
{
<font color="#cc0066"><b>SObjFace</b></font><ITextDocument, &IID_ITextDocument> text (docObj);
<font color="#cc0066"><b>SSelection</b></font> selObj (text);
<font color="#cc0066"><b>SObjFace</b></font><ITextSelection, &IID_ITextSelection> sel (selObj);
long line;
sel->get_CurrentLine (&line);
canvas.Text (20, y, "CurrentLine:");
char buf [10];
wsprintf (buf, "%ld", line);
canvas.Text (200, y, buf);
}
</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
<i>SSelection</i> is a <i>DispObject</i> that can be obtained by calling a method <i>get_Selection</i> of the text document interface.
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->class <font color="#cc0066"><b>SSelection</b></font>: public <font color="#cc0066"><b>DispObject</b></font>
{
public:
<font color="#cc0066"><b>SSelection</b></font> (SObjFace<ITextDocument, &IID_ITextDocument> & doc)
{
HRESULT hr = doc->get_Selection (& _iDisp);
if (FAILED (hr))
throw HEx (hr, "get_Selection failed");
}
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
You might be a little confused if this is your first contact with OLE (an understatement!). So here is a summary of what the various actions are that have to be done in order to accomplish a simple Automation task. Notice, this is the client side of the equation. If you want your application to be an Automation server, things are a bit more complicated. Fortunately, there is more literature about it.
<p>So here's what you have to do.
<ul>
<li>The research.
<ul>
<li>Search your registry (using RegEdt32 or OLE/COM object viewer) to find the ProgID of the application you want to get hold of. HKEY_CLASSES_ROOT is the starting point. You'll see there such keys as Word.Application, Excel.Application and many others.
<li>Find the Type Libraries using OLE/COM object viewer. They will have the class ids and interface ids that you have to copy and paste into your code.
<li>Find the header files for these interfaces.
</ul>
<li>In your program: Convert ProgID to class id.
<li>To connect to a running app or to activate a new one, create SObject using the ClassID.
<li>Obtain the <i>IApplication</i> interface from the object (use the <i>IObjFace</i> template).
<li>Use this interface to get hold of other objects internal to the application. For each such object:
<ul>
<li>Declare a class derived from DispObject
<li>In its constructor use the appropriate get_* method to get access to the internal object.
<li>Create an object of this class, passing it the interface of the parent object.
<li>Obtain the appropriate interface from this object by instantiating the template <i>IObjFace</i>.
<li>Call appropriate methods of this interface.
</ul>
</ul>
So what was this big deal with reference counting in OLE? Beats me! It must have disappeared, once we started using the correct encapsulation. Below is a diagram of class dependencies. OLE objects on the left, OLE interfaces on the right.
<center>
<img src="images/oleclass.gif" width=454 height=200 border=0 alt="Objects and Interfaces">
</center>
At runtime, you start with the SObject that represents the program you're connecting to and then keep going from object to interface and from interface to DispObject. You use objects as sources of interfaces and interfaces for calling specific methods and obtaining other objects.
<p>Finally, you can <a href="source/auto.zip">download</a> the source code that illustrates the application of these techniques.
<hr><!--End Text-->
<!-- end main box -->
</table>
<td width=10><!-- Right margin -->
</table> <!-- End main table -->
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -