4 * Copyright 2008 Thomas Bluemel
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "shelldesktop.h"
23 // Support for multiple monitors is disabled till LVM_SETWORKAREAS gets implemented
24 #ifdef MULTIMONITOR_SUPPORT
30 WINE_DEFAULT_DEBUG_CHANNEL(desktop
);
32 static const WCHAR szProgmanClassName
[] = L
"Progman";
33 static const WCHAR szProgmanWindowName
[] = L
"Program Manager";
35 class CDesktopBrowser
:
36 public CWindowImpl
<CDesktopBrowser
, CWindow
, CFrameWinTraits
>,
37 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
39 public IServiceProvider
44 CComPtr
<IShellDesktopTray
> m_Tray
;
45 CComPtr
<IShellView
> m_ShellView
;
47 LRESULT
_NotifyTray(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
53 HRESULT
Initialize(IShellDesktopTray
*ShellDeskx
);
55 // *** IOleWindow methods ***
56 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
57 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
59 // *** IShellBrowser methods ***
60 virtual HRESULT STDMETHODCALLTYPE
InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
);
61 virtual HRESULT STDMETHODCALLTYPE
SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
);
62 virtual HRESULT STDMETHODCALLTYPE
RemoveMenusSB(HMENU hmenuShared
);
63 virtual HRESULT STDMETHODCALLTYPE
SetStatusTextSB(LPCOLESTR pszStatusText
);
64 virtual HRESULT STDMETHODCALLTYPE
EnableModelessSB(BOOL fEnable
);
65 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorSB(MSG
*pmsg
, WORD wID
);
66 virtual HRESULT STDMETHODCALLTYPE
BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
);
67 virtual HRESULT STDMETHODCALLTYPE
GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
);
68 virtual HRESULT STDMETHODCALLTYPE
GetControlWindow(UINT id
, HWND
*lphwnd
);
69 virtual HRESULT STDMETHODCALLTYPE
SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
);
70 virtual HRESULT STDMETHODCALLTYPE
QueryActiveShellView(struct IShellView
**ppshv
);
71 virtual HRESULT STDMETHODCALLTYPE
OnViewWindowActive(struct IShellView
*ppshv
);
72 virtual HRESULT STDMETHODCALLTYPE
SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
);
74 // *** IServiceProvider methods ***
75 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
78 LRESULT
OnEraseBkgnd(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
79 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
80 LRESULT
OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
81 LRESULT
OnClose(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
82 LRESULT
OnOpenNewWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
83 LRESULT
OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
84 LRESULT
OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
86 DECLARE_WND_CLASS_EX(szProgmanClassName
, CS_DBLCLKS
, COLOR_DESKTOP
)
88 BEGIN_MSG_MAP(CBaseBar
)
89 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBkgnd
)
90 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
91 MESSAGE_HANDLER(WM_SYSCOLORCHANGE
, OnSettingChange
)
92 MESSAGE_HANDLER(WM_SETTINGCHANGE
, OnSettingChange
)
93 MESSAGE_HANDLER(WM_CLOSE
, OnClose
)
94 MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW
, OnOpenNewWindow
)
95 MESSAGE_HANDLER(WM_COMMAND
, OnCommand
)
96 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
99 BEGIN_COM_MAP(CDesktopBrowser
)
100 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
101 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser
, IShellBrowser
)
102 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
106 CDesktopBrowser::CDesktopBrowser():
108 m_hWndShellView(NULL
)
112 CDesktopBrowser::~CDesktopBrowser()
114 if (m_ShellView
.p
!= NULL
&& m_hWndShellView
!= NULL
)
116 m_ShellView
->DestroyViewWindow();
120 #ifdef MULTIMONITOR_SUPPORT
121 BOOL CALLBACK
MonitorEnumProc(
122 _In_ HMONITOR hMonitor
,
124 _In_ LPRECT lprcMonitor
,
128 CAtlList
<RECT
> *list
= (CAtlList
<RECT
>*)dwData
;
129 MONITORINFO MonitorInfo
;
130 MonitorInfo
.cbSize
= sizeof(MonitorInfo
);
131 if (::GetMonitorInfoW(hMonitor
, &MonitorInfo
))
133 list
->AddTail(MonitorInfo
.rcWork
);
140 HRESULT
CDesktopBrowser::_Resize()
144 #ifdef MULTIMONITOR_SUPPORT
146 UINT cMonitors
= GetSystemMetrics(SM_CMONITORS
);
149 SystemParametersInfoW(SPI_GETWORKAREA
, 0, &rcNewSize
, 0);
154 GetSystemMetrics(SM_XVIRTUALSCREEN
),
155 GetSystemMetrics(SM_YVIRTUALSCREEN
),
156 GetSystemMetrics(SM_XVIRTUALSCREEN
) + GetSystemMetrics(SM_CXVIRTUALSCREEN
),
157 GetSystemMetrics(SM_YVIRTUALSCREEN
) + GetSystemMetrics(SM_CYVIRTUALSCREEN
));
160 ::MoveWindow(m_hWnd
, rcNewSize
.left
, rcNewSize
.top
, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, FALSE
);
161 ::MoveWindow(m_hWndShellView
, 0, 0, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, FALSE
);
166 EnumDisplayMonitors(NULL
, NULL
, MonitorEnumProc
, (LPARAM
)&list
);
167 RECT
* prcWorkAreas
= new RECT
[list
.GetCount()];
169 for (POSITION it
= list
.GetHeadPosition(); it
; list
.GetNext(it
))
170 prcWorkAreas
[i
++] = list
.GetAt(it
);
172 HWND hwndListView
= FindWindowExW(m_hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
174 ::SendMessageW(hwndListView
, LVM_SETWORKAREAS
, i
, (LPARAM
)prcWorkAreas
);
178 SystemParametersInfoW(SPI_GETWORKAREA
, 0, &rcNewSize
, 0);
179 ::MoveWindow(m_hWnd
, rcNewSize
.left
, rcNewSize
.top
, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, FALSE
);
180 ::MoveWindow(m_hWndShellView
, 0, 0, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, FALSE
);
186 HRESULT
CDesktopBrowser::Initialize(IShellDesktopTray
*ShellDesk
)
188 CComPtr
<IShellFolder
> psfDesktop
;
190 hRet
= SHGetDesktopFolder(&psfDesktop
);
191 if (FAILED_UNEXPECTEDLY(hRet
))
196 Create(NULL
, NULL
, szProgmanWindowName
, WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
, WS_EX_TOOLWINDOW
);
200 CSFV csfv
= {sizeof(CSFV
), psfDesktop
};
201 hRet
= SHCreateShellFolderViewEx(&csfv
, &m_ShellView
);
202 if (FAILED_UNEXPECTEDLY(hRet
))
205 m_Tray
->RegisterDesktopWindow(m_hWnd
);
206 if (FAILED_UNEXPECTEDLY(hRet
))
210 RECT rcShellView
= {0,0,0,0};
211 fs
.ViewMode
= FVM_ICON
;
212 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
213 hRet
= m_ShellView
->CreateViewWindow(NULL
, &fs
, (IShellBrowser
*)this, &rcShellView
, &m_hWndShellView
);
214 if (FAILED_UNEXPECTEDLY(hRet
))
219 HWND hwndListView
= FindWindowExW(m_hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
220 SetShellWindowEx(m_hWnd
, hwndListView
);
222 m_hAccel
= LoadAcceleratorsW(shell32_hInstance
, MAKEINTRESOURCEW(IDA_DESKBROWSER
));
225 /* A Windows8+ specific hack */
226 ::ShowWindow(m_hWndShellView
, SW_SHOW
);
227 ::ShowWindow(hwndListView
, SW_SHOW
);
235 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetWindow(HWND
*lphwnd
)
243 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode
)
248 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
253 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
258 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared
)
263 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText
)
268 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::EnableModelessSB(BOOL fEnable
)
273 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg
, WORD wID
)
275 if (!::TranslateAcceleratorW(m_hWnd
, m_hAccel
, lpmsg
))
280 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
)
283 * We should use IShellWindows interface here in order to attempt to
284 * find an open shell window that shows the requested pidl and activate it
287 return SHOpenNewFrame((LPITEMIDLIST
)pidl
, NULL
, 0, wFlags
);
290 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
295 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
302 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
309 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
313 *ppshv
= m_ShellView
;
314 if (m_ShellView
!= NULL
)
315 m_ShellView
->AddRef();
320 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
325 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
330 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
332 /* FIXME - handle guidService */
333 return QueryInterface(riid
, ppv
);
336 LRESULT
CDesktopBrowser::_NotifyTray(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
341 hRet
= m_Tray
->GetTrayWindow(&hWndTray
);
343 ::PostMessageW(hWndTray
, uMsg
, wParam
, lParam
);
348 LRESULT
CDesktopBrowser::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
350 switch (LOWORD(wParam
))
352 case FCIDM_DESKBROWSER_CLOSE
:
353 return _NotifyTray(TWM_DOEXITWINDOWS
, 0, 0);
354 case FCIDM_DESKBROWSER_FOCUS
:
355 if (GetKeyState(VK_SHIFT
))
356 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 0xFFFFFFFF);
358 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 1);
359 case FCIDM_DESKBROWSER_SEARCH
:
360 SHFindFiles(NULL
, NULL
);
362 case FCIDM_DESKBROWSER_REFRESH
:
370 LRESULT
CDesktopBrowser::OnEraseBkgnd(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
372 return (LRESULT
)PaintDesktop((HDC
)wParam
);
375 LRESULT
CDesktopBrowser::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
377 if (wParam
== SIZE_MINIMIZED
)
379 /* Hey, we're the desktop!!! */
380 ::ShowWindow(m_hWnd
, SW_RESTORE
);
386 LRESULT
CDesktopBrowser::OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
390 /* Forward the message */
391 SendMessageW(m_hWndShellView
, uMsg
, wParam
, lParam
);
394 if (uMsg
== WM_SETTINGCHANGE
&& wParam
== SPI_SETWORKAREA
&& m_hWndShellView
!= NULL
)
402 LRESULT
CDesktopBrowser::OnClose(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
404 return _NotifyTray(TWM_DOEXITWINDOWS
, 0, 0);
407 LRESULT
CDesktopBrowser::OnOpenNewWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
409 TRACE("Proxy Desktop message 1035 received.\n");
410 SHOnCWMCommandLine((HANDLE
)lParam
);
414 LRESULT
CDesktopBrowser::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
416 ::SetFocus(m_hWndShellView
);
420 HRESULT
CDesktopBrowser_CreateInstance(IShellDesktopTray
*Tray
, REFIID riid
, void **ppv
)
422 return ShellObjectCreatorInit
<CDesktopBrowser
, IShellDesktopTray
*>(Tray
, riid
, ppv
);
425 /*************************************************************************
426 * SHCreateDesktop [SHELL32.200]
429 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*Tray
)
433 SetLastError(ERROR_INVALID_PARAMETER
);
437 CComPtr
<IShellBrowser
> Browser
;
438 HRESULT hr
= CDesktopBrowser_CreateInstance(Tray
, IID_PPV_ARG(IShellBrowser
, &Browser
));
439 if (FAILED_UNEXPECTEDLY(hr
))
442 return static_cast<HANDLE
>(Browser
.Detach());
445 /*************************************************************************
446 * SHCreateDesktop [SHELL32.201]
449 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
451 if (hDesktop
== NULL
)
453 SetLastError(ERROR_INVALID_PARAMETER
);
460 CComPtr
<IShellBrowser
> browser
;
461 CComPtr
<IShellView
> shellView
;
463 browser
.Attach(static_cast<IShellBrowser
*>(hDesktop
));
464 HRESULT hr
= browser
->QueryActiveShellView(&shellView
);
465 if (FAILED_UNEXPECTEDLY(hr
))
468 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
472 if (shellView
->TranslateAcceleratorW(&Msg
) != S_OK
)
474 TranslateMessage(&Msg
);
475 DispatchMessage(&Msg
);