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
23 WINE_DEFAULT_DEBUG_CHANNEL(desktop
);
25 #define SHDESK_TAG 0x4b534544
27 static const WCHAR szProgmanClassName
[] = L
"Progman";
28 static const WCHAR szProgmanWindowName
[] = L
"Program Manager";
30 class CDesktopBrowser
:
31 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
33 public ICommDlgBrowser
,
34 public IServiceProvider
41 HWND hWndDesktopListView
;
42 CComPtr
<IShellDesktopTray
> ShellDesk
;
43 CComPtr
<IShellView
> DesktopView
;
44 IShellBrowser
*DefaultShellBrowser
;
45 LPITEMIDLIST pidlDesktopDirectory
;
46 LPITEMIDLIST pidlDesktop
;
50 HRESULT
Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
);
51 HWND
FindDesktopListView();
53 HWND
DesktopGetWindowControl(IN UINT id
);
54 static LRESULT CALLBACK
ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
);
55 static BOOL
MessageLoop();
57 // *** IOleWindow methods ***
58 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
59 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
61 // *** IShellBrowser methods ***
62 virtual HRESULT STDMETHODCALLTYPE
InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
);
63 virtual HRESULT STDMETHODCALLTYPE
SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
);
64 virtual HRESULT STDMETHODCALLTYPE
RemoveMenusSB(HMENU hmenuShared
);
65 virtual HRESULT STDMETHODCALLTYPE
SetStatusTextSB(LPCOLESTR pszStatusText
);
66 virtual HRESULT STDMETHODCALLTYPE
EnableModelessSB(BOOL fEnable
);
67 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorSB(MSG
*pmsg
, WORD wID
);
68 virtual HRESULT STDMETHODCALLTYPE
BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
);
69 virtual HRESULT STDMETHODCALLTYPE
GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
);
70 virtual HRESULT STDMETHODCALLTYPE
GetControlWindow(UINT id
, HWND
*lphwnd
);
71 virtual HRESULT STDMETHODCALLTYPE
SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
);
72 virtual HRESULT STDMETHODCALLTYPE
QueryActiveShellView(struct IShellView
**ppshv
);
73 virtual HRESULT STDMETHODCALLTYPE
OnViewWindowActive(struct IShellView
*ppshv
);
74 virtual HRESULT STDMETHODCALLTYPE
SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
);
76 // *** ICommDlgBrowser methods ***
77 virtual HRESULT STDMETHODCALLTYPE
OnDefaultCommand(struct IShellView
*ppshv
);
78 virtual HRESULT STDMETHODCALLTYPE
OnStateChange(struct IShellView
*ppshv
, ULONG uChange
);
79 virtual HRESULT STDMETHODCALLTYPE
IncludeObject(struct IShellView
*ppshv
, LPCITEMIDLIST pidl
);
81 // *** IServiceProvider methods ***
82 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
84 BEGIN_COM_MAP(CDesktopBrowser
)
85 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
86 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser
, IShellBrowser
)
87 COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser
, ICommDlgBrowser
)
88 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
92 CDesktopBrowser::CDesktopBrowser()
97 hWndDesktopListView
= NULL
;
98 DefaultShellBrowser
= NULL
;
99 pidlDesktopDirectory
= NULL
;
103 CDesktopBrowser::~CDesktopBrowser()
105 if (DesktopView
.p
!= NULL
)
107 if (hWndShellView
!= NULL
)
108 DesktopView
->DestroyViewWindow();
110 hWndShellView
= NULL
;
111 hWndDesktopListView
= NULL
;
114 if (pidlDesktopDirectory
!= NULL
)
116 ILFree(pidlDesktopDirectory
);
117 pidlDesktopDirectory
= NULL
;
120 if (pidlDesktop
!= NULL
)
127 HRESULT
CDesktopBrowser::Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
)
129 CComPtr
<IShellFolder
> psfDesktopFolder
;
134 ShellDesk
= ShellDeskx
;
137 pidlDesktopDirectory
= SHCloneSpecialIDList(hWnd
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
138 hRet
= SHGetSpecialFolderLocation(hWnd
, CSIDL_DESKTOP
, &pidlDesktop
);
142 hRet
= SHGetDesktopFolder(&psfDesktopFolder
);
146 ZeroMemory(&csfv
, sizeof(csfv
));
147 csfv
.cbSize
= sizeof(csfv
);
148 csfv
.pshf
= psfDesktopFolder
;
149 csfv
.psvOuter
= NULL
;
151 hRet
= SHCreateShellFolderViewEx(&csfv
, &DesktopView
);
156 static CDesktopBrowser
*SHDESK_Create(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
158 IShellDesktopTray
*ShellDesk
;
159 CComObject
<CDesktopBrowser
> *pThis
;
162 ShellDesk
= static_cast<IShellDesktopTray
*>(lpCreateStruct
->lpCreateParams
);
163 if (ShellDesk
== NULL
)
165 WARN("No IShellDesk interface provided!");
169 pThis
= new CComObject
<CDesktopBrowser
>;
174 hRet
= pThis
->Initialize(hWnd
, ShellDesk
);
184 HWND
CDesktopBrowser::FindDesktopListView()
186 return FindWindowExW(hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
189 BOOL
CDesktopBrowser::CreateDeskWnd()
195 if (!GetClientRect(hWnd
, &rcClient
))
200 fs
.ViewMode
= FVM_ICON
;
201 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
202 hRet
= DesktopView
->CreateViewWindow(NULL
, &fs
, static_cast<IShellBrowser
*>(this), &rcClient
, &hWndShellView
);
203 if (!SUCCEEDED(hRet
))
206 SetShellWindowEx(hWnd
, FindDesktopListView());
209 /* A windows 8 specific hack */
210 ::ShowWindow(hWndShellView
, SW_SHOW
);
211 ::ShowWindow(FindDesktopListView(), SW_SHOW
);
217 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetWindow(HWND
*phwnd
)
229 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode
)
234 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
239 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
244 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared
)
249 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText
)
254 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::EnableModelessSB(BOOL fEnable
)
259 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg
, WORD wID
)
264 typedef HRESULT(WINAPI
*SH_OPEN_NEW_FRAME
)(LPITEMIDLIST pidl
, IUnknown
*paramC
, long param10
, long param14
);
266 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
)
268 /* FIXME: Implement executing filebrowser.exe and somehow pass the pidl to it */
270 /* Returning failure here will make windows 7 and 8 to use the default file browser */
274 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
279 HWND
CDesktopBrowser::DesktopGetWindowControl(IN UINT id
)
295 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
299 hWnd
= DesktopGetWindowControl(id
);
310 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
317 hWnd
= DesktopGetWindowControl(id
);
320 *pret
= SendMessageW(hWnd
, uMsg
, wParam
, lParam
);
327 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
329 *ppshv
= DesktopView
;
330 if (DesktopView
!= NULL
)
331 DesktopView
->AddRef();
336 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
341 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
346 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnDefaultCommand(IShellView
*ppshv
)
351 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnStateChange(IShellView
*ppshv
, ULONG uChange
)
356 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::IncludeObject(IShellView
*ppshv
, LPCITEMIDLIST pidl
)
361 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
363 /* FIXME - handle guidService */
364 return QueryInterface(riid
, ppv
);
367 BOOL
CDesktopBrowser::MessageLoop()
372 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
376 TranslateMessage(&Msg
);
377 DispatchMessageW(&Msg
);
384 LRESULT CALLBACK
CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
)
386 CDesktopBrowser
*pThis
= NULL
;
389 if (uMsg
!= WM_NCCREATE
)
391 pThis
= reinterpret_cast<CDesktopBrowser
*>(GetWindowLongPtrW(hwnd
, 0));
396 if (pThis
!= NULL
|| uMsg
== WM_NCCREATE
)
401 return (LRESULT
) PaintDesktop(reinterpret_cast<HDC
>(wParam
));
403 case WM_GETISHELLBROWSER
:
404 Ret
= reinterpret_cast<LRESULT
>(static_cast<IShellBrowser
*>(pThis
));
408 if (wParam
== SIZE_MINIMIZED
)
410 /* Hey, we're the desktop!!! */
417 /* FIXME: Update work area */
421 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
422 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
423 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
424 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
429 case WM_SYSCOLORCHANGE
:
430 case WM_SETTINGCHANGE
:
432 if (uMsg
== WM_SYSCOLORCHANGE
|| wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
434 if (pThis
->hWndShellView
!= NULL
)
436 /* Forward the message */
437 SendMessageW(pThis
->hWndShellView
,
448 pThis
->ShellDesk
->RegisterDesktopWindow(pThis
->hWnd
);
450 if (!pThis
->CreateDeskWnd())
451 WARN("Could not create the desktop view control!\n");
457 LPCREATESTRUCT CreateStruct
= reinterpret_cast<LPCREATESTRUCT
>(lParam
);
458 pThis
= SHDESK_Create(hwnd
, CreateStruct
);
461 WARN("Failed to create desktop structure\n");
465 SetWindowLongPtrW(hwnd
,
467 reinterpret_cast<LONG_PTR
>(pThis
));
480 Ret
= DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
489 RegisterProgmanWindowClass(VOID
)
493 wcProgman
.style
= CS_DBLCLKS
;
494 wcProgman
.lpfnWndProc
= CDesktopBrowser::ProgmanWindowProc
;
495 wcProgman
.cbClsExtra
= 0;
496 wcProgman
.cbWndExtra
= sizeof(CDesktopBrowser
*);
497 wcProgman
.hInstance
= shell32_hInstance
;
498 wcProgman
.hIcon
= NULL
;
499 wcProgman
.hCursor
= LoadCursorW(NULL
, IDC_ARROW
);
500 wcProgman
.hbrBackground
= (HBRUSH
) (COLOR_BACKGROUND
+ 1);
501 wcProgman
.lpszMenuName
= NULL
;
502 wcProgman
.lpszClassName
= szProgmanClassName
;
504 return RegisterClassW(&wcProgman
) != 0;
508 /*************************************************************************
509 * SHCreateDesktop [SHELL32.200]
512 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*ShellDesk
)
517 if (ShellDesk
== NULL
)
519 SetLastError(ERROR_INVALID_PARAMETER
);
523 if (RegisterProgmanWindowClass() == 0)
525 WARN("Failed to register the Progman window class!\n");
529 rcDesk
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
530 rcDesk
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
531 rcDesk
.right
= rcDesk
.left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
532 rcDesk
.bottom
= rcDesk
.top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
534 if (IsRectEmpty(&rcDesk
))
536 rcDesk
.left
= rcDesk
.top
= 0;
537 rcDesk
.right
= GetSystemMetrics(SM_CXSCREEN
);
538 rcDesk
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
541 hWndDesk
= CreateWindowExW(WS_EX_TOOLWINDOW
, szProgmanClassName
, szProgmanWindowName
,
542 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
543 rcDesk
.left
, rcDesk
.top
, rcDesk
.right
, rcDesk
.bottom
,
544 NULL
, NULL
, shell32_hInstance
, reinterpret_cast<LPVOID
>(ShellDesk
));
545 if (hWndDesk
!= NULL
)
546 return (HANDLE
) GetWindowLongPtrW(hWndDesk
, 0);
551 /*************************************************************************
552 * SHCreateDesktop [SHELL32.201]
555 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
557 CDesktopBrowser
*Desk
= reinterpret_cast<CDesktopBrowser
*>(hDesktop
);
559 if (Desk
== NULL
|| Desk
->Tag
!= SHDESK_TAG
)
561 SetLastError(ERROR_INVALID_PARAMETER
);
565 return Desk
->MessageLoop();