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 // taskbar.cpp 00024 // 00025 // Martin Fuchs, 16.08.2003 00026 // 00027 00028 00029 #include <precomp.h> 00030 00031 #include "taskbar.h" 00032 #include "traynotify.h" // for NOTIFYAREA_WIDTH_DEF 00033 00034 00035 DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_SetTaskmanWindow(TEXT("user32"), "SetTaskmanWindow"); 00036 DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_RegisterShellHookWindow(TEXT("user32"), "RegisterShellHookWindow"); 00037 DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_DeregisterShellHookWindow(TEXT("user32"), "DeregisterShellHookWindow"); 00038 00039 /* 00040 DynamicFct<BOOL (WINAPI*)(HWND hWnd, DWORD dwType)> g_RegisterShellHook(TEXT("shell32"), (LPCSTR)0xb5); 00041 00042 // constants for RegisterShellHook() 00043 #define RSH_UNREGISTER 0 00044 #define RSH_REGISTER 1 00045 #define RSH_REGISTER_PROGMAN 2 00046 #define RSH_REGISTER_TASKMAN 3 00047 */ 00048 00049 00050 TaskBarEntry::TaskBarEntry() 00051 { 00052 _id = 0; 00053 _hbmp = 0; 00054 _bmp_idx = 0; 00055 _used = 0; 00056 _btn_idx = 0; 00057 _fsState = 0; 00058 } 00059 00060 TaskBarMap::~TaskBarMap() 00061 { 00062 while(!empty()) { 00063 iterator it = begin(); 00064 DeleteBitmap(it->second._hbmp); 00065 erase(it); 00066 } 00067 } 00068 00069 00070 TaskBar::TaskBar(HWND hwnd) 00071 : super(hwnd), 00072 WM_SHELLHOOK(RegisterWindowMessage(WINMSG_SHELLHOOK)) 00073 { 00074 _last_btn_width = 0; 00075 00076 _mmMetrics_org.cbSize = sizeof(MINIMIZEDMETRICS); 00077 00078 SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(_mmMetrics_org), &_mmMetrics_org, 0); 00079 00080 // configure the window manager to hide windows when they are minimized 00081 // This is neccessary to enable shell hook messages. 00082 if (!(_mmMetrics_org.iArrange & ARW_HIDE)) { 00083 MINIMIZEDMETRICS _mmMetrics_new = _mmMetrics_org; 00084 00085 _mmMetrics_new.iArrange |= ARW_HIDE; 00086 00087 SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(_mmMetrics_new), &_mmMetrics_new, 0); 00088 } 00089 } 00090 00091 TaskBar::~TaskBar() 00092 { 00093 // if (g_RegisterShellHook) 00094 // (*g_RegisterShellHook)(_hwnd, RSH_UNREGISTER); 00095 00096 if (g_DeregisterShellHookWindow) 00097 (*g_DeregisterShellHookWindow)(_hwnd); 00098 else 00099 KillTimer(_hwnd, 0); 00100 00101 if (g_SetTaskmanWindow) 00102 (*g_SetTaskmanWindow)(0); 00103 00104 SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(_mmMetrics_org), &_mmMetrics_org, 0); 00105 } 00106 00107 HWND TaskBar::Create(HWND hwndParent) 00108 { 00109 ClientRect clnt(hwndParent); 00110 00111 int taskbar_pos = 80; // This start position will be adjusted in DesktopBar::Resize(). 00112 00113 return Window::Create(WINDOW_CREATOR(TaskBar), 0, 00114 BtnWindowClass(CLASSNAME_TASKBAR), TITLE_TASKBAR, 00115 WS_CHILD|WS_VISIBLE | CCS_TOP|CCS_NODIVIDER|CCS_NORESIZE, 00116 taskbar_pos, 0, clnt.right-taskbar_pos-(NOTIFYAREA_WIDTH_DEF+1), clnt.bottom, hwndParent); 00117 } 00118 00119 LRESULT TaskBar::Init(LPCREATESTRUCT pcs) 00120 { 00121 if (super::Init(pcs)) 00122 return 1; 00123 00124 /* FIXME: There's an internal padding for non-flat toolbar. Get rid of it somehow. */ 00125 _htoolbar = CreateToolbarEx(_hwnd, 00126 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN| 00127 CCS_TOP|CCS_NODIVIDER|TBSTYLE_LIST|TBSTYLE_TOOLTIPS|TBSTYLE_WRAPABLE,//|TBSTYLE_AUTOSIZE 00128 IDW_TASKTOOLBAR, 0, 0, 0, NULL, 0, 0, 0, 16, 16, sizeof(TBBUTTON)); 00129 00130 SendMessage(_htoolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(TASKBUTTONWIDTH_MAX,TASKBUTTONWIDTH_MAX)); 00131 //SendMessage(_htoolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS); 00132 //SendMessage(_htoolbar, TB_SETDRAWTEXTFLAGS, DT_CENTER|DT_VCENTER, DT_CENTER|DT_VCENTER); 00133 //SetWindowFont(_htoolbar, GetStockFont(ANSI_VAR_FONT), FALSE); 00134 //SendMessage(_htoolbar, TB_SETPADDING, 0, MAKELPARAM(8,8)); 00135 00136 #ifndef __MINGW32__ // TBMETRICS missing in MinGW (as of 20.09.2005) 00137 // set metrics for the Taskbar toolbar to enable button spacing 00138 TBMETRICS metrics; 00139 00140 metrics.cbSize = sizeof(TBMETRICS); 00141 metrics.dwMask = TBMF_BARPAD | TBMF_BUTTONSPACING; 00142 metrics.cxBarPad = 0; 00143 metrics.cyBarPad = 0; 00144 metrics.cxButtonSpacing = 3; 00145 metrics.cyButtonSpacing = 3; 00146 00147 SendMessage(_htoolbar, TB_SETMETRICS, 0, (LPARAM)&metrics); 00148 #endif 00149 00150 _next_id = IDC_FIRST_APP; 00151 00152 // register the taskbar window as task manager window to make the following call to RegisterShellHookWindow working 00153 if (g_SetTaskmanWindow) 00154 (*g_SetTaskmanWindow)(_hwnd); 00155 00156 if (g_RegisterShellHookWindow) { 00157 LOG(TEXT("Using shell hooks for notification of shell events.")); 00158 00159 (*g_RegisterShellHookWindow)(_hwnd); 00160 } else { 00161 LOG(TEXT("Shell hooks not available.")); 00162 00163 SetTimer(_hwnd, 0, 200, NULL); 00164 } 00165 00166 /* Alternatively we could use the RegisterShellHook() function in SHELL32, but this is not yet implemented in the WINE code. 00167 if (g_RegisterShellHook) { 00168 (*g_RegisterShellHook)(0, RSH_REGISTER); 00169 00170 if ((HIWORD(GetVersion())>>14) == W_VER_NT) 00171 (*g_RegisterShellHook)(_hwnd, RSH_REGISTER_TASKMAN); 00172 else 00173 (*g_RegisterShellHook)(_hwnd, RSH_REGISTER); 00174 } 00175 */ 00176 Refresh(); 00177 00178 return 0; 00179 } 00180 00181 LRESULT TaskBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00182 { 00183 switch(nmsg) { 00184 case WM_SIZE: 00185 SendMessage(_htoolbar, WM_SIZE, 0, 0); 00186 ResizeButtons(); 00187 break; 00188 00189 case WM_TIMER: 00190 Refresh(); 00191 return 0; 00192 00193 case WM_CONTEXTMENU: { 00194 Point pt(lparam); 00195 ScreenToClient(_htoolbar, &pt); 00196 00197 if ((HWND)wparam==_htoolbar && SendMessage(_htoolbar, TB_HITTEST, 0, (LPARAM)&pt)>=0) 00198 break; // avoid displaying context menu for application button _and_ desktop bar at the same time 00199 00200 goto def;} 00201 00202 case PM_GET_LAST_ACTIVE: 00203 return (LRESULT)(HWND)_last_foreground_wnd; 00204 00205 default: def: 00206 if (nmsg == WM_SHELLHOOK) { 00207 switch(wparam) { 00208 case HSHELL_WINDOWCREATED: 00209 case HSHELL_WINDOWDESTROYED: 00210 case HSHELL_WINDOWACTIVATED: 00211 case HSHELL_REDRAW: 00212 #ifdef HSHELL_FLASH 00213 case HSHELL_FLASH: 00214 #endif 00215 #ifdef HSHELL_RUDEAPPACTIVATED 00216 case HSHELL_RUDEAPPACTIVATED: 00217 #endif 00218 Refresh(); 00219 break; 00220 } 00221 } else { 00222 return super::WndProc(nmsg, wparam, lparam); 00223 } 00224 } 00225 00226 return 0; 00227 } 00228 00229 int TaskBar::Command(int id, int code) 00230 { 00231 TaskBarMap::iterator found = _map.find_id(id); 00232 00233 if (found != _map.end()) { 00234 ActivateApp(found); 00235 return 0; 00236 } 00237 00238 return super::Command(id, code); 00239 } 00240 00241 int TaskBar::Notify(int id, NMHDR* pnmh) 00242 { 00243 if (pnmh->hwndFrom == _htoolbar) 00244 switch(pnmh->code) { 00245 case NM_RCLICK: { 00246 TBBUTTONINFO btninfo; 00247 TaskBarMap::iterator it; 00248 Point pt(GetMessagePos()); 00249 ScreenToClient(_htoolbar, &pt); 00250 00251 btninfo.cbSize = sizeof(TBBUTTONINFO); 00252 btninfo.dwMask = TBIF_BYINDEX|TBIF_COMMAND; 00253 00254 int idx = SendMessage(_htoolbar, TB_HITTEST, 0, (LPARAM)&pt); 00255 00256 if (idx>=0 && 00257 SendMessage(_htoolbar, TB_GETBUTTONINFO, idx, (LPARAM)&btninfo)!=-1 && 00258 (it=_map.find_id(btninfo.idCommand))!=_map.end()) { 00259 //TaskBarEntry& entry = it->second; 00260 00261 ActivateApp(it, false, false); // don't restore minimized windows on right button click 00262 00263 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003) 00264 static DynamicFct<DWORD(STDAPICALLTYPE*)(RESTRICTIONS)> pSHRestricted(TEXT("SHELL32"), "SHRestricted"); 00265 00266 if (pSHRestricted && !(*pSHRestricted)(REST_NOTRAYCONTEXTMENU)) 00267 #endif 00268 ShowAppSystemMenu(it); 00269 } 00270 break;} 00271 00272 default: 00273 return super::Notify(id, pnmh); 00274 } 00275 00276 return 0; 00277 } 00278 00279 00280 void TaskBar::ActivateApp(TaskBarMap::iterator it, bool can_minimize, bool can_restore) 00281 { 00282 HWND hwnd = it->first; 00283 00284 bool minimize_it = can_minimize && !IsIconic(hwnd) && 00285 (hwnd==GetForegroundWindow() || hwnd==_last_foreground_wnd); 00286 00287 // switch to selected application window 00288 if (can_restore && !minimize_it) 00289 if (IsIconic(hwnd)) 00290 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 00291 00292 // In case minimize_it is true, we _have_ to switch to the app before 00293 // posting SW_MINIMIZE to be compatible with some applications (e.g. "Sleipnir") 00294 SetForegroundWindow(hwnd); 00295 00296 if (minimize_it) { 00297 PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); 00298 _last_foreground_wnd = 0; 00299 } else 00300 _last_foreground_wnd = hwnd; 00301 00302 Refresh(); 00303 } 00304 00305 void TaskBar::ShowAppSystemMenu(TaskBarMap::iterator it) 00306 { 00307 HMENU hmenu = GetSystemMenu(it->first, FALSE); 00308 00309 if (hmenu) { 00310 POINT pt; 00311 00312 GetCursorPos(&pt); 00313 int cmd = TrackPopupMenu(hmenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, _hwnd, NULL); 00314 00315 if (cmd) { 00316 ActivateApp(it, false, false); // reactivate window after the context menu has closed 00317 PostMessage(it->first, WM_SYSCOMMAND, cmd, 0); 00318 } 00319 } 00320 } 00321 00322 00323 HICON get_window_icon_small(HWND hwnd) 00324 { 00325 HICON hIcon = 0; 00326 00327 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00328 00329 if (!hIcon) 00330 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00331 00332 if (!hIcon) 00333 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00334 00335 if (!hIcon) 00336 hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM); 00337 00338 if (!hIcon) 00339 hIcon = (HICON)GetClassLong(hwnd, GCL_HICON); 00340 00341 if (!hIcon) 00342 SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (LPDWORD)&hIcon); 00343 00344 return hIcon; 00345 } 00346 00347 HICON get_window_icon_big(HWND hwnd, bool allow_from_class) 00348 { 00349 HICON hIcon = 0; 00350 00351 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00352 00353 if (!hIcon) 00354 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00355 00356 if (!hIcon) 00357 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00358 00359 if (allow_from_class) { 00360 if (!hIcon) 00361 hIcon = (HICON)GetClassLong(hwnd, GCL_HICON); 00362 00363 if (!hIcon) 00364 hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM); 00365 } 00366 00367 if (!hIcon) 00368 SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (LPDWORD)&hIcon); 00369 00370 return hIcon; 00371 } 00372 00373 // fill task bar with buttons for enumerated top level windows 00374 BOOL CALLBACK TaskBar::EnumWndProc(HWND hwnd, LPARAM lparam) 00375 { 00376 TaskBar* pThis = (TaskBar*)lparam; 00377 00378 DWORD style = GetWindowStyle(hwnd); 00379 DWORD ex_style = GetWindowExStyle(hwnd); 00380 00381 if ((style&WS_VISIBLE) && !(ex_style&WS_EX_TOOLWINDOW) && 00382 !GetParent(hwnd) && !GetWindow(hwnd,GW_OWNER)) { 00383 TCHAR title[BUFFER_LEN]; 00384 00385 if (!GetWindowText(hwnd, title, BUFFER_LEN)) 00386 title[0] = '\0'; 00387 00388 TaskBarMap::iterator found = pThis->_map.find(hwnd); 00389 int last_id = 0; 00390 00391 if (found != pThis->_map.end()) { 00392 last_id = found->second._id; 00393 00394 if (!last_id) 00395 found->second._id = pThis->_next_id++; 00396 } else { 00397 HBITMAP hbmp; 00398 HICON hIcon = get_window_icon_small(hwnd); 00399 BOOL delete_icon = FALSE; 00400 00401 if (!hIcon) { 00402 hIcon = LoadIcon(0, IDI_APPLICATION); 00403 delete_icon = TRUE; 00404 } 00405 00406 if (hIcon) { 00407 hbmp = create_bitmap_from_icon(hIcon, GetSysColorBrush(COLOR_BTNFACE), WindowCanvas(pThis->_htoolbar)); 00408 if (delete_icon) 00409 DestroyIcon(hIcon); // some icons can be freed, some not - so ignore any error return of DestroyIcon() 00410 } else 00411 hbmp = 0; 00412 00413 TBADDBITMAP ab = {0, (UINT_PTR)hbmp}; 00414 int bmp_idx = SendMessage(pThis->_htoolbar, TB_ADDBITMAP, 1, (LPARAM)&ab); 00415 00416 TaskBarEntry entry; 00417 00418 entry._id = pThis->_next_id++; 00419 entry._hbmp = hbmp; 00420 entry._bmp_idx = bmp_idx; 00421 entry._title = title; 00422 00423 pThis->_map[hwnd] = entry; 00424 found = pThis->_map.find(hwnd); 00425 } 00426 00427 TBBUTTON btn = {-2/*I_IMAGENONE*/, 0, TBSTATE_ENABLED/*|TBSTATE_ELLIPSES*/, BTNS_BUTTON, {0, 0}, 0, 0}; 00428 TaskBarEntry& entry = found->second; 00429 00430 ++entry._used; 00431 btn.idCommand = entry._id; 00432 00433 HWND foreground = GetForegroundWindow(); 00434 HWND foreground_owner = GetWindow(foreground, GW_OWNER); 00435 00436 if (hwnd==foreground || hwnd==foreground_owner) { 00437 btn.fsState |= TBSTATE_PRESSED|TBSTATE_CHECKED; 00438 pThis->_last_foreground_wnd = hwnd; 00439 } 00440 00441 if (!last_id) { 00442 // create new toolbar buttons for new windows 00443 if (title[0]) 00444 btn.iString = (INT_PTR)title; 00445 00446 btn.iBitmap = entry._bmp_idx; 00447 entry._btn_idx = SendMessage(pThis->_htoolbar, TB_BUTTONCOUNT, 0, 0); 00448 00449 SendMessage(pThis->_htoolbar, TB_INSERTBUTTON, entry._btn_idx, (LPARAM)&btn); 00450 00451 pThis->ResizeButtons(); 00452 } else { 00453 // refresh attributes of existing buttons 00454 if (btn.fsState != entry._fsState) 00455 SendMessage(pThis->_htoolbar, TB_SETSTATE, entry._id, MAKELONG(btn.fsState,0)); 00456 00457 if (entry._title != title) { 00458 TBBUTTONINFO info; 00459 00460 info.cbSize = sizeof(TBBUTTONINFO); 00461 info.dwMask = TBIF_TEXT; 00462 info.pszText = title; 00463 00464 SendMessage(pThis->_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info); 00465 00466 entry._title = title; 00467 } 00468 } 00469 00470 entry._fsState = btn.fsState; 00471 00472 #ifdef __REACTOS__ // now handled by activating the ARW_HIDE flag with SystemParametersInfo(SPI_SETMINIMIZEDMETRICS) 00473 // move minimized windows out of sight 00474 if (IsIconic(hwnd)) { 00475 RECT rect; 00476 00477 GetWindowRect(hwnd, &rect); 00478 00479 if (rect.bottom > 0) 00480 SetWindowPos(hwnd, 0, -32000, -32000, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); 00481 } 00482 #endif 00483 } 00484 00485 return TRUE; 00486 } 00487 00488 void TaskBar::Refresh() 00489 { 00490 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) 00491 it->second._used = 0; 00492 00493 EnumWindows(EnumWndProc, (LPARAM)this); 00494 //EnumDesktopWindows(GetThreadDesktop(GetCurrentThreadId()), EnumWndProc, (LPARAM)_htoolbar); 00495 00496 set<int> btn_idx_to_delete; 00497 set<HBITMAP> hbmp_to_delete; 00498 00499 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) { 00500 TaskBarEntry& entry = it->second; 00501 00502 if (!entry._used && entry._id) { 00503 // store button indexes to remove 00504 btn_idx_to_delete.insert(entry._btn_idx); 00505 hbmp_to_delete.insert(entry._hbmp); 00506 entry._id = 0; 00507 } 00508 } 00509 00510 if (!btn_idx_to_delete.empty()) { 00511 // remove buttons from right to left 00512 for(set<int>::reverse_iterator it=btn_idx_to_delete.rbegin(); it!=btn_idx_to_delete.rend(); ++it) { 00513 int idx = *it; 00514 00515 SendMessage(_htoolbar, TB_DELETEBUTTON, idx, 0); 00516 00517 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) { 00518 TaskBarEntry& entry = it->second; 00519 00520 // adjust button indexes 00521 if (entry._btn_idx > idx) { 00522 --entry._btn_idx; 00523 --entry._bmp_idx; 00524 00525 TBBUTTONINFO info; 00526 00527 info.cbSize = sizeof(TBBUTTONINFO); 00528 info.dwMask = TBIF_IMAGE; 00529 info.iImage = entry._bmp_idx; 00530 00531 SendMessage(_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info); 00532 } 00533 } 00534 } 00535 00536 for(set<HBITMAP>::iterator it=hbmp_to_delete.begin(); it!=hbmp_to_delete.end(); ++it) { 00537 HBITMAP hbmp = *it; 00538 00539 TBREPLACEBITMAP tbrepl = {0, (UINT_PTR)hbmp, 0, 0}; 00540 SendMessage(_htoolbar, TB_REPLACEBITMAP, 0, (LPARAM)&tbrepl); 00541 00542 DeleteObject(hbmp); 00543 00544 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) 00545 if (it->second._hbmp == hbmp) { 00546 _map.erase(it); 00547 break; 00548 } 00549 } 00550 00551 ResizeButtons(); 00552 } 00553 } 00554 00555 TaskBarMap::iterator TaskBarMap::find_id(int id) 00556 { 00557 for(iterator it=begin(); it!=end(); ++it) 00558 if (it->second._id == id) 00559 return it; 00560 00561 return end(); 00562 } 00563 00564 void TaskBar::ResizeButtons() 00565 { 00566 int btns = _map.size(); 00567 00568 if (btns > 0) { 00569 int bar_width = ClientRect(_hwnd).right; 00570 int btn_width = (bar_width / btns) - 3; 00571 00572 if (btn_width < TASKBUTTONWIDTH_MIN) 00573 btn_width = TASKBUTTONWIDTH_MIN; 00574 else if (btn_width > TASKBUTTONWIDTH_MAX) 00575 btn_width = TASKBUTTONWIDTH_MAX; 00576 00577 if (btn_width != _last_btn_width) { 00578 _last_btn_width = btn_width; 00579 00580 SendMessage(_htoolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(btn_width,btn_width)); 00581 SendMessage(_htoolbar, TB_AUTOSIZE, 0, 0); 00582 } 00583 } 00584 }
ROS Explorer Source Code Documentation
generated on 02.01.2013 by ![]() |