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"
30 #include "../utility/shellclasses.h"
31 #include "../utility/shellbrowserimpl.h"
32 #include "../utility/dragdropimpl.h"
33 #include "../utility/window.h"
35 #include "../globals.h"
36 #include "../externals.h"
37 #include "../explorer_intres.h"
40 #include "../taskbar/desktopbar.h"
41 #include "../shell/mainframe.h" // for MainFrame::Create()
44 static BOOL (WINAPI
*SetShellWindow
)(HWND
);
45 static BOOL (WINAPI
*SetShellWindowEx
)(HWND
, HWND
);
48 BOOL
IsAnyDesktopRunning()
50 HINSTANCE hUser32
= GetModuleHandle(TEXT("user32"));
52 SetShellWindow
= (BOOL(WINAPI
*)(HWND
)) GetProcAddress(hUser32
, "SetShellWindow");
53 SetShellWindowEx
= (BOOL(WINAPI
*)(HWND
,HWND
)) GetProcAddress(hUser32
, "SetShellWindowEx");
55 return GetShellWindow() != 0;
59 static void draw_desktop_background(HWND hwnd
, HDC hdc
)
61 ClientRect
rect(hwnd
);
65 HBRUSH bkgndBrush = CreateSolidBrush(RGB(0,32,160)); // dark blue
66 FillRect(hdc, &rect, bkgndBrush);
67 DeleteBrush(bkgndBrush);
70 rect
.left
= rect
.right
- 280;
71 rect
.top
= rect
.bottom
- 56 - DESKTOPBARBAR_HEIGHT
;
72 rect
.right
= rect
.left
+ 250;
73 rect
.bottom
= rect
.top
+ 40;
75 #include "../buildno.h"
76 static const LPCTSTR BkgndText
= TEXT("ReactOS ")TEXT(KERNEL_VERSION_STR
)TEXT(" Explorer\nby Martin Fuchs");
78 BkMode
bkMode(hdc
, TRANSPARENT
);
80 TextColor
textColor(hdc
, RGB(128,128,192));
81 DrawText(hdc
, BkgndText
, -1, &rect
, DT_RIGHT
);
83 SetTextColor(hdc
, RGB(255,255,255));
86 DrawText(hdc
, BkgndText
, -1, &rect
, DT_RIGHT
);
90 LRESULT
BackgroundWindow::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
94 PaintDesktop((HDC
)wparam
);
97 case WM_MBUTTONDBLCLK
:
98 explorer_show_frame(_hwnd
, SW_SHOWNORMAL
);
102 return super::WndProc(nmsg
, wparam
, lparam
);
109 DesktopWindow::DesktopWindow(HWND hwnd
)
115 DesktopWindow::~DesktopWindow()
118 _pShellView
->Release();
122 HWND
DesktopWindow::Create()
124 IconWindowClass
wcDesktop(TEXT("Progman"), IDI_REACTOS
, CS_DBLCLKS
);
125 wcDesktop
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+1);
127 int width
= GetSystemMetrics(SM_CXSCREEN
);
128 int height
= GetSystemMetrics(SM_CYSCREEN
);
130 HWND hwndDesktop
= Window::Create(WINDOW_CREATOR(DesktopWindow
),
131 WS_EX_TOOLWINDOW
, wcDesktop
, TEXT("Program Manager"), WS_POPUP
|WS_VISIBLE
|WS_CLIPCHILDREN
,
132 0, 0, width
, height
, 0);
134 // work around to display desktop bar in Wine
135 ShowWindow(GET_WINDOW(DesktopWindow
, hwndDesktop
)->_desktopBar
, SW_SHOW
);
137 // work around for Windows NT, Win 98, ...
138 // Without this the desktop has mysteriously only a size of 800x600 pixels.
139 MoveWindow(hwndDesktop
, 0, 0, width
, height
, TRUE
);
145 LRESULT
DesktopWindow::Init(LPCREATESTRUCT pcs
)
147 if (super::Init(pcs
))
150 HRESULT hr
= Desktop()->CreateViewObject(_hwnd
, IID_IShellView
, (void**)&_pShellView
);
152 SFV_CREATE sfv_create;
154 sfv_create.cbSize = sizeof(SFV_CREATE);
155 sfv_create.pshf = Desktop();
156 sfv_create.psvOuter = NULL;
157 sfv_create.psfvcb = NULL;
159 HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
166 fs
.ViewMode
= FVM_ICON
;
167 fs
.fFlags
= FWF_DESKTOP
|FWF_NOCLIENTEDGE
|FWF_NOSCROLL
|FWF_BESTFITWINDOW
|FWF_SNAPTOGRID
; //|FWF_AUTOARRANGE;
169 ClientRect
rect(_hwnd
);
171 hr
= _pShellView
->CreateViewWindow(NULL
, &fs
, this, &rect
, &hWndView
);
173 ///@todo use IShellBrowser::GetViewStateStream() to restore previous view state -> see SHOpenRegStream()
176 g_Globals
._hwndShellView
= hWndView
;
178 // subclass shellview window
179 new DesktopShellView(hWndView
, _pShellView
);
181 _pShellView
->UIActivate(SVUIA_ACTIVATE_FOCUS
);
184 IShellView2* pShellView2;
186 hr = _pShellView->QueryInterface(IID_IShellView2, (void**)&pShellView2);
188 SV2CVW2_PARAMS params;
189 params.cbSize = sizeof(SV2CVW2_PARAMS);
190 params.psvPrev = _pShellView;
192 params.psbOwner = this;
193 params.prcView = ▭
194 params.pvid = params.pvid;//@@
196 hr = pShellView2->CreateViewWindow2(¶ms);
201 IFolderView* pFolderView;
203 hr = _pShellView->QueryInterface(IID_IFolderView, (void**)&pFolderView);
206 hr = pFolderView->GetAutoArrange();
207 hr = pFolderView->SetCurrentViewMode(FVM_DETAILS);
213 if (hWndView
&& SetShellWindowEx
)
214 SetShellWindowEx(_hwnd
, hWndView
);
215 else if (SetShellWindow
)
216 SetShellWindow(_hwnd
);
218 // create the explorer bar
219 _desktopBar
= DesktopBar::Create();
220 g_Globals
._hwndDesktopBar
= _desktopBar
;
226 LRESULT
DesktopWindow::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
230 draw_desktop_background(_hwnd
, PaintCanvas(_hwnd
));
233 case WM_LBUTTONDBLCLK
:
234 case WM_RBUTTONDBLCLK
:
235 case WM_MBUTTONDBLCLK
:
236 explorer_show_frame(_hwnd
, SW_SHOWNORMAL
);
239 case WM_GETISHELLBROWSER
:
240 return (LRESULT
)static_cast<IShellBrowser
*>(this);
244 ///@todo use IShellBrowser::GetViewStateStream() and _pShellView->SaveViewState() to store view state
251 ShowExitWindowsDialog(_hwnd
);
255 if (wparam
== SC_TASKLIST
) {
257 SendMessage(_desktopBar
, nmsg
, wparam
, lparam
);
262 return super::WndProc(nmsg
, wparam
, lparam
);
269 HRESULT
DesktopWindow::OnDefaultCommand(LPIDA pida
)
271 if (MainFrame::OpenShellFolders(pida
, 0))
278 DesktopShellView::DesktopShellView(HWND hwnd
, IShellView
* pShellView
)
280 _pShellView(pShellView
)
282 _hwndListView
= ::GetNextWindow(hwnd
, GW_CHILD
);
284 SetWindowStyle(_hwndListView
, GetWindowStyle(_hwndListView
)&~LVS_ALIGNMASK
);//|LVS_ALIGNTOP|LVS_AUTOARRANGE);
286 // work around for Windows NT, Win 98, ...
287 // Without this the desktop has mysteriously only a size of 800x600 pixels.
288 ClientRect
rect(hwnd
);
289 MoveWindow(_hwndListView
, 0, 0, rect
.right
, rect
.bottom
, TRUE
);
291 // subclass background window
292 new BackgroundWindow(_hwndListView
);
296 PositionIcons(_alignment
);
300 bool DesktopShellView::InitDragDrop()
302 CONTEXT("DesktopShellView::InitDragDrop()");
304 _pDropTarget
= new DesktopDropTarget(_hwnd
);
309 _pDropTarget
->AddRef();
311 if (FAILED(RegisterDragDrop(_hwnd
, _pDropTarget
))) {
312 _pDropTarget
->Release();
317 _pDropTarget
->Release();
321 ftetc
.dwAspect
= DVASPECT_CONTENT
;
323 ftetc
.tymed
= TYMED_HGLOBAL
;
324 ftetc
.cfFormat
= CF_HDROP
;
326 _pDropTarget
->AddSuportedFormat(ftetc
);
331 LRESULT
DesktopShellView::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
335 if (!DoContextMenu(GET_X_LPARAM(lparam
), GET_Y_LPARAM(lparam
)))
336 DoDesktopContextMenu(GET_X_LPARAM(lparam
), GET_Y_LPARAM(lparam
));
339 case PM_POSITION_ICONS
:
340 PositionIcons(wparam
);
345 return super::WndProc(nmsg
, wparam
, lparam
);
351 int DesktopShellView::Command(int id
, int code
)
353 return super::Command(id
, code
);
356 int DesktopShellView::Notify(int id
, NMHDR
* pnmh
)
358 return super::Notify(id
, pnmh
);
361 bool DesktopShellView::DoContextMenu(int x
, int y
)
363 IDataObject
* selection
;
365 HRESULT hr
= _pShellView
->GetItemObject(SVGIO_SELECTION
, IID_IDataObject
, (void**)&selection
);
371 hr
= pidList
.GetData(selection
);
373 selection
->Release();
378 LPIDA pida
= pidList
;
380 selection
->Release();
384 LPCITEMIDLIST parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
386 LPCITEMIDLIST
* apidl
= (LPCITEMIDLIST
*) alloca(pida
->cidl
*sizeof(LPCITEMIDLIST
));
388 for(int i
=pida
->cidl
; i
>0; --i
)
389 apidl
[i
-1] = (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[i
]);
391 hr
= ShellFolderContextMenu(ShellFolder(parent_pidl
), _hwnd
, pida
->cidl
, apidl
, x
, y
);
393 selection
->Release();
400 HRESULT
DesktopShellView::DoDesktopContextMenu(int x
, int y
)
404 HRESULT hr
= DesktopFolder()->GetUIObjectOf(_hwnd
, 0, NULL
, IID_IContextMenu
, NULL
, (LPVOID
*)&pcm
);
407 HMENU hmenu
= CreatePopupMenu();
410 hr
= pcm
->QueryContextMenu(hmenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
-1, CMF_NORMAL
|CMF_EXPLORE
);
413 AppendMenu(hmenu
, MF_SEPARATOR
, 0, NULL
);
414 AppendMenu(hmenu
, 0, FCIDM_SHVIEWLAST
-1, ResString(IDS_ABOUT_EXPLORER
));
416 UINT idCmd
= TrackPopupMenu(hmenu
, TPM_LEFTALIGN
|TPM_RETURNCMD
|TPM_RIGHTBUTTON
, x
, y
, 0, _hwnd
, NULL
);
418 if (idCmd
== FCIDM_SHVIEWLAST
-1) {
419 explorer_about(_hwnd
);
421 CMINVOKECOMMANDINFO cmi
;
423 cmi
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
426 cmi
.lpVerb
= (LPCSTR
)(INT_PTR
)(idCmd
- FCIDM_SHVIEWFIRST
);
427 cmi
.lpParameters
= NULL
;
428 cmi
.lpDirectory
= NULL
;
429 cmi
.nShow
= SW_SHOWNORMAL
;
433 hr
= pcm
->InvokeCommand(&cmi
);
445 static const POINTS s_align_start
[8] = {
450 {0, 1}, // left/bottom
452 {1, 1}, // right/bottom
456 static const POINTS s_align_dir1
[8] = {
467 static const POINTS s_align_dir2
[8] = {
478 typedef pair
<int,int> IconPos
;
479 typedef map
<IconPos
, int> IconMap
;
481 void DesktopShellView::PositionIcons(int alignment
, int dir
)
483 DWORD spacing
= ListView_GetItemSpacing(_hwndListView
, FALSE
);
486 SystemParametersInfo(SPI_GETWORKAREA
, 0, &work_area
, 0);
488 const POINTS
& dir1
= s_align_dir1
[alignment
];
489 const POINTS
& dir2
= s_align_dir2
[alignment
];
490 const POINTS
& start_pos
= s_align_start
[alignment
];
497 int cx
= LOWORD(spacing
);
498 int cy
= HIWORD(spacing
);
500 int dx1
= dir_x1
* cx
;
501 int dy1
= dir_y1
* cy
;
502 int dx2
= dir_x2
* cx
;
503 int dy2
= dir_y2
* cy
;
505 int start_x
= start_pos
.x
* work_area
.right
+ (cx
-32)/2;
506 int start_y
= start_pos
.y
* work_area
.bottom
+ 4/*(cy-32)/2*/;
508 if (start_x
>= work_area
.right
)
511 if (start_y
>= work_area
.bottom
)
517 int cnt
= ListView_GetItemCount(_hwndListView
);
530 for(int idx
=i1
; idx
!=i2
; idx
+=dir
) {
531 pos_idx
[IconPos(y
, x
)] = idx
;
536 if (x
<0 || x
>=work_area
.right
) {
539 } else if (y
<0 || y
>=work_area
.bottom
) {
545 for(IconMap::const_iterator it
=pos_idx
.end(); --it
!=pos_idx
.begin(); ) {
546 const IconPos
& pos
= it
->first
;
548 ListView_SetItemPosition32(_hwndListView
, it
->second
, pos
.second
, pos
.first
);
551 for(IconMap::const_iterator it
=pos_idx
.begin(); it
!=pos_idx
.end(); ++it
) {
552 const IconPos
& pos
= it
->first
;
554 ListView_SetItemPosition32(_hwndListView
, it
->second
, pos
.second
, pos
.first
);