desktopbar.cpp

Go to the documentation of this file.
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 doxygen

ROS Explorer Homepage