1

1. 如何获取控制面板列表,包括它们的名称和图标,以便创建类似于“开始”菜单显示的菜单?

控制面板从“开始”菜单弹出

2.当我点击一个条目时,如何执行对应的控制面板?

顺便问一下,这种PopupMenu是用什么控件来做的?但它有右键单击事件。

更新 :

我使用 PItemIDList 来获取一个文件夹:

var:
PIDL, TempPIDL: PItemIDList;
Path: array[0..MAX_PATH] of Char;
FI: SHFILEINFOW;
begin
SHGetSpecialFolderLocation(0, CSIDL_FAVORITES, PIDL);
SHGetPathFromIDList(PIDL , Path);
Memo1.Lines.Add(Path);
SHGetFileInfo(LPCTSTR(PIDL), 0, FI, SizeOf(FI), SHGFI_PIDL or SHGFI_DISPLAYNAME or SHGFI_ICON);
Memo1.Lines.Add(FI.szDisplayName);
Image1.Picture.Icon.Handle := FI.hIcon;

它显示正常,但是当我将 CSIDL_FAVORITE 更改为 CSIDL_CONTROLS 时,我总是会出错。这是获取控制面板项目的错误方法吗?我也使用另一种方法从这里
使用 CPL 副本 但它无法显示完整的项目。

4

4 回答 4

3

您可以检查所有已注册小程序的注册表。
这描述了如何注册它们: http: //msdn.microsoft.com/en-us/library/windows/desktop/bb757044.aspx
同样,您可以扫描注册表以检查已注册的小程序及其运行方法。

然而,在 64 位 Windows 上会有 32 位应用程序无法加载的 64 位小程序,因此提取图标可能会很痛苦。我不知道您是否可以LoadLibraryEx通过 64 位 DLL 调用 AsResourceLibrary 标志来仅提取图标。


另一种方法是使用 Windows 资源管理器命名空间。获取一些Shell提供开放虚拟路径的组件套件,例如My ComputerandMy Documents而不是c:\等。控制面板有一个特殊的 GUID(我不记得了。但Microsoft TweakUI工具可以使用该 GUID 在任何文件夹中创建控制面板)。您可能可以使用一些 Shell UI 将Control Panel特殊的虚拟文件夹打开到 kind 中ListView,然后获取然后枚举项目并提取对应的图片并将它们重新排列为菜单。然后执行可能会通过双击该 shell 列表视图中的项目来完成。

于 2012-10-24T11:18:26.617 回答
2

控制面板小程序是位于系统文件夹中的 CPL 文件

例如:C:\Windows\system32

我的建议是列出这些文件,然后提取图标并获取它们的文件名

如果您对代码有问题,请在此处发布,以便我们提供帮助

CPL 文件只是 DLL 文件,它们可以包含多个小程序

谷歌搜索后,我找到了这个教程:

http://delphi.about.com/od/kbwinshell/l/aa062403a.htm

于 2012-10-24T09:28:31.997 回答
2

在您的帮助下,我解决了问题!特别感谢大卫赫弗南

1.获取控制面板项我使用Windows Shell获取控制面板项,使用CPL文件获取不到完整项。

代码 :

var
  psfDeskTop: IShellFolder;
  psfControl: IShellFolder;

  pidControl: PITEMIDLIST;
  pidChild: PITEMIDLIST;
  pidAbsolute: PItemIdList;

  pEnumList: IEnumIDList;
  celtFetched: ULONG;

  FileInfo: SHFILEINFOW;

begin

  OleCheck(SHGetDesktopFolder(psfDeskTop));
  OleCheck(SHGetSpecialFolderLocation(0, CSIDL_CONTROLS, pidControl));
  OleCheck(psfDeskTop.BindToObject(pidControl, nil, IID_IShellFolder, psfControl));
  OleCheck(psfControl.EnumObjects(0, SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN or SHCONTF_FOLDERS, pEnumList));

  while pEnumList.Next(1, pidChild, celtFetched) = 0 do
  begin

    pidAbsolute := ILCombine(pidControl, pidChild);
    SHGetFileInfo(LPCTSTR(pidAbsolute), 0, FileInfo, SizeOf(FileInfo), SHGFI_PIDL
      or SHGFI_DISPLAYNAME);
   // SHGetFileInfo can get name and icon 
   //Do something to save item name and icon

  end;

2. Execute 必须ShellExecuteEx用来执行一个PIDL 项。

var 
ShExeInfo : SHELLEXECUTEINFO;

begin

ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo));
    ShExeInfo.cbSize := SizeOf(ShExeInfo);
    ShExeInfo.lpVerb := 'Open';
    // control panel item's PIDL
    ShExeInfo.lpIDList := pidAbsolute;
    ShExeInfo.nShow := SW_SHOWNORMAL;
    ShExeInfo.fMask := SEE_MASK_IDLIST;
end

并使用

 ShellExecuteEx(@ShExeInfo);

最后再次感谢大卫赫弗南。帮了我很多忙。

于 2012-11-04T10:25:54.567 回答
0

遵循 Arioch 的建议

参考:http ://www.geoffchappell.com/studies/windows/shell/shell32/classes/controlpanel.htm

我想到的其他“两种或三种方法”在此处详述:

CONTROL.INI 文件的 [MMCPL] 部分,现在映射到注册表项 HKEY_CURRENT_USER\Control Panel\MMCPL;

注册表项 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Control Panel\CPLs;

此外,还有详细的不加载列表:

如果候选 CPL 模块的文件名显示为以下任一注册表项中的值,则该候选 CPL 模块将被拒绝:

HKEY_CURRENT_USER\Control Panel\don't load
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Control Panel\don't load

如前所述,该项目的挑战是扫描所有适当的位置并以正确的方式获取数据以便能够对其采取行动。这是因为如何呈现一些“较新”的设计控制面板项目(以及出现在那里的 shell 文件夹,我不确定我是否发现了如何访问它们)。我手头没有数据,但如果可以进一步讨论,我可以复制一两个示例。

于 2012-10-25T22:30:25.357 回答