quicklaunch.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005 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  // quicklaunch.cpp
00024  //
00025  // Martin Fuchs, 22.08.2003
00026  //
00027 
00028 
00029 #include <precomp.h>
00030 
00031 #include "../resource.h"
00032 
00033 #include "quicklaunch.h"
00034 
00035 
00036 QuickLaunchEntry::QuickLaunchEntry()
00037 {
00038     _hbmp = 0;
00039 }
00040 
00041 QuickLaunchMap::~QuickLaunchMap()
00042 {
00043     while(!empty()) {
00044         iterator it = begin();
00045         DeleteBitmap(it->second._hbmp);
00046         erase(it);
00047     }
00048 }
00049 
00050 
00051 QuickLaunchBar::QuickLaunchBar(HWND hwnd)
00052  :  super(hwnd)
00053 {
00054     CONTEXT("QuickLaunchBar::QuickLaunchBar()");
00055 
00056     _dir = NULL;
00057     _next_id = IDC_FIRST_QUICK_ID;
00058     _btn_dist = 20;
00059     _size = 0;
00060 
00061     HWND hwndToolTip = (HWND) SendMessage(hwnd, TB_GETTOOLTIPS, 0, 0);
00062 
00063     SetWindowStyle(hwndToolTip, GetWindowStyle(hwndToolTip)|TTS_ALWAYSTIP);
00064 
00065      // delay refresh to some time later
00066     PostMessage(hwnd, PM_REFRESH, 0, 0);
00067 }
00068 
00069 QuickLaunchBar::~QuickLaunchBar()
00070 {
00071     delete _dir;
00072 }
00073 
00074 HWND QuickLaunchBar::Create(HWND hwndParent)
00075 {
00076     CONTEXT("QuickLaunchBar::Create()");
00077 
00078     ClientRect clnt(hwndParent);
00079 
00080     HWND hwnd = CreateToolbarEx(hwndParent,
00081                                 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|
00082                                 CCS_TOP|CCS_NODIVIDER|CCS_NOPARENTALIGN|CCS_NORESIZE|
00083                                 TBSTYLE_TOOLTIPS|TBSTYLE_WRAPABLE|TBSTYLE_FLAT,
00084                                 IDW_QUICKLAUNCHBAR, 0, 0, 0, NULL, 0, 0, 0, 16, 16, sizeof(TBBUTTON));
00085 
00086     if (hwnd)
00087         new QuickLaunchBar(hwnd);
00088 
00089     return hwnd;
00090 }
00091 
00092 void QuickLaunchBar::AddShortcuts()
00093 {
00094     CONTEXT("QuickLaunchBar::AddShortcuts()");
00095 
00096     WaitCursor wait;
00097 
00098     try {
00099         TCHAR path[MAX_PATH];
00100 
00101         SpecialFolderFSPath app_data(CSIDL_APPDATA, _hwnd); ///@todo perhaps also look into CSIDL_COMMON_APPDATA ?
00102 
00103         _stprintf(path, TEXT("%s\\")QUICKLAUNCH_FOLDER, (LPCTSTR)app_data);
00104 
00105         RecursiveCreateDirectory(path);
00106         _dir = new ShellDirectory(GetDesktopFolder(), path, _hwnd);
00107 
00108         _dir->smart_scan(SORT_NAME);
00109 
00110          // immediatelly extract the shortcut icons
00111         for(Entry*entry=_dir->_down; entry; entry=entry->_next)
00112             entry->_icon_id = entry->safe_extract_icon(ICF_NORMAL);
00113     } catch(COMException&) {
00114         return;
00115     }
00116 
00117 
00118     ShellFolder desktop_folder;
00119     WindowCanvas canvas(_hwnd);
00120 
00121     COLORREF bk_color = GetSysColor(COLOR_BTNFACE);
00122     HBRUSH bk_brush = GetSysColorBrush(COLOR_BTNFACE);
00123 
00124     AddButton(ID_MINIMIZE_ALL, g_Globals._icon_cache.get_icon(ICID_MINIMIZE).create_bitmap(bk_color, bk_brush, canvas), ResString(IDS_MINIMIZE_ALL), NULL);
00125     AddButton(ID_EXPLORE, g_Globals._icon_cache.get_icon(ICID_EXPLORER).create_bitmap(bk_color, bk_brush, canvas), ResString(IDS_TITLE), NULL);
00126 
00127     TBBUTTON sep = {0, -1, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
00128     SendMessage(_hwnd, TB_INSERTBUTTON, INT_MAX, (LPARAM)&sep);
00129 
00130     int cur_desktop = g_Globals._desktops._current_desktop;
00131     ResString desktop_fmt(IDS_DESKTOP_NUM);
00132 
00133     HDC hdc = CreateCompatibleDC(canvas);
00134     DWORD size = SendMessage(_hwnd, TB_GETBUTTONSIZE, 0, 0);
00135     int cx = LOWORD(size);
00136     int cy = HIWORD(size);
00137     RECT rect = {0, 0, cx, cy};
00138     RECT textRect = {0, 0, cx-7, cy-7};
00139 
00140     for(int i=0; i<DESKTOP_COUNT; ++i) {
00141         HBITMAP hbmp = CreateCompatibleBitmap(canvas, cx, cy);
00142         HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
00143 
00144         FmtString num_txt(TEXT("%d"), i+1);
00145         TextColor color(hdc, RGB(64,64,64));
00146         BkMode mode(hdc, TRANSPARENT);
00147         FillRect(hdc, &rect, GetSysColorBrush(COLOR_BTNFACE));
00148         DrawText(hdc, num_txt, num_txt.length(), &textRect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
00149 
00150         SelectBitmap(hdc, hbmp_old);
00151 
00152         AddButton(ID_SWITCH_DESKTOP_1+i, hbmp, FmtString(desktop_fmt, i+1), NULL, cur_desktop==i?TBSTATE_ENABLED|TBSTATE_CHECKED:TBSTATE_ENABLED);
00153     }
00154     DeleteDC(hdc);
00155 
00156     SendMessage(_hwnd, TB_INSERTBUTTON, INT_MAX, (LPARAM)&sep);
00157 
00158     for(Entry*entry=_dir->_down; entry; entry=entry->_next) {
00159          // hide files like "desktop.ini"
00160         if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
00161             continue;
00162 
00163          // hide subfolders
00164         if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
00165             HBITMAP hbmp = g_Globals._icon_cache.get_icon(entry->_icon_id).create_bitmap(bk_color, bk_brush, canvas);
00166 
00167             AddButton(_next_id++, hbmp, entry->_display_name, entry);   //entry->_etype==ET_SHELL? desktop_folder.get_name(static_cast<ShellEntry*>(entry)->_pidl): entry->_display_name);
00168         }
00169     }
00170 
00171     _btn_dist = LOWORD(SendMessage(_hwnd, TB_GETBUTTONSIZE, 0, 0));
00172     _size = _entries.size() * _btn_dist;
00173 
00174     SendMessage(GetParent(_hwnd), PM_RESIZE_CHILDREN, 0, 0);
00175 }
00176 
00177 void QuickLaunchBar::AddButton(int id, HBITMAP hbmp, LPCTSTR name, Entry* entry, int flags)
00178 {
00179     TBADDBITMAP ab = {0, (UINT_PTR)hbmp};
00180     int bmp_idx = SendMessage(_hwnd, TB_ADDBITMAP, 1, (LPARAM)&ab);
00181 
00182     QuickLaunchEntry qle;
00183 
00184     qle._hbmp = hbmp;
00185     qle._title = name;
00186     qle._entry = entry;
00187 
00188     _entries[id] = qle;
00189 
00190     TBBUTTON btn = {0, 0, flags, BTNS_BUTTON|BTNS_NOPREFIX, {0, 0}, 0, 0};
00191 
00192     btn.idCommand = id;
00193     btn.iBitmap = bmp_idx;
00194 
00195     SendMessage(_hwnd, TB_INSERTBUTTON, INT_MAX, (LPARAM)&btn);
00196 }
00197 
00198 void QuickLaunchBar::UpdateDesktopButtons(int desktop_idx)
00199 {
00200     for(int i=0; i<DESKTOP_COUNT; ++i) {
00201         TBBUTTONINFO tbi = {sizeof(TBBUTTONINFO), TBIF_STATE, 0, 0, desktop_idx==i? TBSTATE_ENABLED|TBSTATE_CHECKED: TBSTATE_ENABLED};
00202 
00203         SendMessage(_hwnd, TB_SETBUTTONINFO, ID_SWITCH_DESKTOP_1+i, (LPARAM)&tbi);
00204     }
00205 }
00206 
00207 LRESULT QuickLaunchBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00208 {
00209     switch(nmsg) {
00210       case PM_REFRESH:
00211         AddShortcuts();
00212         break;
00213 
00214       case PM_GET_WIDTH: {
00215          // take line wrapping into account
00216         int btns = SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
00217         int rows = SendMessage(_hwnd, TB_GETROWS, 0, 0);
00218 
00219         if (rows<2 || rows==btns)
00220             return _size;
00221 
00222         RECT rect;
00223         int max_cx = 0;
00224 
00225         for(QuickLaunchMap::const_iterator it=_entries.begin(); it!=_entries.end(); ++it) {
00226             SendMessage(_hwnd, TB_GETRECT, it->first, (LPARAM)&rect);
00227 
00228             if (rect.right > max_cx)
00229                 max_cx = rect.right;
00230         }
00231 
00232         return max_cx;}
00233 
00234       case PM_UPDATE_DESKTOP:
00235         UpdateDesktopButtons(wparam);
00236         break;
00237 
00238       case WM_CONTEXTMENU: {
00239         TBBUTTON btn;
00240         QuickLaunchMap::iterator it;
00241         Point screen_pt(lparam), clnt_pt=screen_pt;
00242         ScreenToClient(_hwnd, &clnt_pt);
00243 
00244         Entry* entry = NULL;
00245         int idx = SendMessage(_hwnd, TB_HITTEST, 0, (LPARAM)&clnt_pt);
00246 
00247         if (idx>=0 &&
00248             SendMessage(_hwnd, TB_GETBUTTON, idx, (LPARAM)&btn)!=-1 &&
00249             (it=_entries.find(btn.idCommand))!=_entries.end()) {
00250             entry = it->second._entry;
00251         }
00252 
00253         if (entry) {    // entry is NULL for desktop switch buttons
00254             HRESULT hr = entry->do_context_menu(_hwnd, screen_pt, _cm_ifs);
00255 
00256             if (SUCCEEDED(hr))
00257                 AddShortcuts(); //refresh();
00258             else
00259                 CHECKERROR(hr);
00260         } else
00261             goto def;
00262         break;}
00263 
00264       default: def:
00265         return super::WndProc(nmsg, wparam, lparam);
00266     }
00267 
00268     return 0;
00269 }
00270 
00271 int QuickLaunchBar::Command(int id, int code)
00272 {
00273     CONTEXT("QuickLaunchBar::Command()");
00274 
00275     if ((id&~0xFF) == IDC_FIRST_QUICK_ID) {
00276         QuickLaunchEntry& qle = _entries[id];
00277 
00278         if (qle._entry) {
00279             qle._entry->launch_entry(_hwnd);
00280             return 0;
00281         }
00282     }
00283 
00284     return 0; // Don't return 1 to avoid recursion with DesktopBar::Command()
00285 }
00286 
00287 int QuickLaunchBar::Notify(int id, NMHDR* pnmh)
00288 {
00289     switch(pnmh->code) {
00290       case TTN_GETDISPINFO: {
00291         NMTTDISPINFO* ttdi = (NMTTDISPINFO*) pnmh;
00292 
00293         int id = ttdi->hdr.idFrom;
00294         ttdi->lpszText = _entries[id]._title.str();
00295 #ifdef TTF_DI_SETITEM
00296         ttdi->uFlags |= TTF_DI_SETITEM;
00297 #endif
00298 
00299          // enable multiline tooltips (break at CR/LF and for very long one-line strings)
00300         SendMessage(pnmh->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 400);
00301 
00302         break;}
00303 
00304         return super::Notify(id, pnmh);
00305     }
00306 
00307     return 0;
00308 }

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage