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 'KSED'
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
42 HWND hWndDesktopListView
;
43 CComPtr
<IShellDesktopTray
> ShellDesk
;
44 CComPtr
<IShellView
> DesktopView
;
45 CComPtr
<IShellBrowser
> DefaultShellBrowser
;
46 LPITEMIDLIST pidlDesktopDirectory
;
47 LPITEMIDLIST pidlDesktop
;
49 LRESULT
_NotifyTray(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
54 HRESULT
Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
);
55 HWND
FindDesktopListView ();
57 HWND
DesktopGetWindowControl(IN UINT id
);
58 LRESULT
OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
59 static LRESULT CALLBACK
ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
);
62 // *** IOleWindow methods ***
63 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
64 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
66 // *** IShellBrowser methods ***
67 virtual HRESULT STDMETHODCALLTYPE
InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
);
68 virtual HRESULT STDMETHODCALLTYPE
SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
);
69 virtual HRESULT STDMETHODCALLTYPE
RemoveMenusSB(HMENU hmenuShared
);
70 virtual HRESULT STDMETHODCALLTYPE
SetStatusTextSB(LPCOLESTR pszStatusText
);
71 virtual HRESULT STDMETHODCALLTYPE
EnableModelessSB(BOOL fEnable
);
72 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorSB(MSG
*pmsg
, WORD wID
);
73 virtual HRESULT STDMETHODCALLTYPE
BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
);
74 virtual HRESULT STDMETHODCALLTYPE
GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
);
75 virtual HRESULT STDMETHODCALLTYPE
GetControlWindow(UINT id
, HWND
*lphwnd
);
76 virtual HRESULT STDMETHODCALLTYPE
SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
);
77 virtual HRESULT STDMETHODCALLTYPE
QueryActiveShellView(struct IShellView
**ppshv
);
78 virtual HRESULT STDMETHODCALLTYPE
OnViewWindowActive(struct IShellView
*ppshv
);
79 virtual HRESULT STDMETHODCALLTYPE
SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
);
81 // *** ICommDlgBrowser methods ***
82 virtual HRESULT STDMETHODCALLTYPE
OnDefaultCommand (struct IShellView
*ppshv
);
83 virtual HRESULT STDMETHODCALLTYPE
OnStateChange (struct IShellView
*ppshv
, ULONG uChange
);
84 virtual HRESULT STDMETHODCALLTYPE
IncludeObject (struct IShellView
*ppshv
, LPCITEMIDLIST pidl
);
86 // *** IServiceProvider methods ***
87 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
89 BEGIN_COM_MAP(CDesktopBrowser
)
90 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
91 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser
, IShellBrowser
)
92 COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser
, ICommDlgBrowser
)
93 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
97 CDesktopBrowser::CDesktopBrowser()
101 hWndShellView
= NULL
;
102 hWndDesktopListView
= NULL
;
103 DefaultShellBrowser
= NULL
;
104 pidlDesktopDirectory
= NULL
;
108 CDesktopBrowser::~CDesktopBrowser()
110 if (DesktopView
.p
!= NULL
)
112 if (hWndShellView
!= NULL
)
113 DesktopView
->DestroyViewWindow();
115 hWndShellView
= NULL
;
116 hWndDesktopListView
= NULL
;
119 if (pidlDesktopDirectory
!= NULL
)
121 ILFree(pidlDesktopDirectory
);
122 pidlDesktopDirectory
= NULL
;
125 if (pidlDesktop
!= NULL
)
132 HRESULT
CDesktopBrowser::Initialize(HWND hWndx
, IShellDesktopTray
*ShellDeskx
)
134 CComPtr
<IShellFolder
> psfDesktopFolder
;
139 ShellDesk
= ShellDeskx
;
142 pidlDesktopDirectory
= SHCloneSpecialIDList(hWnd
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
143 hRet
= SHGetSpecialFolderLocation(hWnd
, CSIDL_DESKTOP
, &pidlDesktop
);
147 hRet
= SHGetDesktopFolder(&psfDesktopFolder
);
151 ZeroMemory(&csfv
, sizeof(csfv
));
152 csfv
.cbSize
= sizeof(csfv
);
153 csfv
.pshf
= psfDesktopFolder
;
154 csfv
.psvOuter
= NULL
;
156 hRet
= SHCreateShellFolderViewEx(&csfv
, &DesktopView
);
161 static CDesktopBrowser
*SHDESK_Create(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
163 CComPtr
<IShellDesktopTray
> ShellDesk
;
164 CComObject
<CDesktopBrowser
> *pThis
;
167 ShellDesk
= (IShellDesktopTray
*)lpCreateStruct
->lpCreateParams
;
168 if (ShellDesk
== NULL
)
170 WARN("No IShellDesk interface provided!");
174 pThis
= new CComObject
<CDesktopBrowser
>;
179 hRet
= pThis
->Initialize(hWnd
, ShellDesk
);
189 HWND
CDesktopBrowser::FindDesktopListView ()
191 return FindWindowExW(hWndShellView
, NULL
, WC_LISTVIEW
, NULL
);
194 BOOL
CDesktopBrowser::CreateDeskWnd()
200 if (!GetClientRect(hWnd
, &rcClient
))
205 fs
.ViewMode
= FVM_ICON
;
206 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
207 hRet
= DesktopView
->CreateViewWindow(NULL
, &fs
, (IShellBrowser
*)this, &rcClient
, &hWndShellView
);
208 if (!SUCCEEDED(hRet
))
211 SetShellWindowEx(hWnd
, FindDesktopListView());
216 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetWindow(HWND
*phwnd
)
228 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode
)
233 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::InsertMenusSB(HMENU hmenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths
)
238 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetMenuSB(HMENU hmenuShared
, HOLEMENU holemenuRes
, HWND hwndActiveObject
)
243 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared
)
248 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText
)
253 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::EnableModelessSB(BOOL fEnable
)
258 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg
, WORD wID
)
260 if (!::TranslateAcceleratorW(hWnd
, m_hAccel
, lpmsg
))
265 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl
, UINT wFlags
)
268 * We should use IShellWindows interface here in order to attempt to
269 * find an open shell window that shows the requested pidl and activate it
272 return SHOpenNewFrame((LPITEMIDLIST
)pidl
, NULL
, 0, 0);
275 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetViewStateStream(DWORD grfMode
, IStream
**ppStrm
)
280 HWND
CDesktopBrowser::DesktopGetWindowControl(IN UINT id
)
296 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::GetControlWindow(UINT id
, HWND
*lphwnd
)
300 hWnd
= DesktopGetWindowControl(id
);
311 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SendControlMsg(UINT id
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*pret
)
318 hWnd
= DesktopGetWindowControl(id
);
321 *pret
= SendMessageW(hWnd
,
331 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryActiveShellView(IShellView
**ppshv
)
333 *ppshv
= DesktopView
;
334 if (DesktopView
!= NULL
)
335 DesktopView
->AddRef();
340 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnViewWindowActive(IShellView
*ppshv
)
345 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons
, UINT nButtons
, UINT uFlags
)
350 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnDefaultCommand(IShellView
*ppshv
)
355 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::OnStateChange(IShellView
*ppshv
, ULONG uChange
)
360 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::IncludeObject(IShellView
*ppshv
, LPCITEMIDLIST pidl
)
365 HRESULT STDMETHODCALLTYPE
CDesktopBrowser::QueryService(REFGUID guidService
, REFIID riid
, PVOID
*ppv
)
367 /* FIXME - handle guidService */
368 return QueryInterface(riid
, ppv
);
371 BOOL
CDesktopBrowser::MessageLoop()
376 while ((bRet
= GetMessageW(&Msg
, NULL
, 0, 0)) != 0)
380 if (DesktopView
->TranslateAcceleratorW(&Msg
) != S_OK
)
382 TranslateMessage(&Msg
);
383 DispatchMessage(&Msg
);
391 LRESULT
CDesktopBrowser::_NotifyTray(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
396 hres
= this->ShellDesk
->GetTrayWindow(&hwndTray
);
399 PostMessageW(hwndTray
, uMsg
, wParam
, lParam
);
404 LRESULT
CDesktopBrowser::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
406 switch (LOWORD(wParam
))
408 case FCIDM_DESKBROWSER_CLOSE
:
409 return _NotifyTray(TWM_DOEXITWINDOWS
, 0, 0);
410 case FCIDM_DESKBROWSER_FOCUS
:
411 if (GetKeyState(VK_SHIFT
))
412 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 0xFFFFFFFF);
414 return _NotifyTray(TWM_CYCLEFOCUS
, 1, 1);
415 case FCIDM_DESKBROWSER_SEARCH
:
416 SHFindFiles(NULL
, NULL
);
418 case FCIDM_DESKBROWSER_REFRESH
:
425 LRESULT CALLBACK
CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd
, IN UINT uMsg
, IN WPARAM wParam
, IN LPARAM lParam
)
427 CDesktopBrowser
*pThis
= NULL
;
430 if (uMsg
!= WM_NCCREATE
)
432 pThis
= reinterpret_cast<CDesktopBrowser
*>(GetWindowLongPtrW(hwnd
, 0));
437 if (pThis
!= NULL
|| uMsg
== WM_NCCREATE
)
442 return (LRESULT
)PaintDesktop((HDC
)wParam
);
444 case WM_GETISHELLBROWSER
:
445 Ret
= (LRESULT
)((IShellBrowser
*)pThis
);
449 if (wParam
== SIZE_MINIMIZED
)
451 /* Hey, we're the desktop!!! */
459 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
460 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
461 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
462 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
464 /* FIXME: Update work area */
465 DBG_UNREFERENCED_LOCAL_VARIABLE(rcDesktop
);
469 case WM_SYSCOLORCHANGE
:
470 case WM_SETTINGCHANGE
:
472 if (uMsg
== WM_SYSCOLORCHANGE
|| wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
474 if (pThis
->hWndShellView
!= NULL
)
476 /* Forward the message */
477 SendMessageW(pThis
->hWndShellView
,
488 pThis
->ShellDesk
->RegisterDesktopWindow(pThis
->hWnd
);
490 if (!pThis
->CreateDeskWnd())
491 WARN("Could not create the desktop view control!\n");
493 pThis
->m_hAccel
= LoadAcceleratorsW(shell32_hInstance
, MAKEINTRESOURCEW(3));
500 LPCREATESTRUCT CreateStruct
= (LPCREATESTRUCT
)lParam
;
501 pThis
= SHDESK_Create(hwnd
, CreateStruct
);
504 WARN("Failed to create desktop structure\n");
508 SetWindowLongPtrW(hwnd
,
521 case WM_EXPLORER_OPEN_NEW_WINDOW
:
522 TRACE("Proxy Desktop message 1035 received.\n");
523 SHOnCWMCommandLine((HANDLE
)lParam
);
527 return pThis
->OnCommand(uMsg
, wParam
, lParam
);
530 SetFocus(pThis
->hWndShellView
);
534 Ret
= DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
543 RegisterProgmanWindowClass(VOID
)
547 wcProgman
.style
= CS_DBLCLKS
;
548 wcProgman
.lpfnWndProc
= CDesktopBrowser::ProgmanWindowProc
;
549 wcProgman
.cbClsExtra
= 0;
550 wcProgman
.cbWndExtra
= sizeof(CDesktopBrowser
*);
551 wcProgman
.hInstance
= shell32_hInstance
;
552 wcProgman
.hIcon
= NULL
;
553 wcProgman
.hCursor
= LoadCursorW(NULL
, IDC_ARROW
);
554 wcProgman
.hbrBackground
= NULL
;
555 wcProgman
.lpszMenuName
= NULL
;
556 wcProgman
.lpszClassName
= szProgmanClassName
;
558 return RegisterClassW(&wcProgman
) != 0;
562 /*************************************************************************
563 * SHCreateDesktop [SHELL32.200]
566 HANDLE WINAPI
SHCreateDesktop(IShellDesktopTray
*ShellDesk
)
571 if (ShellDesk
== NULL
)
573 SetLastError(ERROR_INVALID_PARAMETER
);
577 if (RegisterProgmanWindowClass() == 0)
579 WARN("Failed to register the Progman window class!\n");
583 rcDesk
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
584 rcDesk
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
585 rcDesk
.right
= rcDesk
.left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
586 rcDesk
.bottom
= rcDesk
.top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
588 if (IsRectEmpty(&rcDesk
))
590 rcDesk
.left
= rcDesk
.top
= 0;
591 rcDesk
.right
= GetSystemMetrics(SM_CXSCREEN
);
592 rcDesk
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
595 hWndDesk
= CreateWindowExW(WS_EX_TOOLWINDOW
, szProgmanClassName
, szProgmanWindowName
,
596 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
597 rcDesk
.left
, rcDesk
.top
, rcDesk
.right
, rcDesk
.bottom
,
598 NULL
, NULL
, shell32_hInstance
, (LPVOID
)ShellDesk
);
599 if (hWndDesk
!= NULL
)
600 return (HANDLE
)GetWindowLongPtrW(hWndDesk
, 0);
605 /*************************************************************************
606 * SHCreateDesktop [SHELL32.201]
609 BOOL WINAPI
SHDesktopMessageLoop(HANDLE hDesktop
)
611 CDesktopBrowser
*Desk
= static_cast<CDesktopBrowser
*>(hDesktop
);
613 if (Desk
== NULL
|| Desk
->Tag
!= SHDESK_TAG
)
615 SetLastError(ERROR_INVALID_PARAMETER
);
619 return Desk
->MessageLoop();