如何通过HWND得到对应的ICON ?

lownr 2002-01-29 08:16:21
通常我用这行代码获得Window的ICON
HICON hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);

在大多数情况下,这行代码工作很正常,但有时获得的图标是不正确的。

例如:
Windows XP中可以方便的定制文件夹,为文件夹指定一个特别的图标。当打开这个文件夹时,窗口的ICON就变成了指定的ICON。而用上面的代码获得ICON仍然是默认的文件夹图标。

而且我发现有些用Delphi写的程序用上面的代码获得的HICON是NULL,所以我采用下面的方法来获取图标。

1) 首先获得程序文件的EXE文件名:

// 自己编写的函数
GetProcessFilename(hwnd, szbuf, MAX_PATH);


2) 然后用SHGetFileInfo获取这个EXE文件的图标:

SHFILEINFO shfi;
ZeroMemory(&shfi, sizeof(shfi));
DWORD dwret = SHGetFileInfo(szbuf, 0, &shfi, sizeof(shfi),
SHGFI_ICON | SHGFI_ICONLOCATION | SHGFI_LARGEICON);
hIcon = shfi.hIcon;

附:GetProcessFilename实现

// 函数名 :GetProcessFilename
// 描述 :通过窗口句柄获得创建窗口的应用程序的可执行文件名
// NOTE: 部分代码改编自 MSDN 知识库文章 Q175030 的 EnumProcs 函数
// 返回类型 :BOOL - 指示是否成功
// 参数 :HWND hwnd [in] - 窗口句柄
// 参数 :LPTSTR lpszFilename [ptr] - 存放文件名的缓冲区
// 参数 :UINT nBufLen [in] - 缓冲区长度,TCHARs

BOOL GetProcessFilename(HWND hwnd, LPTSTR lpszFilename, UINT nBufLen)
{
BOOL bSuccess = TRUE;

// 通过进程ID获得进程的HANDLE
DWORD dwProcessID;
GetWindowThreadProcessId(hwnd, &dwProcessID);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
if(hProcess == NULL) return FALSE;

// 获取Windows版本信息
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(osver);
GetVersionEx(&osver);

// 根据Win32平台的不同,这个函数的实现有所不同。
if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// Windows NT 平台下的实现
// 首先通过 EnumProcessModules 函数枚举出 process 的第一个 module
// (这个 module 总是 .EXE 文件),然后用 GetModuleFileNameEx 获取 .EXE 的文件名
// NOTE: 之所以不通过直接联接PSAPI.LIB是为了消除程序运行于
// Windows 9x操作系统时显示的警告信息。

HINSTANCE hInstLib; // PSAPI.DLL的实例句柄

hInstLib = LoadLibraryA("PSAPI.DLL");
if(hInstLib == NULL) return FALSE;

// PSAPI function pointers;
BOOL (WINAPI* lpfEnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD);
DWORD (WINAPI* lpfGetModuleFileNameEx)(HANDLE, HMODULE, LPTSTR, DWORD);

// Get procedure addresses.
lpfEnumProcessModules = (BOOL(WINAPI*)(HANDLE, HMODULE*, DWORD, LPDWORD))
GetProcAddress(hInstLib, TEXT("EnumProcessModules"));

lpfGetModuleFileNameEx = (DWORD(WINAPI*)(HANDLE, HMODULE, LPTSTR, DWORD))
GetProcAddress(hInstLib, TEXT("GetModuleFileNameExA"));

if(lpfEnumProcessModules == NULL || lpfGetModuleFileNameEx == NULL)
{
FreeLibrary(hInstLib);
return FALSE;
}

HMODULE hModule;
DWORD dwArraySize;
if(lpfEnumProcessModules(hProcess, &hModule,
sizeof(hModule), &dwArraySize))
{
if(!lpfGetModuleFileNameEx(hProcess, hModule,
lpszFilename, nBufLen))
{
lpszFilename[0] = 0;
bSuccess = FALSE;
}
}
else
{
bSuccess = FALSE;
}

FreeLibrary(hInstLib);
}
else if(osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
// Windows 9x 平台下的实现
HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
if(!GetModuleFileName(hInst, lpszFilename, nBufLen))
bSuccess = FALSE;
}
return bSuccess;
}



======================================

现在的问题是上面两种方法都不能获得自定义文件夹的图标,不知道哪位高手愿意指点一二?

我的联系方式:
OICQ - 9254671
Windows Messenger - dualface@msn.com
...全文
318 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
lownr 2002-01-30
  • 打赏
  • 举报
回复
吐血,原来这么简单,给分。
SuperChen 2002-01-29
  • 打赏
  • 举报
回复
另外,我记得在 Win9x/Win2000 下面可以在某个文件夹下面设一个 desktop.ini(或者类似的名字),在其中设定一些项目就可以达到相同的效果。
SuperChen 2002-01-29
  • 打赏
  • 举报
回复
这么复杂啊,直接用
HICON hIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_SMALL, 0);
应该就可以了吧?
dox 2002-01-29
  • 打赏
  • 举报
回复
关注
lownr 2002-01-29
  • 打赏
  • 举报
回复
没有人看到吗?自己UP一下。

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧