Shell Extension Writing Complete Fool Guide (3) (Michael Dunn)

zhaozj2021-02-11  156

Download Demo Project - 11 kB In the first part and the second part of the guide, I demonstrate how to write a context menu extension. In the third part, I will be a new type of extension and explain how to share the memory of the outer casing and demonstrate how to use MFC outside ATL.

The third part assumes that you already know the basic knowledge of the outer casing expansion (explained in the first part), and you are familiar with MFC. It should be noted that the extension of this requires expansion of 4.71 or higher, so you must run Windows 98 or 2000, or install an active desktop in 95 / NT4 (Active Desktop).

Query Information Extensions (The QueryInfo Extension)

Active Desktop introduces a new feature. If your mouse hover over a specific object, the toolbar prompts the description of the object. For example, hovering on "My Computer", there will be the following tooltips:

Other objects such as "online neighbors" and "control panel" have similar tips. We can also provide our own tool tips to other objects through query information extensions.

The description of QueryInfo Extension is: This is my name; I am called him because he uses such an excuse: iQueryInfo. Now I can say that it still has no official name. I quickly viewed MSDN in October 1999, and didn't even mention this extension. It is clear that it is a supported extension because Microsoft's Office also has QueryInfo extension for its file type, as shown below:

Winzip version 8 also has a QueryInfo extension installed for compressed files:

The best document I have found is Dino Esposito's article on MSDN magazine in March 2000 "Enhance Your's Experience With New Infotip and Icon Overlay Shell Extensions (using new information prompts and icons to enhance you The user experience) ".

QueryInfo extension begins? What can it do?

This housing extension will be a quick text file viewer - it will display the contents of the file size and the first line of the file. When the user hovers the mouse on a TXT file, our information will be displayed on Tooltip.

Start with AppWizard

Run AppWizard and make a new ATL COM Wizard App. We call it txtinfo. Because we should use the MFC this time, please select the Support MFC check box, then click Finish. We now have an empty ATL project that will generate a DLL, but we have to add your own housing to extend COM objects. In the ClassView tree, right-click TxtInfo Classes item, select New ATL Object.

In the ATL Object Wizard, the first panel has chosen Simple Object, as long as you click Next. In the second panel, enter TXTINFOSHLEXT in the SHORT NAME editing control, and then click OK (other edit box in the panel will be complete). This creates a class named ctxtinfoshlext, which contains basic code that implements a COM object. We will add our code to this class.

If you look at the ClassView tree, you will find that we have a CTXTINFOAPP class derived from cwinapp. The emergence of this class and global variable THEAPP makes us use MFC possible, just as we write a normal MFC DLL without ATL.

Interface implementation

Previously, in our context menu extensions, we implemented Explorer to implement our object's ISHELLEXTINIT interface. For the outer shell extension, there is another implementation interface, IPersistFile This is an interface used by QueryInfo extension. Why is it different? If you still remember, iShellextinit :: initialize () receives an iDataObject pointer, and we can enumerate the selected files through this pointer. You can only operate a single file through the IPersistFile extension. Because the mouse cannot hover on the two objects at the same time, QueryInfo extension is only working on one file, so it uses iPersistFile. So we need to add iPersistFile to CTXTINFOSHLEXT implementation interface list. Open txtinfoshlext.h, then add the following red line:

#include

#include

Class ATL_NO_VTABLE CTXTINFOSHLEXT:

Public CComobjectrootex ,

Public ccomcoclass ,

Public IDispatchImpl ,

Public IPERSISTFILE

{

Begin_com_map (ctxtinfoshlext)

COM_ITERFACE_ENTRY (ITXTINFOSHLEXT)

COM_ITERFACE_ENTRY (Idispatch)

Com_interface_entry (IPERSISTFILE)

END_COM_MAP ()

We also need a variable to store the file name of Explorer in our implementation process:

protected:

// itxtinfoshlext

CString m_sfilename;

Note that we can now use an MFC object anywhere.

If you look at the IPERSISTFILE document, you will find a lot of methods. Fortunately, the extension of this article, we only need to implement LOAD () and ignore other. The following is the prototype of the method of IPersistFile.

PUBLIC:

// ipersistfile

Stdmethod (LPCLSID) {Return E_NOTIMPL;}

STDMETHOD (ISDIRTY) () {Return E_NOTIMPL;}

STDMETHOD (LOAD) (LPCOLESTR, DWORD);

STDMETHOD (SAVE) (LPCOLESTR, BOOL) {Return E_NOTIMPL;}

STDMETHOD (LPCOLESTED) {Return E_NOTIMPL;}

Stdmethod (LPOLESTR *) {Return E_NOTIMPL;}

In addition to the way to load () only returns E_NOTIMPL, it means that we don't realize him.

What's more beautiful is that our LOAD () method is very simple. We only need to store the name of the file passing to our files in Explorer. This is the file that hovers hover.

HRESULT CTXTINFOSHLEXT :: Load (LPColestr WSZFileName, DWORD DWMODE)

{

AFX_Manage_State (AFXGETSTATICModuleState ()); // init mfc // Let cstring convert the filename to ANSI if Necessary.

m_sfilename = wszfilename;

Return S_OK;

}

Pay attention to the first line of the function. To make MFC work normally, this line is required. Because our DLL is loaded by non-MFC programs, each of the export functions that use MFC must be manually initialized. If this line is not included, many MFC functions (mostly related to resources) will be interrupted or generated.

The file name is saved in m_sfilename for use. Note that I use the CString assignment operator to convert the string to ANSI, if this DLL is established as ANSI.

Create tooltip text

After the Explorer calls our LOAD () method, it calls QueryInterface () to get another interface: iQueryInfo. IQueryInfo is a fairly simple interface, only two methods (in fact we just use one). Open txtinfoshlext.h again, add the following red color:

Class ATL_NO_VTABLE CTXTINFOSHLEXT:

Public CComobjectrootex ,

Public ccomcoclass ,

Public IDispatchImpl ,

Public ipersistfile,

Public iQueryInfo

{

Begin_com_map (ctxtinfoshlext)

COM_ITERFACE_ENTRY (ITXTINFOSHLEXT)

COM_ITERFACE_ENTRY (Idispatch)

Com_interface_entry (IPERSISTFILE)

COM_ITERFACE_ENTRY (iQueryInfo)

END_COM_MAP ()

Then add iQueryInfo method:

// iQueryInfo

STDMETHOD (DWORD *) {Return E_NOTIMPL;}

STDMETHOD (GetInfotip) (DWORD, LPWSTR *);

GetInfoflags () method is currently not applied, we only return E_NOTIMPL. GetInfotip () is the implementation we return to Explorer and make it displayed on the toolbar prompt. The first is the annoying module:

HRESULT CTXTINFOSHLEXT :: GetInfotip

DWORD DWFLAGS,

LPWSTR * PPWSZTIP)

{

AFX_MANAGE_STATE (AFXGETSTATICModuleState ()); // init mfc

LPMalloc PMalloc;

CSTDIOFILE FILE;

DWORD DWFILESIZE;

Cstring sfirstline;

Bool breadline;

CString Stooltip;

Uses_Conversion;

Again, in order to initialize the MFC, AFX_Manage_State is first called. This must be done in the start of the function, even before the variable definition, because many constructors are called the MFC function.

DWFLAGS is currently not applying. PPWSZTIP is a pointer to a LPWSTR (Unicode string pointer), we set it to the cache we must allocate. The first step, we will try to open the file. We know its file name because we have already stored it in the load () function.

IF (! file.open (m_sfilename, cfile :: moderad | cfile :: sharedenywrite))

Return E_FAIL;

Now, because we need to use the shell memory distributor to assign a cache, we need an IMALLOC interface pointer. This pointer is obtained by calling Shgetmalloc ():

IF (Failed (Shgetmalloc (& PMalloc)))

Return E_FAIL;

Will it be, I have more things about IMALLOC. The next step is to get the size of the file and read the first line of the file:

// Get the size of the file.

DWFILESIZE = file.getLength ();

// read in the first line from the file.

BreadLine = file.readstring (sfirstline);

Breadline is usually TRUE unless this file is not accessible or only 0 bytes long. The next step is to create the first part of the tooltip (Tooltip), list the size of the file:

Stooltip.Format (_T ("File Size:% Lu"), DWFILESize;

Now, if we can read the first line of the file, add it to the tooltip (Tooltip).

IF (BREADLINE)

{

STOOLTIP = _t ("/ n");

Stooltip = sfirstline;

}

Now, we have completed the tooltip. We need to assign a cache. Here we use Imalloc. The pointer returned by SHGETMALLOC () is a copy of the housing IMALLOC interface. Any memory allocated with that interface exists in the process space of the housing, so the housing can be used. More important, the outer casing can also release it. So what we have to do is allocate the cache, and then forget it. The shell will release it after using it.

Another thing you want is that we return to the housing must be unicode. That's why we multiply by sizeof (wchar_t) during the following alloc () call; only the memory of the LSTRLEN (Stooltip) is only half of the memory.

* PPWSZTIP = (LPWSTR) PMalloc-> Alloc ((1 lstrlen (stooltip)) * sizeof (wchar_t));

IF (NULL == * PPWSZTIP)

{

PMalloc-> Release ();

Return E_OUTOFMEMORY;

}

// Use the uncode string copy function to put the tooltip text in the buffer.

WCSCPY (* PPWSZTIP, T2COLE ((LPCTSTSTR) STOOLTIP);

The last thing to do is to release the Imalloc interface we have earlier.

PMalloc-> Release ();

Return S_OK;

}

This is all we have to do. Explorer gets the string in * ppwsztip and display it in Tooltip.

Registered housing extension

QueryInfo extension registration and context menu extensions are slightly different. Our extension is registered under the hkey_classes_root's sub-key, and its name is the file extension we want to handle. In this article, it is HKCR / .txt. But wait, it seems to be a bit strange! You may think that SHELLEX's sub-keys should look like "TooltipHandlers". But no! This button is called "{00021500-0000-0000-c000-000000000046}". Here, I think Microsoft may try to cross our housing extension. If you look at the registry, you will find that the name of the other Shellex child is also GUID. The above GUID is just iQueryInfo's GUID.

Anyway, this is our extension. TXT file call must be scripted:

HKCR

{

Noremove .txt

{

Noremove Shellex

{

Noremove {00021500-0000-0000-c000-000000000046} = s '{F4D78AE1-05AB-11D4-8D3B-444553540000}'

}

}

}

You can call the extension of the extension of the extension by copying the code above, and then changing the extension of any extension you want. Unfortunately, you can't register to meet the purpose of file calls used in * or allfilesystemObjects.

As we mentioned in front of the extension, under NT / 2000, we need to add our extension to "Approved" extension list. Implement this process code in the DllRegisterServer () and DllunregisterServer () functions.

to be continued...

In the fourth part, we will go back to the context menu to see a new extension, drag and dragging the DRAG AND DROP. We will also see more MFC usage.

You can get the latest version of this and other articles from the following URL: http://home.inreach.com/mdunn/code/

转载请注明原文地址:https://www.9cbs.com/read-5956.html

New Post(0)