⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shell.html.primary

📁 Windows API Tutorials, Windows API编程最好的手册.文档格式专门制作成为各个章节相互关联的html格式,大家可以像查阅msdn一样方便使用.各个章节的内容如下: Wi
💻 PRIMARY
📖 第 1 页 / 共 2 页
字号:
<html>
<head>
<title>Windows95 Shell Programming</title>
<meta  name="description" content="Using Win95 Shell in your program">
<meta name="keywords" content="reliable, software, cplusplus, source code, example, tutorial, object oriented, programming">
</head>

<body background="../images/grid.gif" bgcolor="white" text="black">

<!--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">
	<h1 align=center>Using Windows95 Shell and COM</h1>
	<p align=center>A. K. A. OLE
	</font>
</table>
<p>

<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%"> <!-- central table -->
   <tr>
   <td bgcolor="#ffffff">

<hr><!--Text-->
<font size="+1"><b>COM programming is so difficult</b></font> that you shouldn't even try it without MFC. Right or wrong? <font color=red>Absolutely wrong!</font>. Granted, OLE and its successor COM have the elegance of a figure-skating hippopotamus. But putting MFC on top of COM is like dressing the hippo in an oversized clown suit.

<table cellpadding="5">
<tr>
<td width=40><a href="source/treesize.zip"><img src="images/brace.gif" width=16 height=16 border=0 alt="Download"></a>
<td bgcolor="#e0e080">Download the source of a sample application, <a href="source/treesize.zip">TreeSizer</a> (zipped 12K) (courtesy Laszlo Radanyi), that calculates the total size of all files in a given directory and all its subdirectories. It uses the Win95 shell browser to browse directories.
<td width=40>
</table>

<p>So what is a programmer to do when faced with the necessity to use some of the Windows 95 (and Windows NT 4.0) shell features that are only accessible through COM interfaces? Read on...
<p>To begin with, whenever you are planning to use COM, you have to tell the system to initialize the COM subsystem. Similarly, whenever you're done using COM, you should tell the system to uninitialize it. The simplest thing to do, is to define an object whose constructor initializes COM and whose destructor deinitializes it. The best place to place it is to embed it in the Controller object (see the <a href="generic.html">Generic</a> Windows program), like this.
<hr>
	<!--Yellow background table.-->
         	<table cellpadding=10 cellspacing=0 width="100%">
         		<tr>
		<td width=20>
            		<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->class <font color="#cc0066"><b>Controller</b></font>
{
public:
    Controller (HWND hwnd, CREATESTRUCT * pCreate);
    ~Controller ();
    // ...
private:
    <b>UseCom    _comUser;</b> // I'm a COM user
	 
    Model       _model;
    View        _view;
    HINSTANCE   _hInst;
};

</font></pre><!--End Code-->
		<td width=20>
	</table><!--End of yellow background-->
<hr>
This way we are guaranteed that the COM subsystem will be initialized before any calls are made to it and that it will be deinitialized after the program has done its tear-down (i.e., after the View and the Model have been destroyed). 
<p>The UseCom class is very simple.
<hr>
	<!--Yellow background table.-->
         	<table cellpadding=10 cellspacing=0 width="100%">
         		<tr>
		            <td width=20>
            		<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->class <font color="#cc0066"><b>UseCom</b></font>
{
public:
    UseCom ()
    {
        <font color="#009966">HRESULT</font> err = <font color="#000099"><b>CoInitialize</b></font> (0);
        if (err != <font color="#009966">S_OK</font>)
            throw "Couldn't initialize COM";
    }
    ~UseCom ()
    {
        <font color="#000099"><b>CoUninitialize</b></font> ();
    }
};
</font></pre><!--End Code-->
		<td width=20>
	</table><!--End of yellow background-->
<hr>
So far it hasn't been too difficult, has it? That's because we haven't touched the bane of COM programming--reference counting. You see, every time you obtain an interface, its reference count is incremented, every time you're done with it, you are supposed to <i>explicitly</i> decrement it. Oh, and it gets even weirder when you start querying, cloning, passing interfaces around, etc. But wait a moment, we know how to manage such problems! It's called <a href="../resource/index.htm">Resource Management</a>. We should never touch COM interfaces without encapsulating them in smart interface pointers. Here's how it works.
<hr>
	<!--Yellow background table.-->
         	<table cellpadding=10 cellspacing=0 width="100%">
         		<tr>
		            <td width=20>
            		<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->
template &lt;class T&gt;class <font color="#cc0066"><b>SIfacePtr</b></font>
{
public:
    ~SIfacePtr ()
    {
        Free ();
    }
    T * operator-&gt;() { return _p; }
    T const * operator-&gt;() const { return _p; }
    operator T const * () const { return _p; }
    T const &amp; GetAccess () const { return *_p; }

protected:
    SIfacePtr () : _p (0) {}
    void Free ()
    {
        if (_p != 0)
            _p-&gt;<font color="#000099"><b>Release</b></font> ();
        _p = 0;
    }

    T * _p;
private:
    SIfacePtr (SIfacePtr const &amp; p) {}
    void operator = (SIfacePtr const &amp; p) {}
};
</font></pre><!--End Code-->
		<td width=20>
	</table><!--End of yellow background-->

<hr>
Don't worry that this class looks unusable (because it has a protected constructor). We'll never use it directly--we'll <i>inherit</i> from it. By the way, this is a great trick: create a class with a protected <i>do-nothing</i> constructor and keep deriving from it. All the derived classes will have to provide their own specialized public constructors. As you might have guessed, various classes derived from SIfacePtr will differ in the way they obtain, in their constructors, the interface in question.
<p>Private dummy copy constructor and operator= are not strictly necessary, but they will save you hours of debugging if, by mistake, you'll pass a smart interface by value rather than by reference. That's a big no-no. You'll end up releasing the same interface twice and that'll screw the COM's reference counting. Believe me, I've been there. As it is, the compiler will refuse to pass by value an object that has a private copy constructor (dummy or not). It will also issue an error when you try to assign an object that has a private assignment operator. 

<p>To wrap this short introduction up, let me present one more variation on the theme of smart pointers. Shell API's often allocate memory using their own special allocator. That wouldn't be so bad, if it weren't for the fact that they expect you to release this memory using the same allocator. So, whenever the shell hands us such an embarassing package, we'll wrap it up in a special smart pointer.
<hr>
	<!--Yellow background table.-->
   <table cellpadding=10 cellspacing=0 width="100%">
      <tr>
		<td width=20>
            		<td bgcolor="#e0e080">
<pre><font face="courier"><!--Code-->template &lt;class T&gt;
class <font color="#cc0066"><b>SShellPtr</b></font>
{
public:
    ~SShellPtr ()
    {
        Free ();
        _malloc-&gt;<font color="#000099"><b>Release</b></font> ();
    }
    T * weak operator-&gt;() { return _p; }
    T const * operator-&gt;() const { return _p; }
    operator T const * () const { return _p; }
    T const &amp; GetAccess () const { return *_p; }

protected:
    SShellPtr () : _p (0) 
    {
        // Obtain malloc here, rather than
        // in the destructor. 
        // Destructor must be fail-proof.
        // Revisit: Would static IMalloc * _shellMalloc work?
        if (<font color="#000099"><b>SHGetMalloc</b></font> (&amp; _malloc) == <font color="#009966">E_FAIL</font>)
            throw Exception "Couldn't obtain Shell Malloc"; 
    }
    void Free ()
    {
        if (_p != 0)
            _malloc-&gt;<font color="#000099"><b>Free</b></font> (_p);
        _p = 0;
    }

    T * _p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -