📄 atlshellext.h
字号:
ATLTRACENOTIMPL(_T("IShellPropSheetExt::ReplacePage"));
}
// IShellExtInit
STDMETHOD(Initialize)(LPCITEMIDLIST /*pidlFolder*/, IDataObject *lpDataObject, HKEY /*hkeyProgID*/)
{
ATLASSERT(lpDataObject);
STGMEDIUM medium;
FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if( SUCCEEDED(lpDataObject->GetData(&fe, &medium)) ) {
// Get the file name from the CF_HDROP.
UINT uCount = ::DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0);
if(uCount>0) ::DragQueryFile((HDROP)medium.hGlobal, 0, m_szFileName, sizeof(m_szFileName)/sizeof(TCHAR));
::ReleaseStgMedium(&medium);
}
return S_OK;
}
// Callbacks
static UINT CALLBACK PropSheetPageProc(HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
switch( uMsg ) {
case PSPCB_CREATE:
return 1; // Allow dialog creation
case PSPCB_RELEASE:
T *pT = (T *)ppsp->lParam;
ATLASSERT(pT);
pT->Release();
break;
}
return 0;
}
void SetModified(BOOL bChanged=TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent()!=NULL);
::SendMessage(GetParent(), bChanged ? PSM_CHANGED : PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
}
static int CALLBACK PageDlgProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
T *pT = (T *)::GetWindowLong(hWnd, GWL_USERDATA);
LRESULT lRes = 0;
if( uMessage==WM_INITDIALOG ) {
pT = (T *)((LPPROPSHEETPAGE)lParam)->lParam;
::SetWindowLong(hWnd, GWL_USERDATA, (LONG)pT);
// Set the window handle
pT->m_hWnd = hWnd;
lRes = 1;
}
if( pT==NULL ) {
// The first message is WM_SETFONT, not WM_INITDIALOG...
return FALSE;
}
MSG msg = { pT->m_hWnd, uMessage, wParam, lParam, 0, { 0, 0 } };
const MSG *pOldMsg = pT->m_pCurrentMsg;
pT->m_pCurrentMsg = &msg;
// pass to the message map to process
BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMessage, wParam, lParam, lRes, 0);
// restore saved value for the current message
ATLASSERT(pT->m_pCurrentMsg == &msg);
pT->m_pCurrentMsg = pOldMsg;
// set result if message was handled
if(bRet) {
switch (uMessage) {
case WM_COMPAREITEM:
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
case WM_INITDIALOG:
case WM_QUERYDRAGICON:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
return lRes;
}
::SetWindowLong(pT->m_hWnd, DWL_MSGRESULT, lRes);
return TRUE;
}
if( uMessage==WM_NCDESTROY ) {
// clear out window handle
pT->m_hWnd = NULL;
}
return FALSE;
}
};
//////////////////////////////////////////////////////////////////////////////
// CExtractFileIcon
template< class T >
class ATL_NO_VTABLE CExtractFileIcon :
public CComObjectRootEx<CComSingleThreadModel>,
public IExtractIcon
{
public:
BEGIN_COM_MAP(CExtractFileIcon)
COM_INTERFACE_ENTRY_IID(IID_IExtractIcon,IExtractIcon)
END_COM_MAP()
public:
CPidl m_pidl;
public:
void Init(LPCITEMIDLIST pidl)
{
m_pidl.Copy(pidl);
}
// IExtractIcon
STDMETHOD(GetIconLocation)(UINT uFlags,
LPTSTR /*szIconFile*/,
UINT /*cchMax*/,
LPINT piIndex,
LPUINT puFlags)
{
ATLASSERT(piIndex);
ATLASSERT(puFlags);
if( m_pidl.IsEmpty() ) return E_FAIL;
LPCITEMIDLIST pidlLast = CPidl::PidlGetLastItem(m_pidl);
T* pData = (T*) pidlLast;
if( pData!=NULL ) {
switch( pData->type ) {
case 0:
*piIndex = 0;
*puFlags = GIL_NOTFILENAME;
break;
case 1:
*piIndex = 1;
*puFlags = GIL_NOTFILENAME;
break;
default:
*piIndex = 0;
*puFlags = GIL_SIMULATEDOC;
break;
}
}
return S_OK;
}
STDMETHOD(Extract)(LPCTSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize)
{
ATLASSERT(phiconLarge);
ATLASSERT(phiconSmall);
if( m_pidl.IsEmpty() ) return E_FAIL;
LPCITEMIDLIST pidlLast = CPidl::PidlGetLastItem(m_pidl);
T *pData = (T *)pidlLast;
if( pData!=NULL ) {
switch( pData->type ) {
case 0:
{
*phiconLarge = ImageList_GetIcon(_Module.m_ImageLists.m_hImageListLarge, 0, ILD_TRANSPARENT);
*phiconSmall = ImageList_GetIcon(_Module.m_ImageLists.m_hImageListSmall, 0, ILD_TRANSPARENT);
}
break;
case 1:
{
*phiconLarge = ImageList_GetIcon(_Module.m_ImageLists.m_hImageListLarge, 1, ILD_TRANSPARENT);
*phiconSmall = ImageList_GetIcon(_Module.m_ImageLists.m_hImageListSmall, 1, ILD_TRANSPARENT);
}
break;
case 2:
{
TCHAR szPath[MAX_PATH];
TCHAR szExt[MAX_PATH];
::lstrcpy( szPath, pData->ffd.cFileName );
LPTSTR psz = _tcsrchr(szPath, _T('.'));
szExt[0] = _T('\0');
if( psz!=NULL ) ::lstrcpy(szExt, psz);
SHFILEINFO sfi = { 0 };
HIMAGELIST hImageListLarge = (HIMAGELIST) ::SHGetFileInfo(szExt,
FILE_ATTRIBUTE_NORMAL,
&sfi, sizeof(sfi),
SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SYSICONINDEX);
if (hImageListLarge) *phiconLarge = ImageList_GetIcon(hImageListLarge, sfi.iIcon, ILD_TRANSPARENT);
HIMAGELIST hImageListSmall = (HIMAGELIST) ::SHGetFileInfo(szExt,
FILE_ATTRIBUTE_NORMAL,
&sfi, sizeof(sfi),
SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX);
if (hImageListSmall) *phiconSmall = ImageList_GetIcon(hImageListSmall, sfi.iIcon, ILD_TRANSPARENT);
}
break;
}
}
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// CContextMenuImpl
template <class T>
struct _ATL_CTXMENU_ENTRY
{
UINT id;
UINT desc;
void (__stdcall T::*pfn)(); // method to invoke
};
#define BEGIN_CONTEXTMENU_MAP(theClass) \
static const _ATL_CTXMENU_ENTRY<theClass>* _GetCtxMap()\
{\
typedef theClass _atl_event_classtype;\
static const _ATL_CTXMENU_ENTRY<_atl_event_classtype> _ctxmap[] = {
#define CONTEXTMENU_HANDLER(id, desc, func) \
{id, desc, (void (__stdcall _atl_event_classtype::*)())func},\
#define END_CONTEXTMENU_MAP() {0,0,NULL}}; return _ctxmap;}
template <class T>
class ATL_NO_VTABLE CShellContextMenu :
public IContextMenu,
public IShellExtInit
{
public:
CRegKey m_regClass;
CSimpleArray<CComBSTR> m_arrFiles;
// IShellExtInit
public:
STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder,
IDataObject *lpDataObj,
HKEY hkeyProgID)
{
ATLTRACE(_T("CShellContextMenu::Initialize\n"));
// Get file class
m_regClass.Open(hkeyProgID,NULL);
// Get files
if( lpDataObj ) {
CComPtr<IDataObject> spDataObj(lpDataObj);
STGMEDIUM medium;
FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
if( SUCCEEDED(spDataObj->GetData(&fe, &medium)) ) {
// Get the filenames from the CF_HDROP.
UINT uCount = ::DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0);
for( UINT i=0; i<uCount; i++ ) {
TCHAR szFileName[MAX_PATH];
::DragQueryFile((HDROP)medium.hGlobal, i, szFileName, sizeof(szFileName)/sizeof(TCHAR));
m_arrFiles.Add(CComBSTR(szFileName));
}
::ReleaseStgMedium(&medium);
}
}
return S_OK;
}
// IContextMenu
public:
STDMETHOD(QueryContextMenu)(HMENU hMenu,
UINT iIndexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
ATLTRACE(_T("CShellContextMenu::QueryContextMenu\n"));
const _ATL_CTXMENU_ENTRY<T>* pMap = T::_GetCtxMap();
UINT i=0;
while( pMap->pfn!=NULL ) {
if( pMap->id==0 ) {
::InsertMenu(hMenu, iIndexMenu++, MF_SEPARATOR | MF_STRING | MF_BYPOSITION, 0, _T(""));
}
else {
TCHAR szText[128];
::LoadString(_Module.GetResourceInstance(), pMap->id, szText, sizeof(szText)/sizeof(TCHAR));
::InsertMenu(hMenu, iIndexMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + i, szText);
}
i++;
pMap++;
}
T *pT = static_cast<T*>(this);
pT->UpdateMenu(hMenu, idCmdFirst);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, i + 1);
}
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpcmi)
{
ATLTRACE(_T("CShellContextMenu::InvokeCommand\n"));
if( HIWORD(lpcmi->lpVerb) ) return NOERROR; // The command is being sent via a verb
UINT idxCmd = LOWORD(lpcmi->lpVerb);
const _ATL_CTXMENU_ENTRY<T>* pMap = T::_GetCtxMap();
UINT i=0;
while( pMap->pfn!=NULL ) {
if( i==idxCmd ) {
T *pT = static_cast<T*>(this);
CComStdCallThunk<T> thunk;
thunk.Init(pMap->pfn, pT);
VARIANT vRes;
::VariantInit(&vRes);
return DispCallFunc(
&thunk,
0,
CC_STDCALL,
VT_EMPTY, // this is how DispCallFunc() represents void
0,
NULL,
NULL,
&vRes);
}
pMap++;
i++;
}
return E_INVALIDARG;
}
STDMETHOD(GetCommandString)(UINT idCmd, UINT uFlags, LPUINT, LPSTR pszName, UINT cchMax)
{
ATLTRACE(_T("CContextMenu::GetCommandString\n"));
switch( uFlags ) {
case GCS_HELPTEXTA:
case GCS_HELPTEXTW:
{
const _ATL_CTXMENU_ENTRY<T>* pMap = T::_GetCtxMap();
UINT i=0;
while( pMap->pfn!=NULL ) {
if( i==idCmd ) {
if( uFlags==GCS_HELPTEXTA ) {
::LoadStringA(_Module.GetResourceInstance(), pMap->desc, pszName, cchMax);
}
else {
// BUG: LoadStringW() is not supported on Win95
::LoadStringW(_Module.GetResourceInstance(), pMap->desc, (LPWSTR)pszName, cchMax);
}
return S_OK;
}
pMap++;
i++;
}
}
return E_FAIL;
case GCS_VERBA:
case GCS_VERBW:
return E_FAIL;
case GCS_VALIDATE:
return NOERROR;
default:
return E_NOTIMPL;
}
}
void UpdateMenu(HMENU hMenu, UINT iCmdFirst) { };
};
#endif // __ATLCOM_H__
//////////////////////////////////////////////////////////////////////////////
// ::SHGetPathFromIDList() wrapper
class CShellPidlPath
{
public:
CShellPidlPath(LPCITEMIDLIST pidl)
{
ATLASSERT(pidl);
if( ::SHGetPathFromIDList(pidl, m_szPath)==FALSE ) m_szPath[0]=_T('\0');
}
operator LPCTSTR() const { return m_szPath; };
TCHAR m_szPath[MAX_PATH];
};
//////////////////////////////////////////////////////////////////////////////
// Shell Helper Functions
inline LPITEMIDLIST ShellGetFileNamePidl(LPOLESTR pstrFileName)
{
LPSHELLFOLDER pDesktopFolder;
if( FAILED(::SHGetDesktopFolder(&pDesktopFolder)) ) return NULL;
LPITEMIDLIST pidl;
ULONG dwEaten;
ULONG dwAttribs;
if( FAILED( pDesktopFolder->ParseDisplayName(NULL, NULL, pstrFileName, &dwEaten, &pidl, &dwAttribs) ) ) {
pidl = NULL;
}
pDesktopFolder->Release();
return pidl;
}
#endif // __ATLSHELLEXT_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -