00001 /* 00002 * Copyright 2003, 2004 Martin Fuchs 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 00020 // 00021 // Explorer clone 00022 // 00023 // desktopbar.cpp 00024 // 00025 // Martin Fuchs, 22.08.2003 00026 // 00027 00028 00029 #include <precomp.h> 00030 00031 #include "../resource.h" 00032 00033 #include "desktopbar.h" 00034 #include "taskbar.h" 00035 #include "startmenu.h" 00036 #include "traynotify.h" 00037 #include "quicklaunch.h" 00038 00039 #include "../dialogs/settings.h" 00040 00041 00042 DesktopBar::DesktopBar(HWND hwnd) 00043 : super(hwnd), 00044 #ifdef __REACTOS__ 00045 _trayIcon(hwnd, ID_TRAY_VOLUME) 00046 #else 00047 WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED)) 00048 #endif 00049 { 00050 SetWindowIcon(hwnd, IDI_REACTOS); 00051 00052 SystemParametersInfo(SPI_GETWORKAREA, 0, &_work_area_org, 0); 00053 } 00054 00055 DesktopBar::~DesktopBar() 00056 { 00057 // restore work area to the previous size 00058 SystemParametersInfo(SPI_SETWORKAREA, 0, &_work_area_org, 0); 00059 PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWORKAREA, 0); 00060 00061 // exit application after destroying desktop window 00062 PostQuitMessage(0); 00063 } 00064 00065 00066 HWND DesktopBar::Create() 00067 { 00068 static BtnWindowClass wcDesktopBar(CLASSNAME_EXPLORERBAR); 00069 00070 RECT rect; 00071 00072 rect.left = -2; // hide left border 00073 #ifdef TASKBAR_AT_TOP 00074 rect.top = -2; // hide top border 00075 #else 00076 rect.top = GetSystemMetrics(SM_CYSCREEN) - DESKTOPBARBAR_HEIGHT; 00077 #endif 00078 rect.right = GetSystemMetrics(SM_CXSCREEN) + 2; 00079 rect.bottom = rect.top + DESKTOPBARBAR_HEIGHT + 2; 00080 00081 return Window::Create(WINDOW_CREATOR(DesktopBar), WS_EX_PALETTEWINDOW, 00082 wcDesktopBar, TITLE_EXPLORERBAR, 00083 WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, 00084 rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0); 00085 } 00086 00087 00088 LRESULT DesktopBar::Init(LPCREATESTRUCT pcs) 00089 { 00090 if (super::Init(pcs)) 00091 return 1; 00092 00093 // create start button 00094 ResString start_str(IDS_START); 00095 WindowCanvas canvas(_hwnd); 00096 RECT rect = {0, 0}; 00097 DrawText(canvas, start_str, -1, &rect, DT_SINGLELINE|DT_CALCRECT); 00098 int start_btn_width = rect.right+16+8; 00099 00100 _taskbar_pos = start_btn_width + 6; 00101 00102 // create "Start" button 00103 HWND hwndStart = Button(_hwnd, start_str, 1, 1, start_btn_width, REBARBAND_HEIGHT, IDC_START, WS_VISIBLE|WS_CHILD|BS_OWNERDRAW); 00104 new StartButton(hwndStart); 00105 00106 /* Save the handle to the window, needed for push-state handling */ 00107 _hwndStartButton = hwndStart; 00108 00109 // disable double clicks 00110 SetClassLong(hwndStart, GCL_STYLE, GetClassLong(hwndStart, GCL_STYLE) & ~CS_DBLCLKS); 00111 00112 // create task bar 00113 _hwndTaskBar = TaskBar::Create(_hwnd); 00114 00115 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003) 00116 if (!g_Globals._SHRestricted || !SHRestricted(REST_NOTRAYITEMSDISPLAY)) 00117 #endif 00118 // create tray notification area 00119 _hwndNotify = NotifyArea::Create(_hwnd); 00120 00121 00122 // notify all top level windows about the successfully created desktop bar 00123 //@@ Use SendMessage() instead of PostMessage() to avoid problems with delayed created shell service objects? 00124 PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0); 00125 00126 00127 _hwndQuickLaunch = QuickLaunchBar::Create(_hwnd); 00128 00129 // create rebar window to manage task and quick launch bar 00130 #ifndef _NO_REBAR 00131 _hwndrebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, 00132 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN| 00133 RBS_VARHEIGHT|RBS_AUTOSIZE|RBS_DBLCLKTOGGLE| //|RBS_REGISTERDROP 00134 CCS_NODIVIDER|CCS_NOPARENTALIGN|CCS_TOP, 00135 0, 0, 0, 0, _hwnd, 0, g_Globals._hInstance, 0); 00136 00137 REBARBANDINFO rbBand; 00138 00139 rbBand.cbSize = sizeof(REBARBANDINFO); 00140 rbBand.fMask = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE|RBBIM_ID|RBBIM_IDEALSIZE; 00141 #ifndef RBBS_HIDETITLE // missing in MinGW headers as of 25.02.2004 00142 #define RBBS_HIDETITLE 0x400 00143 #endif 00144 rbBand.cyChild = REBARBAND_HEIGHT; 00145 rbBand.cyMaxChild = (ULONG)-1; 00146 rbBand.cyMinChild = REBARBAND_HEIGHT; 00147 rbBand.cyIntegral = REBARBAND_HEIGHT + 3; //@@ OK? 00148 rbBand.cxMinChild = rbBand.cyIntegral * 3; 00149 rbBand.fStyle = RBBS_VARIABLEHEIGHT|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE; 00150 00151 TCHAR QuickLaunchBand[] = _T("Quicklaunch"); 00152 rbBand.lpText = QuickLaunchBand; 00153 rbBand.hwndChild = _hwndQuickLaunch; 00154 rbBand.cx = 250; 00155 rbBand.wID = IDW_QUICKLAUNCHBAR; 00156 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); 00157 00158 TCHAR TaskbarBand[] = _T("Taskbar"); 00159 rbBand.lpText = TaskbarBand; 00160 rbBand.hwndChild = _hwndTaskBar; 00161 rbBand.cx = 200; //pcs->cx-_taskbar_pos-quicklaunch_width-(notifyarea_width+1); 00162 rbBand.wID = IDW_TASKTOOLBAR; 00163 SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); 00164 #endif 00165 00166 00167 RegisterHotkeys(); 00168 00169 // prepare Startmenu, but hide it for now 00170 _startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd, STARTMENUROOT_ICON_SIZE)); 00171 _startMenuRoot->_hwndStartButton = _hwndStartButton; 00172 00173 return 0; 00174 } 00175 00176 00177 StartButton::StartButton(HWND hwnd) 00178 : PictureButton(hwnd, SmallIcon(IDI_STARTMENU), GetSysColorBrush(COLOR_BTNFACE)) 00179 { 00180 } 00181 00182 LRESULT StartButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00183 { 00184 switch(nmsg) { 00185 // one click activation: handle button-down message, don't wait for button-up 00186 case WM_LBUTTONDOWN: 00187 if (!Button_GetState(_hwnd)) { 00188 Button_SetState(_hwnd, TRUE); 00189 00190 SetCapture(_hwnd); 00191 00192 SendMessage(GetParent(_hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(_hwnd),0), 0); 00193 } 00194 00195 Button_SetState(_hwnd, FALSE); 00196 break; 00197 00198 // re-target mouse move messages while moving the mouse cursor through the start menu 00199 case WM_MOUSEMOVE: 00200 if (GetCapture() == _hwnd) { 00201 POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; 00202 00203 ClientToScreen(_hwnd, &pt); 00204 HWND hwnd = WindowFromPoint(pt); 00205 00206 if (hwnd && hwnd!=_hwnd) { 00207 ScreenToClient(hwnd, &pt); 00208 SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y)); 00209 } 00210 } 00211 break; 00212 00213 case WM_LBUTTONUP: 00214 if (GetCapture() == _hwnd) { 00215 ReleaseCapture(); 00216 00217 POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; 00218 00219 ClientToScreen(_hwnd, &pt); 00220 HWND hwnd = WindowFromPoint(pt); 00221 00222 if (hwnd && hwnd!=_hwnd) { 00223 ScreenToClient(hwnd, &pt); 00224 PostMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y)); 00225 PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y)); 00226 } 00227 } 00228 break; 00229 00230 case WM_CANCELMODE: 00231 ReleaseCapture(); 00232 break; 00233 00234 default: 00235 return super::WndProc(nmsg, wparam, lparam); 00236 } 00237 00238 return 0; 00239 } 00240 00241 00242 void DesktopBar::RegisterHotkeys() 00243 { 00244 // register hotkey WIN+E opening explorer 00245 RegisterHotKey(_hwnd, 0, MOD_WIN, 'E'); 00246 00247 ///@todo register all common hotkeys 00248 } 00249 00250 void DesktopBar::ProcessHotKey(int id_hotkey) 00251 { 00252 switch(id_hotkey) { 00253 case 0: explorer_show_frame(SW_SHOWNORMAL); 00254 break; 00255 00256 ///@todo implement all common hotkeys 00257 } 00258 } 00259 00260 00261 LRESULT DesktopBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00262 { 00263 switch(nmsg) { 00264 case WM_NCHITTEST: { 00265 LRESULT res = super::WndProc(nmsg, wparam, lparam); 00266 00267 if (res>=HTSIZEFIRST && res<=HTSIZELAST) { 00268 #ifdef TASKBAR_AT_TOP 00269 if (res == HTBOTTOM) // enable vertical resizing at the lower border 00270 #else 00271 if (res == HTTOP) // enable vertical resizing at the upper border 00272 #endif 00273 return res; 00274 else 00275 return HTCLIENT; // disable any other resizing 00276 } 00277 return res;} 00278 00279 case WM_SYSCOMMAND: 00280 if ((wparam&0xFFF0) == SC_SIZE) { 00281 #ifdef TASKBAR_AT_TOP 00282 if (wparam == SC_SIZE+6)// enable vertical resizing at the lower border 00283 #else 00284 if (wparam == SC_SIZE+3)// enable vertical resizing at the upper border 00285 #endif 00286 goto def; 00287 else 00288 return 0; // disable any other resizing 00289 } else if (wparam == SC_TASKLIST) 00290 ShowStartMenu(); 00291 goto def; 00292 00293 case WM_SIZE: 00294 Resize(LOWORD(lparam), HIWORD(lparam)); 00295 break; 00296 00297 case WM_SIZING: 00298 ControlResize(wparam, lparam); 00299 break; 00300 00301 case PM_RESIZE_CHILDREN: { 00302 ClientRect size(_hwnd); 00303 Resize(size.right, size.bottom); 00304 break;} 00305 00306 case WM_CLOSE: 00307 ShowExitWindowsDialog(_hwnd); 00308 break; 00309 00310 case WM_HOTKEY: 00311 ProcessHotKey(wparam); 00312 break; 00313 00314 case WM_COPYDATA: 00315 return ProcessCopyData((COPYDATASTRUCT*)lparam); 00316 00317 case WM_CONTEXTMENU: { 00318 POINTS p; 00319 p.x = LOWORD(lparam); 00320 p.y = HIWORD(lparam); 00321 PopupMenu menu(IDM_DESKTOPBAR); 00322 SetMenuDefaultItem(menu, 0, MF_BYPOSITION); 00323 menu.TrackPopupMenu(_hwnd, p); 00324 break;} 00325 00326 case PM_GET_LAST_ACTIVE: 00327 if (_hwndTaskBar) 00328 return SendMessage(_hwndTaskBar, nmsg, wparam, lparam); 00329 break; 00330 00331 case PM_REFRESH_CONFIG: ///@todo read desktop bar settings 00332 SendMessage(_hwndNotify, PM_REFRESH_CONFIG, 0, 0); 00333 break; 00334 00335 case WM_TIMER: 00336 if (wparam == ID_TRAY_VOLUME) { 00337 KillTimer(_hwnd, wparam); 00338 launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL, TEXT("-t")); // launch volume control in small mode 00339 } 00340 break; 00341 00342 case PM_GET_NOTIFYAREA: 00343 return (LRESULT)(HWND)_hwndNotify; 00344 00345 default: def: 00346 return super::WndProc(nmsg, wparam, lparam); 00347 } 00348 00349 return 0; 00350 } 00351 00352 int DesktopBar::Notify(int id, NMHDR* pnmh) 00353 { 00354 if (pnmh->code == RBN_CHILDSIZE) { 00355 /* align the task bands to the top, so it's in row with the Start button */ 00356 NMREBARCHILDSIZE* childSize = (NMREBARCHILDSIZE*)pnmh; 00357 00358 if (childSize->wID == IDW_TASKTOOLBAR) { 00359 int cy = childSize->rcChild.top - childSize->rcBand.top; 00360 00361 if (cy) { 00362 childSize->rcChild.bottom -= cy; 00363 childSize->rcChild.top -= cy; 00364 } 00365 } 00366 } 00367 00368 return 0; 00369 } 00370 00371 void DesktopBar::Resize(int cx, int cy) 00372 { 00373 ///@todo general children resizing algorithm 00374 int quicklaunch_width = SendMessage(_hwndQuickLaunch, PM_GET_WIDTH, 0, 0); 00375 int notifyarea_width = SendMessage(_hwndNotify, PM_GET_WIDTH, 0, 0); 00376 00377 HDWP hdwp = BeginDeferWindowPos(3); 00378 00379 if (_hwndrebar) 00380 DeferWindowPos(hdwp, _hwndrebar, 0, _taskbar_pos, 1, cx-_taskbar_pos-(notifyarea_width+1), cy-2, SWP_NOZORDER|SWP_NOACTIVATE); 00381 else { 00382 if (_hwndQuickLaunch) 00383 DeferWindowPos(hdwp, _hwndQuickLaunch, 0, _taskbar_pos, 1, quicklaunch_width, cy-2, SWP_NOZORDER|SWP_NOACTIVATE); 00384 00385 if (_hwndTaskBar) 00386 DeferWindowPos(hdwp, _hwndTaskBar, 0, _taskbar_pos+quicklaunch_width, 0, cx-_taskbar_pos-quicklaunch_width-(notifyarea_width+1), cy, SWP_NOZORDER|SWP_NOACTIVATE); 00387 } 00388 00389 if (_hwndNotify) 00390 DeferWindowPos(hdwp, _hwndNotify, 0, cx-(notifyarea_width+1), 1, notifyarea_width, cy-2, SWP_NOZORDER|SWP_NOACTIVATE); 00391 00392 EndDeferWindowPos(hdwp); 00393 00394 WindowRect rect(_hwnd); 00395 RECT work_area = {0, 0, GetSystemMetrics(SM_CXSCREEN), rect.top}; 00396 SystemParametersInfo(SPI_SETWORKAREA, 0, &work_area, 0); // don't use SPIF_SENDCHANGE because then we have to wait for any message being delivered 00397 PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWORKAREA, 0); 00398 } 00399 00400 00401 int DesktopBar::Command(int id, int code) 00402 { 00403 switch(id) { 00404 case IDC_START: 00405 ShowStartMenu(); 00406 break; 00407 00408 case ID_ABOUT_EXPLORER: 00409 explorer_about(g_Globals._hwndDesktop); 00410 break; 00411 00412 case ID_DESKTOPBAR_SETTINGS: 00413 ExplorerPropertySheet(g_Globals._hwndDesktop); 00414 break; 00415 00416 case ID_MINIMIZE_ALL: 00417 g_Globals._desktops.ToggleMinimize(); 00418 break; 00419 00420 case ID_EXPLORE: 00421 explorer_show_frame(SW_SHOWNORMAL); 00422 break; 00423 00424 case ID_TASKMGR: 00425 launch_file(_hwnd, TEXT("taskmgr.exe"), SW_SHOWNORMAL); 00426 break; 00427 00428 case ID_SWITCH_DESKTOP_1: 00429 case ID_SWITCH_DESKTOP_1+1: 00430 case ID_SWITCH_DESKTOP_1+2: 00431 case ID_SWITCH_DESKTOP_1+3: { 00432 int desktop_idx = id - ID_SWITCH_DESKTOP_1; 00433 00434 g_Globals._desktops.SwitchToDesktop(desktop_idx); 00435 00436 if (_hwndQuickLaunch) 00437 PostMessage(_hwndQuickLaunch, PM_UPDATE_DESKTOP, desktop_idx, 0); 00438 break;} 00439 00440 #ifdef __REACTOS__ 00441 case ID_TRAY_VOLUME: 00442 launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL); // launch volume control application 00443 break; 00444 00445 case ID_VOLUME_PROPERTIES: 00446 launch_cpanel(_hwnd, TEXT("mmsys.cpl")); 00447 break; 00448 #endif 00449 00450 default: 00451 if (_hwndQuickLaunch) 00452 return SendMessage(_hwndQuickLaunch, WM_COMMAND, MAKEWPARAM(id,code), 0); 00453 else 00454 return 1; 00455 } 00456 00457 return 0; 00458 } 00459 00460 00461 void DesktopBar::ShowStartMenu() 00462 { 00463 if (_startMenuRoot) 00464 { 00465 // set the Button, if not set 00466 if (!Button_GetState(_hwndStartButton)) 00467 Button_SetState(_hwndStartButton, TRUE); 00468 00469 _startMenuRoot->TrackStartmenu(); 00470 00471 // StartMenu was closed, release button state 00472 Button_SetState(_hwndStartButton, false); 00473 } 00474 } 00475 00476 00477 /// copy data structure for tray notifications 00478 struct TrayNotifyCDS { 00479 DWORD cookie; 00480 DWORD notify_code; 00481 NOTIFYICONDATA nicon_data; 00482 }; 00483 00484 LRESULT DesktopBar::ProcessCopyData(COPYDATASTRUCT* pcd) 00485 { 00486 // Is this a tray notification message? 00487 if (pcd->dwData == 1) { 00488 TrayNotifyCDS* ptr = (TrayNotifyCDS*) pcd->lpData; 00489 00490 NotifyArea* notify_area = GET_WINDOW(NotifyArea, _hwndNotify); 00491 00492 if (notify_area) 00493 return notify_area->ProcessTrayNotification(ptr->notify_code, &ptr->nicon_data); 00494 } 00495 00496 return FALSE; 00497 } 00498 00499 00500 void DesktopBar::ControlResize(WPARAM wparam, LPARAM lparam) 00501 { 00502 PRECT dragRect = (PRECT) lparam; 00503 //int screenWidth = GetSystemMetrics(SM_CXSCREEN); 00504 int screenHeight = GetSystemMetrics(SM_CYSCREEN); 00505 00506 ///@todo write code for taskbar being at sides or top. 00507 00508 switch(wparam) { 00509 case WMSZ_BOTTOM: ///@todo Taskbar is at the top of the screen 00510 break; 00511 00512 case WMSZ_TOP: // Taskbar is at the bottom of the screen 00513 dragRect->top = screenHeight - (((screenHeight - dragRect->top) + DESKTOPBARBAR_HEIGHT/2) / DESKTOPBARBAR_HEIGHT) * DESKTOPBARBAR_HEIGHT; 00514 if (dragRect->top < screenHeight / 2) 00515 dragRect->top = screenHeight - (screenHeight/2 / DESKTOPBARBAR_HEIGHT * DESKTOPBARBAR_HEIGHT); 00516 else if (dragRect->top > screenHeight - 5) 00517 dragRect->top = screenHeight - 5; 00518 break; 00519 00520 case WMSZ_RIGHT: ///@todo Taskbar is at the left of the screen 00521 break; 00522 00523 case WMSZ_LEFT: ///@todo Taskbar is at the right of the screen 00524 break; 00525 } 00526 } 00527 00528 00529 #ifdef __REACTOS__ 00530 00531 void DesktopBar::AddTrayIcons() 00532 { 00533 _trayIcon.Add(SmallIcon(IDI_SPEAKER), ResString(IDS_VOLUME)); 00534 } 00535 00536 void DesktopBar::TrayClick(UINT id, int btn) 00537 { 00538 switch(id) { 00539 case ID_TRAY_VOLUME: 00540 if (btn == TRAYBUTTON_LEFT) 00541 SetTimer(_hwnd, ID_TRAY_VOLUME, 500, NULL); // wait a bit to correctly handle double clicks 00542 else { 00543 PopupMenu menu(IDM_VOLUME); 00544 SetMenuDefaultItem(menu, 0, MF_BYPOSITION); 00545 menu.TrackPopupMenuAtPos(_hwnd, GetMessagePos()); 00546 } 00547 break; 00548 } 00549 } 00550 00551 void DesktopBar::TrayDblClick(UINT id, int btn) 00552 { 00553 switch(id) { 00554 case ID_TRAY_VOLUME: 00555 KillTimer(_hwnd, ID_TRAY_VOLUME); // finish one-click timer 00556 launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL); // launch volume control application 00557 break; 00558 } 00559 } 00560 00561 #endif
ROS Explorer Source Code Documentation
generated on 02.01.2013 by ![]() |