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
[] = {'P','r','o','g','m','a','n'};
30 static const WCHAR szProgmanWindowName
[] = {
31 'P','r','o','g','r','a','m',' ','M','a','n','a','g','e','r'
34 class CDesktopBrowser
:
35 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
37 public ICommDlgBrowser
,
38 public IServiceProvider
45 HWND hWndDesktopListView
;
46 CComPtr
<IShellDesktopTray
> ShellDesk
;
47 CComPtr
<IShellView
> DesktopView
;
48 IShellBrowser
*DefaultShellBrowser
;
49 LPITEMIDLIST pidlDesktopDirectory
;
50 LPITEMIDLIST pidlDesktop
;
54 HRESULT
Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
);
55 HWND
FindDesktopListView ();
57 HWND
DesktopGetWindowControl(IN UINT id
);
58 static LRESULT CALLBACK
ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
);
59 static BOOL
MessageLoop();
61 // *** IOleWindow methods ***
62 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
63 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
65 // *** IShellBrowser methods ***
66 virtual HRESULT STDMETHODCALLTYPE
InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
);
67 virtual HRESULT STDMETHODCALLTYPE
SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
);
68 virtual HRESULT STDMETHODCALLTYPE
RemoveMenusSB(HMENU hmenuShared
);
69 virtual HRESULT STDMETHODCALLTYPE
SetStatusTextSB(LPCOLESTR pszStatusText
);
70 virtual HRESULT STDMETHODCALLTYPE
EnableModelessSB(BOOL fEnable
);
71 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorSB(MSG
*pmsg
, WORD wID
);
72 virtual HRESULT STDMETHODCALLTYPE
BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
);
73 virtual HRESULT STDMETHODCALLTYPE
GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
);
74 virtual HRESULT STDMETHODCALLTYPE
GetControlWindow(UINT id
, HWND
*lphwnd
);
75 virtual HRESULT STDMETHODCALLTYPE
SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
);
76 virtual HRESULT STDMETHODCALLTYPE
QueryActiveShellView(struct IShellView
**ppshv
);
77 virtual HRESULT STDMETHODCALLTYPE
OnViewWindowActive(struct IShellView
*ppshv
);
78 virtual HRESULT STDMETHODCALLTYPE
SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
);
80 // *** ICommDlgBrowser methods ***
81 virtual HRESULT STDMETHODCALLTYPE
OnDefaultCommand (struct IShellView
*ppshv
);
82 virtual HRESULT STDMETHODCALLTYPE
OnStateChange (struct IShellView
*ppshv
, ULONG uChange
);
83 virtual HRESULT STDMETHODCALLTYPE
IncludeObject (struct IShellView
*ppshv
, LPCITEMIDLIST pidl
);
85 // *** IServiceProvider methods ***
86 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
88 BEGIN_COM_MAP(CDesktopBrowser
)
89 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
90 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser
, IShellBrowser
)
91 COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser
, ICommDlgBrowser
)
92 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
96 CDesktopBrowser::CDesktopBrowser()
100 hWndShellView
= NULL
;
101 hWndDesktopListView
= NULL
;
102 DefaultShellBrowser
= NULL
;
103 pidlDesktopDirectory
= NULL
;
107 CDesktopBrowser::~CDesktopBrowser()
109 if (DesktopView
.p
!= NULL
)
111 if (hWndShellView
!= NULL
)
112 DesktopView
->DestroyViewWindow();
114 hWndShellView
= NULL
;
115 hWndDesktopListView
= NULL
;
118 if (pidlDesktopDirectory
!= NULL
)
120 ILFree(pidlDesktopDirectory
);
121 pidlDesktopDirectory
= NULL
;
124 if (pidlDesktop
!= NULL
)
131 HRESULT
CDesktopBrowser::Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
)
133 CComPtr
<IShellFolder
> psfDesktopFolder
;
138 ShellDesk
= ShellDeskx
;
141 pidlDesktopDirectory
= SHCloneSpecialIDList(hWnd
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
142 hRet
= SHGetSpecialFolderLocation(hWnd
, CSIDL_DESKTOP
, &pidlDesktop
);
146 hRet
= SHGetDesktopFolder(&psfDesktopFolder
);
150 ZeroMemory(&csfv
, sizeof(csfv
));
151 csfv
.cbSize
= sizeof(csfv
);
152 csfv
.pshf
= psfDesktopFolder
;
153 csfv
.psvOuter
= NULL
;
155 hRet
= SHCreateShellFolderViewEx(&csfv
, &DesktopView
);
160 static CDesktopBrowser
*SHDESK_Create(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
162 IShellDesktopTray
*ShellDesk
;
163 CComObject
<CDesktopBrowser
> *pThis
;
166 ShellDesk
= (IShellDesktopTray
*)lpCreateStruct
->lpCreateParams
;
167 if (ShellDesk
== NULL
)
169 WARN("No IShellDesk interface provided!");
173 pThis
= new CComObject
<CDesktopBrowser
>;
178 hRet
= pThis
->Initialize(hWnd
, ShellDesk
);
188 HWND
CDesktopBrowser::FindDesktopListView ()
190 return FindWindowExW(hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
193 BOOL
CDesktopBrowser::CreateDeskWnd()
199 if (!GetClientRect(hWnd
, &rcClient
))
204 fs
.ViewMode
= FVM_ICON
;
205 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
206 hRet
= DesktopView
->CreateViewWindow(NULL
, &fs
, (IShellBrowser
*)this, &rcClient
, &hWndShellView
);
207 if (!SUCCEEDED(hRet
))
210 SetShellWindowEx(hWnd
, FindDesktopListView());
215 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetWindow(HWND
*phwnd
)
227 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode
)
232 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
237 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
242 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared
)
247 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText
)
252 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::EnableModelessSB(BOOL fEnable
)
257 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg
, WORD wID
)
262 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
)
267 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
272 HWND
CDesktopBrowser::DesktopGetWindowControl(IN UINT id
)
288 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
292 hWnd
= DesktopGetWindowControl(id
);
303 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
310 hWnd
= DesktopGetWindowControl(id
);
313 *pret
= SendMessageW(hWnd
,
323 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
325 *ppshv
= DesktopView
;
326 if (DesktopView
!= NULL
)
327 DesktopView
->AddRef();
332 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
337 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
342 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnDefaultCommand(IShellView
*ppshv
)
347 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnStateChange(IShellView
*ppshv
, ULONG uChange
)
352 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::IncludeObject(IShellView
*ppshv
, LPCITEMIDLIST pidl
)
357 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
359 /* FIXME - handle guidService */
360 return QueryInterface(riid
, ppv
);
363 BOOL
CDesktopBrowser::MessageLoop()
368 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
372 TranslateMessage(&Msg
);
373 DispatchMessageW(&Msg
);
380 LRESULT CALLBACK
CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
)
382 CDesktopBrowser
*pThis
= NULL
;
385 if (uMsg
!= WM_NCCREATE
)
387 pThis
= (CDesktopBrowser
*)GetWindowLongPtrW(hwnd
,
393 if (pThis
!= NULL
|| uMsg
== WM_NCCREATE
)
398 return (LRESULT
)PaintDesktop((HDC
)wParam
);
400 case WM_GETISHELLBROWSER
:
401 Ret
= (LRESULT
)((IShellBrowser
*)pThis
);
405 if (wParam
== SIZE_MINIMIZED
)
407 /* Hey, we're the desktop!!! */
415 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
416 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
417 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
418 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
420 /* FIXME: Update work area */
424 case WM_SYSCOLORCHANGE
:
425 case WM_SETTINGCHANGE
:
427 if (uMsg
== WM_SYSCOLORCHANGE
|| wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
429 if (pThis
->hWndShellView
!= NULL
)
431 /* Forward the message */
432 SendMessageW(pThis
->hWndShellView
,
443 pThis
->ShellDesk
->RegisterDesktopWindow(pThis
->hWnd
);
445 if (!pThis
->CreateDeskWnd())
446 WARN("Could not create the desktop view control!\n");
452 LPCREATESTRUCT CreateStruct
= (LPCREATESTRUCT
)lParam
;
453 pThis
= SHDESK_Create(hwnd
, CreateStruct
);
456 WARN("Failed to create desktop structure\n");
460 SetWindowLongPtrW(hwnd
,
475 Ret
= DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
484 RegisterProgmanWindowClass(VOID
)
488 wcProgman
.style
= CS_DBLCLKS
;
489 wcProgman
.lpfnWndProc
= CDesktopBrowser::ProgmanWindowProc
;
490 wcProgman
.cbClsExtra
= 0;
491 wcProgman
.cbWndExtra
= sizeof(CDesktopBrowser
*);
492 wcProgman
.hInstance
= shell32_hInstance
;
493 wcProgman
.hIcon
= NULL
;
494 wcProgman
.hCursor
= LoadCursorW(NULL
, IDC_ARROW
);
495 wcProgman
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+ 1);
496 wcProgman
.lpszMenuName
= NULL
;
497 wcProgman
.lpszClassName
= szProgmanClassName
;
499 return RegisterClassW(&wcProgman
) != 0;
503 /*************************************************************************
504 * SHCreateDesktop [SHELL32.200]
507 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*ShellDesk
)
512 if (ShellDesk
== NULL
)
514 SetLastError(ERROR_INVALID_PARAMETER
);
518 if (RegisterProgmanWindowClass() == 0)
520 WARN("Failed to register the Progman window class!\n");
524 rcDesk
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
525 rcDesk
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
526 rcDesk
.right
= rcDesk
.left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
527 rcDesk
.bottom
= rcDesk
.top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
529 if (IsRectEmpty(&rcDesk
))
531 rcDesk
.left
= rcDesk
.top
= 0;
532 rcDesk
.right
= GetSystemMetrics(SM_CXSCREEN
);
533 rcDesk
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
536 hWndDesk
= CreateWindowExW(0, szProgmanClassName
, szProgmanWindowName
,
537 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
538 rcDesk
.left
, rcDesk
.top
, rcDesk
.right
, rcDesk
.bottom
,
539 NULL
, NULL
, shell32_hInstance
, (LPVOID
)ShellDesk
);
540 if (hWndDesk
!= NULL
)
541 return (HANDLE
)GetWindowLongPtrW(hWndDesk
, 0);
546 /*************************************************************************
547 * SHCreateDesktop [SHELL32.201]
550 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
552 CDesktopBrowser
*Desk
= (CDesktopBrowser
*)hDesktop
;
554 if (Desk
== NULL
|| Desk
->Tag
!= SHDESK_TAG
)
556 SetLastError(ERROR_INVALID_PARAMETER
);
560 return Desk
->MessageLoop();