我有一个用CBS_OWNERDRAWFIXED
和创建的所有者绘制的组合框,没有 CBS_HASSTRINGS
。
这个组合框应该显示正在运行的进程的顶级窗口列表。我在名为RunningProcess
的类中保留有关此窗口(图标,标题,句柄)的相关信息。这是填充组合框的代码:
void populateProcessList(HWND combobox) {
SendMessage(combobox, CB_RESETCONTENT, 0, 0);
std::vector<RunningProcess*> topLevelWindows = RunningProcesses::enumerateTopLevelWindows();
for (int index = 0; index < topLevelWindows.size(); index++) {
RunningProcess *proc = topLevelWindows[index];
SendMessage(combobox, CB_ADDSTRING, 0, (LPARAM)proc);
}
}
MSDN documentation说:
如果使用所有者绘制的样式创建但没有
CBS_HASSTRINGS
样式的组合框,则lParam
参数的值将存储为项目数据,而不是其指向的字符串。可以通过发送CB_GETITEMDATA
或CB_SETITEMDATA
消息来检索或修改商品数据。
现在,当我捕获WM_DRAWITEM
消息时,我使用此代码段获取RunningProcess
对象并使用内部数据
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
RunningProcess *proc = (RunningProcess*)lpdis->itemData;
显然,调试器显示内存无法读取,否则我不会在这里寻求帮助!
你可以帮我解决这个问题吗?请告诉我,为了更好地理解我的问题,你还需要什么吗? P.S。这是enumerateTopLevelWindows
函数及其一些依赖项:
BOOL RunningProcesses::processWindows(HWND window, LPARAM lParam) {
std::vector<RunningProcess*>& windows = *(std::vector<RunningProcess*>*)lParam;
TCHAR windowTitle[260];
HICON windowIcon;
GetWindowText(window, windowTitle, 260);
windowIcon = RunningProcesses::getAppIcon(window);
windows.push_back(new RunningProcess(window, windowTitle, windowIcon));
return TRUE;
}
std::vector<RunningProcess*> RunningProcesses::enumerateTopLevelWindows() {
std::vector<RunningProcess*> windows;
BOOL ret = EnumWindows(RunningProcesses::processWindows, reinterpret_cast<LPARAM>(&windows));
return windows;
}
HICON RunningProcesses::getAppIcon(HWND window) {
HICON iconHandle = (HICON)SendMessage(window, WM_GETICON, ICON_SMALL2, 0);
if (iconHandle == nullptr)
iconHandle = (HICON)SendMessage(window, WM_GETICON, ICON_SMALL, 0);
if (iconHandle == nullptr)
iconHandle = (HICON)SendMessage(window, WM_GETICON, ICON_BIG, 0);
if (iconHandle == nullptr)
iconHandle = (HICON)GetClassLongPtr(window, GCL_HICON);
if (iconHandle == nullptr)
iconHandle = (HICON)GetClassLongPtr(window, GCL_HICONSM);
if (iconHandle == nullptr)
return nullptr;
return iconHandle;
}
RunningProcess
类如下:
class RunningProcess {
public:
RunningProcess(HWND hWnd, TCHAR* windowTitle, HICON windowIcon) {
m_hWnd = hWnd;
lstrcpy(m_windowTitle, windowTitle);
m_windowIcon = windowIcon;
}
~RunningProcess();
const TCHAR* getTitle() const { return m_windowTitle; }
const char* getTitleMb() const {
unsigned bufferLen = lstrlen(m_windowTitle);
char *mbTitle = new char[bufferLen + 1];
wcstombs(mbTitle, m_windowTitle, bufferLen + 1);
return mbTitle;
}
const HWND getHandle() const { return m_hWnd; }
const HICON getIcon() const { return m_windowIcon; }
private:
HWND m_hWnd;
TCHAR m_windowTitle[260];
HICON m_windowIcon;
};
答案 0 :(得分:1)
您未检查lpdis->itemID
-1
值。确保你在这种情况下崩溃。你的代码必须像这样
PDRAWITEMSTRUCT lpdis = (PDRAWITEMSTRUCT) lParam;
if (lpdis->itemID == -1)
{
// assert (lpdis->itemData == MAXULONG_PTR);
}
else
{
RunningProcess *proc = (RunningProcess*)lpdis->itemData;
}
一般规则如何调试此案例:
在RunningProcess
构造函数和析构函数中添加DbgPrint("%s<%p>\n", __FUNCTION__, this);
以获取创建和销毁的所有对象的视图地址。并将崩溃时的lpdis->itemData
与此地址进行比较 - 您只是查看 - 您是否已删除对象或lpdis->itemData
完全无效(永远不会指向任何RunningProcess
甚至已删除)。在您的情况下,我确定lpdis->itemData == MAXULONG_PTR
和lpdis->itemID == -1