Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentaskbar.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 case WM_SYSCOLORCHANGE: 00206 SendMessage(_htoolbar, WM_SYSCOLORCHANGE, 0, 0); 00207 break; 00208 00209 default: def: 00210 if (nmsg == WM_SHELLHOOK) { 00211 switch(wparam) { 00212 case HSHELL_WINDOWCREATED: 00213 case HSHELL_WINDOWDESTROYED: 00214 case HSHELL_WINDOWACTIVATED: 00215 case HSHELL_REDRAW: 00216 #ifdef HSHELL_FLASH 00217 case HSHELL_FLASH: 00218 #endif 00219 #ifdef HSHELL_RUDEAPPACTIVATED 00220 case HSHELL_RUDEAPPACTIVATED: 00221 #endif 00222 Refresh(); 00223 break; 00224 } 00225 } else { 00226 return super::WndProc(nmsg, wparam, lparam); 00227 } 00228 } 00229 00230 return 0; 00231 } 00232 00233 int TaskBar::Command(int id, int code) 00234 { 00235 TaskBarMap::iterator found = _map.find_id(id); 00236 00237 if (found != _map.end()) { 00238 ActivateApp(found); 00239 return 0; 00240 } 00241 00242 return super::Command(id, code); 00243 } 00244 00245 int TaskBar::Notify(int id, NMHDR* pnmh) 00246 { 00247 if (pnmh->hwndFrom == _htoolbar) 00248 switch(pnmh->code) { 00249 case NM_RCLICK: { 00250 TBBUTTONINFO btninfo; 00251 TaskBarMap::iterator it; 00252 Point pt(GetMessagePos()); 00253 ScreenToClient(_htoolbar, &pt); 00254 00255 btninfo.cbSize = sizeof(TBBUTTONINFO); 00256 btninfo.dwMask = TBIF_BYINDEX|TBIF_COMMAND; 00257 00258 int idx = SendMessage(_htoolbar, TB_HITTEST, 0, (LPARAM)&pt); 00259 00260 if (idx>=0 && 00261 SendMessage(_htoolbar, TB_GETBUTTONINFO, idx, (LPARAM)&btninfo)!=-1 && 00262 (it=_map.find_id(btninfo.idCommand))!=_map.end()) { 00263 //TaskBarEntry& entry = it->second; 00264 00265 ActivateApp(it, false, false); // don't restore minimized windows on right button click 00266 00267 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003) 00268 static DynamicFct<DWORD(STDAPICALLTYPE*)(RESTRICTIONS)> pSHRestricted(TEXT("SHELL32"), "SHRestricted"); 00269 00270 if (pSHRestricted && !(*pSHRestricted)(REST_NOTRAYCONTEXTMENU)) 00271 #endif 00272 ShowAppSystemMenu(it); 00273 } 00274 break;} 00275 00276 default: 00277 return super::Notify(id, pnmh); 00278 } 00279 00280 return 0; 00281 } 00282 00283 00284 void TaskBar::ActivateApp(TaskBarMap::iterator it, bool can_minimize, bool can_restore) 00285 { 00286 HWND hwnd = it->first; 00287 00288 bool minimize_it = can_minimize && !IsIconic(hwnd) && 00289 (hwnd==GetForegroundWindow() || hwnd==_last_foreground_wnd); 00290 00291 // switch to selected application window 00292 if (can_restore && !minimize_it) 00293 if (IsIconic(hwnd)) 00294 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 00295 00296 // In case minimize_it is true, we _have_ to switch to the app before 00297 // posting SW_MINIMIZE to be compatible with some applications (e.g. "Sleipnir") 00298 SetForegroundWindow(hwnd); 00299 00300 if (minimize_it) { 00301 PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); 00302 _last_foreground_wnd = 0; 00303 } else 00304 _last_foreground_wnd = hwnd; 00305 00306 Refresh(); 00307 } 00308 00309 void TaskBar::ShowAppSystemMenu(TaskBarMap::iterator it) 00310 { 00311 HMENU hmenu = GetSystemMenu(it->first, FALSE); 00312 00313 if (hmenu) { 00314 POINT pt; 00315 00316 GetCursorPos(&pt); 00317 int cmd = TrackPopupMenu(hmenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, _hwnd, NULL); 00318 00319 if (cmd) { 00320 ActivateApp(it, false, false); // reactivate window after the context menu has closed 00321 PostMessage(it->first, WM_SYSCOMMAND, cmd, 0); 00322 } 00323 } 00324 } 00325 00326 00327 HICON get_window_icon_small(HWND hwnd) 00328 { 00329 HICON hIcon = 0; 00330 00331 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00332 00333 if (!hIcon) 00334 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00335 00336 if (!hIcon) 00337 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00338 00339 if (!hIcon) 00340 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM); 00341 00342 if (!hIcon) 00343 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON); 00344 00345 if (!hIcon) 00346 SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (LPDWORD)&hIcon); 00347 00348 return hIcon; 00349 } 00350 00351 HICON get_window_icon_big(HWND hwnd, bool allow_from_class) 00352 { 00353 HICON hIcon = 0; 00354 00355 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00356 00357 if (!hIcon) 00358 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00359 00360 if (!hIcon) 00361 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon); 00362 00363 if (allow_from_class) { 00364 if (!hIcon) 00365 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON); 00366 00367 if (!hIcon) 00368 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM); 00369 } 00370 00371 if (!hIcon) 00372 SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (LPDWORD)&hIcon); 00373 00374 return hIcon; 00375 } 00376 00377 // fill task bar with buttons for enumerated top level windows 00378 BOOL CALLBACK TaskBar::EnumWndProc(HWND hwnd, LPARAM lparam) 00379 { 00380 TaskBar* pThis = (TaskBar*)lparam; 00381 00382 DWORD style = GetWindowStyle(hwnd); 00383 DWORD ex_style = GetWindowExStyle(hwnd); 00384 00385 if ((style&WS_VISIBLE) && !(ex_style&WS_EX_TOOLWINDOW) && 00386 !GetParent(hwnd) && !GetWindow(hwnd,GW_OWNER)) { 00387 TCHAR title[BUFFER_LEN]; 00388 00389 if (!GetWindowText(hwnd, title, BUFFER_LEN)) 00390 title[0] = '\0'; 00391 00392 TaskBarMap::iterator found = pThis->_map.find(hwnd); 00393 int last_id = 0; 00394 00395 if (found != pThis->_map.end()) { 00396 last_id = found->second._id; 00397 00398 if (!last_id) 00399 found->second._id = pThis->_next_id++; 00400 } else { 00401 HBITMAP hbmp; 00402 HICON hIcon = get_window_icon_small(hwnd); 00403 BOOL delete_icon = FALSE; 00404 00405 if (!hIcon) { 00406 hIcon = LoadIcon(0, IDI_APPLICATION); 00407 delete_icon = TRUE; 00408 } 00409 00410 if (hIcon) { 00411 hbmp = create_bitmap_from_icon(hIcon, GetSysColorBrush(COLOR_BTNFACE), WindowCanvas(pThis->_htoolbar)); 00412 if (delete_icon) 00413 DestroyIcon(hIcon); // some icons can be freed, some not - so ignore any error return of DestroyIcon() 00414 } else 00415 hbmp = 0; 00416 00417 TBADDBITMAP ab = {0, (UINT_PTR)hbmp}; 00418 int bmp_idx = SendMessage(pThis->_htoolbar, TB_ADDBITMAP, 1, (LPARAM)&ab); 00419 00420 TaskBarEntry entry; 00421 00422 entry._id = pThis->_next_id++; 00423 entry._hbmp = hbmp; 00424 entry._bmp_idx = bmp_idx; 00425 entry._title = title; 00426 00427 pThis->_map[hwnd] = entry; 00428 found = pThis->_map.find(hwnd); 00429 } 00430 00431 TBBUTTON btn = {-2/*I_IMAGENONE*/, 0, TBSTATE_ENABLED/*|TBSTATE_ELLIPSES*/, BTNS_BUTTON, {0, 0}, 0, 0}; 00432 TaskBarEntry& entry = found->second; 00433 00434 ++entry._used; 00435 btn.idCommand = entry._id; 00436 00437 HWND foreground = GetForegroundWindow(); 00438 HWND foreground_owner = GetWindow(foreground, GW_OWNER); 00439 00440 if (hwnd==foreground || hwnd==foreground_owner) { 00441 btn.fsState |= TBSTATE_PRESSED|TBSTATE_CHECKED; 00442 pThis->_last_foreground_wnd = hwnd; 00443 } 00444 00445 if (!last_id) { 00446 // create new toolbar buttons for new windows 00447 if (title[0]) 00448 btn.iString = (INT_PTR)title; 00449 00450 btn.iBitmap = entry._bmp_idx; 00451 entry._btn_idx = SendMessage(pThis->_htoolbar, TB_BUTTONCOUNT, 0, 0); 00452 00453 SendMessage(pThis->_htoolbar, TB_INSERTBUTTON, entry._btn_idx, (LPARAM)&btn); 00454 00455 pThis->ResizeButtons(); 00456 } else { 00457 // refresh attributes of existing buttons 00458 if (btn.fsState != entry._fsState) 00459 SendMessage(pThis->_htoolbar, TB_SETSTATE, entry._id, MAKELONG(btn.fsState,0)); 00460 00461 if (entry._title != title) { 00462 TBBUTTONINFO info; 00463 00464 info.cbSize = sizeof(TBBUTTONINFO); 00465 info.dwMask = TBIF_TEXT; 00466 info.pszText = title; 00467 00468 SendMessage(pThis->_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info); 00469 00470 entry._title = title; 00471 } 00472 } 00473 00474 entry._fsState = btn.fsState; 00475 00476 #ifdef __REACTOS__ // now handled by activating the ARW_HIDE flag with SystemParametersInfo(SPI_SETMINIMIZEDMETRICS) 00477 // move minimized windows out of sight 00478 if (IsIconic(hwnd)) { 00479 RECT rect; 00480 00481 GetWindowRect(hwnd, &rect); 00482 00483 if (rect.bottom > 0) 00484 SetWindowPos(hwnd, 0, -32000, -32000, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); 00485 } 00486 #endif 00487 } 00488 00489 return TRUE; 00490 } 00491 00492 void TaskBar::Refresh() 00493 { 00494 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) 00495 it->second._used = 0; 00496 00497 EnumWindows(EnumWndProc, (LPARAM)this); 00498 //EnumDesktopWindows(GetThreadDesktop(GetCurrentThreadId()), EnumWndProc, (LPARAM)_htoolbar); 00499 00500 set<int> btn_idx_to_delete; 00501 set<HBITMAP> hbmp_to_delete; 00502 00503 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) { 00504 TaskBarEntry& entry = it->second; 00505 00506 if (!entry._used && entry._id) { 00507 // store button indexes to remove 00508 btn_idx_to_delete.insert(entry._btn_idx); 00509 hbmp_to_delete.insert(entry._hbmp); 00510 entry._id = 0; 00511 } 00512 } 00513 00514 if (!btn_idx_to_delete.empty()) { 00515 // remove buttons from right to left 00516 for(set<int>::reverse_iterator it=btn_idx_to_delete.rbegin(); it!=btn_idx_to_delete.rend(); ++it) { 00517 int idx = *it; 00518 00519 SendMessage(_htoolbar, TB_DELETEBUTTON, idx, 0); 00520 00521 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) { 00522 TaskBarEntry& entry = it->second; 00523 00524 // adjust button indexes 00525 if (entry._btn_idx > idx) { 00526 --entry._btn_idx; 00527 --entry._bmp_idx; 00528 00529 TBBUTTONINFO info; 00530 00531 info.cbSize = sizeof(TBBUTTONINFO); 00532 info.dwMask = TBIF_IMAGE; 00533 info.iImage = entry._bmp_idx; 00534 00535 SendMessage(_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info); 00536 } 00537 } 00538 } 00539 00540 for(set<HBITMAP>::iterator it=hbmp_to_delete.begin(); it!=hbmp_to_delete.end(); ++it) { 00541 HBITMAP hbmp = *it; 00542 00543 TBREPLACEBITMAP tbrepl = {0, (UINT_PTR)hbmp, 0, 0}; 00544 SendMessage(_htoolbar, TB_REPLACEBITMAP, 0, (LPARAM)&tbrepl); 00545 00546 DeleteObject(hbmp); 00547 00548 for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) 00549 if (it->second._hbmp == hbmp) { 00550 _map.erase(it); 00551 break; 00552 } 00553 } 00554 00555 ResizeButtons(); 00556 } 00557 } 00558 00559 TaskBarMap::iterator TaskBarMap::find_id(int id) 00560 { 00561 for(iterator it=begin(); it!=end(); ++it) 00562 if (it->second._id == id) 00563 return it; 00564 00565 return end(); 00566 } 00567 00568 void TaskBar::ResizeButtons() 00569 { 00570 int btns = _map.size(); 00571 00572 if (btns > 0) { 00573 int bar_width = ClientRect(_hwnd).right; 00574 int btn_width = (bar_width / btns) - 3; 00575 00576 if (btn_width < TASKBUTTONWIDTH_MIN) 00577 btn_width = TASKBUTTONWIDTH_MIN; 00578 else if (btn_width > TASKBUTTONWIDTH_MAX) 00579 btn_width = TASKBUTTONWIDTH_MAX; 00580 00581 if (btn_width != _last_btn_width) { 00582 _last_btn_width = btn_width; 00583 00584 SendMessage(_htoolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(btn_width,btn_width)); 00585 SendMessage(_htoolbar, TB_AUTOSIZE, 0, 0); 00586 } 00587 } 00588 } Generated on Sun May 27 2012 04:18:39 for ReactOS by
1.7.6.1
|