ATL工程,实现IShellExtInit,IShellPropSheetExt两个接口,定制自己的属性页,然后加入到资源管理器的右键文件属性页中,主要源代码如下,全部的工程代码打包传给援助者。
// SecuManage.h : Declaration of the CSecuManage
#ifndef __SECUMANAGE_H_
#define __SECUMANAGE_H_
#include "resource.h"       // main symbols
#include <comdef.h>
#include <shlobj.h>
// CSecuManage
class ATL_NO_VTABLE CSecuManage : 
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSecuManage, &CLSID_SecuManage>,
public IDispatchImpl<ISecuManage, &IID_ISecuManage, &LIBID_SECUMANAGERLib>,
public IShellExtInit,
public IShellPropSheetExt
{
public:
CSecuManage()
{
m_hListFileName=NULL;
m_hcbxAction=NULL;
memset(m_szFiles,0,MAX_SELECT_FILES*MAX_PATH);
}
DECLARE_REGISTRY_RESOURCEID(IDR_SECUMANAGE)
DECLARE_NOT_AGGREGATABLE(CSecuManage)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CSecuManage)
COM_INTERFACE_ENTRY(ISecuManage)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellExtInit)
COM_INTERFACE_ENTRY(IShellPropSheetExt)
END_COM_MAP()

protected:
// ISecuManage// ISecuManage
public:
    // IShellExtInit
    STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);    // IShellPropSheetExt
    STDMETHOD(AddPages)(LPFNADDPROPSHEETPAGE, LPARAM);
    STDMETHOD(ReplacePage)(UINT, LPFNADDPROPSHEETPAGE, LPARAM) { return E_NOTIMPL; }public:
BOOL OnInitDialog ( HWND hwnd);
BOOL OnApply ( HWND hwnd, PSHNOTIFY* phdr );
public:
private:
HWND m_hFileAttributDlg;
HWND m_hListFileName;
HWND m_hcbxAction;
int m_nSelectFiles;
char m_szFiles[MAX_SELECT_FILES][MAX_PATH];
};#endif //__SECUMANAGE_H_
// SecuManage.cpp : Implementation of CSecuManage
#include "stdafx.h"
#include "SecuManager.h"
#include "SecuManage.h"
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "comctl32.lib")
// CSecuManage
CSecuManage *g_pThis=NULL;BOOL CALLBACK PropPageDlgProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
// CSecuManage IShellExtInit methods
HRESULT CSecuManage::Initialize ( LPCITEMIDLIST pidlFolder,LPDATAOBJECT pDataObj,HKEY hProgID)
{
TCHAR     szFile [MAX_PATH];
UINT      uNumFiles;
HDROP     hdrop;
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg;
INITCOMMONCONTROLSEX iccex = { sizeof(INITCOMMONCONTROLSEX), ICC_DATE_CLASSES };
InitCommonControlsEx ( &iccex );

//g_pThis=this;//?????????????
    if ( FAILED( pDataObj->GetData ( &etc, &stg )))
        return E_INVALIDARG;

    hdrop = (HDROP) GlobalLock ( stg.hGlobal );
    if ( NULL == hdrop )
{
        ReleaseStgMedium ( &stg );
        return E_INVALIDARG;
}
    uNumFiles = DragQueryFile ( hdrop, 0xFFFFFFFF, NULL, 0 );
if(uNumFiles>MAX_SELECT_FILES)
{
MessageBox(NULL,"所选文件超过允许范围!","错误",MB_OK|MB_ICONERROR);
return E_FAIL;
}
m_nSelectFiles=uNumFiles;
    for ( UINT uFile = 0; uFile < uNumFiles; uFile++ )
{
        // Get the next filename.
        if ( 0 == DragQueryFile ( hdrop, uFile, szFile, MAX_PATH ))
            continue;
        if ( PathIsDirectory ( szFile ))
            continue;
memset(m_szFiles[uFile],0,MAX_PATH);
strcpy(m_szFiles[uFile],szFile);//将在资源管理器中选中的文件保存到类的m_szFiles数组中。

    GlobalUnlock ( stg.hGlobal );
    ReleaseStgMedium ( &stg );
    return (m_nSelectFiles> 0 ) ? S_OK : E_FAIL;
}
// CSecuManage IShellPropSheetExt methods
HRESULT CSecuManage::AddPages ( LPFNADDPROPSHEETPAGE lpfnAddPageProc,
   LPARAM lParam )
{
PROPSHEETPAGE  psp;
HPROPSHEETPAGE hPage;
// Set up the PROPSHEETPAGE struct.
ZeroMemory ( &psp, sizeof(PROPSHEETPAGE) );
psp.dwSize      = sizeof(PROPSHEETPAGE);
psp.dwFlags     = PSP_USEREFPARENT | PSP_USETITLE | PSP_DEFAULT | PSP_USEICONID;// | PSP_USECALLBACK;
psp.hInstance   = _Module.GetModuleInstance();
psp.pszTemplate = MAKEINTRESOURCE(IDD_FILE_PROPPAGE);
psp.pszIcon     = MAKEINTRESOURCE(IDI_ICON_BOOKS);
psp.pszTitle    = _T("安全管理");
psp.pfnDlgProc  = PropPageDlgProc;
psp.lParam      = (LPARAM)this;//(LPARAM)((char*)this+8);赋值问题?????????,传递当前对象指针
psp.pfnCallback = NULL;//PropPageCallbackProc;
psp.pcRefParent = (UINT*) &_Module.m_nLockCnt;

// Create the page & get a handle.
hPage = CreatePropertySheetPage ( &psp );
if ( NULL != hPage )
{
// Call the shell's callback function, so it adds the page to the property sheet.
if ( !lpfnAddPageProc(hPage, lParam))
{
DestroyPropertySheetPage ( hPage );
}
}
    return 1;
}BOOL CALLBACK PropPageDlgProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
BOOL bRet = FALSE;
switch ( uMsg )
{
case WM_INITDIALOG:
g_pThis=(CSecuManage *)lParam;//不是AddPages(..)传来的this指针值?????????????
bRet = g_pThis->OnInitDialog (hwnd);
        break;
case WM_NOTIFY:
{
            NMHDR* phdr = (NMHDR*) lParam;
            switch ( phdr->code )
{
case PSN_APPLY:
bRet = g_pThis->OnApply ( hwnd, (PSHNOTIFY*) phdr );
//MessageBox(NULL,"In OnApply ( HWND hwnd, PSHNOTIFY* phdr)","tips",MB_OK|MB_ICONINFORMATION);
                break;
case DTN_DATETIMECHANGE:
// If the user changes any of the DTP controls, enable the Apply button.
SendMessage ( GetParent(hwnd), PSM_CHANGED, (WPARAM) hwnd, 0 );
                break;
}
}
        break;
}

    return bRet;
}
BOOL CSecuManage::OnInitDialog(HWND hwnd)//, LPARAM lParam )// 

m_hListFileName=::GetDlgItem(hwnd,IDC_LIST_FILE_NAME);//获取文件列表框句柄
    for ( int i=0;i<3;i++)
{
        char szFile[MAX_PATH]={0};
strcpy(szFile,m_szFiles[i]);//文件名已不存在?????????
        PathStripPath((char *)szFile);
::SendMessage(m_hListFileName,LB_ADDSTRING,0,(LPARAM)szFile);
}
m_hcbxAction=::GetDlgItem(hwnd,IDC_COMBO_ACTION);
SendMessage(m_hcbxAction,CB_ADDSTRING,0,(LPARAM)"aaaaaaaaa");
SendMessage(m_hcbxAction,CB_ADDSTRING,0,(LPARAM)"bbbbbbbbb");
    return FALSE;  
}BOOL CSecuManage::OnApply ( HWND hwnd, PSHNOTIFY* phdr)
{
int nIndex=-1;
nIndex=SendMessage(m_hcbxAction,CB_GETCURSEL,0,0);
if(CB_ERR==nIndex)
return FALSE;
char szItemText[MAX_PATH]={0};
int nChars=SendMessage(m_hcbxAction,CB_GETLBTEXT,CB_GETCURSEL,(LPARAM)szItemText);
MessageBox(NULL,szItemText,"选中的项是",MB_OK|MB_ICONINFORMATION);
    return TRUE;
}
问题一:
CSecuManage::AddPages(..)函数中,psp.lParam= (LPARAM)this赋值有问题。赋值前this的值如果为0x02754728,赋值后psp.lParam的值却为0x02754720,总比this指针的值小8,什么原因?
问题二:
我定义一个全局的CSecuManage *g_pThis=NULL;
在处理WM_INITDIALOG消息时
  case WM_INITDIALOG:
g_pThis=(CSecuManage *)lParam;
bRet = g_pThis->OnInitDialog (hwnd);
break;
在函数中CSecuManage::OnInitDialog(..)访问不到CSecuManage::Initialize(..)存入m_szFiles数组中的文件名
问题三:
我想将BOOL CALLBACK PropPageDlgProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )消息处理函数封装在CSecuManage类里,但编译提示出错,需改为静态函数才可编译通过,但改为静态函数又不能在此函数中访问CSecuManage的类成员(方法与属性),请问如何解决?
问题四:假设能够通过全局g_pThis访问到CSecuManage的类成员(方法与属性),但当用户多次弹出多个属性页时,这种利用全局变量的机制肯定行不通,如何解决呢?