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 BOOL WINAPI
SetShellWindowEx(HWND
, HWND
);
27 #define SHDESK_TAG 0x4b534544
29 static const WCHAR szProgmanClassName
[] = L
"Progman";
30 static const WCHAR szProgmanWindowName
[] = L
"Program Manager";
32 class CDesktopBrowser
:
33 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
35 public ICommDlgBrowser
,
36 public IServiceProvider
43 HWND hWndDesktopListView
;
44 CComPtr
<IShellDesktopTray
> ShellDesk
;
45 CComPtr
<IShellView
> DesktopView
;
46 CComPtr
<IShellBrowser
> DefaultShellBrowser
;
47 LPITEMIDLIST pidlDesktopDirectory
;
48 LPITEMIDLIST pidlDesktop
;
52 HRESULT
Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
);
53 HWND
FindDesktopListView ();
55 HWND
DesktopGetWindowControl(IN UINT id
);
56 static LRESULT CALLBACK
ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
);
57 static BOOL
MessageLoop();
59 // *** IOleWindow methods ***
60 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
61 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
63 // *** IShellBrowser methods ***
64 virtual HRESULT STDMETHODCALLTYPE
InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
);
65 virtual HRESULT STDMETHODCALLTYPE
SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
);
66 virtual HRESULT STDMETHODCALLTYPE
RemoveMenusSB(HMENU hmenuShared
);
67 virtual HRESULT STDMETHODCALLTYPE
SetStatusTextSB(LPCOLESTR pszStatusText
);
68 virtual HRESULT STDMETHODCALLTYPE
EnableModelessSB(BOOL fEnable
);
69 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorSB(MSG
*pmsg
, WORD wID
);
70 virtual HRESULT STDMETHODCALLTYPE
BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
);
71 virtual HRESULT STDMETHODCALLTYPE
GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
);
72 virtual HRESULT STDMETHODCALLTYPE
GetControlWindow(UINT id
, HWND
*lphwnd
);
73 virtual HRESULT STDMETHODCALLTYPE
SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
);
74 virtual HRESULT STDMETHODCALLTYPE
QueryActiveShellView(struct IShellView
**ppshv
);
75 virtual HRESULT STDMETHODCALLTYPE
OnViewWindowActive(struct IShellView
*ppshv
);
76 virtual HRESULT STDMETHODCALLTYPE
SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
);
78 // *** ICommDlgBrowser methods ***
79 virtual HRESULT STDMETHODCALLTYPE
OnDefaultCommand (struct IShellView
*ppshv
);
80 virtual HRESULT STDMETHODCALLTYPE
OnStateChange (struct IShellView
*ppshv
, ULONG uChange
);
81 virtual HRESULT STDMETHODCALLTYPE
IncludeObject (struct IShellView
*ppshv
, LPCITEMIDLIST pidl
);
83 // *** IServiceProvider methods ***
84 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
86 BEGIN_COM_MAP(CDesktopBrowser
)
87 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
88 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser
, IShellBrowser
)
89 COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser
, ICommDlgBrowser
)
90 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
94 CDesktopBrowser::CDesktopBrowser()
99 hWndDesktopListView
= NULL
;
100 DefaultShellBrowser
= NULL
;
101 pidlDesktopDirectory
= NULL
;
105 CDesktopBrowser::~CDesktopBrowser()
107 if (DesktopView
.p
!= NULL
)
109 if (hWndShellView
!= NULL
)
110 DesktopView
->DestroyViewWindow();
112 hWndShellView
= NULL
;
113 hWndDesktopListView
= NULL
;
116 if (pidlDesktopDirectory
!= NULL
)
118 ILFree(pidlDesktopDirectory
);
119 pidlDesktopDirectory
= NULL
;
122 if (pidlDesktop
!= NULL
)
129 HRESULT
CDesktopBrowser::Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
)
131 CComPtr
<IShellFolder
> psfDesktopFolder
;
136 ShellDesk
= ShellDeskx
;
139 pidlDesktopDirectory
= SHCloneSpecialIDList(hWnd
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
140 hRet
= SHGetSpecialFolderLocation(hWnd
, CSIDL_DESKTOP
, &pidlDesktop
);
144 hRet
= SHGetDesktopFolder(&psfDesktopFolder
);
148 ZeroMemory(&csfv
, sizeof(csfv
));
149 csfv
.cbSize
= sizeof(csfv
);
150 csfv
.pshf
= psfDesktopFolder
;
151 csfv
.psvOuter
= NULL
;
153 hRet
= SHCreateShellFolderViewEx(&csfv
, &DesktopView
);
158 static CDesktopBrowser
*SHDESK_Create(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
160 CComPtr
<IShellDesktopTray
> ShellDesk
;
161 CComObject
<CDesktopBrowser
> *pThis
;
164 ShellDesk
= (IShellDesktopTray
*)lpCreateStruct
->lpCreateParams
;
165 if (ShellDesk
== NULL
)
167 WARN("No IShellDesk interface provided!");
171 pThis
= new CComObject
<CDesktopBrowser
>;
176 hRet
= pThis
->Initialize(hWnd
, ShellDesk
);
186 HWND
CDesktopBrowser::FindDesktopListView ()
188 return FindWindowExW(hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
191 BOOL
CDesktopBrowser::CreateDeskWnd()
197 if (!GetClientRect(hWnd
, &rcClient
))
202 fs
.ViewMode
= FVM_ICON
;
203 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
204 hRet
= DesktopView
->CreateViewWindow(NULL
, &fs
, (IShellBrowser
*)this, &rcClient
, &hWndShellView
);
205 if (!SUCCEEDED(hRet
))
208 SetShellWindowEx(hWnd
, FindDesktopListView());
213 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetWindow(HWND
*phwnd
)
225 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode
)
230 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
235 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
240 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared
)
245 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText
)
250 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::EnableModelessSB(BOOL fEnable
)
255 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg
, WORD wID
)
260 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
)
263 * We should use IShellWindows interface here in order to attempt to
264 * find an open shell window that shows the requested pidl and activate it
267 return SHOpenNewFrame((LPITEMIDLIST
)pidl
, NULL
, 0, 0);
270 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
275 HWND
CDesktopBrowser::DesktopGetWindowControl(IN UINT id
)
291 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
295 hWnd
= DesktopGetWindowControl(id
);
306 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
313 hWnd
= DesktopGetWindowControl(id
);
316 *pret
= SendMessageW(hWnd
,
326 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
328 *ppshv
= DesktopView
;
329 if (DesktopView
!= NULL
)
330 DesktopView
->AddRef();
335 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
340 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
345 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnDefaultCommand(IShellView
*ppshv
)
350 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnStateChange(IShellView
*ppshv
, ULONG uChange
)
355 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::IncludeObject(IShellView
*ppshv
, LPCITEMIDLIST pidl
)
360 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
362 /* FIXME - handle guidService */
363 return QueryInterface(riid
, ppv
);
366 BOOL
CDesktopBrowser::MessageLoop()
371 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
375 TranslateMessage(&Msg
);
376 DispatchMessageW(&Msg
);
383 LRESULT CALLBACK
CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
)
385 CDesktopBrowser
*pThis
= NULL
;
388 if (uMsg
!= WM_NCCREATE
)
390 pThis
= reinterpret_cast<CDesktopBrowser
*>(GetWindowLongPtrW(hwnd
, 0));
395 if (pThis
!= NULL
|| uMsg
== WM_NCCREATE
)
400 return (LRESULT
)PaintDesktop((HDC
)wParam
);
402 case WM_GETISHELLBROWSER
:
403 Ret
= (LRESULT
)((IShellBrowser
*)pThis
);
407 if (wParam
== SIZE_MINIMIZED
)
409 /* Hey, we're the desktop!!! */
417 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
418 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
419 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
420 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
422 /* FIXME: Update work area */
423 DBG_UNREFERENCED_LOCAL_VARIABLE(rcDesktop
);
427 case WM_SYSCOLORCHANGE
:
428 case WM_SETTINGCHANGE
:
430 if (uMsg
== WM_SYSCOLORCHANGE
|| wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
432 if (pThis
->hWndShellView
!= NULL
)
434 /* Forward the message */
435 SendMessageW(pThis
->hWndShellView
,
446 pThis
->ShellDesk
->RegisterDesktopWindow(pThis
->hWnd
);
448 if (!pThis
->CreateDeskWnd())
449 WARN("Could not create the desktop view control!\n");
455 LPCREATESTRUCT CreateStruct
= (LPCREATESTRUCT
)lParam
;
456 pThis
= SHDESK_Create(hwnd
, CreateStruct
);
459 WARN("Failed to create desktop structure\n");
463 SetWindowLongPtrW(hwnd
,
476 case WM_EXPLORER_OPEN_NEW_WINDOW
:
477 DbgPrint("Proxy Desktop message 1035 received.\n");
478 SHOnCWMCommandLine((HANDLE
)lParam
);
483 Ret
= DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
492 RegisterProgmanWindowClass(VOID
)
496 wcProgman
.style
= CS_DBLCLKS
;
497 wcProgman
.lpfnWndProc
= CDesktopBrowser::ProgmanWindowProc
;
498 wcProgman
.cbClsExtra
= 0;
499 wcProgman
.cbWndExtra
= sizeof(CDesktopBrowser
*);
500 wcProgman
.hInstance
= shell32_hInstance
;
501 wcProgman
.hIcon
= NULL
;
502 wcProgman
.hCursor
= LoadCursorW(NULL
, IDC_ARROW
);
503 wcProgman
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+ 1);
504 wcProgman
.lpszMenuName
= NULL
;
505 wcProgman
.lpszClassName
= szProgmanClassName
;
507 return RegisterClassW(&wcProgman
) != 0;
511 /*************************************************************************
512 * SHCreateDesktop [SHELL32.200]
515 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*ShellDesk
)
520 if (ShellDesk
== NULL
)
522 SetLastError(ERROR_INVALID_PARAMETER
);
526 if (RegisterProgmanWindowClass() == 0)
528 WARN("Failed to register the Progman window class!\n");
532 rcDesk
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
533 rcDesk
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
534 rcDesk
.right
= rcDesk
.left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
535 rcDesk
.bottom
= rcDesk
.top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
537 if (IsRectEmpty(&rcDesk
))
539 rcDesk
.left
= rcDesk
.top
= 0;
540 rcDesk
.right
= GetSystemMetrics(SM_CXSCREEN
);
541 rcDesk
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
544 hWndDesk
= CreateWindowExW(WS_EX_TOOLWINDOW
, szProgmanClassName
, szProgmanWindowName
,
545 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
546 rcDesk
.left
, rcDesk
.top
, rcDesk
.right
, rcDesk
.bottom
,
547 NULL
, NULL
, shell32_hInstance
, (LPVOID
)ShellDesk
);
548 if (hWndDesk
!= NULL
)
549 return (HANDLE
)GetWindowLongPtrW(hWndDesk
, 0);
554 /*************************************************************************
555 * SHCreateDesktop [SHELL32.201]
558 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
560 CDesktopBrowser
*Desk
= static_cast<CDesktopBrowser
*>(hDesktop
);
562 if (Desk
== NULL
|| Desk
->Tag
!= SHDESK_TAG
)
564 SetLastError(ERROR_INVALID_PARAMETER
);
568 return Desk
->MessageLoop();