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 static const IShellBrowserVtbl SHDESK_Vtbl
;
35 static const ICommDlgBrowserVtbl SHDESK_ICommDlgBrowser_Vtbl
;
36 static const IServiceProviderVtbl SHDESK_IServiceProvider_Vtbl
;
38 typedef struct _SHDESK
41 const IShellBrowserVtbl
*lpVtbl
;
42 const ICommDlgBrowserVtbl
*lpVtblCommDlgBrowser
;
43 const IServiceProviderVtbl
*lpVtblServiceProvider
;
47 HWND hWndDesktopListView
;
48 IShellDesktopTray
*ShellDesk
;
49 IShellView
*DesktopView
;
50 IShellBrowser
*DefaultShellBrowser
;
51 LPITEMIDLIST pidlDesktopDirectory
;
52 LPITEMIDLIST pidlDesktop
;
56 IUnknown_from_impl(SHDESK
*This
)
58 return (IUnknown
*)&This
->lpVtbl
;
61 static IShellBrowser
*
62 IShellBrowser_from_impl(SHDESK
*This
)
64 return (IShellBrowser
*)&This
->lpVtbl
;
68 IOleWindow_from_impl(SHDESK
*This
)
70 return (IOleWindow
*)&This
->lpVtbl
;
73 static ICommDlgBrowser
*
74 ICommDlgBrowser_from_impl(SHDESK
*This
)
76 return (ICommDlgBrowser
*)&This
->lpVtblCommDlgBrowser
;
79 static IServiceProvider
*
80 IServiceProvider_from_impl(SHDESK
*This
)
82 return (IServiceProvider
*)&This
->lpVtblServiceProvider
;
86 impl_from_IShellBrowser(IShellBrowser
*iface
)
88 return (SHDESK
*)((ULONG_PTR
)iface
- FIELD_OFFSET(SHDESK
, lpVtbl
));
92 impl_from_ICommDlgBrowser(ICommDlgBrowser
*iface
)
94 return (SHDESK
*)((ULONG_PTR
)iface
- FIELD_OFFSET(SHDESK
, lpVtblCommDlgBrowser
));
98 impl_from_IServiceProvider(IServiceProvider
*iface
)
100 return (SHDESK
*)((ULONG_PTR
)iface
- FIELD_OFFSET(SHDESK
, lpVtblServiceProvider
));
104 SHDESK_Free(SHDESK
*This
)
106 if (This
->ShellDesk
!= NULL
)
107 IShellDesktopTray_Release(This
->ShellDesk
);
109 if (This
->DesktopView
!= NULL
)
111 if (This
->hWndShellView
!= NULL
)
112 IShellView_DestroyViewWindow(This
->DesktopView
);
114 IShellView_Release(This
->DesktopView
);
115 This
->DesktopView
= NULL
;
116 This
->hWndShellView
= NULL
;
117 This
->hWndDesktopListView
= NULL
;
120 if (This
->pidlDesktopDirectory
!= NULL
)
122 ILFree(This
->pidlDesktopDirectory
);
123 This
->pidlDesktopDirectory
= NULL
;
126 if (This
->pidlDesktop
!= NULL
)
128 ILFree(This
->pidlDesktop
);
129 This
->pidlDesktop
= NULL
;
132 ZeroMemory(This
, sizeof(SHDESK
));
133 LocalFree((HLOCAL
)This
);
136 static ULONG STDMETHODCALLTYPE
137 SHDESK_Release(IShellBrowser
*iface
)
139 SHDESK
*This
= impl_from_IShellBrowser(iface
);
142 Ret
= InterlockedDecrement(&This
->Ref
);
149 static ULONG STDMETHODCALLTYPE
150 SHDESK_AddRef(IShellBrowser
*iface
)
152 SHDESK
*This
= impl_from_IShellBrowser(iface
);
154 return InterlockedIncrement(&This
->Ref
);
157 static HRESULT STDMETHODCALLTYPE
158 SHDESK_QueryInterface(IShellBrowser
*iface
, REFIID riid
, LPVOID
*ppvObj
)
165 This
= impl_from_IShellBrowser(iface
);
167 if (IsEqualIID(riid
, &IID_IUnknown
))
169 *ppvObj
= IUnknown_from_impl(This
);
171 else if (This
->DefaultShellBrowser
!= NULL
)
173 return IShellBrowser_QueryInterface(This
->DefaultShellBrowser
, riid
, ppvObj
);
175 else if (IsEqualIID(riid
, &IID_IOleWindow
))
177 *ppvObj
= IOleWindow_from_impl(This
);
179 else if (IsEqualIID(riid
, &IID_IShellBrowser
))
181 *ppvObj
= IShellBrowser_from_impl(This
);
183 else if (IsEqualIID(riid
, &IID_ICommDlgBrowser
))
185 *ppvObj
= ICommDlgBrowser_from_impl(This
);
187 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
189 *ppvObj
= IServiceProvider_from_impl(This
);
194 return E_NOINTERFACE
;
197 SHDESK_AddRef(iface
);
202 SHDESK_Create(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
204 IShellFolder
*psfDesktopFolder
;
205 IShellDesktopTray
*ShellDesk
;
210 ShellDesk
= (IShellDesktopTray
*)lpCreateStruct
->lpCreateParams
;
211 if (ShellDesk
== NULL
)
213 WARN("No IShellDesk interface provided!");
217 This
= (PSHDESK
)LocalAlloc(LMEM_FIXED
, sizeof(SHDESK
));
221 ZeroMemory(This
, sizeof(SHDESK
));
222 This
->Tag
= SHDESK_TAG
;
223 This
->lpVtbl
= &SHDESK_Vtbl
;
224 This
->lpVtblCommDlgBrowser
= &SHDESK_ICommDlgBrowser_Vtbl
;
225 This
->lpVtblServiceProvider
= &SHDESK_IServiceProvider_Vtbl
;
228 This
->ShellDesk
= ShellDesk
;
229 IShellDesktopTray_AddRef(ShellDesk
);
231 This
->pidlDesktopDirectory
= SHCloneSpecialIDList(This
->hWnd
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
232 hRet
= SHGetSpecialFolderLocation(This
->hWnd
, CSIDL_DESKTOP
, &This
->pidlDesktop
);
233 if (!SUCCEEDED(hRet
))
236 hRet
= SHGetDesktopFolder(&psfDesktopFolder
);
237 if (!SUCCEEDED(hRet
))
240 ZeroMemory(&csfv
, sizeof(csfv
));
241 csfv
.cbSize
= sizeof(csfv
);
242 csfv
.pshf
= psfDesktopFolder
;
243 csfv
.psvOuter
= NULL
;
245 hRet
= SHCreateShellFolderViewEx(&csfv
, &This
->DesktopView
);
246 IShellFolder_Release(psfDesktopFolder
);
248 if (!SUCCEEDED(hRet
))
251 SHDESK_Release(IShellBrowser_from_impl(This
));
259 SHDESK_FindDesktopListView (SHDESK
*This
)
261 return FindWindowExW(This
->hWndShellView
,
268 SHDESK_CreateDeskWnd(SHDESK
*This
)
270 IShellBrowser
*ShellBrowser
;
275 if (!GetClientRect(This
->hWnd
,
281 ShellBrowser
= IShellBrowser_from_impl(This
);
283 fs
.ViewMode
= FVM_ICON
;
284 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
285 hRet
= IShellView_CreateViewWindow(This
->DesktopView
, NULL
, &fs
, ShellBrowser
, &rcClient
, &This
->hWndShellView
);
286 if (!SUCCEEDED(hRet
))
289 SetShellWindowEx (This
->hWnd
,
290 SHDESK_FindDesktopListView (This
));
295 static HRESULT STDMETHODCALLTYPE
296 SHDESK_GetWindow(IShellBrowser
*iface
, HWND
*phwnd
)
298 SHDESK
*This
= impl_from_IShellBrowser(iface
);
300 if (This
->hWnd
!= NULL
)
310 static HRESULT STDMETHODCALLTYPE
311 SHDESK_ContextSensitiveHelp(IShellBrowser
*iface
, BOOL fEnterMode
)
316 static HRESULT STDMETHODCALLTYPE
317 SHDESK_InsertMenusSB(IShellBrowser
*iface
, HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
322 static HRESULT STDMETHODCALLTYPE
323 SHDESK_SetMenuSB(IShellBrowser
*iface
, HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
328 static HRESULT STDMETHODCALLTYPE
329 SHDESK_RemoveMenusSB(IShellBrowser
*iface
, HMENU hmenuShared
)
334 static HRESULT STDMETHODCALLTYPE
335 SHDESK_SetStatusTextSB(IShellBrowser
*iface
, LPCOLESTR lpszStatusText
)
340 static HRESULT STDMETHODCALLTYPE
341 SHDESK_EnableModelessSB(IShellBrowser
*iface
, BOOL fEnable
)
346 static HRESULT STDMETHODCALLTYPE
347 SHDESK_TranslateAcceleratorSB(IShellBrowser
*iface
, LPMSG lpmsg
, WORD wID
)
352 static HRESULT STDMETHODCALLTYPE
353 SHDESK_BrowseObject(IShellBrowser
*iface
, LPCITEMIDLIST pidl
, UINT wFlags
)
358 static HRESULT STDMETHODCALLTYPE
359 SHDESK_GetViewStateStream(IShellBrowser
*iface
, DWORD grfMode
, IStream
**ppStrm
)
365 DesktopGetWindowControl(IN SHDESK
*This
,
382 static HRESULT STDMETHODCALLTYPE
383 SHDESK_GetControlWindow(IShellBrowser
*iface
, UINT id
, HWND
*lphwnd
)
385 SHDESK
*This
= impl_from_IShellBrowser(iface
);
388 hWnd
= DesktopGetWindowControl(This
,
400 static HRESULT STDMETHODCALLTYPE
401 SHDESK_SendControlMsg(IShellBrowser
*iface
, UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
403 SHDESK
*This
= impl_from_IShellBrowser(iface
);
409 hWnd
= DesktopGetWindowControl(This
,
413 *pret
= SendMessageW(hWnd
,
423 static HRESULT STDMETHODCALLTYPE
424 SHDESK_QueryActiveShellView(IShellBrowser
*iface
, IShellView
**ppshv
)
426 IShellView
*ActiveView
;
427 SHDESK
*This
= impl_from_IShellBrowser(iface
);
429 ActiveView
= This
->DesktopView
;
430 SHDESK_AddRef(iface
);
436 static HRESULT STDMETHODCALLTYPE
437 SHDESK_OnViewWindowActive(IShellBrowser
*iface
, IShellView
*ppshv
)
442 static HRESULT STDMETHODCALLTYPE
443 SHDESK_SetToolbarItems(IShellBrowser
*iface
, LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
448 static HRESULT STDMETHODCALLTYPE
449 SHDESK_ICommDlgBrowser_QueryInterface(ICommDlgBrowser
*iface
, REFIID riid
, LPVOID
*ppvObj
)
451 SHDESK
*This
= impl_from_ICommDlgBrowser(iface
);
452 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
454 return SHDESK_QueryInterface(ShellBrowser
, riid
, ppvObj
);
457 static ULONG STDMETHODCALLTYPE
458 SHDESK_ICommDlgBrowser_Release(ICommDlgBrowser
*iface
)
460 SHDESK
*This
= impl_from_ICommDlgBrowser(iface
);
461 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
463 return SHDESK_Release(ShellBrowser
);
466 static ULONG STDMETHODCALLTYPE
467 SHDESK_ICommDlgBrowser_AddRef(ICommDlgBrowser
*iface
)
469 SHDESK
*This
= impl_from_ICommDlgBrowser(iface
);
470 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
472 return SHDESK_AddRef(ShellBrowser
);
475 static HRESULT STDMETHODCALLTYPE
476 SHDESK_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser
*iface
, IShellView
*ppshv
)
481 static HRESULT STDMETHODCALLTYPE
482 SHDESK_ICommDlgBrowser_OnStateChange(ICommDlgBrowser
*iface
, IShellView
*ppshv
, ULONG uChange
)
487 static HRESULT STDMETHODCALLTYPE
488 SHDESK_ICommDlgBrowser_IncludeObject(ICommDlgBrowser
*iface
, IShellView
*ppshv
, LPCITEMIDLIST pidl
)
493 static const ICommDlgBrowserVtbl SHDESK_ICommDlgBrowser_Vtbl
=
496 SHDESK_ICommDlgBrowser_QueryInterface
,
497 SHDESK_ICommDlgBrowser_AddRef
,
498 SHDESK_ICommDlgBrowser_Release
,
499 /* ICommDlgBrowser */
500 SHDESK_ICommDlgBrowser_OnDefaultCommand
,
501 SHDESK_ICommDlgBrowser_OnStateChange
,
502 SHDESK_ICommDlgBrowser_IncludeObject
505 static HRESULT STDMETHODCALLTYPE
506 SHDESK_IServiceProvider_QueryInterface(IServiceProvider
*iface
, REFIID riid
, LPVOID
*ppvObj
)
508 SHDESK
*This
= impl_from_IServiceProvider(iface
);
509 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
511 return SHDESK_QueryInterface(ShellBrowser
, riid
, ppvObj
);
514 static ULONG STDMETHODCALLTYPE
515 SHDESK_IServiceProvider_Release(IServiceProvider
*iface
)
517 SHDESK
*This
= impl_from_IServiceProvider(iface
);
518 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
520 return SHDESK_Release(ShellBrowser
);
523 static ULONG STDMETHODCALLTYPE
524 SHDESK_IServiceProvider_AddRef(IServiceProvider
*iface
)
526 SHDESK
*This
= impl_from_IServiceProvider(iface
);
527 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
529 return SHDESK_AddRef(ShellBrowser
);
532 static HRESULT STDMETHODCALLTYPE
533 SHDESK_IServiceProvider_QueryService(IServiceProvider
*iface
, REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
535 /* FIXME - handle guidService */
536 return SHDESK_IServiceProvider_QueryInterface(iface
, riid
, ppv
);
539 static const IServiceProviderVtbl SHDESK_IServiceProvider_Vtbl
=
542 SHDESK_IServiceProvider_QueryInterface
,
543 SHDESK_IServiceProvider_AddRef
,
544 SHDESK_IServiceProvider_Release
,
545 /* IServiceProvider */
546 SHDESK_IServiceProvider_QueryService
550 SHDESK_MessageLoop(SHDESK
*This
)
555 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
559 TranslateMessage(&Msg
);
560 DispatchMessageW(&Msg
);
567 static LRESULT CALLBACK
568 ProgmanWindowProc(IN HWND hwnd
,
576 if (uMsg
!= WM_NCCREATE
)
578 This
= (SHDESK
*)GetWindowLongPtrW(hwnd
,
584 if (This
!= NULL
|| uMsg
== WM_NCCREATE
)
589 return (LRESULT
)PaintDesktop((HDC
)wParam
);
591 case WM_GETISHELLBROWSER
:
592 Ret
= (LRESULT
)IShellBrowser_from_impl(This
);
596 if (wParam
== SIZE_MINIMIZED
)
598 /* Hey, we're the desktop!!! */
606 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
607 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
608 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
609 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
611 /* FIXME: Update work area */
615 case WM_SYSCOLORCHANGE
:
617 InvalidateRect(This
->hWnd
,
621 if (This
->hWndShellView
!= NULL
)
623 /* Forward the message */
624 SendMessageW(This
->hWndShellView
,
634 IShellDesktopTray_RegisterDesktopWindow(This
->ShellDesk
,
637 if (!SHDESK_CreateDeskWnd(This
))
638 WARN("Could not create the desktop view control!\n");
644 LPCREATESTRUCT CreateStruct
= (LPCREATESTRUCT
)lParam
;
645 This
= SHDESK_Create(hwnd
, CreateStruct
);
648 WARN("Failed to create desktop structure\n");
652 SetWindowLongPtrW(hwnd
,
667 Ret
= DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
676 RegisterProgmanWindowClass(VOID
)
680 wcProgman
.style
= CS_DBLCLKS
;
681 wcProgman
.lpfnWndProc
= ProgmanWindowProc
;
682 wcProgman
.cbClsExtra
= 0;
683 wcProgman
.cbWndExtra
= sizeof(PSHDESK
);
684 wcProgman
.hInstance
= shell32_hInstance
;
685 wcProgman
.hIcon
= NULL
;
686 wcProgman
.hCursor
= LoadCursorW(NULL
,
688 wcProgman
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+ 1);
689 wcProgman
.lpszMenuName
= NULL
;
690 wcProgman
.lpszClassName
= szProgmanClassName
;
692 return RegisterClassW(&wcProgman
) != 0;
696 /*************************************************************************
697 * SHCreateDesktop [SHELL32.200]
700 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*ShellDesk
)
705 if (ShellDesk
== NULL
)
707 SetLastError(ERROR_INVALID_PARAMETER
);
711 if (RegisterProgmanWindowClass() == 0)
713 WARN("Failed to register the Progman window class!\n");
717 rcDesk
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
718 rcDesk
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
719 rcDesk
.right
= rcDesk
.left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
720 rcDesk
.bottom
= rcDesk
.top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
722 if (IsRectEmpty(&rcDesk
))
724 rcDesk
.left
= rcDesk
.top
= 0;
725 rcDesk
.right
= GetSystemMetrics(SM_CXSCREEN
);
726 rcDesk
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
729 hWndDesk
= CreateWindowExW(0, szProgmanClassName
, szProgmanWindowName
,
730 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
731 rcDesk
.left
, rcDesk
.top
, rcDesk
.right
, rcDesk
.bottom
,
732 NULL
, NULL
, shell32_hInstance
, (LPVOID
)ShellDesk
);
733 if (hWndDesk
!= NULL
)
734 return (HANDLE
)GetWindowLongPtrW(hWndDesk
, 0);
739 /*************************************************************************
740 * SHCreateDesktop [SHELL32.201]
743 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
745 PSHDESK Desk
= (PSHDESK
)hDesktop
;
747 if (Desk
== NULL
|| Desk
->Tag
!= SHDESK_TAG
)
749 SetLastError(ERROR_INVALID_PARAMETER
);
753 return SHDESK_MessageLoop(Desk
);
756 static const IShellBrowserVtbl SHDESK_Vtbl
=
759 SHDESK_QueryInterface
,
764 SHDESK_ContextSensitiveHelp
,
766 SHDESK_InsertMenusSB
,
768 SHDESK_RemoveMenusSB
,
769 SHDESK_SetStatusTextSB
,
770 SHDESK_EnableModelessSB
,
771 SHDESK_TranslateAcceleratorSB
,
773 SHDESK_GetViewStateStream
,
774 SHDESK_GetControlWindow
,
775 SHDESK_SendControlMsg
,
776 SHDESK_QueryActiveShellView
,
777 SHDESK_OnViewWindowActive
,
778 SHDESK_SetToolbarItems