context menu implementation for desktop window

svn path=/trunk/; revision=7140
This commit is contained in:
Martin Fuchs 2003-12-20 18:23:10 +00:00
parent f1977c73d3
commit 69090b81d4
14 changed files with 264 additions and 98 deletions

View file

@ -171,6 +171,9 @@ LRESULT DesktopWindow::Init(LPCREATESTRUCT pcs)
///@todo use IShellBrowser::GetViewStateStream() to restore previous view state -> see SHOpenRegStream()
if (SUCCEEDED(hr)) {
// subclass shellview window
new DesktopShellView(hWndView, _pShellView);
_pShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
/*
@ -207,6 +210,7 @@ LRESULT DesktopWindow::Init(LPCREATESTRUCT pcs)
// Without this the desktop has mysteriously only a size of 800x600 pixels.
MoveWindow(hwndFolderView, 0, 0, rect.right, rect.bottom, TRUE);
// subclass background window
new BackgroundWindow(hwndFolderView);
}
}
@ -265,10 +269,75 @@ LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
}
HRESULT DesktopWindow::OnDefaultCommand(LPIDA pIDList)
HRESULT DesktopWindow::OnDefaultCommand(LPIDA pida)
{
if (MainFrame::OpenShellFolders(pIDList, 0))
if (MainFrame::OpenShellFolders(pida, 0))
return S_OK;
return E_NOTIMPL;
}
DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView)
: super(hwnd),
_pShellView(pShellView)
{
}
LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_CONTEXTMENU:
if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)))
goto def; ///@todo desktop context menu
break;
default: def:
return super::WndProc(nmsg, wparam, lparam);
}
return 0;
}
int DesktopShellView::Command(int id, int code)
{
return super::Command(id, code);
}
int DesktopShellView::Notify(int id, NMHDR* pnmh)
{
return super::Notify(id, pnmh);
}
bool DesktopShellView::DoContextMenu(int x, int y)
{
IDataObject* selection;
HRESULT hr = _pShellView->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&selection);
if (FAILED(hr))
return false;
PIDList pidList;
hr = pidList.GetData(selection);
if (FAILED(hr)) {
selection->Release();
//CHECKERROR(hr);
return false;
}
LPIDA pida = pidList;
LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
LPCITEMIDLIST first_pidl = (LPCITEMIDLIST)((LPBYTE)pida+pida->aoffset[1]);
ShellFolder folder(parent_pidl);
hr = ShellFolderContextMenu(folder, _hwnd, pida->cidl, &first_pidl, x, y);
selection->Release();
CHECKERROR(hr);
return true;
}

View file

@ -78,5 +78,23 @@ protected:
IShellView* _pShellView;
WindowHandle _desktopBar;
virtual HRESULT OnDefaultCommand(LPIDA pIDList);
virtual HRESULT OnDefaultCommand(LPIDA pida);
};
/// subclassed ShellView window
struct DesktopShellView : public SubclassedWindow
{
typedef SubclassedWindow super;
DesktopShellView(HWND hwnd, IShellView* pShellView);
protected:
IShellView* _pShellView;
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
int Command(int id, int code);
int Notify(int id, NMHDR* pnmh);
bool DoContextMenu(int x, int y);
};

View file

@ -48,3 +48,4 @@ If you search for more information, look into the CVS repository.
19.10.2003 m. fuchs implemented floating start menus
29.11.2003 m. fuchs implemented GDB stub for remote debugging
06.12.2003 m. fuchs basic support to display NTFS streams in winefile windows
20.12.2003 m. fuchs context menu implementation for desktop window

View file

@ -2,8 +2,8 @@
<table border="0" width="100%" cellspacing="0">
<tr>
<td><address style="align: right;"><small>
ROS Explore Source Code Documentation
<br>generated on 06.12.2003 by <a href="http://www.doxygen.org/index.html">
ROS Explorer Source Code Documentation
<br>generated on 20.12.2003 by <a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
</small></address>
</td>

View file

@ -211,15 +211,15 @@ ChildWindow* MainFrame::CreateChild(LPCITEMIDLIST pidl, int mode)
}
int MainFrame::OpenShellFolders(LPIDA pIDList, HWND hFrameWnd)
int MainFrame::OpenShellFolders(LPIDA pida, HWND hFrameWnd)
{
int cnt = 0;
LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
ShellFolder folder(parent_pidl);
for(int i=pIDList->cidl; i>0; --i) {
LPCITEMIDLIST pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
for(int i=pida->cidl; i>0; --i) {
LPCITEMIDLIST pidl = (LPCITEMIDLIST)((LPBYTE)pida+pida->aoffset[i]);
SFGAOF attribs = SFGAO_FOLDER;
HRESULT hr = folder->GetAttributesOf(1, &pidl, &attribs);

View file

@ -41,7 +41,7 @@ struct MainFrame : public PreTranslateWindow
static HWND Create();
static HWND Create(LPCTSTR path, int mode=OWM_EXPLORE|OWM_DETAILS);
static HWND Create(LPCITEMIDLIST pidl, int mode=OWM_EXPLORE|OWM_DETAILS|OWM_PIDL);
static int OpenShellFolders(LPIDA pIDList, HWND hFrameWnd);
static int OpenShellFolders(LPIDA pida, HWND hFrameWnd);
ChildWindow* CreateChild(LPCTSTR path=NULL, int mode=OWM_EXPLORE|OWM_DETAILS);
ChildWindow* CreateChild(LPCITEMIDLIST pidl, int mode=OWM_EXPLORE|OWM_DETAILS|OWM_PIDL);

View file

@ -209,7 +209,6 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO
LPARAM itemData = TreeView_GetItemData(hwndTreeView, hItem);
if (itemData) {
HWND hwndParent = ::GetParent(hwndTreeView);
Entry* entry = (Entry*)itemData;
IShellFolder* shell_folder;
@ -228,55 +227,7 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO
if (shell_folder) {
LPCITEMIDLIST pidl = static_cast<ShellEntry*>(entry)->_pidl;
IContextMenu* pcm;
HRESULT hr = shell_folder->GetUIObjectOf(hwndParent, 1, &pidl, IID_IContextMenu, NULL, (LPVOID*)&pcm);
// HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm);
if (SUCCEEDED(hr)) {
HMENU hPopup = CreatePopupMenu();
if (hPopup) {
hr = pcm->QueryContextMenu(hPopup, 0, 1, 0x7fff, CMF_NORMAL|CMF_EXPLORE);
if (SUCCEEDED(hr)) {
IContextMenu2* pcm2;
pcm->QueryInterface(IID_IContextMenu2, (LPVOID*)&pcm2);
UINT idCmd = TrackPopupMenu(hPopup,
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,
pptScreen->x,
pptScreen->y,
0,
hwndParent,
NULL);
if (pcm2) {
pcm2->Release();
pcm2 = NULL;
}
if (idCmd) {
CMINVOKECOMMANDINFO cmi;
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
cmi.fMask = 0;
cmi.hwnd = hwndParent;
cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - 1);
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = pcm->InvokeCommand(&cmi);
}
}
}
pcm->Release();
}
shell_folder->Release();
ShellFolderContextMenu(shell_folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y);
}
}
}
@ -485,11 +436,11 @@ int ShellBrowserChild::Notify(int id, NMHDR* pnmh)
}
HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pIDList)
HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pida)
{
CONTEXT("ShellBrowserChild::OnDefaultCommand()");
if (pIDList->cidl>=1) {
if (pida->cidl>=1) {
if (_left_hwnd) { // explorer mode
if (_last_sel) {
ShellDirectory* parent = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, _last_sel);
@ -501,8 +452,8 @@ HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pIDList)
return e.Error();
}
UINT firstOffset = pIDList->aoffset[1];
LPITEMIDLIST pidl = (LPITEMIDLIST)((LPBYTE)pIDList+firstOffset);
UINT firstOffset = pida->aoffset[1];
LPITEMIDLIST pidl = (LPITEMIDLIST)((LPBYTE)pida+firstOffset);
Entry* entry = parent->find_entry(pidl);
@ -512,11 +463,11 @@ HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pIDList)
}
}
} else { // no tree control
if (MainFrame::OpenShellFolders(pIDList, _hWndFrame))
if (MainFrame::OpenShellFolders(pida, _hWndFrame))
return S_OK;
/* create new Frame Window
if (MainFrame::OpenShellFolders(pIDList, 0))
if (MainFrame::OpenShellFolders(pida, 0))
return S_OK;
*/
}

View file

@ -123,7 +123,7 @@ protected:
int InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder);
bool InitDragDrop();
HRESULT OnDefaultCommand(LPIDA pIDList);
HRESULT OnDefaultCommand(LPIDA pida);
void OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh);
void OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv);

View file

@ -58,42 +58,23 @@ HRESULT IShellBrowserImpl::QueryInterface(REFIID iid, void** ppvObject)
// process default command: look for folders and traverse into them
HRESULT IShellBrowserImpl::OnDefaultCommand(IShellView* ppshv)
{
static UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
IDataObject* selection;
HRESULT hr = ppshv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&selection);
if (FAILED(hr))
return hr;
PIDList pidList;
FORMATETC fetc;
fetc.cfFormat = CF_IDLIST;
fetc.ptd = NULL;
fetc.dwAspect = DVASPECT_CONTENT;
fetc.lindex = -1;
fetc.tymed = TYMED_HGLOBAL;
hr = selection->QueryGetData(&fetc);
if (FAILED(hr))
hr = pidList.GetData(selection);
if (FAILED(hr)) {
selection->Release();
return hr;
}
STGMEDIUM stgm = {sizeof(STGMEDIUM), {0}, 0};
hr = selection->GetData(&fetc, &stgm);
if (FAILED(hr))
return hr;
DWORD pData = (DWORD)GlobalLock(stgm.hGlobal);
LPIDA pIDList = (LPIDA)pData;
HRESULT ret = OnDefaultCommand(pIDList);
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
hr = OnDefaultCommand(pidList);
selection->Release();
return ret;
return hr;
}

View file

@ -72,7 +72,7 @@ struct IShellBrowserImpl : public IShellBrowser, public ICommDlgBrowser
protected:
DWORD _dwRef;
virtual HRESULT OnDefaultCommand(LPIDA pIDList) {return E_NOTIMPL;}
virtual HRESULT OnDefaultCommand(LPIDA pida) {return E_NOTIMPL;}
};
#ifndef WM_GETISHELLBROWSER

View file

@ -421,3 +421,55 @@ UINT ILGetSize(LPCITEMIDLIST pidl)
}
#endif
HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* apidl, int x, int y)
{
IContextMenu* pcm;
HRESULT hr = shell_folder->GetUIObjectOf(hwndParent, cidl, apidl, IID_IContextMenu, NULL, (LPVOID*)&pcm);
// HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm);
if (SUCCEEDED(hr)) {
HMENU hPopup = CreatePopupMenu();
if (hPopup) {
hr = pcm->QueryContextMenu(hPopup, 0, 1, 0x7fff, CMF_NORMAL|CMF_EXPLORE);
if (SUCCEEDED(hr)) {
IContextMenu2* pcm2;
pcm->QueryInterface(IID_IContextMenu2, (LPVOID*)&pcm2);
UINT idCmd = TrackPopupMenu(hPopup, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL);
if (pcm2) {
pcm2->Release();
pcm2 = NULL;
}
if (idCmd) {
CMINVOKECOMMANDINFO cmi;
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
cmi.fMask = 0;
cmi.hwnd = hwndParent;
cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - 1);
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = pcm->InvokeCommand(&cmi);
}
}
}
pcm->Release();
}
shell_folder->Release();
return hr;
}

View file

@ -937,3 +937,53 @@ struct ShellItemEnumerator : public SIfacePtr<IEnumIDList>
CHECKERROR(folder->EnumObjects(0, flags, &_p));
}
};
/// list of PIDLs
struct PIDList
{
PIDList()
{
memset(&_stgm, 0, sizeof(STGMEDIUM));
}
~PIDList()
{
if (_stgm.hGlobal) {
GlobalUnlock(_stgm.hGlobal);
ReleaseStgMedium(&_stgm);
}
}
HRESULT GetData(IDataObject* selection)
{
static UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
FORMATETC fetc;
fetc.cfFormat = CF_IDLIST;
fetc.ptd = NULL;
fetc.dwAspect = DVASPECT_CONTENT;
fetc.lindex = -1;
fetc.tymed = TYMED_HGLOBAL;
HRESULT hr = selection->QueryGetData(&fetc);
if (FAILED(hr))
return hr;
hr = selection->GetData(&fetc, &_stgm);
if (FAILED(hr))
return hr;
_pIDList = (LPIDA)GlobalLock(_stgm.hGlobal);
return hr;
}
operator LPIDA() {return _pIDList;}
protected:
STGMEDIUM _stgm;
LPIDA _pIDList;
};
extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* ppidl, int x, int y);

View file

@ -257,7 +257,7 @@ LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
int Window::Command(int id, int code)
{
return 0;
return 1; // WM_COMMAND not yet handled
}
int Window::Notify(int id, NMHDR* pnmh)
@ -277,12 +277,42 @@ void Window::CancelModes(HWND hwnd)
SubclassedWindow::SubclassedWindow(HWND hwnd)
: super(hwnd)
{
_orgWndProc = SubclassWindow(_hwnd, WindowWndProc);
_orgWndProc = SubclassWindow(_hwnd, SubclassedWndProc);
if (!_orgWndProc)
delete this;
}
LRESULT CALLBACK SubclassedWindow::SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
{
SubclassedWindow* pThis = GET_WINDOW(SubclassedWindow, hwnd);
assert(pThis);
if (pThis) {
switch(nmsg) {
case WM_COMMAND:
if (!pThis->Command(LOWORD(wparam), HIWORD(wparam)))
return 0;
break;
case WM_NOTIFY:
return pThis->Notify(wparam, (NMHDR*)lparam);
case WM_CREATE:
return pThis->Init((LPCREATESTRUCT)lparam);
case WM_NCDESTROY:
delete pThis;
return 0;
default:
return pThis->WndProc(nmsg, wparam, lparam);
}
}
return CallWindowProc(pThis->_orgWndProc, hwnd, nmsg, wparam, lparam);
}
LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
/*@@TODO: replaced by StartMenu::TrackStartmenu()
@ -294,6 +324,16 @@ LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
return CallWindowProc(_orgWndProc, _hwnd, nmsg, wparam, lparam);
}
int SubclassedWindow::Command(int id, int code)
{
return 1; // WM_COMMAND not yet handled
}
int SubclassedWindow::Notify(int id, NMHDR* pnmh)
{
return CallWindowProc(_orgWndProc, _hwnd, WM_NOTIFY, id, (LPARAM)pnmh);
}
ChildWindow::ChildWindow(HWND hwnd)
: super(hwnd)

View file

@ -169,7 +169,11 @@ struct SubclassedWindow : public Window
protected:
WNDPROC _orgWndProc;
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
virtual int Command(int id, int code);
virtual int Notify(int id, NMHDR* pnmh);
};