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
, TRUE
);
161 ::MoveWindow(m_hWndShellView
, 0, 0, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, TRUE
);
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
, TRUE
);
180 ::MoveWindow(m_hWndShellView
, 0, 0, rcNewSize
.right
- rcNewSize
.left
, rcNewSize
.bottom
- rcNewSize
.top
, TRUE
);
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 DWORD dwFlags
= ((wFlags
& SBSP_EXPLOREMODE
) != 0) ? SH_EXPLORER_CMDLINE_FLAG_E
: 0;
288 return SHOpenNewFrame(ILClone(pidl
), NULL
, 0, dwFlags
);
291 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
296 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
303 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
310 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
314 *ppshv
= m_ShellView
;
315 if (m_ShellView
!= NULL
)
316 m_ShellView
->AddRef();
321 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
326 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
331 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
333 /* FIXME - handle guidService */
334 return QueryInterface(riid
, ppv
);
337 LRESULT
CDesktopBrowser::_NotifyTray(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
342 hRet
= m_Tray
->GetTrayWindow(&hWndTray
);
344 ::PostMessageW(hWndTray
, uMsg
, wParam
, lParam
);
349 LRESULT
CDesktopBrowser::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
351 switch (LOWORD(wParam
))
353 case FCIDM_DESKBROWSER_CLOSE
:
354 return _NotifyTray(TWM_DOEXITWINDOWS
, 0, 0);
355 case FCIDM_DESKBROWSER_FOCUS
:
356 if (GetKeyState(VK_SHIFT
))
357 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 0xFFFFFFFF);
359 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 1);
360 case FCIDM_DESKBROWSER_SEARCH
:
361 SHFindFiles(NULL
, NULL
);
363 case FCIDM_DESKBROWSER_REFRESH
:
365 m_ShellView
->Refresh();
373 LRESULT
CDesktopBrowser::OnEraseBkgnd(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
375 return (LRESULT
)PaintDesktop((HDC
)wParam
);
378 LRESULT
CDesktopBrowser::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
380 if (wParam
== SIZE_MINIMIZED
)
382 /* Hey, we're the desktop!!! */
383 ::ShowWindow(m_hWnd
, SW_RESTORE
);
389 LRESULT
CDesktopBrowser::OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
393 /* Forward the message */
394 SendMessageW(m_hWndShellView
, uMsg
, wParam
, lParam
);
397 if (uMsg
== WM_SETTINGCHANGE
&& wParam
== SPI_SETWORKAREA
&& m_hWndShellView
!= NULL
)
405 LRESULT
CDesktopBrowser::OnClose(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
407 return _NotifyTray(TWM_DOEXITWINDOWS
, 0, 0);
410 LRESULT
CDesktopBrowser::OnOpenNewWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
412 TRACE("Proxy Desktop message 1035 received.\n");
413 SHOnCWMCommandLine((HANDLE
)lParam
);
417 LRESULT
CDesktopBrowser::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
419 ::SetFocus(m_hWndShellView
);
423 HRESULT
CDesktopBrowser_CreateInstance(IShellDesktopTray
*Tray
, REFIID riid
, void **ppv
)
425 return ShellObjectCreatorInit
<CDesktopBrowser
, IShellDesktopTray
*>(Tray
, riid
, ppv
);
428 /*************************************************************************
429 * SHCreateDesktop [SHELL32.200]
432 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*Tray
)
436 SetLastError(ERROR_INVALID_PARAMETER
);
440 CComPtr
<IShellBrowser
> Browser
;
441 HRESULT hr
= CDesktopBrowser_CreateInstance(Tray
, IID_PPV_ARG(IShellBrowser
, &Browser
));
442 if (FAILED_UNEXPECTEDLY(hr
))
445 return static_cast<HANDLE
>(Browser
.Detach());
448 /*************************************************************************
449 * SHCreateDesktop [SHELL32.201]
452 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
454 if (hDesktop
== NULL
)
456 SetLastError(ERROR_INVALID_PARAMETER
);
463 CComPtr
<IShellBrowser
> browser
;
464 CComPtr
<IShellView
> shellView
;
466 browser
.Attach(static_cast<IShellBrowser
*>(hDesktop
));
467 HRESULT hr
= browser
->QueryActiveShellView(&shellView
);
468 if (FAILED_UNEXPECTEDLY(hr
))
471 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
475 if (shellView
->TranslateAcceleratorW(&Msg
) != S_OK
)
477 TranslateMessage(&Msg
);
478 DispatchMessage(&Msg
);