?? ole.html
字號(hào):
<html>
<head>
<title> OLE </title>
<meta name="description" content="OLE in C++">
<meta name="keywords" content="ole, interfaces, reliable, software, cplusplus, source code, example, windows, tutorial, object oriented, programming">
</head>
<body background="../images/grid.gif" bgcolor="white" text="black">
<script language="JAVASCRIPT">
<!--
if (navigator.onLine){
document.write("<!-- Spidersoft WebZIP Ad Banner Insert -->");
document.write("<TABLE width=100% border=0 cellpadding=0 cellspacing=0>");
document.write("<TR>");
document.write("<TD>");
document.write("<ILAYER id=ad1 visibility=hidden height=60></ILAYER>");
document.write("<NOLAYER>");
document.write("<IFRAME SRC='http://www.spidersoft.com/ads/bwz468_60.htm' width=100% height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no></IFRAME>");
document.write("</NOLAYER>");
document.write("</TD>");
document.write("</TR>");
document.write("</TABLE>");
document.write("<!-- End of Spidersoft WebZIP Ad Banner Insert-->");
}
//-->
</script>
<!--Home button and Title-->
<table cellpadding=10 width="100%">
<tr>
<td width=100 align=center valign=middle>
<a href="../index.htm">
<img src="../images/rsbullet.gif" alt="RS" border=0 width=39 height=39>
<br>Home</a>
<td>
<font face="arial" color="#009966">
<center><i>
<b><font size="+3">Rationalizing OLE</font></b>
<p align=center><font size="+1">Building <b>smart</b> OLE on top of, you know, the <b>other</b> OLE.</font>
</i></center>
</font>
</table>
<table width="100%"><!-- main table -->
<tr>
<td width=10> <!-- Left margin -->
<td> <!-- Middle column, there is also the right margin at the end -->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td bgcolor=white>
<hr><!--Text-->
<font size="+1"><b>First of all, you have to tell the world</b></font> that you're going to use OLE. Here's a little class that will do it for you. Just embed an object of this class in some high-level object that's constructed before you do anything with OLE and destroyed after you're done with OLE. In a Windows program, the Controller is a perfect host for <i>UseOle</i>.
<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>UseOle</b></font>
{
public:
UseOle () { OleInitialize (0); }
~UseOle () { OleUninitialize (); }
};
class <font color="#cc0066"><b>Controller</b></font>
{
public:
Controller(HWND hwnd, CREATESTRUCT * pCreate);
~Controller() { PostQuitMessage(0); }
void Paint (HWND hwnd);
private:
<b>UseOle</b> useOle;
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
Next, you need to create an <i><b>OLE object</b></i> that is the provider of interfaces. The abstract base class <i>CoObject</i> declares the method <i>AcquireInterface</i>. The actual class <i>SObject</i> (smart object) provides one particular implementation of <i>CoObject</i> that uses, internally, OLE's infamous <i>IUnknown</i>.
<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>CoObject</b></font>
{
public:
virtual void * AcquireInterface (IID const & iid) = 0;
};
class <font color="#cc0066"><b>SObject</b></font>: public <font color="#cc0066"><b>CoObject</b></font>
{
public:
SObject (CLSID const & classId, bool running = false);
~SObject ()
{
if (_iUnk)
_iUnk-><font color="#000099"><b>Release</b></font> ();
}
void * AcquireInterface (IID const & iid);
private:
<font color="#009966">IUnknown</font> * _iUnk;
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
Let's have a look at the implementation of the constructor and the <i>AcquireInterface</i> method.
<p>The constructor gets hold of the object by calling the API <i>GetActiveObject</i> and/or <i>CoCreateInstance</i>. The difference between the two is that <i>GetActiveObject</i> will try to get hold of an <b>already running</b> object, whereas <i>CoCreateInstance</i> will try the same, but if it fails, it'll start whatever <i>exe</i> is necessary for this object to run. Some objects actually specify a preference: they want a new server to be started every time <i>CoCreateInstance</i> is called. <i>GetActiveObject</i> lets you bypass that.
<p>Notice that this is just one example how you get hold of an OLE object. You may want to play with some of the parameters--for instance, I am passing <i>CLSCTX_SERVER</i> as an argument to <i>CoCreateInstance</i>. That will make sure that the object will live in a separate process from the client. In many cases you'd rather have the object as an inproc server--a DLL that is loaded into the client's address space. For more details, look up <i>CoCreateInstance</i> in your friendly <i>help</i>.
<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>SObject::SObject</b></font> (<font color="#009966">CLSID</font> const & classId, bool running)
:_iUnk (0)
{
<font color="#009966">HRESULT</font> hr = <font color="#009966">S_OK</font>;
if (running)
{
::<font color="#000099"><b>GetActiveObject</b></font> (classId, 0, & _iUnk);
}
if (_iUnk == 0)
{
hr = ::<font color="#000099"><b>CoCreateInstance</b></font> (
classId,
0,
<font color="#009966">CLSCTX_SERVER</font>,
<font color="#009966">IID_IUnknown</font>,
(void**)& _iUnk);
}
if (FAILED (hr))
throw HEx (hr, "Couldn't create instance");
}</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
I will explain the strange exception type, <i>HEx</i>, in a moment.
<p>Here's our implementation of <i>AcquireInterface</i> that simply calls the <i>QueryInterface</i> method of <i>IUnknown</i> (or, should I say, the <i>unfortunate</i> <i>QueryInterface</i> of the <i>unfortunate</i> <i>IUnknown</i>).
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
void * <font color="#cc0066"><b>SObject::AcquireInterface</b></font> (IID const & iid)
{
void * p = 0;
HRESULT hr = _iUnk-><font color="#000099"><b>QueryInterface</b></font> (iid, & p);
if (FAILED (hr))
{
if (hr == <font color="#009966">E_NOINTERFACE</font>)
throw "No such interface";
else
throw HEx (hr, "Couldn't acquire interface");
}
return p;
}
</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
The method <i>AcquireInterface</i> is one of these exceptional <b><i>Acquire</i></b> methods of <a href="../resource/index.htm">Resource Management</a> that release raw resources. We wan't call it other than inside of the constructor of a smart interface pointer. (By the way, the template parameter is an IID <i>pointer</i> because the compiler won't accept references as template arguments. I'm not sure why.)
<p>So here it is, the template for a smart interface pointer.
<hr><!--End Text-->
<!--Yellow background-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
template<class I, IID const * iid>class <font color="#cc0066"><b>SFace</b></font>
{
public:
~SFace ()
{
if (_i)
_i-><font color="#000099"><b>Release</b></font> ();
}
I * operator-> () { return _i; }
protected:
SFace () : _i (0) {}
SFace (void * i)
{
_i = static_cast<I*> (i);
}
protected:
I * _i;
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
As you can see, this particular template can't be instantiated. That's because all its constructors are protected. But don't worry, we'll create other classes that will provide their own specialized constructors.
<p>Here's one that uses our CoObject (or any other object derived from it) as an interface source.
<hr><!--End Text-->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td width=20>
<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
template<class I, IID const * iid>class <font color="#cc0066"><b>SObjFace</b></font>: public <font color="#cc0066"><b>SFace</b></font><I, iid>
{
public:
SObjFace (CoObject & obj)
: SFace<I, iid> (obj.AcquireInterface (*iid))
{}
};</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
Finally, let me introduce the <i>HEx</i> class (<i>HRESULT</i> Exception). It is an exception class that is capable of displaying meaningful error messages. For my limited purposes, I chose to simply display the messages directly on the canvas of the main screen. Feel free to implement your own <i>Display</i> method to pop up a message box or something.
<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>HEx</b></font>
{
public:
HEx (<font color="#009966">HRESULT</font> hr, char const * str = 0)
: _hr (hr), _str (str)
{}
void Display (int x, int y, Canvas & canvas)
{
if (_str != 0)
{
canvas.Text (x, y, _str);
y += 20;
}
if (<font color="#009966">FAILED</font> (_hr))
{
char * msg;
::<font color="#000099"><b>FormatMessage</b></font> (
<font color="#009966">FORMAT_MESSAGE_ALLOCATE_BUFFER</font> | <font color="#009966">FORMAT_MESSAGE_FROM_SYSTEM</font>,
0,
_hr,
<font color="#000099"><b>MAKELANGID</b></font> (<font color="#009966">LANG_NEUTRAL</font>, <font color="#009966">SUBLANG_DEFAULT</font>),
reinterpret_cast<char *> (& msg),
0,
0);
canvas.Text (x, y, msg);
::<font color="#000099"><b>LocalFree</b></font> (msg);
}
}
private:
<font color="#009966">HRESULT</font> _hr;
char const * _str;
};
</font></pre><!--End Code-->
<td width=20>
</table>
<!--End of yellow background-->
<hr><!--Text-->
There <i>will</i> be sample code for downloading. I just need to explain what <a href="auto.html">Automation</a> is.
<hr><!--End Text-->
<!-- end main box -->
</table>
<td width=10><!-- Right margin -->
</table> <!-- End main table -->
<layer src="http://www.spidersoft.com/ads/bwz468_60.htm" visibility=hidden id=a1 width=600 onload="moveToAbsolute(ad1.pageX,ad1.pageY); a1.clip.height=60;visibility='show';"></layer>
</body>
</html>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -