gpt4 book ai didi

c++ - 更改资源管理器数据提供者的类别

转载 作者:行者123 更新时间:2023-11-28 01:01:07 34 4
gpt4 key购买 nike

如何基于this example更改或设置Shell扩展的类别?



在屏幕截图中,扩展名位于类别More或德语Weitere中。

最佳答案

所有Shell扩展处理程序都是进程内组件对象模型(COM)对象。必须为它们分配一个GUID并按照注册Shell扩展处理程序中所述进行注册。它们被实现为DLL,并且必须导出以下标准函数:
DllMain。 DLL的标准入口点。
DllGetClassObject。公开对象的类工厂。
DllCanUnloadNow。 COM调用此函数以确定对象是否正在为任何客户端提供服务。如果不是,则系统可以卸载DLL并释放关联的内存。
与所有COM对象一样,Shell扩展处理程序必须实现IUnknown接口和类工厂。大多数还必须在Windows XP或更早版本中实现IPersistFile或IShellExtInit接口。在Windows Vista中,这些被IInitializeWithStream,IInitializeWithItem和IInitializeWithFile取代。命令行管理程序使用这些接口来初始化处理程序。
IPersistFile接口必须通过以下方式实现:


图标处理程序
资料处理常式
放置处理程序


IShellExtInit接口必须通过以下方式实现:


快捷菜单处理程序
拖放处理程序
属性表处理程序


实施IPersistFile
IPersistFile接口旨在允许从磁盘文件加载对象或将其保存到磁盘文件。除了IUnknown之外,它还有六个方法,五个方法以及从IPersist继承的GetClassID方法。对于Shell扩展,IPersist仅用于初始化Shell扩展处理程序对象。因为通常不需要读取或写入磁盘,所以只有GetClassID和Load方法需要非令牌实现。
Shell首先调用GetClassID,然后该函数返回扩展处理程序对象的类标识符(CLSID)。然后,Shell调用Load并传入两个值。第一个是pszFile,是一个Unicode字符串,其中包含Shell将要对其进行操作的文件或文件夹的名称。第二个是dwMode,它表示文件访问模式。因为通常不需要访问文件,所以dwMode通常为零。该方法根据需要存储这些值,以供以后参考。
以下代码片段说明了典型的Shell扩展处理程序如何实现GetClassID和Load方法。它旨在处理ANSI或Unicode。 CLSID_SampleExtHandler是扩展处理程序对象的GUID,而CSampleShellExtension是用于实现接口的类的名称。 m_szFileName和m_dwMode变量是专用变量,用于存储文件的名称和访问标志。

class CSampleShellExtension : public IPersistFile
{
// Method declarations not included

private:
WCHAR m_szFileName[MAX_PATH]; // The file name
DWORD m_dwMode; // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
*pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
m_dwMode = dwMode;
return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile);
}


//下一节继续执行示例。

实现IShellExtInit
除了IUnknown外,IShellExtInit接口只有一种方法IShellExtInit :: Initialize。该方法具有三个参数,Shell可以使用这些参数来传递各种类型的信息。传入的值取决于处理程序的类型,有些可以设置为NULL。
pidlFolder保存文件夹的指向项目标识符列表(PIDL)的指针。这是绝对的PIDL。对于属性表扩展名,此值为NULL。对于快捷菜单扩展名,是文件夹的PIDL包含显示其快捷菜单的项目。对于非默认的拖放处理程序,它是目标文件夹的PIDL。
pDataObject包含一个指向数据对象的IDataObject接口的指针。数据对象以CF_HDROP格式保存一个或多个文件名。
hRegKey持有文件对象或文件夹类型的注册表项。
IShellExtInit :: Initialize方法可根据需要存储文件名,IDataObject指针和注册表项,以备后用。以下代码片段说明了IShellExtInit :: Initialize的实现。为简单起见,本示例假定数据对象仅包含一个文件。通常,数据对象可能包含多个文件,每个文件都需要提取。

 // This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit {
// Method declarations not included

private:
// IDList of the folder for extensions invoked on the folder, such as
// background context menu handlers or nondefault drag-and-drop handlers.
PIDLIST_ABSOLUTE m_pidlFolder;

// The data object contains an expression of the items that the handler is
// being initialized for. Use SHCreateShellItemArrayFromDataObject to
// convert this object to an array of items. Use SHGetItemFromObject if you
// are only interested in a single Shell item. If you need a file system
// path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
IDataObject *m_pdtobj;

// For context menu handlers, the registry key provides access to verb
// instance data that might be stored there. This is a rare feature to use
// so most extensions do not need this variable.
HKEY m_hRegKey; }
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.
IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTEpidlFolder,__in_opt IDataObject *pDataObject, __in_opt HKEY hRegKey)
{
// In some cases,handlers are initialized multiple times. Therefore,
// clear any previous state here.
CoTaskMemFree(m_pidlFolder);
m_pidlFolder = NULL;

if (m_pdtobj)
{
m_pdtobj->Release();
}

if (m_hRegKey)
{
RegCloseKey(m_hRegKey);
m_hRegKey = NULL;
}

// Capture the inputs for use later.
HRESULT hr = S_OK;

if (pidlFolder)
{
m_pidlFolder = ILClone(pidlFolder); // Make a copy to use later.
hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
}

if (SUCCEEDED(hr))
{
// If a data object pointer was passed into the method, save it and
// extract the file name.
if (pDataObject)
{
m_pdtobj = pDataObject;
m_pdtobj->AddRef();
}

// It is uncommon to use the registry handle, but if you need it,
// duplicate it now.
if (hRegKey)
{
LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey);
hr = HRESULT_FROM_WIN32(result);
}
}

return hr; }


每当您创建或更改Shell扩展处理程序时,重要的是通知系统您已进行了更改。通过调用SHChangeNotify并指定SHCNE_ASSOCCHANGED事件来执行此操作。如果您不调用SHChangeNotify,则更改可能要到重新引导系统才能被识别。
还有一些其他因素适用于Windows 2000系统。有关详细信息,请参见“在Windows 2000系统上注册Shell扩展处理程序”部分。
与所有组件对象模型(COM)对象一样,您必须使用Windows软件开发工具包(SDK)附带的Guidgen.exe之类的工具为处理程序创建GUID。在HKEY_CLASSES_ROOT \ CLSID下创建一个子项,其名称是该GUID的字符串形式。由于Shell扩展处理程序是进程内服务器,因此您还必须在该GUID子项下创建一个InprocServer32子项,并将(默认)值设置为处理程序DLL的路径。使用单元线程模型。这里显示一个示例:

 HKEY_CLASSES_ROOT    CLSID
{00021500-0000-0000-C000-000000000046}
InprocServer32
(Default) = %windir%\System32\Example.dll
ThreadingModel = Apartment


每当Shell采取可能涉及Shell扩展处理程序的操作时,它都会检查适当的注册表子项。注册扩展处理程序的子项将控制何时调用扩展程序。例如,一种常见的做法是在命令行管理程序显示文件类型成员的快捷菜单时,调用快捷菜单处理程序。在这种情况下,必须在文件类型的ProgID子项下注册处理程序。

关于c++ - 更改资源管理器数据提供者的类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8636053/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com