今天被”Windows Shell外壳编程”搞残了.本来就是想在自己的应用程序中浏览文件,右键能够显示系统菜单.但是网上搜了一大堆资料都是讲”Shell扩展编程”的,差点没把我气死.后来在看雪找到了一个主题,见:http://bbs.pediy.com/showthread.php?p=573210
下载了一个”WTLExplorer”,哇塞!妈妈咪呀!这正是我所想要的,不过很可惜弹出的系统菜单不支持子菜单项的现实,于是又修改了一下终于可行了.
将ShellMgr.cpp文件中的DoContextMenu函数修改为:
BOOL CShellMgr::DoContextMenu(HWND hWnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi, POINT point) {
LPCONTEXTMENU spContextMenu;
LPCONTEXTMENU pCtxMenuTemp = NULL;
int menuType = 0;
g_pIContext2 = NULL;
g_pIContext3 = NULL;
HRESULT hr = lpsfParent->GetUIObjectOf(hWnd, 1, (const struct _ITEMIDLIST**)&lpi, IID_IContextMenu, 0, (LPVOID*)&pCtxMenuTemp);
if (FAILED(hr))
return FALSE;
if (pCtxMenuTemp->QueryInterface(IID_IContextMenu3, (void**)&spContextMenu) == NO_ERROR) {
menuType = 3;
} else if (pCtxMenuTemp->QueryInterface(IID_IContextMenu2, (void**)&spContextMenu) == NO_ERROR) {
menuType = 2;
} else if (pCtxMenuTemp->QueryInterface(IID_IContextMenu, (void**)&spContextMenu) == NO_ERROR) {
menuType = 1;
}
HMENU hMenu = ::CreatePopupMenu();
if (hMenu == NULL)
return FALSE;
// Get the context menu for the item.
hr = spContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE | CMF_NORMAL);
if (FAILED(hr))
return FALSE;
// subclass window
WNDPROC oldWndProc = NULL;
if (menuType > 1) {
// only subclass if it is IID_IContextMenu2 or IID_IContextMenu3
oldWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWL_WNDPROC, (LONG)HookWndProc);
if (menuType == 2) {
g_pIContext2 = (LPCONTEXTMENU2)spContextMenu;
} else {
g_pIContext3 = (LPCONTEXTMENU3)spContextMenu;
}
}
int idCmd = ::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
// unsubclass
if (oldWndProc) {
SetWindowLongPtr(hWnd, GWL_WNDPROC, (LONG)oldWndProc);
}
if (idCmd != 0) {
USES_CONVERSION;
// Execute the command that was selected.
CMINVOKECOMMANDINFO cmi = { 0 };
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
cmi.fMask = 0;
cmi.hwnd = hWnd;
cmi.lpVerb = T2CA(MAKEINTRESOURCE(idCmd - 1));
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = spContextMenu->InvokeCommand(&cmi);
}
::DestroyMenu(hMenu);
return TRUE;
}
再添加一个静态函数HookWndProc:
static LRESULT CALLBACK HookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_MENUCHAR: // only supported by IContextMenu3
if (g_pIContext3) {
LRESULT lResult = 0;
g_pIContext3->HandleMenuMsg2(message, wParam, lParam, &lResult);
return(lResult);
}
break;
case WM_DRAWITEM:
case WM_MEASUREITEM:
if (wParam) {
break; // if wParam != 0 then the message is not menu-related
}
case WM_INITMENUPOPUP:
if (g_pIContext2) {
g_pIContext2->HandleMenuMsg(message, wParam, lParam);
} else {
g_pIContext3->HandleMenuMsg(message, wParam, lParam);
}
return(message == WM_INITMENUPOPUP ? 0 : TRUE);
break;
default:
break;
}
return ::CallWindowProc((WNDPROC)GetProp(hWnd, TEXT("oldWndProc")), hWnd, message, wParam, lParam);
}
这样就能显示系统菜单的子菜单项了,效果如图:
文档信息
- 本文作者:zhupite
- 本文链接:https://zhupite.com/program/WindowsShell%E5%A4%96%E5%A3%B3%E7%BC%96%E7%A8%8B%E5%88%9D%E6%8E%A2%E4%B9%8BWTLExplorer.html
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)