update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / taskbar / desktopbar.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  // desktopbar.cpp
24  //
25  // Martin Fuchs, 22.08.2003
26  //
27
28
29 #include "../utility/utility.h"
30
31 #include "../explorer.h"
32 #include "../globals.h"
33 #include "../externals.h"
34 #include "../explorer_intres.h"
35
36 #include "desktopbar.h"
37 #include "taskbar.h"
38 #include "startmenu.h"
39 #include "traynotify.h"
40 #include "quicklaunch.h"
41
42
43 DesktopBar::DesktopBar(HWND hwnd)
44  :      super(hwnd),
45          // initialize Common Controls library
46         WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED))
47 {
48         SystemParametersInfo(SPI_GETWORKAREA, 0, &_work_area_org, 0);
49 }
50
51 DesktopBar::~DesktopBar()
52 {
53          // restore work area to the previous size
54         SystemParametersInfo(SPI_SETWORKAREA, 0, &_work_area_org, 0);
55         PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWORKAREA, 0);
56
57          // exit application after destroying desktop window
58         PostQuitMessage(0);
59 }
60
61
62 HWND DesktopBar::Create()
63 {
64         RECT rect;
65
66         rect.left = -2; // hide left border
67 #ifdef TASKBAR_AT_TOP
68         rect.top = -2;  // hide top border
69 #else
70         rect.top = GetSystemMetrics(SM_CYSCREEN) - DESKTOPBARBAR_HEIGHT;
71 #endif
72         rect.right = GetSystemMetrics(SM_CXSCREEN) + 2;
73         rect.bottom = rect.top + DESKTOPBARBAR_HEIGHT + 2;
74
75         return Window::Create(WINDOW_CREATOR(DesktopBar), WS_EX_PALETTEWINDOW,
76                                                         BtnWindowClass(CLASSNAME_EXPLORERBAR), TITLE_EXPLORERBAR,
77                                                         WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE,
78                                                         rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0);
79 }
80
81
82 LRESULT DesktopBar::Init(LPCREATESTRUCT pcs)
83 {
84         if (super::Init(pcs))
85                 return 1;
86
87          // create start button
88         new PictureButton(Button(_hwnd, ResString(IDS_START), 2, 2, STARTBUTTON_WIDTH, DESKTOPBARBAR_HEIGHT-8, IDC_START, WS_VISIBLE|WS_CHILD|BS_OWNERDRAW),
89                                                 SmallIcon(IDI_STARTMENU)/*, GetStockBrush(WHITE_BRUSH)*/);
90
91          // create task bar
92         _hwndTaskBar = TaskBar::Create(_hwnd);
93
94          // create tray notification area
95         _hwndNotify = NotifyArea::Create(_hwnd);
96
97         _hwndQuickLaunch = QuickLaunchBar::Create(_hwnd);
98
99         RegisterHotkeys();
100
101          // notify all top level windows about the successfully created desktop bar
102         PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0);
103
104         return 0;
105 }
106
107
108 void DesktopBar::RegisterHotkeys()
109 {
110          // register hotkey WIN+E opening explorer
111         RegisterHotKey(_hwnd, 0, MOD_WIN, 'E');
112
113                 //TODO: register all common hotkeys
114 }
115
116 void DesktopBar::ProcessHotKey(int id_hotkey)
117 {
118         switch(id_hotkey) {
119           case 0:       explorer_show_frame(_hwnd, SW_SHOWNORMAL);      break;
120                 //TODO: implement all common hotkeys
121         }
122 }
123
124
125 LRESULT DesktopBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
126 {
127         switch(nmsg) {
128           case WM_NCHITTEST: {
129                 LRESULT res = super::WndProc(nmsg, wparam, lparam);
130
131                 if (res>=HTSIZEFIRST && res<=HTSIZELAST) {
132 #ifdef TASKBAR_AT_TOP
133                         if (res == HTBOTTOM)    // enable vertical resizing at the lower border
134 #else
135                         if (res == HTTOP)               // enable vertical resizing at the upper border
136 #endif
137                                 return res;
138                         else
139                                 return HTCLIENT;        // disable any other resizing
140                 }
141                 return res;}
142
143           case WM_SYSCOMMAND:
144                 if ((wparam&0xFFF0) == SC_SIZE) {
145 #ifdef TASKBAR_AT_TOP
146                         if (wparam == SC_SIZE+6)// enable vertical resizing at the lower border
147 #else
148                         if (wparam == SC_SIZE+3)// enable vertical resizing at the upper border
149 #endif
150                                 goto def;
151                         else
152                                 return 0;                       // disable any other resizing
153                 } else if (wparam == SC_TASKLIST)
154                         ShowStartMenu();
155                 goto def;
156
157           case WM_SIZE: {
158                 int cx = LOWORD(lparam);
159                 int cy = HIWORD(lparam);
160
161                 if (_hwndTaskBar)
162                         MoveWindow(_hwndTaskBar, TASKBAR_LEFT+QUICKLAUNCH_WIDTH, 0, cx-TASKBAR_LEFT-QUICKLAUNCH_WIDTH-(NOTIFYAREA_WIDTH+1), cy, TRUE);
163
164                 if (_hwndNotify)
165                         MoveWindow(_hwndNotify, cx-(NOTIFYAREA_WIDTH+1), 1, NOTIFYAREA_WIDTH, cy-2, TRUE);
166
167                 if (_hwndQuickLaunch)
168                         MoveWindow(_hwndQuickLaunch, TASKBAR_LEFT, 1, QUICKLAUNCH_WIDTH, cy-2, TRUE);
169
170                 WindowRect rect(_hwnd);
171                 RECT work_area = {0, 0, GetSystemMetrics(SM_CXSCREEN), rect.top};
172                 SystemParametersInfo(SPI_SETWORKAREA, 0, &work_area, 0);        // don't use SPIF_SENDCHANGE because then we have to wait for any message being delivered
173                 PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWORKAREA, 0);
174                 break;}
175
176           case WM_CLOSE:
177                 break;
178
179           case WM_HOTKEY:
180                 ProcessHotKey(wparam);
181                 break;
182
183           case WM_COPYDATA:
184                 return ProcessCopyData((COPYDATASTRUCT*)lparam);
185
186           default: def:
187                 return super::WndProc(nmsg, wparam, lparam);
188         }
189
190         return 0;
191 }
192
193
194 int DesktopBar::Command(int id, int code)
195 {
196         switch(id) {
197           case IDC_START:       //TODO: startmenu should popup for WM_LBUTTONDOWN, not for WM_COMMAND
198                 ShowStartMenu();
199                 break;
200
201           default:
202                 if ((id&~0xFF) == IDC_FIRST_QUICK_ID)
203                         SendMessage(_hwndQuickLaunch, WM_COMMAND, MAKEWPARAM(id,code), 0);
204         }
205
206         return 0;
207 }
208
209
210 void DesktopBar::ShowStartMenu()
211 {
212          // create Startmenu
213         StartMenuRoot* startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd));
214
215         if (startMenuRoot)
216                 startMenuRoot->TrackStartmenu();
217 }
218
219
220  /// copy data structure for tray notifications
221 struct TrayNotifyCDS {
222         DWORD   cookie;
223         DWORD   notify_code;
224         NOTIFYICONDATA nicon_data;
225 };
226
227 LRESULT DesktopBar::ProcessCopyData(COPYDATASTRUCT* pcd)
228 {
229          // Is this a tray notification message?
230         if (pcd->dwData == 1) {
231                 TrayNotifyCDS* ptr = (TrayNotifyCDS*) pcd->lpData;
232
233                 //TODO: process the differnt versions of the NOTIFYICONDATA structure (look at cbSize to decide which one)
234
235                 NotifyArea* notify_area = GET_WINDOW(NotifyArea, _hwndNotify);
236
237                 if (notify_area)
238                         return notify_area->ProcessTrayNotification(ptr->notify_code, &ptr->nicon_data);
239         }
240
241         return 0;
242 }