mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 11:35:58 +00:00
f9b5ca3c79
CORE-9198 #resolve svn path=/trunk/; revision=66372
591 lines
15 KiB
C++
591 lines
15 KiB
C++
/*
|
|
* Copyright 2003, 2004, 2005 Martin Fuchs
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
//
|
|
// Explorer clone
|
|
//
|
|
// taskbar.cpp
|
|
//
|
|
// Martin Fuchs, 16.08.2003
|
|
//
|
|
|
|
|
|
#include <precomp.h>
|
|
|
|
#include "taskbar.h"
|
|
#include "traynotify.h" // for NOTIFYAREA_WIDTH_DEF
|
|
|
|
|
|
DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_SetTaskmanWindow(TEXT("user32"), "SetTaskmanWindow");
|
|
DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_RegisterShellHookWindow(TEXT("user32"), "RegisterShellHookWindow");
|
|
DynamicFct<BOOL (WINAPI*)(HWND hwnd)> g_DeregisterShellHookWindow(TEXT("user32"), "DeregisterShellHookWindow");
|
|
|
|
/*
|
|
DynamicFct<BOOL (WINAPI*)(HWND hWnd, DWORD dwType)> g_RegisterShellHook(TEXT("shell32"), (LPCSTR)0xb5);
|
|
|
|
// constants for RegisterShellHook()
|
|
#define RSH_UNREGISTER 0
|
|
#define RSH_REGISTER 1
|
|
#define RSH_REGISTER_PROGMAN 2
|
|
#define RSH_REGISTER_TASKMAN 3
|
|
*/
|
|
|
|
|
|
TaskBarEntry::TaskBarEntry()
|
|
{
|
|
_id = 0;
|
|
_hbmp = 0;
|
|
_bmp_idx = 0;
|
|
_used = 0;
|
|
_btn_idx = 0;
|
|
_fsState = 0;
|
|
}
|
|
|
|
TaskBarMap::~TaskBarMap()
|
|
{
|
|
while(!empty()) {
|
|
iterator it = begin();
|
|
DeleteBitmap(it->second._hbmp);
|
|
erase(it);
|
|
}
|
|
}
|
|
|
|
|
|
TaskBar::TaskBar(HWND hwnd)
|
|
: super(hwnd),
|
|
WM_SHELLHOOK(RegisterWindowMessage(WINMSG_SHELLHOOK))
|
|
{
|
|
_last_btn_width = 0;
|
|
|
|
_mmMetrics_org.cbSize = sizeof(MINIMIZEDMETRICS);
|
|
|
|
SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(_mmMetrics_org), &_mmMetrics_org, 0);
|
|
|
|
// configure the window manager to hide windows when they are minimized
|
|
// This is neccessary to enable shell hook messages.
|
|
if (!(_mmMetrics_org.iArrange & ARW_HIDE)) {
|
|
MINIMIZEDMETRICS _mmMetrics_new = _mmMetrics_org;
|
|
|
|
_mmMetrics_new.iArrange |= ARW_HIDE;
|
|
|
|
SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(_mmMetrics_new), &_mmMetrics_new, 0);
|
|
}
|
|
}
|
|
|
|
TaskBar::~TaskBar()
|
|
{
|
|
// if (g_RegisterShellHook)
|
|
// (*g_RegisterShellHook)(_hwnd, RSH_UNREGISTER);
|
|
|
|
if (g_DeregisterShellHookWindow)
|
|
(*g_DeregisterShellHookWindow)(_hwnd);
|
|
else
|
|
KillTimer(_hwnd, 0);
|
|
|
|
if (g_SetTaskmanWindow)
|
|
(*g_SetTaskmanWindow)(0);
|
|
|
|
SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(_mmMetrics_org), &_mmMetrics_org, 0);
|
|
}
|
|
|
|
HWND TaskBar::Create(HWND hwndParent)
|
|
{
|
|
ClientRect clnt(hwndParent);
|
|
|
|
int taskbar_pos = 80; // This start position will be adjusted in DesktopBar::Resize().
|
|
|
|
return Window::Create(WINDOW_CREATOR(TaskBar), 0,
|
|
BtnWindowClass(CLASSNAME_TASKBAR), TITLE_TASKBAR,
|
|
WS_CHILD|WS_VISIBLE | CCS_TOP|CCS_NODIVIDER|CCS_NORESIZE,
|
|
taskbar_pos, 0, clnt.right-taskbar_pos-(NOTIFYAREA_WIDTH_DEF+1), clnt.bottom, hwndParent);
|
|
}
|
|
|
|
LRESULT TaskBar::Init(LPCREATESTRUCT pcs)
|
|
{
|
|
if (super::Init(pcs))
|
|
return 1;
|
|
|
|
/* FIXME: There's an internal padding for non-flat toolbar. Get rid of it somehow. */
|
|
_htoolbar = CreateToolbarEx(_hwnd,
|
|
WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|
|
|
CCS_TOP|CCS_NODIVIDER|TBSTYLE_LIST|TBSTYLE_TOOLTIPS|TBSTYLE_WRAPABLE,//|TBSTYLE_AUTOSIZE
|
|
IDW_TASKTOOLBAR, 0, 0, 0, NULL, 0, 0, 0, 16, 16, sizeof(TBBUTTON));
|
|
|
|
SendMessage(_htoolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(TASKBUTTONWIDTH_MAX,TASKBUTTONWIDTH_MAX));
|
|
//SendMessage(_htoolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
|
|
//SendMessage(_htoolbar, TB_SETDRAWTEXTFLAGS, DT_CENTER|DT_VCENTER, DT_CENTER|DT_VCENTER);
|
|
//SetWindowFont(_htoolbar, GetStockFont(ANSI_VAR_FONT), FALSE);
|
|
//SendMessage(_htoolbar, TB_SETPADDING, 0, MAKELPARAM(8,8));
|
|
|
|
// set metrics for the Taskbar toolbar to enable button spacing
|
|
TBMETRICS metrics;
|
|
|
|
metrics.cbSize = sizeof(TBMETRICS);
|
|
metrics.dwMask = TBMF_BARPAD | TBMF_BUTTONSPACING;
|
|
metrics.cxBarPad = 0;
|
|
metrics.cyBarPad = 0;
|
|
metrics.cxButtonSpacing = 3;
|
|
metrics.cyButtonSpacing = 3;
|
|
|
|
SendMessage(_htoolbar, TB_SETMETRICS, 0, (LPARAM)&metrics);
|
|
|
|
_next_id = IDC_FIRST_APP;
|
|
|
|
// register the taskbar window as task manager window to make the following call to RegisterShellHookWindow working
|
|
if (g_SetTaskmanWindow)
|
|
(*g_SetTaskmanWindow)(_hwnd);
|
|
|
|
if (g_RegisterShellHookWindow) {
|
|
LOG(TEXT("Using shell hooks for notification of shell events."));
|
|
|
|
(*g_RegisterShellHookWindow)(_hwnd);
|
|
} else {
|
|
LOG(TEXT("Shell hooks not available."));
|
|
|
|
SetTimer(_hwnd, 0, 200, NULL);
|
|
}
|
|
|
|
/* Alternatively we could use the RegisterShellHook() function in SHELL32, but this is not yet implemented in the WINE code.
|
|
if (g_RegisterShellHook) {
|
|
(*g_RegisterShellHook)(0, RSH_REGISTER);
|
|
|
|
if ((HIWORD(GetVersion())>>14) == W_VER_NT)
|
|
(*g_RegisterShellHook)(_hwnd, RSH_REGISTER_TASKMAN);
|
|
else
|
|
(*g_RegisterShellHook)(_hwnd, RSH_REGISTER);
|
|
}
|
|
*/
|
|
Refresh();
|
|
|
|
return 0;
|
|
}
|
|
|
|
LRESULT TaskBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
switch(nmsg) {
|
|
case WM_SIZE:
|
|
SendMessage(_htoolbar, WM_SIZE, 0, 0);
|
|
ResizeButtons();
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
Refresh();
|
|
return 0;
|
|
|
|
case WM_CONTEXTMENU: {
|
|
Point pt(lparam);
|
|
ScreenToClient(_htoolbar, &pt);
|
|
|
|
if ((HWND)wparam==_htoolbar && SendMessage(_htoolbar, TB_HITTEST, 0, (LPARAM)&pt)>=0)
|
|
break; // avoid displaying context menu for application button _and_ desktop bar at the same time
|
|
|
|
goto def;}
|
|
|
|
case PM_GET_LAST_ACTIVE:
|
|
return (LRESULT)(HWND)_last_foreground_wnd;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
SendMessage(_htoolbar, WM_SYSCOLORCHANGE, 0, 0);
|
|
break;
|
|
|
|
default: def:
|
|
if (nmsg == WM_SHELLHOOK) {
|
|
switch(wparam) {
|
|
case HSHELL_WINDOWCREATED:
|
|
case HSHELL_WINDOWDESTROYED:
|
|
case HSHELL_WINDOWACTIVATED:
|
|
case HSHELL_REDRAW:
|
|
#ifdef HSHELL_FLASH
|
|
case HSHELL_FLASH:
|
|
#endif
|
|
#ifdef HSHELL_RUDEAPPACTIVATED
|
|
case HSHELL_RUDEAPPACTIVATED:
|
|
#endif
|
|
Refresh();
|
|
break;
|
|
}
|
|
} else {
|
|
return super::WndProc(nmsg, wparam, lparam);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TaskBar::Command(int id, int code)
|
|
{
|
|
TaskBarMap::iterator found = _map.find_id(id);
|
|
|
|
if (found != _map.end()) {
|
|
ActivateApp(found);
|
|
return 0;
|
|
}
|
|
|
|
return super::Command(id, code);
|
|
}
|
|
|
|
int TaskBar::Notify(int id, NMHDR* pnmh)
|
|
{
|
|
if (pnmh->hwndFrom == _htoolbar)
|
|
switch(pnmh->code) {
|
|
case NM_RCLICK: {
|
|
TBBUTTONINFO btninfo;
|
|
TaskBarMap::iterator it;
|
|
Point pt(GetMessagePos());
|
|
ScreenToClient(_htoolbar, &pt);
|
|
|
|
btninfo.cbSize = sizeof(TBBUTTONINFO);
|
|
btninfo.dwMask = TBIF_BYINDEX|TBIF_COMMAND;
|
|
|
|
int idx = SendMessage(_htoolbar, TB_HITTEST, 0, (LPARAM)&pt);
|
|
|
|
if (idx>=0 &&
|
|
SendMessage(_htoolbar, TB_GETBUTTONINFO, idx, (LPARAM)&btninfo)!=-1 &&
|
|
(it=_map.find_id(btninfo.idCommand))!=_map.end()) {
|
|
//TaskBarEntry& entry = it->second;
|
|
|
|
ActivateApp(it, false, false); // don't restore minimized windows on right button click
|
|
|
|
static DynamicFct<DWORD(STDAPICALLTYPE*)(RESTRICTIONS)> pSHRestricted(TEXT("SHELL32"), "SHRestricted");
|
|
|
|
if (pSHRestricted && !(*pSHRestricted)(REST_NOTRAYCONTEXTMENU))
|
|
ShowAppSystemMenu(it);
|
|
}
|
|
break;}
|
|
|
|
default:
|
|
return super::Notify(id, pnmh);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void TaskBar::ActivateApp(TaskBarMap::iterator it, bool can_minimize, bool can_restore)
|
|
{
|
|
HWND hwnd = it->first;
|
|
|
|
bool minimize_it = can_minimize && !IsIconic(hwnd) &&
|
|
(hwnd==GetForegroundWindow() || hwnd==_last_foreground_wnd);
|
|
|
|
// switch to selected application window
|
|
if (can_restore && !minimize_it)
|
|
if (IsIconic(hwnd))
|
|
PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
|
|
|
|
// In case minimize_it is true, we _have_ to switch to the app before
|
|
// posting SW_MINIMIZE to be compatible with some applications (e.g. "Sleipnir")
|
|
SetForegroundWindow(hwnd);
|
|
|
|
if (minimize_it) {
|
|
PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
|
_last_foreground_wnd = 0;
|
|
} else
|
|
_last_foreground_wnd = hwnd;
|
|
|
|
Refresh();
|
|
}
|
|
|
|
void TaskBar::ShowAppSystemMenu(TaskBarMap::iterator it)
|
|
{
|
|
HMENU hmenu = GetSystemMenu(it->first, FALSE);
|
|
|
|
if (hmenu) {
|
|
POINT pt;
|
|
|
|
GetCursorPos(&pt);
|
|
int cmd = TrackPopupMenu(hmenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, _hwnd, NULL);
|
|
|
|
if (cmd) {
|
|
ActivateApp(it, false, false); // reactivate window after the context menu has closed
|
|
PostMessage(it->first, WM_SYSCOMMAND, cmd, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
HICON get_window_icon_small(HWND hwnd)
|
|
{
|
|
HICON hIcon = 0;
|
|
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (!hIcon)
|
|
hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM);
|
|
|
|
if (!hIcon)
|
|
hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON);
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
return hIcon;
|
|
}
|
|
|
|
HICON get_window_icon_big(HWND hwnd, bool allow_from_class)
|
|
{
|
|
HICON hIcon = 0;
|
|
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
if (allow_from_class) {
|
|
if (!hIcon)
|
|
hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON);
|
|
|
|
if (!hIcon)
|
|
hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM);
|
|
}
|
|
|
|
if (!hIcon)
|
|
SendMessageTimeout(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)&hIcon);
|
|
|
|
return hIcon;
|
|
}
|
|
|
|
// fill task bar with buttons for enumerated top level windows
|
|
BOOL CALLBACK TaskBar::EnumWndProc(HWND hwnd, LPARAM lparam)
|
|
{
|
|
TaskBar* pThis = (TaskBar*)lparam;
|
|
|
|
DWORD style = GetWindowStyle(hwnd);
|
|
DWORD ex_style = GetWindowExStyle(hwnd);
|
|
|
|
if ((style&WS_VISIBLE) && !(ex_style&WS_EX_TOOLWINDOW) &&
|
|
!GetParent(hwnd) && !GetWindow(hwnd,GW_OWNER)) {
|
|
TCHAR title[BUFFER_LEN];
|
|
|
|
if (!GetWindowText(hwnd, title, BUFFER_LEN))
|
|
title[0] = '\0';
|
|
|
|
TaskBarMap::iterator found = pThis->_map.find(hwnd);
|
|
int last_id = 0;
|
|
|
|
if (found != pThis->_map.end()) {
|
|
last_id = found->second._id;
|
|
|
|
if (!last_id)
|
|
found->second._id = pThis->_next_id++;
|
|
} else {
|
|
HBITMAP hbmp;
|
|
HICON hIcon = get_window_icon_small(hwnd);
|
|
BOOL delete_icon = FALSE;
|
|
|
|
if (!hIcon) {
|
|
hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
delete_icon = TRUE;
|
|
}
|
|
|
|
if (hIcon) {
|
|
hbmp = create_bitmap_from_icon(hIcon, GetSysColorBrush(COLOR_BTNFACE), WindowCanvas(pThis->_htoolbar));
|
|
if (delete_icon)
|
|
DestroyIcon(hIcon); // some icons can be freed, some not - so ignore any error return of DestroyIcon()
|
|
} else
|
|
hbmp = 0;
|
|
|
|
TBADDBITMAP ab = {0, (UINT_PTR)hbmp};
|
|
int bmp_idx = SendMessage(pThis->_htoolbar, TB_ADDBITMAP, 1, (LPARAM)&ab);
|
|
|
|
TaskBarEntry entry;
|
|
|
|
entry._id = pThis->_next_id++;
|
|
entry._hbmp = hbmp;
|
|
entry._bmp_idx = bmp_idx;
|
|
entry._title = title;
|
|
|
|
pThis->_map[hwnd] = entry;
|
|
found = pThis->_map.find(hwnd);
|
|
}
|
|
|
|
TBBUTTON btn = {-2/*I_IMAGENONE*/, 0, TBSTATE_ENABLED/*|TBSTATE_ELLIPSES*/, BTNS_BUTTON, {0, 0}, 0, 0};
|
|
TaskBarEntry& entry = found->second;
|
|
|
|
++entry._used;
|
|
btn.idCommand = entry._id;
|
|
|
|
HWND foreground = GetForegroundWindow();
|
|
HWND foreground_owner = GetWindow(foreground, GW_OWNER);
|
|
|
|
if (hwnd==foreground || hwnd==foreground_owner) {
|
|
btn.fsState |= TBSTATE_PRESSED|TBSTATE_CHECKED;
|
|
pThis->_last_foreground_wnd = hwnd;
|
|
}
|
|
|
|
if (!last_id) {
|
|
// create new toolbar buttons for new windows
|
|
if (title[0])
|
|
btn.iString = (INT_PTR)title;
|
|
|
|
btn.iBitmap = entry._bmp_idx;
|
|
entry._btn_idx = SendMessage(pThis->_htoolbar, TB_BUTTONCOUNT, 0, 0);
|
|
|
|
SendMessage(pThis->_htoolbar, TB_INSERTBUTTON, entry._btn_idx, (LPARAM)&btn);
|
|
|
|
pThis->ResizeButtons();
|
|
} else {
|
|
// refresh attributes of existing buttons
|
|
if (btn.fsState != entry._fsState)
|
|
SendMessage(pThis->_htoolbar, TB_SETSTATE, entry._id, MAKELONG(btn.fsState,0));
|
|
|
|
if (entry._title != title) {
|
|
TBBUTTONINFO info;
|
|
|
|
info.cbSize = sizeof(TBBUTTONINFO);
|
|
info.dwMask = TBIF_TEXT;
|
|
info.pszText = title;
|
|
|
|
SendMessage(pThis->_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info);
|
|
|
|
entry._title = title;
|
|
}
|
|
}
|
|
|
|
entry._fsState = btn.fsState;
|
|
|
|
#ifdef __REACTOS__ // now handled by activating the ARW_HIDE flag with SystemParametersInfo(SPI_SETMINIMIZEDMETRICS)
|
|
// move minimized windows out of sight
|
|
if (IsIconic(hwnd)) {
|
|
RECT rect;
|
|
|
|
GetWindowRect(hwnd, &rect);
|
|
|
|
if (rect.bottom > 0)
|
|
SetWindowPos(hwnd, 0, -32000, -32000, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TaskBar::Refresh()
|
|
{
|
|
for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it)
|
|
it->second._used = 0;
|
|
|
|
EnumWindows(EnumWndProc, (LPARAM)this);
|
|
//EnumDesktopWindows(GetThreadDesktop(GetCurrentThreadId()), EnumWndProc, (LPARAM)_htoolbar);
|
|
|
|
set<int> btn_idx_to_delete;
|
|
set<HBITMAP> hbmp_to_delete;
|
|
|
|
for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it) {
|
|
TaskBarEntry& entry = it->second;
|
|
|
|
if (!entry._used && entry._id) {
|
|
// store button indexes to remove
|
|
btn_idx_to_delete.insert(entry._btn_idx);
|
|
hbmp_to_delete.insert(entry._hbmp);
|
|
entry._id = 0;
|
|
}
|
|
}
|
|
|
|
if (!btn_idx_to_delete.empty()) {
|
|
// remove buttons from right to left
|
|
for(set<int>::reverse_iterator it=btn_idx_to_delete.rbegin(); it!=btn_idx_to_delete.rend(); ++it) {
|
|
int idx = *it;
|
|
|
|
if (!SendMessage(_htoolbar, TB_DELETEBUTTON, idx, 0))
|
|
MessageBoxW(NULL, L"failed to delete button", NULL, MB_OK);
|
|
|
|
|
|
for(TaskBarMap::iterator it2=_map.begin(); it2!=_map.end(); ++it2) {
|
|
TaskBarEntry& entry = it2->second;
|
|
|
|
// adjust button indexes
|
|
if (entry._btn_idx > idx) {
|
|
--entry._btn_idx;
|
|
#if 0
|
|
--entry._bmp_idx;
|
|
|
|
TBBUTTONINFO info;
|
|
|
|
info.cbSize = sizeof(TBBUTTONINFO);
|
|
info.dwMask = TBIF_IMAGE;
|
|
info.iImage = entry._bmp_idx;
|
|
|
|
if (!SendMessage(_htoolbar, TB_SETBUTTONINFO, entry._id, (LPARAM)&info))
|
|
MessageBoxW(NULL, L"failed to set button info", NULL, MB_OK);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
for(set<HBITMAP>::iterator it=hbmp_to_delete.begin(); it!=hbmp_to_delete.end(); ++it) {
|
|
HBITMAP hbmp = *it;
|
|
#if 0
|
|
TBREPLACEBITMAP tbrepl = {0, (UINT_PTR)hbmp, 0, 0};
|
|
SendMessage(_htoolbar, TB_REPLACEBITMAP, 0, (LPARAM)&tbrepl);
|
|
#endif
|
|
DeleteObject(hbmp);
|
|
|
|
for(TaskBarMap::iterator it=_map.begin(); it!=_map.end(); ++it)
|
|
if (it->second._hbmp == hbmp) {
|
|
_map.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ResizeButtons();
|
|
}
|
|
}
|
|
|
|
TaskBarMap::iterator TaskBarMap::find_id(int id)
|
|
{
|
|
for(iterator it=begin(); it!=end(); ++it)
|
|
if (it->second._id == id)
|
|
return it;
|
|
|
|
return end();
|
|
}
|
|
|
|
void TaskBar::ResizeButtons()
|
|
{
|
|
int btns = _map.size();
|
|
|
|
if (btns > 0) {
|
|
int bar_width = ClientRect(_hwnd).right;
|
|
int btn_width = (bar_width / btns) - 3;
|
|
|
|
if (btn_width < TASKBUTTONWIDTH_MIN)
|
|
btn_width = TASKBUTTONWIDTH_MIN;
|
|
else if (btn_width > TASKBUTTONWIDTH_MAX)
|
|
btn_width = TASKBUTTONWIDTH_MAX;
|
|
|
|
if (btn_width != _last_btn_width) {
|
|
_last_btn_width = btn_width;
|
|
|
|
SendMessage(_htoolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(btn_width,btn_width));
|
|
SendMessage(_htoolbar, TB_AUTOSIZE, 0, 0);
|
|
}
|
|
}
|
|
}
|