only for RuBoard - do not distribute or recompile |
Now that you know how a property sheet handler works, let's discuss the interfaces involved in a little more detail.
The implementation of IShellExtInit is exactly the same as it was in Chapter 4. (For the details of the IShellExtInit interface, see Section 4.4 in Chapter 4.) Well, almost. The functionality provided by IShellExtInit which is used to determine which files are selected in the Exploreris generic enough to be wrapped in a class. All future extensions that must implement IShellExtInit in this book will use this class. The class is called clsDropFiles, and the complete class listing is shown in Example 6.1.
Option Explicit Private m_nFiles As Long Private m_sDropFiles( ) As String Public Sub GetDropFiles(pDataObj As IDataObject, _ ByVal sExtension As String) Dim FmtEtc As FORMATETC Dim pMedium As STGMEDIUM Dim i As Long Dim lresult As Long Dim sTemp As String Dim lIndex As Long With FmtEtc .cfFormat = CF_HDROP .ptd = 0 .dwAspect = DVASPECT_CONTENT .lIndex = -1 .TYMED = TYMED_HGLOBAL End With pDataObj.GetData FmtEtc, pMedium m_nFiles = DragQueryFile(pMedium.pData, &HFFFFFFFF, _ vbNullString, 0) lIndex = 0 For i = 0 To m_nFiles - 1 sTemp = Space(255) lresult = DragQueryFile(pMedium.pData, i, sTemp, Len(sTemp)) If (lresult > 0) Then sTemp = Left$(sTemp, lresult) If LCase(Right(sTemp, 4)) = sExtension Then ReDim Preserve m_sDropFiles(lIndex + 1) m_sDropFiles(lIndex) = sTemp lIndex = lIndex + 1 End If End If Next i m_nFiles = lIndex ReleaseStgMedium pMedium End Sub Public Property Get Count( ) As Integer Count = m_nFiles End Property Public Property Get Files(nIndex As Integer) As String Files = "" If (m_nFiles) Then If (nIndex >= 0) And (nIndex < m_nFiles) Then Files = m_sDropFiles(nIndex) End If End If End Property Public Property Get SelectedFile( ) As String SelectedFile = "" If (m_nFiles) Then SelectedFile = m_sDropFiles(0) End If End Property
Now that we have a class that handles the extraction of filenames from IDataObject , implementing IShellExtInit becomes a little easier. The complete listing for IShellExtInit::Initialize is shown in Example 6.2.
Private m_clsDropFiles As clsDropFiles Private Sub IShellExtInit_Initialize( _ ByVal pidlFolder As VBShellLib.LPCITEMIDLIST, _ ByVal pDataObj As VBShellLib.IDataObject, _ ByVal hKeyProgID As VBShellLib.HKEY) Set m_clsDropFiles = New clsDropFiles m_clsDropFiles.GetDropFiles pDataObj, ".rad" End Sub
All IShellExtInit::Initialize needs to do is declare an instance of clsDropFiles and call the member function, GetDropFiles . GetDropFiles takes as parameters an IDataObject reference and a file filter and creates an internal array holding all of the filenames contained within the data object that have the extension .rad .
IShellPropSheetExt contains two methods , AddPages and ReplacePage , for adding and replacing property sheets (see Table 6.1). There is really nothing unusual about this interface; we don't have to do anything crazy like vtable swapping! The implementation of this interface, on the other hand, is a wild ride, to say the least. But we'll talk about that later. For now, let's familiarize ourselves with the interface and the methods it contains.
Method | Description |
---|---|
AddPages | Adds a page(s) to a property sheet for a file object. |
ReplacePage | Replaces a page in a property sheet for a Control Panel applet. Not used for shell property sheet extensions. |
AddPages is the method responsible for adding a property sheet to an existing property page dialog. When a property sheet is about to be displayed, the shell calls AddPages for each handler registered to the selected file type. Its syntax is as follows :
HRESULT STDMETHODCALLTYPE AddPages( LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam );
The parameters are as follows:
[in] The address of a function that the property sheet extension must call to display a property page.
[in] Parameter to pass to the function specified by lpfnAddPage .
ReplacePage is used to replace property sheet pages for a Control Panel object. It is not used for property sheet handlers. Its syntax is as follows:
HRESULT STDMETHODCALLTYPE ReplacePage(UINT uPageID , LPFNADDPROPSHEETPAGE lpfnReplacePage , LPARAM lParam );
The parameters to ReplacePage are the same as AddPages , with the exception of one parameter:
This is the identifier of the page to replace. Since ReplacePage is used exclusively with Control Panel applets, the valid values for this parameter can be found in the Cplext.h header file in the Platform SDK.
The IDL listing for IShellPropSheetExt is shown in Example 6.3.
typedef struct { long x; long y; } POINT; typedef struct MSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; typedef struct { HWND hwndFrom; UINT idFrom; UINT code; } NMHDR; typedef enum { PSPCB_RELEASE = 1, PSPCB_CREATE = 2 } PROPSHEETCALLBACKMSG; typedef enum { PSP_DEFAULT = 0x00000000, PSP_DLGINDIRECT = 0x00000001, PSP_USEHICON = 0x00000002, PSP_USEICONID = 0x00000004, PSP_USETITLE = 0x00000008, PSP_RTLREADING = 0x00000010, PSP_HASHELP = 0x00000020, PSP_USEREFPARENT = 0x00000040, PSP_USECALLBACK = 0x00000080, PSP_PREMATURE = 0x00000400, PSP_HIDEHEADER = 0x00000800, PSP_USEHEADERTITLE = 0x00001000, PSP_USEHEADERSUBTITLE = 0x00002000 } PROPERTYSHEETFLAG; typedef enum { PSN_SETACTIVE = -200, PSN_KILLACTIVE = -201, PSN_APPLY = -202, PSN_RESET = -203, PSN_QUERYCANCEL = -209 } PROPSHEETNOTIFYMSG; typedef struct { DWORD dwSize; DWORD dwFlags; HINSTANCE hInstance; LPCSTRVB pszTemplate; HICON hIcon; LPCSTRVB pszTitle; DLGPROC pfnDlgProc; LPARAM lParam; LPFNPSPCALLBACK pfnCallback; long pcRefParent; LPCTSTRVB pszHeaderTitle; LPCTSTRVB pszHeaderSubTitle; } PROPSHEETPAGE; [ uuid(000214e9-0000-0000-c000-000000000046), helpstring("IShellPropSheetExt Interface"), odl ] interface IShellPropSheetExt : IUnknown { HRESULT AddPages([in] LPFNADDPROPSHEETPAGE lpfnAddPage, [in] LPARAM lParam); HRESULT ReplacePage([in] UINT uPageID, [in] LPFNADDPROPSHEETPAGE lpfnReplaceWith, [in] LPARAM lParam); }
only for RuBoard - do not distribute or recompile |