update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / desktop / desktop.cpp
1 /*
2  * Copyright 2003 Martin Fuchs
3  *
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.
8  *
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.
13  *
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
17  */
18
19
20  //
21  // Explorer clone
22  //
23  // desktop.cpp
24  //
25  // Martin Fuchs, 09.08.2003
26  //
27
28
29 #include "../utility/utility.h"
30 #include "../utility/shellclasses.h"
31 #include "../utility/shellbrowserimpl.h"
32 #include "../utility/window.h"
33
34 #include "desktop.h"
35 #include "../taskbar/desktopbar.h"
36
37 #include "../externals.h"
38 #include "../explorer_intres.h"
39
40
41 static BOOL (WINAPI*SetShellWindow)(HWND);
42 static BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
43
44
45 BOOL IsAnyDesktopRunning()
46 {
47         HINSTANCE shell32 = GetModuleHandle(_T("user32"));
48
49         SetShellWindow = (BOOL(WINAPI*)(HWND)) GetProcAddress(shell32, "SetShellWindow");
50         SetShellWindowEx = (BOOL(WINAPI*)(HWND,HWND)) GetProcAddress(shell32, "SetShellWindowEx");
51
52         return GetShellWindow() != 0;
53 }
54
55
56 static void draw_desktop_background(HWND hwnd, HDC hdc)
57 {
58         ClientRect rect(hwnd);
59
60         PaintDesktop(hdc);
61 /*
62         HBRUSH bkgndBrush = CreateSolidBrush(RGB(0,32,160));    // dark blue
63         FillRect(hdc, &rect, bkgndBrush);
64         DeleteBrush(bkgndBrush);
65 */
66
67         rect.left = rect.right - 280;
68         rect.top = rect.bottom - 56 - DESKTOPBARBAR_HEIGHT;
69         rect.right = rect.left + 250;
70         rect.bottom = rect.top + 40;
71
72 #include "../buildno.h"
73         static const LPCTSTR BkgndText = _T("ReactOS ")_T(KERNEL_VERSION_STR)_T(" Explorer\nby Martin Fuchs");
74
75         BkMode bkMode(hdc, TRANSPARENT);
76
77         TextColor textColor(hdc, RGB(128,128,192));
78         DrawText(hdc, BkgndText, -1, &rect, DT_RIGHT);
79
80         SetTextColor(hdc, RGB(255,255,255));
81         --rect.right;
82         ++rect.top;
83         DrawText(hdc, BkgndText, -1, &rect, DT_RIGHT);
84 }
85
86
87 LRESULT BackgroundWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
88 {
89         switch(nmsg) {
90           case WM_ERASEBKGND:
91                 PaintDesktop((HDC)wparam);
92                 return TRUE;
93
94           case WM_MBUTTONDBLCLK:
95                 explorer_show_frame(_hwnd, SW_SHOWNORMAL);
96                 break;
97
98           default:
99                 return super::WndProc(nmsg, wparam, lparam);
100         }
101
102         return 0;
103 }
104
105
106 DesktopWindow::DesktopWindow(HWND hwnd)
107  :      super(hwnd)
108 {
109         _pShellView = NULL;
110 }
111
112 DesktopWindow::~DesktopWindow()
113 {
114         if (_pShellView)
115                 _pShellView->Release();
116 }
117
118
119 HWND DesktopWindow::Create()
120 {
121         IconWindowClass wcDesktop(_T("Progman"), IDI_REACTOS, CS_DBLCLKS);
122         wcDesktop.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);
123
124         int width = GetSystemMetrics(SM_CXSCREEN);
125         int height = GetSystemMetrics(SM_CYSCREEN);
126
127         HWND hwndDesktop = Window::Create(WINDOW_CREATOR(DesktopWindow),
128                                         WS_EX_TOOLWINDOW, wcDesktop, _T("Program Manager"), WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN,
129                                         0, 0, width, height, 0);
130
131          // work around to display desktop bar in Wine
132         ShowWindow(GET_WINDOW(DesktopWindow, hwndDesktop)->_desktopBar, SW_SHOW);
133
134          // work around for Windows NT, Win 98, ...
135          // Without this the desktop has mysteriously only a size of 800x600 pixels.
136         MoveWindow(hwndDesktop, 0, 0, width, height, TRUE);
137
138         return hwndDesktop;
139 }
140
141
142 LRESULT DesktopWindow::Init(LPCREATESTRUCT pcs)
143 {
144         if (super::Init(pcs))
145                 return 1;
146
147         HRESULT hr = Desktop()->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
148 /* also possible:
149         SFV_CREATE sfv_create;
150
151         sfv_create.cbSize = sizeof(SFV_CREATE);
152         sfv_create.pshf = Desktop();
153         sfv_create.psvOuter = NULL;
154         sfv_create.psfvcb = NULL;
155
156         HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
157 */
158         HWND hWndView = 0;
159
160         if (SUCCEEDED(hr)) {
161                 FOLDERSETTINGS fs;
162
163                 fs.ViewMode = FVM_ICON;
164                 fs.fFlags = FWF_DESKTOP|FWF_NOCLIENTEDGE|FWF_NOSCROLL|FWF_BESTFITWINDOW|FWF_SNAPTOGRID;
165
166                 ClientRect rect(_hwnd);
167
168                 hr = _pShellView->CreateViewWindow(NULL, &fs, this, &rect, &hWndView);
169
170                 //TODO: use IShellBrowser::GetViewStateStream() to restore previous view state -> see SHOpenRegStream()
171
172                 if (SUCCEEDED(hr)) {
173                         _pShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
174
175                 /*
176                         IShellView2* pShellView2;
177
178                         hr = _pShellView->QueryInterface(IID_IShellView2, (void**)&pShellView2);
179
180                         SV2CVW2_PARAMS params;
181                         params.cbSize = sizeof(SV2CVW2_PARAMS);
182                         params.psvPrev = _pShellView;
183                         params.pfs = &fs;
184                         params.psbOwner = this;
185                         params.prcView = ▭
186                         params.pvid = params.pvid;//@@
187
188                         hr = pShellView2->CreateViewWindow2(&params);
189                         params.pvid;
190                 */
191
192                 /*
193                         IFolderView* pFolderView;
194
195                         hr = _pShellView->QueryInterface(IID_IFolderView, (void**)&pFolderView);
196
197                         if (SUCCEEDED(hr)) {
198                                 hr = pFolderView->GetAutoArrange();
199                                 hr = pFolderView->SetCurrentViewMode(FVM_DETAILS);
200                         }
201                 */
202
203                         HWND hwndFolderView = ::GetNextWindow(hWndView, GW_CHILD);
204
205                          // work around for Windows NT, Win 98, ...
206                          // Without this the desktop has mysteriously only a size of 800x600 pixels.
207                         MoveWindow(hwndFolderView, 0, 0, rect.right, rect.bottom, TRUE);
208
209                         new BackgroundWindow(hwndFolderView);
210                 }
211         }
212
213         if (hWndView && SetShellWindowEx)
214                 SetShellWindowEx(_hwnd, hWndView);
215         else if (SetShellWindow)
216                 SetShellWindow(_hwnd);
217
218          // create the explorer bar
219         _desktopBar = DesktopBar::Create();
220
221         return 0;
222 }
223
224
225 LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
226 {
227         switch(nmsg) {
228           case WM_PAINT:
229                 draw_desktop_background(_hwnd, PaintCanvas(_hwnd));
230                 break;
231
232           case WM_LBUTTONDBLCLK:
233           case WM_RBUTTONDBLCLK:
234           case WM_MBUTTONDBLCLK:
235                 explorer_show_frame(_hwnd, SW_SHOWNORMAL);
236                 break;
237
238           case WM_GETISHELLBROWSER:
239                 return (LRESULT)static_cast<IShellBrowser*>(this);
240
241           case WM_DESTROY:
242
243                 //TODO: use IShellBrowser::GetViewStateStream() and _pShellView->SaveViewState() to store view state
244                 
245                 if (SetShellWindow)
246                         SetShellWindow(0);
247                 break;
248
249           case WM_CLOSE:
250                 break;  // Over-ride close. We need to close desktop some other way.
251
252           case WM_SYSCOMMAND:
253                 if (wparam == SC_TASKLIST) {
254                         if (_desktopBar)
255                                 SendMessage(_desktopBar, nmsg, wparam, lparam);
256                 }
257                 goto def;
258
259           default: def:
260                 return super::WndProc(nmsg, wparam, lparam);
261         }
262
263         return 0;
264 }