2 * Copyright 2003 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 // Martin Fuchs, 09.08.2003
29 #include "../utility/utility.h"
31 #include "../explorer.h" // for MainFrame::OpenShellFolders()
34 #include "../globals.h"
35 #include "../externals.h"
37 #include "../taskbar/desktopbar.h"
39 #include "../explorer_intres.h"
42 static BOOL (WINAPI
*SetShellWindow
)(HWND
);
43 static BOOL (WINAPI
*SetShellWindowEx
)(HWND
, HWND
);
53 // show all hidden windows
54 for(iterator it_dsk
=begin(); it_dsk
!=end(); ++it_dsk
)
55 for(WindowSet::iterator it
=it_dsk
->_windows
.begin(); it
!=it_dsk
->_windows
.end(); ++it
)
56 ShowWindowAsync(*it
, SW_SHOW
);
61 resize(DESKTOP_COUNT
);
64 static BOOL CALLBACK
SwitchDesktopEnumFct(HWND hwnd
, LPARAM lparam
)
66 WindowSet
& windows
= *(WindowSet
*)lparam
;
68 if (IsWindowVisible(hwnd
))
69 if (hwnd
!=g_Globals
._hwndDesktopBar
&& hwnd
!=g_Globals
._hwndDesktop
)
75 void Desktops::SwitchToDesktop(int idx
)
77 if (_current_desktop
== idx
)
80 Desktop
& desktop
= (*this)[idx
];
82 // save currently visible application windows
83 Desktop
& old_desktop
= (*this)[_current_desktop
];
84 WindowSet
& windows
= old_desktop
._windows
;
87 EnumWindows(SwitchDesktopEnumFct
, (LPARAM
)&windows
);
89 // hide all windows we found
90 for(WindowSet::iterator it
=windows
.begin(); it
!=windows
.end(); ++it
)
91 ShowWindowAsync(*it
, SW_HIDE
);
93 // show all windows of the new desktop
94 for(WindowSet::iterator it
=desktop
._windows
.begin(); it
!=desktop
._windows
.end(); ++it
)
95 ShowWindowAsync(*it
, SW_SHOW
);
97 desktop
._windows
.clear();
99 _current_desktop
= idx
;
103 static BOOL CALLBACK
MinimizeDesktopEnumFct(HWND hwnd
, LPARAM lparam
)
105 list
<MinimizeStruct
>& minimized
= *(list
<MinimizeStruct
>*)lparam
;
107 if (IsWindowVisible(hwnd
))
108 if (hwnd
!=g_Globals
._hwndDesktopBar
&& hwnd
!=g_Globals
._hwndDesktop
)
109 if (!IsIconic(hwnd
)) {
110 minimized
.push_back(MinimizeStruct(hwnd
, GetWindowStyle(hwnd
)));
111 ShowWindowAsync(hwnd
, SW_MINIMIZE
);
117 /// minimize/restore all windows on the desktop
118 void Desktops::ToggleMinimize()
120 list
<MinimizeStruct
>& minimized
= (*this)[_current_desktop
]._minimized
;
122 if (minimized
.empty()) {
123 EnumWindows(MinimizeDesktopEnumFct
, (LPARAM
)&minimized
);
125 for(list
<MinimizeStruct
>::const_iterator it
=minimized
.begin(); it
!=minimized
.end(); ++it
)
126 ShowWindowAsync(it
->first
, it
->second
&WS_MAXIMIZE
? SW_MAXIMIZE
: SW_RESTORE
);
133 BOOL
IsAnyDesktopRunning()
135 HINSTANCE hUser32
= GetModuleHandle(TEXT("user32"));
137 SetShellWindow
= (BOOL(WINAPI
*)(HWND
)) GetProcAddress(hUser32
, "SetShellWindow");
138 SetShellWindowEx
= (BOOL(WINAPI
*)(HWND
,HWND
)) GetProcAddress(hUser32
, "SetShellWindowEx");
140 return GetShellWindow() != 0;
144 static void draw_desktop_background(HWND hwnd
, HDC hdc
)
146 ClientRect
rect(hwnd
);
150 HBRUSH bkgndBrush = CreateSolidBrush(RGB(0,32,160)); // dark blue
151 FillRect(hdc, &rect, bkgndBrush);
152 DeleteBrush(bkgndBrush);
155 rect
.left
= rect
.right
- 280;
156 rect
.top
= rect
.bottom
- 56 - DESKTOPBARBAR_HEIGHT
;
157 rect
.right
= rect
.left
+ 250;
158 rect
.bottom
= rect
.top
+ 40;
160 #include "../buildno.h"
161 static const LPCTSTR BkgndText
= TEXT("ReactOS ")TEXT(KERNEL_VERSION_STR
)TEXT(" Explorer\nby Martin Fuchs");
163 BkMode
bkMode(hdc
, TRANSPARENT
);
165 TextColor
textColor(hdc
, RGB(128,128,192));
166 DrawText(hdc
, BkgndText
, -1, &rect
, DT_RIGHT
);
168 SetTextColor(hdc
, RGB(255,255,255));
171 DrawText(hdc
, BkgndText
, -1, &rect
, DT_RIGHT
);
175 BackgroundWindow::BackgroundWindow(HWND hwnd
)
178 // set background brush for the short moment of displaying the
179 // background color while moving foreground windows
180 SetClassLong(hwnd
, GCL_HBRBACKGROUND
, COLOR_BACKGROUND
+1);
183 LRESULT
BackgroundWindow::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
187 PaintDesktop((HDC
)wparam
);
190 case WM_MBUTTONDBLCLK
:
191 explorer_show_frame(SW_SHOWNORMAL
);
195 return super::WndProc(nmsg
, wparam
, lparam
);
202 DesktopWindow::DesktopWindow(HWND hwnd
)
208 DesktopWindow::~DesktopWindow()
211 _pShellView
->Release();
215 HWND
DesktopWindow::Create()
217 static IconWindowClass
wcDesktop(TEXT("Progman"), IDI_REACTOS
, CS_DBLCLKS
);
218 wcDesktop
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+1);
220 int width
= GetSystemMetrics(SM_CXSCREEN
);
221 int height
= GetSystemMetrics(SM_CYSCREEN
);
223 HWND hwndDesktop
= Window::Create(WINDOW_CREATOR(DesktopWindow
),
224 WS_EX_TOOLWINDOW
, wcDesktop
, TEXT("Program Manager"), WS_POPUP
|WS_VISIBLE
|WS_CLIPCHILDREN
,
225 0, 0, width
, height
, 0);
227 // work around to display desktop bar in Wine
228 ShowWindow(GET_WINDOW(DesktopWindow
, hwndDesktop
)->_desktopBar
, SW_SHOW
);
230 // work around for Windows NT, Win 98, ...
231 // Without this the desktop has mysteriously only a size of 800x600 pixels.
232 MoveWindow(hwndDesktop
, 0, 0, width
, height
, TRUE
);
238 LRESULT
DesktopWindow::Init(LPCREATESTRUCT pcs
)
240 if (super::Init(pcs
))
243 HRESULT hr
= GetDesktopFolder()->CreateViewObject(_hwnd
, IID_IShellView
, (void**)&_pShellView
);
245 SFV_CREATE sfv_create;
247 sfv_create.cbSize = sizeof(SFV_CREATE);
248 sfv_create.pshf = GetDesktopFolder();
249 sfv_create.psvOuter = NULL;
250 sfv_create.psfvcb = NULL;
252 HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
259 fs
.ViewMode
= FVM_ICON
;
260 fs
.fFlags
= FWF_DESKTOP
|FWF_NOCLIENTEDGE
|FWF_NOSCROLL
|FWF_BESTFITWINDOW
|FWF_SNAPTOGRID
; //|FWF_AUTOARRANGE;
262 ClientRect
rect(_hwnd
);
264 hr
= _pShellView
->CreateViewWindow(NULL
, &fs
, this, &rect
, &hWndView
);
266 ///@todo use IShellBrowser::GetViewStateStream() to restore previous view state -> see SHOpenRegStream()
269 g_Globals
._hwndShellView
= hWndView
;
271 // subclass shellview window
272 new DesktopShellView(hWndView
, _pShellView
);
274 _pShellView
->UIActivate(SVUIA_ACTIVATE_FOCUS
);
277 IShellView2* pShellView2;
279 hr = _pShellView->QueryInterface(IID_IShellView2, (void**)&pShellView2);
281 SV2CVW2_PARAMS params;
282 params.cbSize = sizeof(SV2CVW2_PARAMS);
283 params.psvPrev = _pShellView;
285 params.psbOwner = this;
286 params.prcView = ▭
287 params.pvid = params.pvid;//@@
289 hr = pShellView2->CreateViewWindow2(¶ms);
294 IFolderView* pFolderView;
296 hr = _pShellView->QueryInterface(IID_IFolderView, (void**)&pFolderView);
299 hr = pFolderView->GetAutoArrange();
300 hr = pFolderView->SetCurrentViewMode(FVM_DETAILS);
306 if (hWndView
&& SetShellWindowEx
)
307 SetShellWindowEx(_hwnd
, hWndView
);
308 else if (SetShellWindow
)
309 SetShellWindow(_hwnd
);
311 // create the explorer bar
312 _desktopBar
= DesktopBar::Create();
313 g_Globals
._hwndDesktopBar
= _desktopBar
;
319 LRESULT
DesktopWindow::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
323 draw_desktop_background(_hwnd
, PaintCanvas(_hwnd
));
326 case WM_LBUTTONDBLCLK
:
327 case WM_RBUTTONDBLCLK
:
328 case WM_MBUTTONDBLCLK
:
329 explorer_show_frame(SW_SHOWNORMAL
);
332 case WM_GETISHELLBROWSER
:
333 return (LRESULT
)static_cast<IShellBrowser
*>(this);
337 ///@todo use IShellBrowser::GetViewStateStream() and _pShellView->SaveViewState() to store view state
344 ShowExitWindowsDialog(_hwnd
);
348 if (wparam
== SC_TASKLIST
) {
350 SendMessage(_desktopBar
, nmsg
, wparam
, lparam
);
355 return super::WndProc(nmsg
, wparam
, lparam
);
362 HRESULT
DesktopWindow::OnDefaultCommand(LPIDA pida
)
364 if (MainFrame::OpenShellFolders(pida
, 0))
371 DesktopShellView::DesktopShellView(HWND hwnd
, IShellView
* pShellView
)
373 _pShellView(pShellView
)
375 _hwndListView
= ::GetNextWindow(hwnd
, GW_CHILD
);
377 SetWindowStyle(_hwndListView
, GetWindowStyle(_hwndListView
)&~LVS_ALIGNMASK
);//|LVS_ALIGNTOP|LVS_AUTOARRANGE);
379 // work around for Windows NT, Win 98, ...
380 // Without this the desktop has mysteriously only a size of 800x600 pixels.
381 ClientRect
rect(hwnd
);
382 MoveWindow(_hwndListView
, 0, 0, rect
.right
, rect
.bottom
, TRUE
);
384 // subclass background window
385 new BackgroundWindow(_hwndListView
);
390 bool DesktopShellView::InitDragDrop()
392 CONTEXT("DesktopShellView::InitDragDrop()");
394 _pDropTarget
= new DesktopDropTarget(_hwnd
);
399 _pDropTarget
->AddRef();
401 if (FAILED(RegisterDragDrop(_hwnd
, _pDropTarget
))) {
402 _pDropTarget
->Release();
407 _pDropTarget
->Release();
411 ftetc
.dwAspect
= DVASPECT_CONTENT
;
413 ftetc
.tymed
= TYMED_HGLOBAL
;
414 ftetc
.cfFormat
= CF_HDROP
;
416 _pDropTarget
->AddSuportedFormat(ftetc
);
421 LRESULT
DesktopShellView::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
425 if (!DoContextMenu(GET_X_LPARAM(lparam
), GET_Y_LPARAM(lparam
)))
426 DoDesktopContextMenu(GET_X_LPARAM(lparam
), GET_Y_LPARAM(lparam
));
430 return super::WndProc(nmsg
, wparam
, lparam
);
436 int DesktopShellView::Command(int id
, int code
)
438 return super::Command(id
, code
);
441 int DesktopShellView::Notify(int id
, NMHDR
* pnmh
)
443 return super::Notify(id
, pnmh
);
446 bool DesktopShellView::DoContextMenu(int x
, int y
)
448 IDataObject
* selection
;
450 HRESULT hr
= _pShellView
->GetItemObject(SVGIO_SELECTION
, IID_IDataObject
, (void**)&selection
);
456 hr
= pidList
.GetData(selection
);
458 selection
->Release();
463 LPIDA pida
= pidList
;
465 selection
->Release();
469 LPCITEMIDLIST parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
471 LPCITEMIDLIST
* apidl
= (LPCITEMIDLIST
*) alloca(pida
->cidl
*sizeof(LPCITEMIDLIST
));
473 for(int i
=pida
->cidl
; i
>0; --i
)
474 apidl
[i
-1] = (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[i
]);
476 hr
= ShellFolderContextMenu(ShellFolder(parent_pidl
), _hwnd
, pida
->cidl
, apidl
, x
, y
);
478 selection
->Release();
485 HRESULT
DesktopShellView::DoDesktopContextMenu(int x
, int y
)
489 HRESULT hr
= DesktopFolder()->GetUIObjectOf(_hwnd
, 0, NULL
, IID_IContextMenu
, NULL
, (LPVOID
*)&pcm
);
492 HMENU hmenu
= CreatePopupMenu();
495 hr
= pcm
->QueryContextMenu(hmenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
-1, CMF_NORMAL
|CMF_EXPLORE
);
498 AppendMenu(hmenu
, MF_SEPARATOR
, 0, NULL
);
499 AppendMenu(hmenu
, 0, FCIDM_SHVIEWLAST
-1, ResString(IDS_ABOUT_EXPLORER
));
501 UINT idCmd
= TrackPopupMenu(hmenu
, TPM_LEFTALIGN
|TPM_RETURNCMD
|TPM_RIGHTBUTTON
, x
, y
, 0, _hwnd
, NULL
);
503 if (idCmd
== FCIDM_SHVIEWLAST
-1) {
504 explorer_about(_hwnd
);
506 CMINVOKECOMMANDINFO cmi
;
508 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
511 cmi
.lpVerb
= (LPCSTR
)(INT_PTR
)(idCmd
- FCIDM_SHVIEWFIRST
);
512 cmi
.lpParameters
= NULL
;
513 cmi
.lpDirectory
= NULL
;
514 cmi
.nShow
= SW_SHOWNORMAL
;
518 hr
= pcm
->InvokeCommand(&cmi
);