![]() |
#2
mybeibuwan2025-03-13 19:48
我用VC6语言测试也是这个输出结果,下面给出源码
// 工程1.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "工程1.h" #include "工程1Dlg.h" #include <shlobj.h> // Shell API 相关定义 #pragma comment(lib, "shell32.lib") // 链接 Shell32 库 #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define UNICODE #define _UNICODE ///////////////////////////////////////////////////////////////////////////// // CMy1App BEGIN_MESSAGE_MAP(CMy1App, CWinApp) //{{AFX_MSG_MAP(CMy1App) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMy1App construction CMy1App::CMy1App() { // TODO: add construction code here, // Place all significant initialization in InitInstance IShellFolder* pDesktopFolder = NULL; SHGetDesktopFolder(&pDesktopFolder); // 获取桌面 IShellFolder 接口 LPITEMIDLIST pidlControlPanel = NULL; SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlControlPanel); // 获取控制面板 PIDL? IShellFolder* pControlPanelFolder = NULL; pDesktopFolder->BindToObject(pidlControlPanel, NULL, IID_IShellFolder, (void**)&pControlPanelFolder); // 绑定到控制面板? IEnumIDList* pEnum = NULL; pControlPanelFolder->EnumObjects(NULL, SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnum); // 获取枚举器 LPITEMIDLIST pidlItem = NULL; while (pEnum->Next(1, &pidlItem, NULL) == S_OK) { // 获取显示名称 STRRET strret; pControlPanelFolder->GetDisplayNameOf(pidlItem, SHGDN_NORMAL, &strret); WCHAR wszName[MAX_PATH]; switch (strret.uType) { case STRRET_WSTR: wcscpy(wszName, strret.pOleStr); // 直接拷贝宽字符串 CoTaskMemFree(strret.pOleStr); // 释放内存?:ml-citation{ref="1,2" data="citationList"} break; case STRRET_OFFSET: wsprintfW(wszName, L"%s", (LPCWSTR)(((BYTE*)pidlItem) + strret.uOffset)); break; case STRRET_CSTR: MultiByteToWideChar(CP_ACP, 0, strret.cStr, -1, wszName, MAX_PATH); // ANSI 转宽字符 break; } // 输出名称 MessageBoxW(NULL, _T(wszName), L"提示", MB_OK); // 释放 PIDL CoTaskMemFree(pidlItem); } // pEnum->Release(); } ///////////////////////////////////////////////////////////////////////////// // The one and only CMy1App object CMy1App theApp; ///////////////////////////////////////////////////////////////////////////// // CMy1App initialization BOOL CMy1App::InitInstance() { AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CMy1Dlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } |
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ActiveX, ShellAPI, ShlObj, ComObj,
Vcl.StdCtrls;
procedure EnumControlPanelItems();
var
controlPIDL, parentPIDL, pidlChild2: PItemIDList;
shellFolder1, shellFolder2: IShellFolder;
enumIDL1, enumIDL2: IEnumIDList;
pidlSub1, pidlSub2: PItemIDList;
dwFetched: DWORD;
dName: String; // 对象显示名称
begin
CoInitialize(nil);
try
// 获取控制面板PIDL
SHGetSpecialFolderLocation(0, CSIDL_CONTROLS, controlPIDL);
outputdebugstring(pwidechar('controlPIDL:' + inttostr(ILGetSize(controlPIDL))));
// 绑定“控制面板”文件夹shellFolder1
SHBindToParent(controlPIDL, IShellFolder, Pointer(shellFolder1), parentPIDL);
// 获取控制面板枚举对象enumIDL1
shellFolder1.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_SHAREABLE, enumIDL1);
// 这里可以正确列举控制面板第一级功能模块
while enumIDL1.Next(1, pidlSub1, dwFetched) = S_OK do
begin
// 获取显示名
dName := GetDisplayName(shellFolder1, pidlSub1);
outputdebugstring(pwidechar(dName));
// 错误原因可能是下面2个方法上,1:BindToObject,2:EnumObjects,可能是参数传递有问题
// 绑定到第二级下级文件夹的 IShellFolder 接口
shellFolder1.BindToObject(pidlSub1, nil, IID_IShellFolder, Pointer(shellFolder2));
// OLECheck((SHBindToObject(shellFolder1, pidlSub1, nil, IID_IShellFolder, Pointer(shellFolder2))));
// 获取第二级下级枚举对象enumIDL2
shellFolder2.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_SHAREABLE, enumIDL2);
// 是这里不能正确列举第二级下级子项目,大多返回S_FALSE,很多子项都不能列举出来
while enumIDL2.Next(1, pidlSub2, dwFetched) = S_OK do
begin
dName := GetDisplayName(shellFolder2, pidlSub2);
outputdebugstring(pwidechar(' ' + dName + inttostr(ILGetSize(pidlSub2))));
CoTaskMemFree(pidlSub2);
end;
CoTaskMemFree(pidlSub1);
end;
// 释放PIDL
CoTaskMemFree(parentPIDL);
CoTaskMemFree(controlPIDL);
finally
CoUninitialize;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
EnumControlPanelItems;
end;
下面给出执行源码输出结果
Debug Output: 系统和安全 Process Project1.exe (23360)
Debug Output: 网络和 Internet Process Project1.exe (23360)
Debug Output: 硬件和声音 Process Project1.exe (23360)
Debug Output: 程序 Process Project1.exe (23360)
Debug Output: 用户帐户 Process Project1.exe (23360)
Debug Output: 邮件176 Process Project1.exe (23360)
Debug Output: 外观和个性化 Process Project1.exe (23360)
Debug Output: 时钟和区域 Process Project1.exe (23360)
Debug Output: 轻松使用 Process Project1.exe (23360)
Debug Output: 所有控制面板项 Process Project1.exe (23360)
Debug Output: Flash Player174 Process Project1.exe (23360)
Debug Output: 邮件176 Process Project1.exe (23360)
Debug Output: 360强力卸载156 Process Project1.exe (23360)
Debug Output: 128 Process Project1.exe (23360)
Debug Output:
[此贴子已经被作者于2025-3-13 19:43编辑过]