diff options
Diffstat (limited to 'Src/omBrowser/toolbar.cpp')
-rw-r--r-- | Src/omBrowser/toolbar.cpp | 3572 |
1 files changed, 3572 insertions, 0 deletions
diff --git a/Src/omBrowser/toolbar.cpp b/Src/omBrowser/toolbar.cpp new file mode 100644 index 00000000..d1a0d78c --- /dev/null +++ b/Src/omBrowser/toolbar.cpp @@ -0,0 +1,3572 @@ +#include "main.h" +#include "./toolbar.h" +#include "./graphics.h" +#include "./resource.h" +#include "./toolbarItem.h" +#include "./toolbarStatic.h" +#include "./toolbarButton.h" +#include "./toolbarRating.h" +#include "./toolbarProgress.h" +#include "./toolbarAddress.h" +#include "../winamp/wa_dlg.h" +#include "../Plugins/General/gen_ml/ml_ipc_0313.h" +#include "./ifc_imageloader.h" +#include "./ifc_skinhelper.h" +#include "./ifc_omservice.h" +#include "./ifc_omservicecommand.h" +#include "./menu.h" +#include "./ifc_wasabihelper.h" + +#include "./browserUiCommon.h" + + +#include <windows.h> +#include <shlwapi.h> +#include <commctrl.h> +#include <strsafe.h> +#include <vector> + +#define TOOLBAR_SPACE_LEFT 0 +#define TOOLBAR_SPACE_TOP 4 +#define TOOLBAR_SPACE_RIGHT 1 +#define TOOLBAR_SPACE_BOTTOM 3 + +#define TOOLBAR_HIDDENHEIGHT 3 + +#define TOOLBAR_ICONSTATE_NORMAL 0 +#define TOOLBAR_ICONSTATE_HIGHLIGHTED 1 +#define TOOLBAR_ICONSTATE_PRESSED 2 +#define TOOLBAR_ICONSTATE_DISABLED 3 +#define TOOLBAR_ICONSTATE_COUNT 4 + +#define TBS_MENULOOP 0x00000001 +#define TBS_HIDDEN 0x00000002 +#define TBS_HIDETIMERSET 0x00000004 +#define TBS_NOFOCUSRECT 0x00000008 + +#define ICON_NONE (-1) +#define ICON_CHEVRON (-2) // - resolved on the fly +#define ICON_SEPARATOR 0 +#define ICON_CHEVRON_BOTTOM 1 +#define ICON_CHEVRON_TOP 2 +#define ICON_BACK 3 +#define ICON_FORWARD 4 +#define ICON_REFRESH 5 +#define ICON_STOP 6 +#define ICON_HOME 7 +#define ICON_ERROR 8 +#define ICON_LOCK 9 +#define ICON_HISTORY 10 +#define ICON_ADDRESSBAR 11 + +#define ICON_SEPARATOR_WIDTH 6 +#define ICON_CHEVRON_WIDTH 13 +#define ICON_HISTORY_WIDTH 9 +#define ICON_ARROW_WIDTH 17 + +#define TOOLBRUSH_BACK 0 +#define TOOLBRUSH_FRAME 1 +#define TOOLBRUSH_ITEMBK 2 +#define TOOLBRUSH_LAST TOOLBRUSH_ITEMBK + +#define ID_CHEVRON_CLICKED 1 + +#define TOOLBAR_BKCOLOR WADLG_LISTHEADER_BGCOLOR +#define TOOLBAR_FGCOLOR WADLG_LISTHEADER_FONTCOLOR + +#define EDIT_ALPHA 50 +#define TEXT_ALPHA 127 +#define HIGHLIGHT_ALPHA 160 +#define TIMER_AUTOHIDE_ID 14 +#define TIMER_AUTOHIDE_DELAY 300 + +#define AUTOHIDE_ANIMATETIME 200 + +typedef std::vector<ToolbarItem*> ItemList; + +typedef struct __TOOLBAR +{ + UINT ref; + UINT flags; + HBRUSH szBrushes[TOOLBRUSH_LAST + 1]; + HIMAGELIST imageList; + HFONT textFont; + ItemList *items; + ToolbarItem *chevron; + ToolbarItem *pressed; + ToolbarItem *highlighted; + UINT resolveCache; + HFONT ownedFont; + HWND hTooltip; + COLORREF rgbBk; + COLORREF rgbFg; + COLORREF rgbText; + COLORREF rgbHilite; + COLORREF rgbFrame; + COLORREF rgbEdit; + COLORREF rgbEditBk; + size_t iFocused; + HWND hBrowser; + TOOLBARTEXTMETRIC textMetric; +} TOOLBAR; + +typedef struct __TOOLBARMOUSEHOOK +{ + HHOOK hHook; + HWND hwnd; +} TOOLBARMOUSEHOOK; + +static size_t tlsIndex = TLS_OUT_OF_INDEXES; + +typedef ToolbarItem *(CALLBACK *TOOLBARITEMFACTORY)(ToolbarItem::Template * /*itemTemplate*/); + +typedef struct __TOOLBARITEMCLASS +{ + LPCSTR name; + TOOLBARITEMFACTORY creator; + LPCWSTR text; + LPCWSTR description; + INT iconId; + INT commandId; + UINT style; +} TOOLBARITEMCLASS; + +#define REGISTER_ITEM(__name, __creator, __textId, __descriptionId, __iconId, __commandId, __style)\ + { (__name), (__creator), MAKEINTRESOURCE(__textId),\ + MAKEINTRESOURCE(__descriptionId), (__iconId), (__commandId), (__style) } + +#define REGISTER_STATIC(__name, __textId, __descriptionId, __iconId, __style)\ + REGISTER_ITEM(__name, ToolbarStatic::CreateInstance, __textId, __descriptionId, __iconId, 0, __style) + +#define REGISTER_BUTTON(__name, __textId, __descriptionId, __iconId, __commandId, __style)\ + REGISTER_ITEM(__name, ToolbarButton::CreateInstance, __textId, __descriptionId, __iconId, __commandId, __style) + +#define REGISTER_RATING(__name, __textId, __descriptionId, __style)\ + REGISTER_ITEM(__name, ToolbarRating::CreateInstance, __textId, __descriptionId, ICON_NONE, 0, __style) + +#define REGISTER_PROGRESS(__name, __textId, __descriptionId, __style)\ + REGISTER_ITEM(__name, ToolbarProgress::CreateInstance, __textId, __descriptionId, ICON_NONE, 0, __style) + +#define REGISTER_ADDRESSBAR(__name, __style)\ + REGISTER_ITEM(__name, ToolbarAddress::CreateInstance, NULL, NULL, ICON_NONE, 0, __style) + +const static TOOLBARITEMCLASS szRegisteredToolItems[] = +{ + REGISTER_STATIC(TOOLITEM_SEPARATOR, IDS_SEPARATOR, 0, ICON_SEPARATOR, ToolbarStatic::styleSeparator), + REGISTER_STATIC(TOOLITEM_SPACE, IDS_SPACE, 0, ICON_NONE, ToolbarStatic::styleSpacer), + REGISTER_STATIC(TOOLITEM_FLEXSPACE, IDS_FLEXSPACE, 0, ICON_NONE, ToolbarStatic::styleSpacer | ToolbarItem::styleFlexible), + REGISTER_RATING(TOOLITEM_USERRATING, IDS_RATED, NULL, ToolbarItem::styleWantKey), + REGISTER_PROGRESS(TOOLITEM_DOWNLOADPROGRESS, NULL, NULL, ToolbarItem::stateDisabled), + REGISTER_ADDRESSBAR(TOOLITEM_ADDRESSBAR, ToolbarItem::styleFlexible | ToolbarItem::styleWantKey | ToolbarItem::styleTabstop), + + REGISTER_BUTTON(TOOLITEM_CHEVRON, IDS_MORE, IDS_MORE_DESCRIPTION, ICON_CHEVRON, + ID_CHEVRON_CLICKED, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_HOME, IDS_HOME, IDS_HOME_DESCRIPTION, ICON_HOME, + ID_NAVIGATION_HOME, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_BACK, IDS_BACK, IDS_BACK_DESCRIPTION, ICON_BACK, + ID_NAVIGATION_BACK, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_FORWARD, IDS_FORWARD, IDS_FORWARD_DESCRIPTION, ICON_FORWARD, + ID_NAVIGATION_FORWARD, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_STOP, IDS_STOP, IDS_STOP_DESCRIPTION, ICON_STOP, + ID_NAVIGATION_STOP, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_REFRESH, IDS_REFRESH, IDS_REFRESH_DESCRIPTION, ICON_REFRESH, + ID_NAVIGATION_REFRESH, ToolbarItem::styleWantKey), + REGISTER_BUTTON(TOOLITEM_BUTTON_HISTORY, IDS_HISTORY, IDS_HISTORY_DESCRIPTION, ICON_HISTORY, + ID_NAVIGATION_HISTORY, ToolbarItem::styleWantKey), + + REGISTER_BUTTON(TOOLITEM_CMDLINK_INFO, IDS_SERVICE_GETINFO, IDS_SERVICE_GETINFO_DESCRIPTION, ICON_NONE, + ID_SERVICE_GETINFO, ToolbarItem::styleWantKey | ToolbarButton::styleCommandLink), + REGISTER_BUTTON(TOOLITEM_CMDLINK_REPORT, IDS_SERVICE_REPORT, IDS_SERVICE_REPORT_DESCRIPTION, ICON_NONE, + ID_SERVICE_REPORT, ToolbarItem::styleWantKey | ToolbarButton::styleCommandLink), + REGISTER_BUTTON(TOOLITEM_CMDLINK_UNSUBSCRIBE, IDS_SERVICE_UNSUBSCRIBE, IDS_SERVICE_UNSUBSCRIBE_DESCRIPTION, ICON_NONE, + ID_SERVICE_UNSUBSCRIBE, ToolbarItem::styleWantKey | ToolbarButton::styleCommandLink), + + REGISTER_BUTTON(TOOLITEM_BUTTON_SECURECONNECTION, IDS_SECURE_CONNECTION, IDS_SECURE_CONNECTION, ICON_LOCK, + ID_BROWSER_SECURECONNECTION, ToolbarItem::styleWantKey), + + REGISTER_BUTTON(TOOLITEM_BUTTON_SCRIPTERROR, IDS_SCRIPT_ERROR, IDS_SCRIPT_ERROR_DESCRIPTION, ICON_ERROR, + ID_BROWSER_SCRIPTERROR, ToolbarItem::styleWantKey), + + + +}; + +#define GetToolbar(__hwnd) ((TOOLBAR*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0)) +static LRESULT CALLBACK Toolbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK Toolbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam); + + +typedef struct __TOOLBARITEMINSERTREC +{ + LPCSTR name; + UINT style; +} TOOLBARITEMINSERTREC; + +BOOL Toolbar_RegisterClass(HINSTANCE hInstance) +{ + WNDCLASS wc; + ATOM klassAtom; + ifc_wasabihelper *wasabi; + + if (GetClassInfo(hInstance, NWC_ONLINEMEDIATOOLBAR, &wc)) + return TRUE; + + ZeroMemory(&wc, sizeof(WNDCLASS)); + + wc.hInstance = hInstance; + wc.lpszClassName = NWC_ONLINEMEDIATOOLBAR; + wc.lpfnWndProc = Toolbar_WindowProc; + wc.style = 0; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.cbWndExtra = sizeof(TOOLBAR*); + + klassAtom = RegisterClassW(&wc); + if (0 == klassAtom) + return FALSE; + + if (SUCCEEDED(Plugin_GetWasabiHelper(&wasabi))) + { + api_application *application; + if (SUCCEEDED(wasabi->GetApplicationApi(&application))) + { + application->DirectMouseWheel_RegisterSkipClass(klassAtom); + application->Release(); + } + wasabi->Release(); + } + return TRUE; +} + +static BOOL Toolbar_ClearItems(TOOLBAR *toolbar) +{ + if (NULL == toolbar) return FALSE; + if (NULL == toolbar->items) return TRUE; + + size_t index = toolbar->items->size(); + + while(index--) + { + ToolbarItem *item = toolbar->items->at(index); + if (NULL != item) item->Release(); + } + toolbar->items->clear(); + return TRUE; + +} +static ULONG Toolbar_AddRef(TOOLBAR *toolbar) +{ + if (NULL == toolbar) return 0; + return InterlockedIncrement((LONG*)&toolbar->ref); +} + +static ULONG Toolbar_Release(TOOLBAR *toolbar) +{ + if (0 == toolbar || 0 == toolbar->ref) return 0; + LONG r = InterlockedDecrement((LONG*)&toolbar->ref); + if (0 == r) + { + if (NULL != toolbar->hTooltip) + DestroyWindow(toolbar->hTooltip); + + if (NULL != toolbar->chevron) + toolbar->chevron->Release(); + + if (NULL != toolbar->items) + { + Toolbar_ClearItems(toolbar); + delete(toolbar->items); + } + + if (NULL != toolbar->imageList) + ImageList_Destroy(toolbar->imageList); + + if (NULL != toolbar->ownedFont) + DeleteObject(toolbar->ownedFont); + + + free(toolbar); + } + return r; +} + +static const TOOLBARITEMCLASS *Toolbar_FindClass(LPCSTR pszName) +{ + if (NULL == pszName) return NULL; + + for (INT i =0; i < ARRAYSIZE(szRegisteredToolItems); i++) + { + if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, + szRegisteredToolItems[i].name, -1, pszName, -1)) + { + return &szRegisteredToolItems[i]; + } + } + return NULL; +} + +static ToolbarItem* Toolbar_CreateItem(LPCSTR pszName, UINT styleOverride) +{ + const TOOLBARITEMCLASS *iClass = Toolbar_FindClass(pszName); + if (NULL == iClass || NULL == iClass->creator) + return NULL; + + ToolbarItem::Template iTemplate; + ZeroMemory(&iTemplate, sizeof(ToolbarItem::Template)); + + iTemplate.name = iClass->name; + iTemplate.text = iClass->text; + iTemplate.description= iClass->description; + iTemplate.iconId = iClass->iconId; + iTemplate.commandId = iClass->commandId; + iTemplate.style = iClass->style | styleOverride; + return iClass->creator(&iTemplate); +} + +static BOOL Toolbar_GetClientRect(HWND hwnd, RECT *prc) +{ + if (!GetClientRect(hwnd, prc)) + return FALSE; + prc->left += TOOLBAR_SPACE_LEFT; + prc->right -= TOOLBAR_SPACE_RIGHT; + + if (0 != (TBS_BOTTOMDOCK & GetWindowLongPtr(hwnd, GWL_STYLE))) + { + prc->top += TOOLBAR_SPACE_TOP; + prc->bottom -= TOOLBAR_SPACE_BOTTOM; + } + else + { + prc->top += TOOLBAR_SPACE_BOTTOM; + prc->bottom -= TOOLBAR_SPACE_TOP; + } + return TRUE; +} +static void Toolbar_UpdateColorTable(HWND hwnd, ifc_skinhelper *skinHelper) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + if (NULL == skinHelper || FAILED(skinHelper->GetColor(TOOLBAR_BKCOLOR, &toolbar->rgbBk))) + toolbar->rgbBk = GetSysColor(COLOR_WINDOW); + + if (NULL == skinHelper || FAILED(skinHelper->GetColor(TOOLBAR_FGCOLOR, &toolbar->rgbFg))) + toolbar->rgbFg = GetSysColor(COLOR_WINDOWTEXT); + + COLORREF rgbItemBk; + if (NULL == skinHelper || FAILED(skinHelper->GetColor(WADLG_ITEMBG, &rgbItemBk))) + rgbItemBk = GetSysColor(COLOR_WINDOW); + + COLORREF rgbItem; + if (NULL == skinHelper || FAILED(skinHelper->GetColor(WADLG_ITEMFG, &rgbItem))) + rgbItem = GetSysColor(COLOR_WINDOWTEXT); + + if (NULL != skinHelper) + { + const INT szFrameColors[] = + { + WADLG_HILITE, + WADLG_LISTHEADER_FRAME_MIDDLECOLOR, + WADLG_LISTHEADER_FRAME_BOTTOMCOLOR, + WADLG_LISTHEADER_FRAME_TOPCOLOR, + }; + + for (INT i = 0; i < ARRAYSIZE(szFrameColors); i++) + { + if (SUCCEEDED(skinHelper->GetColor(szFrameColors[i], &toolbar->rgbFrame))) + toolbar->rgbFrame = GetSysColor(COLOR_GRAYTEXT); + + INT distance = GetColorDistance(toolbar->rgbFrame, rgbItemBk); + if (distance < 0) distance = -distance; + if (distance >= 40) break; + } + } + else + toolbar->rgbFrame = GetSysColor(COLOR_GRAYTEXT); + + toolbar->rgbEdit = BlendColors(toolbar->rgbBk, rgbItem, EDIT_ALPHA); + toolbar->rgbEditBk = BlendColors(toolbar->rgbBk, rgbItemBk, EDIT_ALPHA); + toolbar->rgbText = BlendColors(toolbar->rgbFg, toolbar->rgbBk, TEXT_ALPHA); + toolbar->rgbHilite = BlendColors(toolbar->rgbFg, toolbar->rgbBk, HIGHLIGHT_ALPHA); + +} +static void Toolbar_UpdateTextMetrics(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + ZeroMemory(&toolbar->textMetric, sizeof(TOOLBARTEXTMETRIC)); + + RECT clientRect; + if (!Toolbar_GetClientRect(hwnd, &clientRect)) + return; + + INT iconCX, iconCY; + if (NULL == toolbar->imageList || + FALSE == ImageList_GetIconSize(toolbar->imageList, &iconCX, &iconCY)) + { + iconCX = 0; + iconCY = 0; + } + else + { + iconCY = iconCY / TOOLBAR_ICONSTATE_COUNT; + } + + + HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); + if (NULL == hdc) return; + + HFONT originalFont = (HFONT)SelectObject(hdc, toolbar->textFont); + + TEXTMETRIC tm; + if (GetTextMetrics(hdc, &tm)) + { + toolbar->textMetric.height = tm.tmHeight; + toolbar->textMetric.aveCharWidth = tm.tmAveCharWidth; + toolbar->textMetric.overhang = tm.tmOverhang; + + INT clientHeight = clientRect.bottom - clientRect.top; + if (tm.tmHeight >= iconCY) + { + toolbar->textMetric.baseY = tm.tmAscent - tm.tmInternalLeading; + INT t = clientHeight - toolbar->textMetric.baseY; + toolbar->textMetric.origY = clientRect.top + t/2; + if (0 != t%2) + { + toolbar->textMetric.origY += 1; + toolbar->textMetric.baseY += 1; + } + } + else + { + toolbar->textMetric.baseY = (clientHeight - iconCY)/2; + if (tm.tmDescent > toolbar->textMetric.baseY) + toolbar->textMetric.baseY = tm.tmDescent; + //toolbar->textMetric.baseY += 8; + toolbar->textMetric.baseY = clientHeight - toolbar->textMetric.baseY; + toolbar->textMetric.origY = (clientRect.top + toolbar->textMetric.baseY + tm.tmDescent) - tm.tmHeight; + toolbar->textMetric.baseY -= toolbar->textMetric.origY; + } + } + + SelectObject(hdc, originalFont); + ReleaseDC(hwnd, hdc); +} +static HIMAGELIST Toolbar_LoadImagelist(TOOLBAR *toolbar, HINSTANCE hInstance, LPCWSTR pszPath, INT iconWidth, INT iconStatesCount) +{ + if (iconWidth <= 0 || iconStatesCount <= 0 || NULL == pszPath) + return NULL; + + HBITMAP bitmap = NULL; + + ifc_omimageloader *loader; + if (SUCCEEDED(Plugin_QueryImageLoader(hInstance, pszPath, FALSE, &loader))) + { + loader->LoadBitmap(&bitmap, NULL, NULL); + loader->Release(); + } + + DIBSECTION dib; + if (NULL == bitmap || + sizeof(DIBSECTION) != GetObject(bitmap, sizeof(DIBSECTION), &dib)) + { + if (NULL != bitmap) DeleteObject(bitmap); + return NULL; + } + + if (dib.dsBm.bmHeight < 0) dib.dsBm.bmHeight = -dib.dsBm.bmHeight; + + Image_Colorize((BYTE*)dib.dsBm.bmBits, dib.dsBm.bmWidth, dib.dsBm.bmHeight, dib.dsBm.bmBitsPixel, + ColorAdjustLuma(toolbar->rgbBk, -140, TRUE), toolbar->rgbFg, FALSE); + + Image_BlendOnColorEx((BYTE*)dib.dsBm.bmBits, dib.dsBm.bmWidth, dib.dsBm.bmHeight, + 0, 0, dib.dsBm.bmWidth, dib.dsBm.bmHeight, dib.dsBm.bmBitsPixel, FALSE, toolbar->rgbBk); + + + if (iconWidth > dib.dsBm.bmWidth) iconWidth = dib.dsBm.bmWidth; + + INT iconHeight = dib.dsBm.bmHeight / iconStatesCount; + INT initial = dib.dsBm.bmWidth / iconWidth; + + HIMAGELIST himl = ImageList_Create(iconWidth, iconHeight * iconStatesCount, ILC_COLOR24, initial, 1); + if (NULL != himl) + { + INT index = ImageList_Add(himl, bitmap, NULL); + if (-1 == index) + { + ImageList_Destroy(himl); + himl = NULL; + } + } + DeleteObject(bitmap); + return himl; +} + +static LONG Toolbar_ShowChevron(HWND hwnd, const RECT *prcClient) // return client cx change +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->chevron && toolbar->chevron->IsRectEmpty()) + { + RECT chevronRect; + CopyRect(&chevronRect, prcClient); + if (toolbar->chevron->AdjustRect(hwnd, &chevronRect)) + { + chevronRect.left = prcClient->right - (chevronRect.right - chevronRect.left); + chevronRect.right = prcClient->right; + if (toolbar->chevron->SetRect(&chevronRect)) + return (chevronRect.left - prcClient->right); + } + } + return 0; +} + +static ToolbarItem *Toolbar_GetItem(TOOLBAR *toolbar, size_t index) +{ + if (NULL == toolbar || NULL == toolbar->items) + return NULL; + + size_t count = toolbar->items->size(); + + if (index < count) + return toolbar->items->at(index); + if (index == count) + return toolbar->chevron; + + return NULL; +} + +static BOOL Toolbar_IsItemAcceptFocus(ToolbarItem *item, BOOL fTabstopOnly) +{ + if (NULL == item) + return FALSE; + + UINT itemStyle = item->GetStyle(); + if (0 != ((ToolbarItem::stateDisabled | ToolbarItem::stateHidden) & itemStyle)) + return FALSE; + + UINT mask = ToolbarItem::styleTabstop; + if (FALSE == fTabstopOnly) mask |= ToolbarItem::styleWantKey; + if (0 == (mask & itemStyle)) + return FALSE; + + return (FALSE == item->IsRectEmpty()); +} + +static void Toolbar_UpdateTabstop(HWND hwnd) +{ + BOOL fEnable = FALSE; + UINT windowStyle = GetWindowStyle(hwnd); + + if (0 != (TBS_TABSTOP & windowStyle)) + { + fEnable = TRUE; + } + else + { + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->items) + { + size_t index = toolbar->items->size(); + while(index--) + { + if (FALSE != Toolbar_IsItemAcceptFocus(toolbar->items->at(index), TRUE)) + { + fEnable = TRUE; + break; + } + } + } + } + + if (FALSE != fEnable) + { + if (0 == (WS_TABSTOP & windowStyle)) + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_TABSTOP); + } + else + { + if (0 != (WS_TABSTOP & windowStyle)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_TABSTOP); + } + } +} +static INT Toolbar_InsertItemInternal(TOOLBAR *toolbar, ToolbarItem *item, INT insertBefore, HWND hwnd) +{ + if (NULL == toolbar || NULL == toolbar->items || NULL == item) + return ITEM_ERR; + + INT index = ITEM_ERR; + + if (TBIP_FIRST == insertBefore) + { + toolbar->items->insert(toolbar->items->begin(), item); + index = 0; + } + else if (TBIP_LAST == insertBefore) + { + toolbar->items->push_back(item); + index = ((INT)toolbar->items->size() - 1); + } + else + { + if (insertBefore < 0) insertBefore = 0; + else if (insertBefore >= (INT)toolbar->items->size()) insertBefore = (INT)toolbar->items->size(); + toolbar->items->insert(toolbar->items->begin() + insertBefore, item); + index = insertBefore; + } + + if (ITEM_ERR != index) + { + item->AddRef(); + item->UpdateSkin(hwnd); + } + + return index; +} + +static size_t Toolbar_GetFocusIndex(HWND hwnd, size_t focusIndex, INT searchDirection, BOOL fTabstopOnly) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items || 0 == toolbar->items->size()) + return ((size_t)-1); + + + ToolbarItem *item = Toolbar_GetItem(toolbar, focusIndex); + if (NULL != item && Toolbar_IsItemAcceptFocus(item, fTabstopOnly)) + return focusIndex; + + if (0 == searchDirection) + return ((size_t)-1); + + if (searchDirection > 0) + { + size_t count = toolbar->items->size(); + size_t i = focusIndex + 1; + for (; i < count; i++) + { + if (Toolbar_IsItemAcceptFocus(toolbar->items->at(i), fTabstopOnly)) + return i; + } + if (i == count && Toolbar_IsItemAcceptFocus(toolbar->chevron, fTabstopOnly)) + return i; + } + else + { + size_t count = toolbar->items->size(); + if (focusIndex == count && Toolbar_IsItemAcceptFocus(toolbar->chevron, fTabstopOnly)) + return count; + + size_t i = focusIndex; + if (i <= count) + { + while(i--) + { + if (Toolbar_IsItemAcceptFocus(toolbar->items->at(i), fTabstopOnly)) + return i; + } + } + } + + return ((size_t)-1); +} + +static void Toolbar_OffsetItems(ToolbarItem **itemList, INT count, INT offsetX, INT offsetY) +{ + while(count-- > 0) + { + if (NULL != itemList[count]) + itemList[count]->OffsetRect(offsetX, offsetY); + } +} +static void Toolbar_HideItems(ToolbarItem **itemList, INT count, INT *chevronItemCount) +{ + INT chevronItems = 0; + while(count-- > 0) + { + if (NULL != itemList[count]) + { + if (0 == (ToolbarItem::styleNoChevron & itemList[count]->GetStyle())) + chevronItems++; + itemList[count]->SetRectEmpty(); + } + } + + if (NULL != chevronItemCount) + *chevronItemCount = chevronItems; +} + +static LONG Toolbar_CutoffItems(ToolbarItem **itemList, INT count, LONG cutoffCX) +{ + RECT elementRect; + LONG left = cutoffCX; + ToolbarItem *item; + while(count-- > 0) + { + item = itemList[count]; + if (NULL == item) + continue; + + DWORD style = item->GetStyle(); + if (0 == (ToolbarItem::styleChevronOnly & style) && + (0 == (ToolbarItem::stateHidden & style) || 0 == (ToolbarItem::stylePopup & style)) && + item->GetRect(&elementRect)) + { + if (elementRect.right <= cutoffCX) + return elementRect.right; + + if (0 == count) + left = elementRect.left; + + item->SetRectEmpty(); + } + } + return left; +} + +static LONG Toolbar_CalculateClient(HWND hwnd, ToolbarItem **itemList, INT count, const RECT *prcClient, INT *deltaCX) +{ + ToolbarItem *item; + RECT elementRect; + INT index; + UINT style; + LONG elementLeft = prcClient->left; + + for (index = 0; index < count; index++) + { + item = itemList[index]; + if (NULL != item) + { + style = item->GetStyle(); + if (0 != (ToolbarItem::styleChevronOnly & style) || + (0 != (ToolbarItem::stateHidden & style) && 0!= (ToolbarItem::stylePopup & style))) + { + item->SetRectEmpty(); + continue; + } + + CopyRect(&elementRect, prcClient); + elementRect.left = elementLeft; + + if (0 != (ToolbarItem::styleFlexible & style)) + { + RECT testRect; + INT flexMinimum = 0; + SetRect(&testRect, elementRect.left, elementRect.top, elementRect.left, elementRect.bottom); + if (item->AdjustRect(hwnd, &testRect) && testRect.right > elementRect.left) + { + flexMinimum = (testRect.right - elementRect.left); + } + + if (index != (count -1)) + { + INT delta = 0; + INT section; + + if ((elementRect.left + flexMinimum) < prcClient->right) + { + CopyRect(&testRect, &elementRect); + testRect.left += flexMinimum; + + section = Toolbar_CalculateClient(hwnd, itemList + (index + 1), + count - index - 1, &testRect, &delta); + } + else + { + section = prcClient->right - (elementRect.left + flexMinimum); + } + + if (section < 0) + { // we need to move back + item->SetRectEmpty(); + elementLeft += (flexMinimum - section); + if (index > 0) + elementLeft = Toolbar_CutoffItems(itemList, index, elementLeft); + return (elementLeft - prcClient->left); + } + + if (NULL != deltaCX) + *deltaCX += delta; + + elementRect.right = elementRect.right - section + delta; + if (elementRect.right < elementRect.left) + elementRect.right = elementRect.left; + } + + if (item->AdjustRect(hwnd, &elementRect)) + { + item->SetRect(&elementRect); + Toolbar_OffsetItems(itemList + (index + 1), count - index - 1, elementRect.right - elementRect.left - flexMinimum, 0); + elementLeft = prcClient->right; + break; + } + } + + if (item->AdjustRect(hwnd, &elementRect)) + { + if (elementRect.right > prcClient->right) + { + INT chevronItems; + Toolbar_HideItems(itemList + index, count - index, &chevronItems); + + if (chevronItems > 0) + { + LONG delta = Toolbar_ShowChevron(hwnd, prcClient); + if (NULL != deltaCX) *deltaCX += delta; + elementLeft = (index > 0) ? + Toolbar_CutoffItems(itemList, index, prcClient->right + delta) : + (prcClient->left + delta); + } + break; + } + + item->SetRect(&elementRect); + elementLeft += (elementRect.right - elementRect.left); + } + } + } + return (elementLeft - prcClient->left); +} + + +static void Toolbar_UpdateLayout(HWND hwnd, BOOL fRedraw) +{ + UINT windowStyle = GetWindowStyle(hwnd); + if (0 != (TBS_LOCKUPDATE & windowStyle)) return; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + RECT clientRect; + if (!Toolbar_GetClientRect(hwnd, &clientRect)) return; + + Toolbar_UpdateTextMetrics(hwnd); + + size_t count = (NULL != toolbar->items) ? toolbar->items->size() : 0; + + if (NULL != toolbar->chevron) + { + INT chevronOnly = 0; + ToolbarItem *item; + for (size_t i = 0; i < count; i++) + { + item = toolbar->items->at(i); + UINT style = item->GetStyle(); + + if (NULL != item && + 0 != (ToolbarItem::styleChevronOnly & style) && + 0 == (ToolbarItem::stateHidden & style)) + { + chevronOnly++; + } + } + + toolbar->chevron->SetRectEmpty(); + if (0 != chevronOnly) + clientRect.right += Toolbar_ShowChevron(hwnd, &clientRect); + } + + + Toolbar_CalculateClient(hwnd, toolbar->items->size() ? &toolbar->items->at(0) : nullptr, (INT)count, &clientRect, NULL); + + if (((size_t)-1) != toolbar->iFocused) + { + size_t focusIndex = Toolbar_GetFocusIndex(hwnd, toolbar->iFocused, -1, FALSE); + if (focusIndex != toolbar->iFocused) + { + ToolbarItem *itemNew, *itemOld; + + itemOld = Toolbar_GetItem(toolbar, toolbar->iFocused); + itemNew = Toolbar_GetItem(toolbar, focusIndex); + toolbar->iFocused = focusIndex; + + if (NULL != itemOld) + itemOld->SetFocus(hwnd, itemNew, FALSE); + if (NULL != itemNew) + itemNew->SetFocus(hwnd, itemOld, TRUE); + } + } + + if (FALSE != fRedraw) + { + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_NOERASE); + } +} + +static ToolbarItem *Toolbar_HitTest(HWND hwnd, POINT pt) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar) + { + ToolbarItem *item; + size_t count = (NULL != toolbar->items) ? toolbar->items->size() : 0; + for (size_t i = 0; i <= count; i++) + { + item = (i < count) ? toolbar->items->at(i) : toolbar->chevron; + + if (NULL != item && item->PtInItem(pt)) + return item; + } + } + return NULL; +} +static HFONT Toolbar_CreateFont(HFONT skinFont) +{ + LOGFONT lf; + if (NULL == skinFont) return NULL; + + INT skinHeight = (sizeof(LOGFONT) == GetObject(skinFont, sizeof(LOGFONT), &lf)) ? lf.lfHeight : -11; + ZeroMemory(&lf, sizeof(LOGFONT)); + + lf.lfHeight = skinHeight; + lf.lfWeight = FW_DONTCARE; + lf.lfItalic = FALSE; + lf.lfUnderline = FALSE; + lf.lfStrikeOut = FALSE; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"MS Shell Dlg 2"); + + return CreateFontIndirect(&lf); +} + + +static HWND Toolbar_CreateTooltip(HINSTANCE hInstance, HWND hOwner) +{ + HWND hTooltip = CreateWindowExW(WS_EX_TRANSPARENT , TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_ALWAYSTIP, + 0, 0, 0, 0, + hOwner, NULL, hInstance, NULL); + + if (NULL == hTooltip) + return NULL; + + SetWindowPos(hTooltip, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); + SendMessage(hTooltip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1000, 0)); + SendMessage(hTooltip, TTM_SETDELAYTIME, TTDT_RESHOW, MAKELPARAM(-2, 0)); + + OSVERSIONINFO ov; + ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (::GetVersionEx(&ov) && + ov.dwMajorVersion >= 6 && + VER_PLATFORM_WIN32_NT == ov.dwPlatformId) + { + RECT rcMargin; + SetRect(&rcMargin, 3, 1, 3, 1); + SendMessage(hTooltip, TTM_SETMARGIN, 0, (LPARAM)&rcMargin); + } + + TOOLINFO ti; + ZeroMemory(&ti, sizeof(TOOLINFO)); + ti.cbSize = sizeof(TOOLINFO); + ti.hwnd = hOwner; + ti.lpszText = LPSTR_TEXTCALLBACK; + SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti); + + SendMessage(hTooltip, TTM_SETMAXTIPWIDTH, 0, 1000); + + return hTooltip; +} +static void Toolbar_RelayTooltipMsg(HWND hTooltip, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MSG msg; + + msg.hwnd = hwnd; + msg.message = uMsg; + msg.wParam = wParam; + msg.lParam = lParam; + + //DWORD pts = GetMessagePos(); + //POINTSTOPOINT(msg.pt, pts); + //msg.time = GetMessageTime(); + + SendMessage(hTooltip, TTM_RELAYEVENT, 0, (LPARAM)&msg); +} +static void Toolbar_SetTooltipItem(HWND hwnd, ToolbarItem *item) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + TOOLINFO ti; + + ti.cbSize = sizeof(TOOLINFO); + ti.hwnd = hwnd; + ti.uId = 0; + ti.lpszText = NULL; + + if (SendMessage(toolbar->hTooltip, TTM_GETTOOLINFO, 0, (LPARAM)&ti)) + { + RECT clientRect, toolRect; + Toolbar_GetClientRect(hwnd, &clientRect); + + if (NULL == item || FALSE == item->GetRect(&toolRect)) + { + SendMessage(toolbar->hTooltip, TTM_ACTIVATE, FALSE, 0L); + return; + } + + toolRect.top = clientRect.top; + toolRect.bottom = clientRect.bottom; + + if (ti.lParam != (LPARAM)item || !::EqualRect(&ti.rect, &toolRect)) + { + CopyRect(&ti.rect, &toolRect); + ti.lParam = (LPARAM)item; + SendMessage(toolbar->hTooltip, TTM_SETTOOLINFO, 0, (LPARAM)&ti); + } + SendMessage(toolbar->hTooltip, TTM_ACTIVATE, TRUE, 0L); + } + +} +static void Toolbar_ClearBrushCache(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + for (INT i = 0; i < ARRAYSIZE(toolbar->szBrushes); i++) + { + if (NULL != toolbar->szBrushes[i]) + { + DeleteObject(toolbar->szBrushes[i]); + toolbar->szBrushes[i] = NULL; + } + } +} + +static HBRUSH Toolbar_GetBrush(HWND hwnd, UINT brushId) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return NULL; + + if (brushId >= ARRAYSIZE(toolbar->szBrushes)) + return NULL; + + if (NULL == toolbar->szBrushes[brushId]) + { + COLORREF brushColor = 0x00FF00FF; + switch(brushId) + { + case TOOLBRUSH_BACK: brushColor = toolbar->rgbBk;break; + case TOOLBRUSH_FRAME: brushColor = toolbar->rgbFrame; break; + case TOOLBRUSH_ITEMBK: brushColor = toolbar->rgbEditBk; break; + } + toolbar->szBrushes[brushId] = CreateSolidBrush(brushColor); + } + return toolbar->szBrushes[brushId]; +} + + +static HRGN Toolbar_GetFrameRgn(const RECT *prcToolbar, BOOL bottomDock) +{ + if (TOOLBAR_SPACE_TOP < 1) + return NULL; + + HRGN regionFrame; + INT origY = (FALSE != bottomDock) ? prcToolbar->top : prcToolbar->bottom - 1; + regionFrame = CreateRectRgn(prcToolbar->left, origY, prcToolbar->right, origY + 1); + return regionFrame; +} + +static void Toolbar_PaintBack(HWND hwnd, HDC hdc, const RECT *prcToolbar, HRGN regionPaint) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + UINT windowStyle = GetWindowStyle(hwnd); + + if (0 == (TBS_HIDDEN & toolbar->flags)) + { + HRGN regionFrame = Toolbar_GetFrameRgn(prcToolbar, (0 != (TBS_BOTTOMDOCK & windowStyle))); + if (NULL != regionFrame) + { + if (FillRgn(hdc, regionFrame, Toolbar_GetBrush(hwnd, TOOLBRUSH_FRAME))) + CombineRgn(regionPaint, regionPaint, regionFrame, RGN_DIFF); + DeleteObject(regionFrame); + } + } + + FillRgn(hdc, regionPaint, Toolbar_GetBrush(hwnd, TOOLBRUSH_BACK)); +} + + + +static void Toolbar_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + RECT clientRect; + GetClientRect(hwnd, &clientRect); + + DWORD windowStyle = GetWindowStyle(hwnd); + + HRGN paintRegion = CreateRectRgnIndirect(prcPaint); + + if (0 == (TBS_HIDDEN & toolbar->flags)) + { + INT savedDC = SaveDC(hdc); + + HRGN itemRegion = CreateRectRgn(0,0,0,0); + + SetBkColor(hdc, toolbar->rgbBk); + SetTextColor(hdc, toolbar->rgbText); + SelectObject(hdc, toolbar->textFont); + + ToolbarItem *item; + RECT paintRect; + UINT style; + + BOOL fFocused = (GetFocus() == hwnd); + UINT commonState= 0; + + if (0 != (WS_DISABLED & windowStyle)) + commonState |= ToolbarItem::stateDisabled; + + size_t count = (NULL != toolbar->items) ? toolbar->items->size() : 0; + for (size_t i = 0; i <= count; i++) + { + item = (i < count) ? toolbar->items->at(i) : toolbar->chevron; + + if (NULL != item && item->IntersectRect(&paintRect, prcPaint)) + { + style = item->GetStyle() | commonState; + if (i == toolbar->iFocused && fFocused) + style |= ToolbarItem::stateFocused; + + if (0 != (TBS_NOFOCUSRECT & toolbar->flags)) + style |= ToolbarItem::stateNoFocusRect; + + if (0 == (ToolbarItem::stateHidden & style) && + item->Paint(hwnd, hdc, &paintRect, style)) + { + SetRectRgn(itemRegion, paintRect.left, paintRect.top, paintRect.right, paintRect.bottom); + CombineRgn(paintRegion, paintRegion, itemRegion, RGN_DIFF); + } + } + } + DeleteObject(itemRegion); + RestoreDC(hdc, savedDC); + } + + Toolbar_PaintBack(hwnd, hdc, &clientRect, paintRegion); + DeleteObject(paintRegion); + +} + +static INT Toolbar_FindListItem(ToolbarItem **itemList, INT start, INT count, LPCSTR pszName, INT cchName) +{ + ToolbarItem *item; + for (INT i = start; i < count; i++) + { + item = itemList[i]; + if (NULL != item && item->IsEqual(pszName, cchName)) + { + return i; + } + } + return ITEM_ERR; +} +static INT Toolbar_ResolveName(HWND hwnd, LPCSTR pszName) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items) + return ITEM_ERR; + + UINT index; + UINT count = (UINT)toolbar->items->size(); + + if (IS_INTRESOURCE(pszName)) + { + index = (UINT)(UINT_PTR)pszName; + + if (index == count && NULL != toolbar->chevron) + return index; + + return (index < count) ? index : ITEM_ERR; + } + + INT cchName = lstrlenA(pszName); + if (0 == cchName) return ITEM_ERR; + + if (count == toolbar->resolveCache) + { + if (toolbar->chevron->IsEqual(pszName, cchName)) + index = count; + else + { + index = ITEM_ERR; + toolbar->resolveCache = 0; + } + } + else + { + index = ITEM_ERR; + } + + if (ITEM_ERR == index) + index = Toolbar_FindListItem(toolbar->items->size() ? & toolbar->items->at(0) : nullptr, toolbar->resolveCache, count, pszName, cchName); + + if (ITEM_ERR == index && 0 != toolbar->resolveCache) + index = Toolbar_FindListItem(toolbar->items->size() ? &toolbar->items->at(0) : nullptr, 0, toolbar->resolveCache, pszName, cchName); + + if (ITEM_ERR == index && NULL != toolbar->chevron && toolbar->chevron->IsEqual(pszName, cchName)) + index = count; + + + toolbar->resolveCache = (ITEM_ERR != index) ? index : 0; + return index; +} + +static BOOL Toolbar_DisplayChevronMenu(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items) return FALSE; + + HMENU hMenu = CreatePopupMenu(); + if (NULL == hMenu) return FALSE; + + size_t count = toolbar->items->size(); + UINT insertedCount = 0; + MENUITEMINFO mi; + mi.cbSize = sizeof(MENUITEMINFO); + + UINT style; + WCHAR szBuffer[80] = {0}; + INT commandId = 0; + ToolbarItem *item; + BOOL insertBreak = FALSE; + for (size_t i = 0; i < count; i++) + { + item = toolbar->items->at(i); + if (NULL != item) + { + style = item->GetStyle(); + if(0 == ((ToolbarItem::stateHidden | ToolbarItem::styleNoChevron) & style) && + item->IsRectEmpty() && + FALSE != item->FillMenuInfo(hwnd, &mi, szBuffer, ARRAYSIZE(szBuffer))) + { + if (MIIM_FTYPE == mi.fMask && MFT_MENUBREAK == mi.fType) + { + if (insertedCount > 0) + insertBreak = TRUE; + } + else + { + if (FALSE != InsertMenuItem(hMenu, insertedCount, TRUE, &mi)) + { + if (insertBreak) + { + mi.fMask = MIIM_FTYPE; + mi.fType = MFT_MENUBREAK; + if (InsertMenuItem(hMenu, insertedCount, TRUE, &mi)) + insertedCount++; + insertBreak = FALSE; + } + insertedCount++; + } + } + + } + } + } + + if (NULL != hMenu && insertedCount > 0) + { + RECT windowRect; + GetWindowRect(hwnd, &windowRect); + UINT windowStyle = GetWindowStyle(hwnd); + UINT menuStyle = TPM_RIGHTALIGN | TPM_RETURNCMD; + POINT menuOrig; + menuOrig.x = windowRect.right; + if (0 != (TBS_BOTTOMDOCK & windowStyle)) + { + menuOrig.y = windowRect.top; + menuStyle |= (TPM_BOTTOMALIGN | TPM_VERNEGANIMATION); + } + else + { + menuOrig.y = windowRect.bottom; + menuStyle |= (TPM_TOPALIGN | TPM_VERPOSANIMATION); + } + + commandId = Menu_TrackPopup(hMenu, menuStyle, menuOrig.x, menuOrig.y, hwnd, NULL); + + + } + + DestroyMenu(hMenu); + + if (0 != commandId) + Toolbar_SendCommand(hwnd, commandId); + + + return TRUE; +} + +static void Toolbar_DisplayContextMenu(HWND hwnd, INT x, INT y) +{ + HMENU hMenu = Menu_GetMenu(MENU_TOOLBAR, 0); + if (NULL != hMenu) + { + UINT windowStyle = GetWindowStyle(hwnd); + CheckMenuRadioItem(hMenu, ID_TOOLBAR_DOCKTOP, ID_TOOLBAR_DOCKBOTTOM, + (0 != (TBS_BOTTOMDOCK & windowStyle)) ? ID_TOOLBAR_DOCKBOTTOM :ID_TOOLBAR_DOCKTOP, + MF_BYCOMMAND); + + CheckMenuItem(hMenu, ID_TOOLBAR_AUTOHIDE, + MF_BYCOMMAND | ((0 != (TBS_AUTOHIDE & windowStyle)) ? MF_CHECKED :MF_UNCHECKED)); + + CheckMenuItem(hMenu, ID_TOOLBAR_TABSTOP, + MF_BYCOMMAND | ((0 != (TBS_TABSTOP & windowStyle)) ? MF_CHECKED :MF_UNCHECKED)); + + Menu_TrackPopup(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN, x, y, hwnd, NULL); + + Menu_ReleaseMenu(hMenu, MENU_TOOLBAR); + } + +} + +static BOOL Toolbar_InstallMouseHook(HWND hwnd) +{ + if (TLS_OUT_OF_INDEXES == tlsIndex) + { + tlsIndex = Plugin_TlsAlloc(); + if (TLS_OUT_OF_INDEXES == tlsIndex) return FALSE; + } + + TOOLBARMOUSEHOOK *hook = (TOOLBARMOUSEHOOK*)calloc(1, sizeof(TOOLBARMOUSEHOOK)); + if (NULL == hook) return FALSE; + + hook->hwnd = hwnd; + hook->hHook = SetWindowsHookEx(WH_MOUSE, Toolbar_MouseHook, NULL, GetCurrentThreadId()); + if (NULL == hook->hHook) + { + free(hook); + return FALSE; + } + + Plugin_TlsSetValue(tlsIndex, hook); + return TRUE; +} + +static void Toolbar_TrackMouseLeave(HWND hwnd) +{ + TRACKMOUSEEVENT tm; + tm.cbSize = sizeof(TRACKMOUSEEVENT); + tm.dwFlags = TME_QUERY; + tm.hwndTrack = hwnd; + if (TrackMouseEvent(&tm) && 0 == (TME_LEAVE & tm.dwFlags)) + { + tm.cbSize = sizeof(TRACKMOUSEEVENT); + tm.dwFlags = TME_LEAVE; + tm.hwndTrack = hwnd; + TrackMouseEvent(&tm); + } +} + +static BOOL Toolbar_RemoveMouseHook(HWND hwnd, BOOL fOnlyMine) +{ + if (TLS_OUT_OF_INDEXES == tlsIndex) return FALSE; + + TOOLBARMOUSEHOOK *hook = (TOOLBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex); + if (NULL == hook) return FALSE; + + if (FALSE != fOnlyMine && hwnd != hook->hwnd) + return FALSE; + + Plugin_TlsSetValue(tlsIndex, NULL); + + if (NULL != hook->hHook) + UnhookWindowsHookEx(hook->hHook); + + if (NULL != hook->hwnd && hwnd != hook->hwnd) + { + Toolbar_TrackMouseLeave(hook->hwnd); + } + + free(hook); + return TRUE; +} + +static void Toolbar_AutoShowWindow(HWND hwnd) +{ + KillTimer(hwnd, TIMER_AUTOHIDE_ID); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + HWND hFocus = GetFocus(); + + BOOL fFocused = (hFocus == hwnd); + + UINT windowStyle = GetWindowStyle(hwnd); + if ((TBS_AUTOHIDE | WS_VISIBLE) != ((TBS_AUTOHIDE | WS_VISIBLE) & windowStyle)) + return; + + if (0 == (TBS_HIDDEN & toolbar->flags)) + { + if (0 != (TBS_HIDETIMERSET & toolbar->flags)) + toolbar->flags &= ~TBS_HIDETIMERSET; + + if (FALSE == fFocused) + Toolbar_TrackMouseLeave(hwnd); + return; + } + + Toolbar_RemoveMouseHook(hwnd, FALSE); + + if (FALSE == fFocused && FALSE == Toolbar_InstallMouseHook(hwnd)) + return; + + toolbar->flags &= ~TBS_HIDDEN; + + RECT windowRect; + if (GetWindowRect(hwnd, &windowRect)) + { + HWND hParent = GetParent(hwnd); + if(NULL != hParent) + { + MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&windowRect, 2); + INT height = Toolbar_GetIdealHeight(hwnd); + INT x = windowRect.left; + INT y = windowRect.top; + UINT swpFlags = SWP_NOMOVE | SWP_NOREDRAW; + UINT animateFlags = AW_SLIDE | AW_VER_POSITIVE; + + if (0 != (TBS_BOTTOMDOCK & windowStyle)) + { + y = windowRect.bottom - height; + swpFlags &= ~SWP_NOMOVE; + animateFlags = AW_SLIDE | AW_VER_NEGATIVE; + } + SetWindowPos(hwnd, HWND_TOP, x, y, windowRect.right - windowRect.left, height, swpFlags); + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE); + BOOL result = AnimateWindow(hwnd, AUTOHIDE_ANIMATETIME, animateFlags); + if (!result) + { + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE); + InvalidateRect(hwnd, NULL, TRUE); + } + } + } + + + if (FALSE == fFocused) + Toolbar_TrackMouseLeave(hwnd); +} + +static void CALLBACK Toolbar_AutoHideTimerProc(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD time) +{ + KillTimer(hwnd, eventId); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_AUTOHIDE & windowStyle)) return; + + toolbar->flags &= ~TBS_HIDETIMERSET; + if (0 != ((TBS_HIDDEN | TBS_MENULOOP) & toolbar->flags)) + return; + + HWND hFocus = ::GetFocus(); + if (hwnd == hFocus || IsChild(hwnd, hFocus)) + return; + + Toolbar_RemoveMouseHook(hwnd, TRUE); + RECT windowRect; + if (GetWindowRect(hwnd, &windowRect)) + { + HWND hParent = GetParent(hwnd); + if(NULL != hParent) + { + MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&windowRect, 2); + INT height = TOOLBAR_HIDDENHEIGHT; + INT x = windowRect.left; + INT y = windowRect.top; + UINT swpFlags = SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW; + UINT animateFlags = AW_HIDE | AW_SLIDE | AW_VER_NEGATIVE; + HWND zOrder = HWND_TOP; + + if (0 != (TBS_BOTTOMDOCK & windowStyle)) + { + y = windowRect.bottom - height; + swpFlags &= ~SWP_NOMOVE; + zOrder = HWND_BOTTOM; + animateFlags = AW_HIDE | AW_SLIDE | AW_VER_POSITIVE; + } + + AnimateWindow(hwnd, AUTOHIDE_ANIMATETIME, animateFlags); + + if (NULL != toolbar->hBrowser) + { + RECT invalidRect; + CopyRect(&invalidRect, &windowRect); + MapWindowPoints(hParent, toolbar->hBrowser, (POINT*)&invalidRect, 2); + RedrawWindow(toolbar->hBrowser, &invalidRect, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); + } + + SetWindowPos(hwnd, zOrder, x, y, windowRect.right - windowRect.left, height, swpFlags); + + if (0 != (WS_VISIBLE & windowStyle)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE); + InvalidateRect(hwnd, NULL, TRUE); + } + } + } + + toolbar->flags |= TBS_HIDDEN; +} + +static void Toolbar_AutoHideWindow(HWND hwnd, BOOL fImmediate) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + if (0 != ((TBS_HIDDEN | TBS_MENULOOP) & toolbar->flags)) + { + return; + } + + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_AUTOHIDE & windowStyle)) return; + + if (FALSE == fImmediate) + { + if (SetTimer(hwnd, TIMER_AUTOHIDE_ID, TIMER_AUTOHIDE_DELAY, Toolbar_AutoHideTimerProc)) + toolbar->flags |= TBS_HIDETIMERSET; + } + else + { + Toolbar_AutoHideTimerProc(hwnd, WM_TIMER, TIMER_AUTOHIDE_ID, GetTickCount()); + } +} + +static void Toolbar_UpdateUiFlags(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + UINT uiState = (UINT)SendMessage(hwnd, WM_QUERYUISTATE, 0, 0L); + + if (0 != (UISF_HIDEFOCUS & uiState)) toolbar->flags |= TBS_NOFOCUSRECT; + else toolbar->flags &= ~TBS_NOFOCUSRECT; +} +static void Toolbar_NotifyParent(HWND hwnd, UINT eventId) +{ + HWND hParent = GetParent(hwnd); + if (NULL == hParent) return; + UINT controlId = (UINT)GetWindowLongPtr(hwnd, GWLP_ID); + SENDCMD(hParent, controlId, eventId, hwnd); +} +static LRESULT Toolbar_OnCreate(HWND hwnd, CREATESTRUCT *pcs) +{ + TOOLBAR *toolbar = (TOOLBAR*)calloc(1, sizeof(TOOLBAR)); + if (NULL != toolbar) + { + Toolbar_AddRef(toolbar); + + SetLastError(ERROR_SUCCESS); + if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)toolbar) && ERROR_SUCCESS != GetLastError()) + { + free(toolbar); + toolbar = NULL; + } + } + + if (NULL == toolbar) + { + DestroyWindow(hwnd); + return -1; + } + + toolbar->chevron = Toolbar_CreateItem(TOOLITEM_CHEVRON, 0); + toolbar->items = new ItemList(); + toolbar->hTooltip = Toolbar_CreateTooltip(pcs->hInstance, hwnd); + + if (NULL != toolbar->hTooltip) + { + ifc_skinhelper *skinHelper; + if (SUCCEEDED(Plugin_GetSkinHelper(&skinHelper))) + { + skinHelper->SkinControl(toolbar->hTooltip, SKINNEDWND_TYPE_TOOLTIP, + SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT); + + skinHelper->Release(); + } + } + + if (0 != (TBS_AUTOHIDE & pcs->style)) + toolbar->flags |= TBS_HIDDEN; + + return 0; +} + +static void Toolbar_OnDestroy(HWND hwnd) +{ + Toolbar_RemoveMouseHook(hwnd, TRUE); + Toolbar_ClearBrushCache(hwnd); + + TOOLBAR *toolbar = GetToolbar(hwnd); + SetWindowLongPtr(hwnd, 0, 0L); + + Toolbar_Release(toolbar); +} + +static void Toolbar_OnPaint(HWND hwnd) +{ + PAINTSTRUCT ps; + if (BeginPaint(hwnd, &ps)) + { + if (ps.rcPaint.left != ps.rcPaint.right) + Toolbar_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase); + EndPaint(hwnd, &ps); + } +} + +static void Toolbar_OnPrintClient(HWND hwnd, HDC hdc, UINT options) +{ + RECT clientRect; + if (GetClientRect(hwnd, &clientRect)) + Toolbar_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options)); +} + +static void Toolbar_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp) +{ + if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags)) + return; + + Toolbar_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags)); +} + +static void Toolbar_OnSetRedraw(HWND hwnd, BOOL allowRedraw) +{ + UINT windowStyle = GetWindowStyle(hwnd); + if (FALSE == allowRedraw) + { + if (0 == (TBS_LOCKUPDATE & windowStyle)) + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | TBS_LOCKUPDATE); + } + else + { + if (0 != (TBS_LOCKUPDATE & windowStyle)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~TBS_LOCKUPDATE); + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + } + DefWindowProcW(hwnd, WM_SETREDRAW, (WPARAM)allowRedraw, 0L); +} + + +static void Toolbar_OnEnterMenuLoop(HWND hwnd, BOOL fContext) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + toolbar->flags |= TBS_MENULOOP; +} +static void Toolbar_OnExitMenuLoop(HWND hwnd, BOOL fContext) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + toolbar->flags &= ~TBS_MENULOOP; + + Toolbar_TrackMouseLeave(hwnd); +} + +static void Toolbar_OnSetFocus(HWND hwnd, HWND hFocus) +{ + UINT windowStyle = GetWindowStyle(hwnd); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + + BOOL focusDirLeft = FALSE; + if (0 != (0x8000 & GetAsyncKeyState(VK_LEFT))) + { + focusDirLeft = TRUE; + } + else if (0 != (0x8000 & GetAsyncKeyState(VK_TAB))) + { + if (0 != (0x8000 & GetAsyncKeyState(VK_SHIFT))) + focusDirLeft = TRUE; + } + else if (0 != (0x8000 & GetAsyncKeyState(VK_LBUTTON)) || 0 != (0x8000 & GetAsyncKeyState(VK_RBUTTON)) || + 0 != (0x8000 & GetAsyncKeyState(VK_MBUTTON)) || 0 != (0x8000 & GetAsyncKeyState(VK_XBUTTON1)) || + 0 != (0x8000 & GetAsyncKeyState(VK_XBUTTON2))) + { + // mouse press (?) + } + + if ((size_t)-1 != toolbar->iFocused) + toolbar->iFocused = Toolbar_GetFocusIndex(hwnd, toolbar->iFocused, 0, FALSE); + + if ((size_t)-1 == toolbar->iFocused) + { + if (0 != (TBS_TABSTOP & windowStyle)) + { + if (FALSE == focusDirLeft) + toolbar->iFocused = Toolbar_GetFocusIndex(hwnd, 0, 1, FALSE); + else + { + size_t last = (NULL != toolbar->items) ? toolbar->items->size() : 0; + if (last > 0) + toolbar->iFocused = Toolbar_GetFocusIndex(hwnd, last - 1, -1, FALSE); + } + } + else + { + size_t lim, index; + INT inc; + if (FALSE == focusDirLeft) + { + lim = toolbar->items->size(); + index = 0; + inc = 1; + } + else + { + lim = (size_t)-1; + index = toolbar->items->size(); + if (index > 0) index--; + inc = -1; + } + + for (; index != lim; index += inc) + { + UINT itemStyle = toolbar->items->at(index)->GetStyle(); + UINT mask = ToolbarItem::styleTabstop | ToolbarItem::stateDisabled | ToolbarItem::stateHidden; + if (ToolbarItem::styleTabstop == (mask & itemStyle)) + { + toolbar->iFocused = index; + break; + } + } + } + } + + if (((size_t)-1) != toolbar->iFocused) + { + ToolbarItem *item = Toolbar_GetItem(toolbar, toolbar->iFocused); + if (NULL != item) item->SetFocus(hwnd, NULL, TRUE); + } + + + if (0 != (WS_TABSTOP & windowStyle)) + Toolbar_AutoShowWindow(hwnd); +} + +static void Toolbar_OnKillFocus(HWND hwnd, HWND hFocus) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && ((size_t)-1) != toolbar->iFocused) + { + ToolbarItem *item = Toolbar_GetItem(toolbar, toolbar->iFocused); + if (NULL != item) item->SetFocus(hwnd, NULL, FALSE); + toolbar->iFocused = ((size_t)-1); + } + Toolbar_AutoHideWindow(hwnd, TRUE); +} + +static void Toolbar_OnKeyDown(HWND hwnd, INT vKey, UINT flags) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + Toolbar_AutoShowWindow(hwnd); + + INT searchDirection = 0; + if (VK_LEFT == vKey) searchDirection = -1; + else if (VK_RIGHT == vKey) searchDirection = 1; + + toolbar->iFocused = Toolbar_GetFocusIndex(hwnd, toolbar->iFocused, searchDirection, FALSE); + + ToolbarItem *focusedItem = Toolbar_GetItem(toolbar, toolbar->iFocused); + + BOOL fHandled = (NULL != focusedItem && focusedItem->KeyDown(hwnd, vKey, flags)); + if (!fHandled) + { + switch(vKey) + { + case VK_LEFT: + Toolbar_NextItem(hwnd, TBNS_PREVITEM, FALSE); + break; + case VK_RIGHT: + Toolbar_NextItem(hwnd, TBNS_NEXTITEM, FALSE); + break; + case VK_HOME: + case VK_PRIOR: + { + size_t first = 0; + first = Toolbar_GetFocusIndex(hwnd, first, 1, FALSE); + if (((size_t)-1) != first) + Toolbar_NextItem(hwnd, MAKEINTRESOURCE(first), TRUE); + } + break; + case VK_END: + case VK_NEXT: + { + size_t last = toolbar->items->size(); + last = Toolbar_GetFocusIndex(hwnd, last, -1, FALSE); + if (((size_t)-1) != last) + Toolbar_NextItem(hwnd, MAKEINTRESOURCE(last), TRUE); + } + break; + + } + } +} + +static void Toolbar_OnKeyUp(HWND hwnd, INT vKey, UINT flags) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + toolbar->iFocused = Toolbar_GetFocusIndex(hwnd, toolbar->iFocused, FALSE, FALSE); + + ToolbarItem *focusedItem = Toolbar_GetItem(toolbar, toolbar->iFocused); + + BOOL fHandled = (NULL != focusedItem && focusedItem->KeyUp(hwnd, vKey, flags)); +} + +static void Toolbar_OnMouseMove(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + Toolbar_AutoShowWindow(hwnd); + + POINT pt; + POINTSTOPOINT(pt, pts); + + RECT clientRect; + Toolbar_GetClientRect(hwnd, &clientRect); + + if (NULL != toolbar->pressed) + { + if (!PtInRect(&clientRect, pt)) + { + toolbar->pressed->MouseLeave(hwnd); + } + else + { + toolbar->pressed->MouseMove(hwnd, mouseFlags, pt); + } + return; + } + + ToolbarItem *item = (PtInRect(&clientRect, pt)) ? Toolbar_HitTest(hwnd, pt) : NULL; + + ToolbarItem *prevHighlighted = toolbar->highlighted; + if (NULL != toolbar->highlighted) + { + if (item != toolbar->highlighted) + { + toolbar->highlighted->MouseLeave(hwnd); + toolbar->highlighted = NULL; + } + } + + if (NULL != item) + { + UINT style = item->GetStyle(); + if (0 == ((ToolbarItem::stateDisabled | ToolbarItem::stateHidden | ToolbarItem::styleStatic) & style)) + { + toolbar->highlighted = item; + item->MouseMove(hwnd, mouseFlags, pt); + Toolbar_TrackMouseLeave(hwnd); + } + } + + if (NULL != toolbar->hTooltip) + { + if (prevHighlighted == toolbar->highlighted || NULL != prevHighlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_MOUSEMOVE, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); + + if (prevHighlighted != toolbar->highlighted) + { + Toolbar_SetTooltipItem(hwnd, toolbar->highlighted); + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_MOUSEMOVE, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); + + } + } +} + +static void Toolbar_OnMouseLeave(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + if (NULL != toolbar->highlighted) + { + toolbar->highlighted->MouseLeave(hwnd); + toolbar->highlighted = NULL; + } + + Toolbar_SetTooltipItem(hwnd, NULL); + + + POINT cursor; + if (GetFocus() != hwnd && GetCursorPos(&cursor)) + { + HWND hCursor = WindowFromPoint(cursor); + if (NULL != hCursor && + GetWindowThreadProcessId(hwnd, NULL) != GetWindowThreadProcessId(hCursor, NULL)) + { + Toolbar_AutoHideWindow(hwnd, FALSE); + } + } +} + +static void Toolbar_OnLButtonDown(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + Toolbar_SetTooltipItem(hwnd, NULL); + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_LBUTTONDOWN, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); + + POINT pt; + POINTSTOPOINT(pt, pts); + + RECT clientRect; + Toolbar_GetClientRect(hwnd, &clientRect); + + ToolbarItem *item = (PtInRect(&clientRect, pt)) ? Toolbar_HitTest(hwnd, pt) : NULL; + + if (NULL != item) + { + if (0 == ((ToolbarItem::stateDisabled | ToolbarItem::stateHidden | ToolbarItem::styleStatic) & item->GetStyle())) + { + item->LButtonDown(hwnd, mouseFlags, pt); + toolbar->pressed = item; + } + } + + SetCapture(hwnd); +} + +static void Toolbar_OnLButtonUp(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_LBUTTONUP, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); + + POINT pt; + POINTSTOPOINT(pt, pts); + + RECT clientRect; + Toolbar_GetClientRect(hwnd, &clientRect); + + ToolbarItem *item = (PtInRect(&clientRect, pt)) ? Toolbar_HitTest(hwnd, pt) : NULL; + + if (NULL != toolbar->pressed) + { + ToolbarItem *pressed = toolbar->pressed; + toolbar->pressed = NULL; + Toolbar_AddRef(toolbar); + pressed->AddRef(); + if (pressed == item) + pressed->Click(hwnd, mouseFlags, pt); + + pressed->LButtonUp(hwnd, mouseFlags, pt); + pressed->Release(); + Toolbar_Release(toolbar); + } + + if (hwnd == GetCapture()) + ReleaseCapture(); +} + +static void Toolbar_OnRButtonDown(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + Toolbar_SetTooltipItem(hwnd, NULL); + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_RBUTTONDOWN, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); + +} + +static void Toolbar_OnRButtonUp(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_RBUTTONUP, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); +} + +static void Toolbar_OnMButtonDown(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + Toolbar_SetTooltipItem(hwnd, NULL); + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_MBUTTONDOWN, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); +} + +static void Toolbar_OnMButtonUp(HWND hwnd, UINT mouseFlags, POINTS pts) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + if (NULL != toolbar->highlighted) + Toolbar_RelayTooltipMsg(toolbar->hTooltip, hwnd, WM_MBUTTONUP, (WPARAM)mouseFlags, *((LPARAM*)(&pts))); +} + +static void Toolbar_OnContextMenu(HWND hwnd, HWND hOwner, POINTS pts) +{ + POINT pt; + POINTSTOPOINT(pt, pts); + + if (-1 == pt.x || -1 == pt.y) + { + RECT windowRect; + GetWindowRect(hwnd, &windowRect); + if (!GetCursorPos(&pt) || !PtInRect(&windowRect, pt)) + { + pt.x = windowRect.left + 2; + pt.y = windowRect.top + 2; + } + } + else + { + POINT localPt = pt; + MapWindowPoints(HWND_DESKTOP, hwnd, &localPt, 1); + + RECT clientRect; + Toolbar_GetClientRect(hwnd, &clientRect); + ToolbarItem *item = (PtInRect(&clientRect, localPt)) ? Toolbar_HitTest(hwnd, localPt) : NULL; + + if (NULL != item) + { + UINT itemStyle = item->GetStyle(); + if (0 == ((ToolbarItem::stateHidden | ToolbarItem::stateDisabled) & itemStyle)) + { + RECT itemRect; + if (item->GetRect(&itemRect) && PtInRect(&itemRect, localPt)) + { + if (FALSE != item->DisplayContextMenu(hwnd, pt.x, pt.y)) + return; + } + } + } + } + + Toolbar_DisplayContextMenu(hwnd, pt.x, pt.y); +} +static void Toolbar_OnCaptureChanged(HWND hwnd, HWND hCapture) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + Toolbar_TrackMouseLeave(hwnd); +} +static LRESULT Toolbar_OnGetFont(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return NULL; + return (LRESULT)toolbar->textFont; +} + + +static void Toolbar_OnSetFont(HWND hwnd, HFONT hFont, BOOL fRedraw) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + toolbar->textFont = hFont; + + Toolbar_UpdateTextMetrics(hwnd); + + if (FALSE != fRedraw) + InvalidateRect(hwnd, NULL, TRUE); +} + + +static void Toolbar_GetTootipDispInfo(HWND hwnd, NMTTDISPINFO *pdisp) +{ + ToolbarItem *item = (ToolbarItem*)pdisp->lParam; + if (NULL != item) + { + item->GetTip(pdisp->szText, ARRAYSIZE(pdisp->szText)); + } +} + +static LRESULT Toolbar_OnTooltipNotify(HWND hwnd, NMHDR *pnmh) +{ + switch(pnmh->code) + { + case TTN_GETDISPINFO: + Toolbar_GetTootipDispInfo(hwnd, (NMTTDISPINFO*)pnmh); + break; + } + return 0; +} +static LRESULT Toolbar_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return 0; + + if (toolbar->hTooltip == pnmh->hwndFrom && NULL != toolbar->hTooltip) + return Toolbar_OnTooltipNotify(hwnd, pnmh); + + return 0; +} + +static void Toolbar_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND hControl) +{ + BOOL fEnabled; + switch(commandId) + { + case ID_TOOLBAR_DOCKTOP: + case ID_TOOLBAR_DOCKBOTTOM: + fEnabled = (ID_TOOLBAR_DOCKBOTTOM == commandId); + if (fEnabled != Toolbar_EnableBottomDock(hwnd, fEnabled)) + Toolbar_NotifyParent(hwnd, TBN_DOCKCHANGED); + break; + case ID_TOOLBAR_AUTOHIDE: + fEnabled = (0 == (TBS_AUTOHIDE & GetWindowStyle(hwnd))); + if (fEnabled != Toolbar_EnableAutoHide(hwnd, fEnabled)) + Toolbar_NotifyParent(hwnd, TBN_AUTOHIDECHANGED); + break; + case ID_TOOLBAR_TABSTOP: + fEnabled = (0 == (TBS_TABSTOP & GetWindowStyle(hwnd))); + if (fEnabled != Toolbar_EnableTabStop(hwnd, fEnabled)) + Toolbar_NotifyParent(hwnd, TBN_TABSTOPCHANGED); + break; + } +} + +static BOOL Toolbar_ProcessTabKey(HWND hwnd, UINT messageId) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + + BOOL focusDirLeft = (0 != (0x8000 & GetAsyncKeyState(VK_SHIFT))); + + size_t lim, index; + INT inc; + if (FALSE == focusDirLeft) + { + inc = 1; + lim = toolbar->items->size(); + index = toolbar->iFocused; + if ((size_t)-1 == index) index = 0; + index++; + if (index >= lim) return FALSE; + } + else + { + inc = -1; + lim = (size_t)-1; + index = toolbar->iFocused; + if ((size_t)-1 == index) index = toolbar->items->size(); + index--; + if (index >= toolbar->items->size()) return FALSE; + } + + for (; index != lim; index += inc) + { + ToolbarItem *item = toolbar->items->at(index); + if (FALSE != Toolbar_IsItemAcceptFocus(item, TRUE)) + { + item->SetFocus(hwnd, NULL, TRUE); + return TRUE; + } + } + + return FALSE; +} + +static LRESULT Toolbar_OnGetDlgCode(HWND hwnd, INT vKey, MSG *pMsg) +{ + if (NULL != pMsg) + { + switch(vKey) + { + case VK_TAB: + if (FALSE == Toolbar_ProcessTabKey(hwnd, pMsg->message)) + { + if (WM_KEYDOWN == pMsg->message) + Toolbar_AutoHideWindow(hwnd, TRUE); + + return 0; + } + break; + + } + } + + return DLGC_WANTALLKEYS; +} + + +static void Toolbar_OnUpdateUiState(HWND hwnd, INT action, INT state) +{ + DefWindowProc(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(action, state), 0L); + Toolbar_UpdateUiFlags(hwnd); +} + +static void Toolbar_OnEnable(HWND hwnd, BOOL fEnable) +{ + InvalidateRect(hwnd, NULL, FALSE); +} + +static LRESULT Toolbar_OnSetCursor(HWND hwnd, HWND hCursor, UINT hitTest, UINT messageId) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + + if (0 == (TBS_MENULOOP & toolbar->flags) && hwnd == hCursor) + { + ToolbarItem *item = (NULL != toolbar->pressed) ? toolbar->pressed : toolbar->highlighted; + if (NULL != item && FALSE != item->SetCursor(hwnd, hCursor, hitTest, messageId)) + { + return TRUE; + } + } + + return DefWindowProcW(hwnd, WM_SETCURSOR, (WPARAM)hCursor, MAKELPARAM(hitTest, messageId)); +} + +static LRESULT Toolbar_OnColorEdit(HWND hwnd, HDC hdcCtrl, HWND hwndCtrl) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return 0; + + SetTextColor(hdcCtrl, toolbar->rgbEdit); + SetBkColor(hdcCtrl, toolbar->rgbEditBk); + return (LRESULT)Toolbar_GetBrush(hwnd, TOOLBRUSH_ITEMBK); +} + +static LRESULT Toolbar_OnColorStatic(HWND hwnd, HDC hdcCtrl, HWND hwndCtrl) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return 0; + + SetTextColor(hdcCtrl, toolbar->rgbText); + SetBkColor(hdcCtrl, toolbar->rgbBk); + return (LRESULT)Toolbar_GetBrush(hwnd, TOOLBRUSH_BACK); +} + + +static LRESULT Toolbar_OnGetIdealHeight(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->imageList) return 0; + + INT toolbarHeight, iconWidth; + if (!ImageList_GetIconSize(toolbar->imageList, &iconWidth, &toolbarHeight)) + toolbarHeight = 0; + else + toolbarHeight /= TOOLBAR_ICONSTATE_COUNT; + + HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); + if (NULL != hdc) + { + HFONT originalFont = (HFONT)SelectObject(hdc, toolbar->textFont); + TEXTMETRIC tm; + if (GetTextMetrics(hdc, &tm)) + { + tm.tmHeight += ((tm.tmHeight - (tm.tmAscent - tm.tmInternalLeading))/2 + 2); + if (toolbarHeight <= tm.tmHeight) + toolbarHeight = tm.tmHeight + 4; + } + SelectObject(hdc, originalFont); + ReleaseDC(hwnd, hdc); + } + return toolbarHeight + TOOLBAR_SPACE_TOP + TOOLBAR_SPACE_BOTTOM; +} + +static void Toolbar_OnUpdateSkin(HWND hwnd, BOOL fRedraw) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return; + + ifc_skinhelper *skinHelper; + if (FAILED(Plugin_GetSkinHelper(&skinHelper))) + skinHelper = NULL; + + Toolbar_UpdateColorTable(hwnd, skinHelper); + Toolbar_ClearBrushCache(hwnd); + + if (NULL != toolbar->imageList) + ImageList_Destroy(toolbar->imageList); + + toolbar->imageList = Toolbar_LoadImagelist(toolbar, Plugin_GetInstance(), + MAKEINTRESOURCE(IDR_TOOLBARLARGE_IMAGE), + 21, TOOLBAR_ICONSTATE_COUNT); + + if (NULL != toolbar->ownedFont) + { + DeleteObject(toolbar->ownedFont); + } + + HFONT font = (NULL != skinHelper) ? skinHelper->GetFont() : NULL; + + if (0/* create custom font */) + { + toolbar->ownedFont = Toolbar_CreateFont(font); + if (NULL != toolbar->ownedFont) + font = toolbar->ownedFont; + } + else + { + toolbar->ownedFont = NULL; + } + + SendMessage(hwnd, WM_SETFONT, (WPARAM)font, FALSE); + + if (NULL != toolbar->hTooltip) + { + SendMessage(toolbar->hTooltip, WM_SETFONT, (WPARAM)(toolbar->textFont), TRUE); + } + + Toolbar_UpdateUiFlags(hwnd); + + if (NULL != toolbar->items) + { + size_t index = toolbar->items->size(); + while(index-- > 0) + { + ToolbarItem *item = toolbar->items->at(index); + if (NULL != item) + { + item->UpdateSkin(hwnd); + } + } + } + + Toolbar_UpdateLayout(hwnd, FALSE); + + if (FALSE != fRedraw) + InvalidateRect(hwnd, NULL, TRUE); + + if (NULL != skinHelper) + skinHelper->Release(); +} + + +static LRESULT Toolbar_OnGetIconSize(HWND hwnd, INT iconIndex, SIZE *pSize) +{ + if (NULL == pSize) return FALSE; + TOOLBAR *toolbar = GetToolbar(hwnd); + + if (ICON_CHEVRON == iconIndex) + { + UINT windowStyle = GetWindowStyle(hwnd); + iconIndex = (0 != (TBS_BOTTOMDOCK & windowStyle)) ? ICON_CHEVRON_BOTTOM : ICON_CHEVRON_TOP; + } + + if (NULL == toolbar || + NULL == toolbar->imageList || + iconIndex < 0 || + iconIndex >= ImageList_GetImageCount(toolbar->imageList)) + { + ZeroMemory(pSize, sizeof(SIZE)); + return FALSE; + } + + INT cx, cy; + BOOL result = ImageList_GetIconSize(toolbar->imageList, &cx, &cy); + + if (FALSE != result) + { + pSize->cy = cy / TOOLBAR_ICONSTATE_COUNT; + switch(iconIndex) + { + case ICON_SEPARATOR: + pSize->cx = ICON_SEPARATOR_WIDTH; + break; + case ICON_CHEVRON_TOP: + case ICON_CHEVRON_BOTTOM: + pSize->cx = ICON_CHEVRON_WIDTH; + break; + case ICON_HISTORY: + pSize->cx = ICON_HISTORY_WIDTH; + break; + case ICON_BACK: + case ICON_FORWARD: + pSize->cx =ICON_ARROW_WIDTH; + break; + default: + pSize->cx = cx; + break; + } + + } + else + ZeroMemory(pSize, sizeof(SIZE)); + return result; +} + +static LRESULT Toolbar_OnSendCommand(HWND hwnd, INT commandId) +{ + HWND hParent = GetParent(hwnd); + if (NULL == hParent) return FALSE; + + if (ID_CHEVRON_CLICKED == commandId) + { + Toolbar_DisplayChevronMenu(hwnd); + return 0; + } + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->items) + { + size_t index= toolbar->items->size(); + while(index--) + toolbar->items->at(index)->CommandSent(hwnd, commandId); + } + return SendMessage(hParent, WM_COMMAND, MAKEWPARAM(commandId, 0), (LPARAM)hwnd); +} + +static LRESULT Toolbar_OnDrawIcon(HWND hwnd, TOOLBARDRAWICONPARAM *iconParam) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == iconParam) return FALSE; + INT iconIndex = iconParam->iconIndex; + if (ICON_CHEVRON == iconIndex) + { + UINT windowStyle = GetWindowStyle(hwnd); + iconIndex = (0 != (TBS_BOTTOMDOCK & windowStyle)) ? ICON_CHEVRON_BOTTOM : ICON_CHEVRON_TOP; + } + + if (NULL == toolbar->imageList || + iconIndex < 0 || + iconIndex >= ImageList_GetImageCount(toolbar->imageList)) + { + return FALSE; + } + + + + INT frameHeight, frameWidth; + if (!ImageList_GetIconSize(toolbar->imageList, &frameWidth, &frameHeight)) + { + frameHeight = 0; + frameWidth = 0; + } + + INT offsetY; + if (0 != (ToolbarItem::stateDisabled & iconParam->itemState)) + offsetY = TOOLBAR_ICONSTATE_DISABLED; + else if (0 != (ToolbarItem::statePressed & iconParam->itemState)) + offsetY = TOOLBAR_ICONSTATE_PRESSED; + else if (0 != (ToolbarItem::stateHighlighted & iconParam->itemState)) + offsetY = TOOLBAR_ICONSTATE_HIGHLIGHTED; + else + offsetY = TOOLBAR_ICONSTATE_NORMAL; + + frameHeight = frameHeight / TOOLBAR_ICONSTATE_COUNT; + + IMAGELISTDRAWPARAMS param; + param.cbSize = sizeof(IMAGELISTDRAWPARAMS) - sizeof(DWORD) * 3; + param.himl = toolbar->imageList; + param.i = iconIndex; + param.hdcDst = iconParam->hdcDst; + param.x = iconParam->x; + param.y = iconParam->y; + param.cx = (iconParam->cx > frameWidth) ? frameWidth : iconParam->cx; + param.cy = (iconParam->cy > frameHeight) ? frameHeight : iconParam->cy; + param.xBitmap = 0; + param.yBitmap = frameHeight * offsetY; + param.rgbBk = CLR_NONE; + param.rgbFg = CLR_NONE; + param.fStyle = ILD_NORMAL; + param.dwRop = SRCCOPY; + param.fState = ILS_NORMAL; + param.Frame = 0; + param.crEffect = 0; + + return ImageList_DrawIndirect(¶m); +} + +static LRESULT Toolbar_OnGetItemCount(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items) return 0; + return (INT)toolbar->items->size(); +} + +static LRESULT Toolbar_OnClear(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + if (NULL == toolbar->items) return TRUE; + + Toolbar_ClearItems(toolbar); + + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_LOCKUPDATE & windowStyle)) + { + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + + return TRUE; +} + +static LRESULT Toolbar_OnInsertItem(HWND hwnd, TOOLBARINSERTITEM *insertItem) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items || + NULL == insertItem || insertItem->cbSize != sizeof(TOOLBARINSERTITEM)) + { + return -1; + } + + INT index = ITEM_ERR; + + UINT styleOverride = 0; + if (0 != (TBIS_HIDDEN & insertItem->style)) styleOverride |= ToolbarItem::stateHidden; + if (0 != (TBIS_DISABLED & insertItem->style)) styleOverride |= ToolbarItem::stateDisabled; + if (0 != (TBIS_CHEVRONONLY & insertItem->style)) styleOverride |= ToolbarItem::styleChevronOnly; + if (0 != (TBIS_NOCHEVRON & insertItem->style)) styleOverride |= ToolbarItem::styleNoChevron; + if (0 != (TBIS_POPUP & insertItem->style)) styleOverride |= ToolbarItem::stylePopup; + + ToolbarItem *item = Toolbar_CreateItem(insertItem->pszName, styleOverride); + if (NULL != item) + { + index = Toolbar_InsertItemInternal(toolbar, item, insertItem->insertBefore, hwnd); + item->Release(); + if (ITEM_ERR != index) + { + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_LOCKUPDATE & windowStyle)) + { + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + } + } + + return index; +} + +static LRESULT Toolbar_OnFindItem(HWND hwnd, LPCSTR pszName) +{ + return Toolbar_ResolveName(hwnd, pszName); +} + +static LRESULT Toolbar_OnRemoveItem(HWND hwnd, LPCSTR pszName) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items || index == toolbar->items->size()) + return FALSE; + + ToolbarItem *item = toolbar->items->at(index); + toolbar->items->erase(toolbar->items->begin() + index); + if (NULL != item) item->Release(); + + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_LOCKUPDATE & windowStyle)) + { + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + + return TRUE; +} + + +static LRESULT Toolbar_OnSetItemInt(HWND hwnd, LPCSTR pszName, INT value) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return FALSE; + return toolbar->items->at(index)->SetValueInt(hwnd, value); +} + +static LRESULT Toolbar_OnSetItemString(HWND hwnd, LPCSTR pszName, LPCWSTR value) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return FALSE; + return toolbar->items->at(index)->SetValueStr(hwnd, value); +} +static COLORREF Toolbar_OnGetBkColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbBk : 0x00FF00FF; +} +static COLORREF Toolbar_OnGetFgColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbFg : 0x00FF00FF; +} + +static COLORREF Toolbar_OnGetTextColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbText : 0x00FF00FF; +} + +static COLORREF Toolbar_OnGetHiliteColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbHilite : 0x00FF00FF; +} + +static COLORREF Toolbar_OnGetEditColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbEdit : 0x00FF00FF; +} + +static COLORREF Toolbar_OnGetEditBkColor(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + return (NULL != toolbar) ? toolbar->rgbEditBk : 0x00FF00FF; +} + +static LRESULT Toolbar_OnEnableItem(HWND hwnd, LPCSTR pszName, BOOL fEnable) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return FALSE; + + ToolbarItem *item = toolbar->items->at(index); + if (NULL == item) return FALSE; + + item->SetStyle(hwnd, (0 != fEnable) ? 0 : ToolbarItem::stateDisabled, ToolbarItem::stateDisabled); + if (FALSE == fEnable && toolbar->highlighted == item) + Toolbar_SetTooltipItem(hwnd, NULL); + + Toolbar_UpdateTabstop(hwnd); + + return TRUE; +} + +static LRESULT Toolbar_OnGetItemStyle(HWND hwnd, LPCSTR pszName, UINT fMask) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return 0; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return 0; + + UINT itemStyle = toolbar->items->at(index)->GetStyle(); + return (itemStyle & fMask); +} + +static LRESULT Toolbar_OnGetItemCommand(HWND hwnd, LPCSTR pszName) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return 0; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return 0; + + return toolbar->items->at(index)->GetCommandId(); +} + +static LRESULT Toolbar_OnShowItem(HWND hwnd, LPCSTR pszName, BOOL fShow) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return FALSE; + + ToolbarItem *item = toolbar->items->at(index); + if (NULL == item) return FALSE; + + UINT style = item->GetStyle(); + if ((0 != (ToolbarItem::stateHidden & style)) == (FALSE == fShow)) + return TRUE; + + item->SetStyle(hwnd, (0 != fShow) ? 0 : ToolbarItem::stateHidden, ToolbarItem::stateHidden); + + UINT windowStyle = GetWindowStyle(hwnd); + if (0 == (TBS_LOCKUPDATE & windowStyle)) + { + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + + return TRUE; +} + +static LRESULT Toolbar_OnSetItemDescription(HWND hwnd, LPCSTR pszName, LPCWSTR pszDescription) +{ + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (index == toolbar->items->size()) return FALSE; + + ToolbarItem *item = toolbar->items->at(index); + if (NULL == item) return FALSE; + + if (FALSE == item->SetDescription(hwnd, pszDescription)) + return FALSE; + + if (IsWindowVisible(hwnd) && IsWindowEnabled(hwnd)) + Toolbar_UpdateTip(hwnd); + + return TRUE; +} + + +static void Toolbar_OnUpdateTip(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->hTooltip) + { + TOOLINFO ti; + ti.cbSize = sizeof(TOOLINFO); + ti.uId = 0; + ti.hinst = NULL; + ti.hwnd = hwnd; + ti.lpszText = LPSTR_TEXTCALLBACK; + SendMessage(toolbar->hTooltip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + } + +} + +static LRESULT Toolbar_OnGetTextMetrics(HWND hwnd, TOOLBARTEXTMETRIC *metric) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + CopyMemory(metric, &toolbar->textMetric, sizeof(TOOLBARTEXTMETRIC)); + return TRUE; +} + +static LRESULT Toolbar_OnGetBkBrush(HWND hwnd) +{ + return (LRESULT)Toolbar_GetBrush(hwnd, TOOLBRUSH_BACK); +} + +static LRESULT Toolbar_OnLayout(HWND hwnd, TOOLBARLAYOUT *layout) +{ + if (NULL == layout) + return FALSE; + + CopyRect(&layout->clientRect, layout->prcParent); + DWORD windowStyle = GetWindowStyle(hwnd); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || 0 == (WS_VISIBLE & windowStyle)) + { + layout->insertAfter = HWND_BOTTOM; + SetRectEmpty(&layout->toolbarRect); + return TRUE; + } + + CopyRect(&layout->toolbarRect, layout->prcParent); + + INT toolbarHeight, clientInflate; + + if (0 != (TBS_AUTOHIDE & windowStyle)) + { + clientInflate = TOOLBAR_HIDDENHEIGHT; + toolbarHeight = (0 == (TBS_HIDDEN & toolbar->flags)) ? + Toolbar_GetIdealHeight(hwnd) : TOOLBAR_HIDDENHEIGHT; + } + else + { + toolbarHeight = Toolbar_GetIdealHeight(hwnd); + clientInflate = toolbarHeight; + } + + + if (0 != (TBS_BOTTOMDOCK & windowStyle)) + { + layout->toolbarRect.top = layout->toolbarRect.bottom - toolbarHeight; + if (layout->toolbarRect.top < layout->prcParent->top) + layout->toolbarRect.top = layout->prcParent->top; + layout->clientRect.bottom -= clientInflate; + layout->insertAfter = (0 == (TBS_AUTOHIDE & windowStyle) || 0 != (TBS_HIDDEN & toolbar->flags)) ? + HWND_BOTTOM : HWND_TOP; + } + else + { + layout->toolbarRect.bottom = layout->toolbarRect.top + toolbarHeight; + if (layout->toolbarRect.bottom > layout->prcParent->bottom) + layout->toolbarRect.bottom = layout->prcParent->bottom; + layout->clientRect.top += clientInflate; + layout->insertAfter = HWND_TOP; + } + + return TRUE; +} + +static BOOL Toolbar_OnNextItem(HWND hwnd, LPCSTR pszName, BOOL fUseName) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + + size_t focusIndex = toolbar->iFocused; + if (FALSE == fUseName) + { + focusIndex = Toolbar_GetFocusIndex(hwnd, toolbar->iFocused, 0, FALSE); + if (((size_t)-1) == focusIndex) + { + if (TBNS_NEXTITEM == pszName) + { + focusIndex = toolbar->items->size(); + if (focusIndex > 0) focusIndex--; + } + else + { + focusIndex = 0; + } + } + else + { + if (TBNS_NEXTITEM == pszName) + { + if (focusIndex <= toolbar->items->size()) + focusIndex = Toolbar_GetFocusIndex(hwnd, focusIndex + 1, 1, FALSE); + } + else + { + if (focusIndex > 0) + focusIndex = Toolbar_GetFocusIndex(hwnd, focusIndex - 1, -1, FALSE); + } + + if (((size_t)-1) == focusIndex) + focusIndex = toolbar->iFocused; + } + } + else + { + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index || + !Toolbar_IsItemAcceptFocus(Toolbar_GetItem(toolbar, index), FALSE)) + return FALSE; + focusIndex = (size_t)index; + } + + BOOL focusChanged = FALSE; + if (focusIndex != toolbar->iFocused) + { + ToolbarItem *itemNew, *itemOld; + + itemOld = Toolbar_GetItem(toolbar, toolbar->iFocused); + itemNew = Toolbar_GetItem(toolbar, focusIndex); + toolbar->iFocused = focusIndex; + + if (NULL != itemOld) itemOld->SetFocus(hwnd, itemNew, FALSE); + if (NULL != itemNew) itemNew->SetFocus(hwnd, itemOld, TRUE); + + focusChanged = TRUE; + } + + HWND hFocus = GetFocus(); + if (hwnd != hFocus && FALSE == IsChild(hwnd, hFocus)) + { + if (IsWindowVisible(hwnd) && IsWindowEnabled(hwnd)) + { + HWND hRoot = GetAncestor(hwnd, GA_ROOT); + if (NULL != hRoot) + SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwnd, TRUE); + if (hwnd != GetFocus()) + SetFocus(hwnd); + } + } + else if (FALSE == focusChanged) + { + ToolbarItem *item = Toolbar_GetItem(toolbar, toolbar->iFocused); + if (NULL != item) item->SetFocus(hwnd, item, TRUE); + } + + return TRUE; +} + +static BOOL Toolbar_OnGetItemInfo(HWND hwnd, LPCSTR pszName, TBITEMINFO *itemInfo) +{ + if (NULL == itemInfo) + return FALSE; + + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || index == toolbar->items->size()) return FALSE; + + ToolbarItem *item = toolbar->items->at(index); + if (NULL == item) return FALSE; + + BOOL result = TRUE; + + itemInfo->commandId = item->GetCommandId(); + itemInfo->style = item->GetStyle(); + + if (NULL != itemInfo->pszText) + { + if (FAILED(item->GetText(itemInfo->pszText, itemInfo->cchText))) + result = FALSE; + } + + if (NULL != itemInfo->pszDescription) + { + if (FAILED(item->GetDescription(itemInfo->pszDescription, itemInfo->cchDescription))) + result = FALSE; + } + return result; +} + + +static HRESULT Toolbar_GetServiceCommandState(HWND hBrowser,ifc_omservicecommand *serviceCommand, const GUID *commandGroup, UINT commandId, HRESULT defaultState) +{ + HRESULT state = (NULL != serviceCommand) ? serviceCommand->QueryState(hBrowser, commandGroup, commandId) : defaultState; + if (E_NOTIMPL == state) + state = defaultState; + return state; +} + +static INT Toolbar_InsertItemHelper(HWND hwnd, LPCSTR pszName, UINT overrideStyle, INT insertBefore) +{ + INT index = ITEM_ERR; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->items) + { + ToolbarItem *item = Toolbar_CreateItem(pszName, overrideStyle); + if (NULL != item) + { + index = Toolbar_InsertItemInternal(toolbar, item, insertBefore, hwnd); + item->Release(); + } + } + return index; +} +static INT Toolbar_AddItemHelper(HWND hwnd, LPCSTR pszName, UINT overrideStyle) +{ + return Toolbar_InsertItemHelper(hwnd, pszName, overrideStyle, TBIP_LAST); +} + +static INT Toolbar_AddItemHelper2(HWND hwnd, LPCSTR pszName, UINT overrideStyle, ifc_omservicecommand *serviceCommand, const GUID *commandGroup, ULONG commandId, HRESULT defaultState) +{ + HWND hBrowser = GetParent(hwnd); + HRESULT commandState = Toolbar_GetServiceCommandState(hBrowser, serviceCommand, commandGroup, commandId, defaultState); + if (CMDSTATE_ENABLED != commandState) + return ITEM_ERR; + + return Toolbar_AddItemHelper(hwnd, pszName, overrideStyle); +} + +static LRESULT Toolbar_OnAutoPopulate(HWND hwnd, ifc_omservice *service, UINT flags) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || NULL == toolbar->items) + return 0; + + ifc_omservicecommand *serviceCommand; + if (NULL == service || FAILED(service->QueryInterface(IFC_OmServiceCommand, (void**)&serviceCommand))) + serviceCommand = NULL; + + UINT windowStyle = GetWindowStyle(hwnd); + + Toolbar_ClearItems(toolbar); + + ToolbarItem *item; + HRESULT commandStatus; + size_t blockSize, currentSize; + + HWND hBrowser = GetParent(hwnd); + + // Back/Forward + commandStatus = Toolbar_GetServiceCommandState(hBrowser, serviceCommand, &CMDGROUP_NAVIGATION, NAVCOMMAND_BACKFORWARD, CMDSTATE_ENABLED); + if (SUCCEEDED(commandStatus)) + { + Toolbar_AddItemHelper(hwnd, TOOLITEM_BUTTON_BACK, ToolbarItem::stateDisabled); + Toolbar_AddItemHelper(hwnd, TOOLITEM_BUTTON_FORWARD, ToolbarItem::stateDisabled); + + // History + if (0 != toolbar->items->size()) + { + Toolbar_AddItemHelper2(hwnd, TOOLITEM_BUTTON_HISTORY, ToolbarItem::stateDisabled | ToolbarItem::styleNoChevron, + serviceCommand, &CMDGROUP_NAVIGATION, NAVCOMMAND_HISTORY, CMDSTATE_ENABLED); + } + } + + blockSize = toolbar->items->size(); + + // Home + Toolbar_AddItemHelper2(hwnd, TOOLITEM_BUTTON_HOME, ToolbarItem::stateDisabled, + serviceCommand, &CMDGROUP_NAVIGATION, NAVCOMMAND_HOME, CMDSTATE_ENABLED); + + // Refresh + Toolbar_AddItemHelper2(hwnd, TOOLITEM_BUTTON_REFRESH, ToolbarItem::stateDisabled, + serviceCommand, &CMDGROUP_NAVIGATION, NAVCOMMAND_REFRESH, CMDSTATE_ENABLED); + + // Stop + Toolbar_AddItemHelper2(hwnd, TOOLITEM_BUTTON_STOP, ToolbarItem::stateDisabled, + serviceCommand, &CMDGROUP_NAVIGATION, NAVCOMMAND_STOP, CMDSTATE_ENABLED); + + currentSize = toolbar->items->size(); + if (0 != blockSize && 0 != currentSize && blockSize != currentSize) + Toolbar_InsertItemHelper(hwnd, TOOLITEM_SPACE, ToolbarItem::styleNoChevron, (INT)blockSize); + + BOOL fShowFlexSpace = TRUE; + + // Addressbar + UINT style = ToolbarItem::styleNoChevron | ToolbarItem::stateDisabled | ToolbarItem::stylePopup; + + if (0 == (TBS_FORCEADDRESS & windowStyle) && + CMDSTATE_ENABLED != Toolbar_GetServiceCommandState(hBrowser, serviceCommand, + &CMDGROUP_ADDRESSBAR, ADDRESSCOMMAND_VISIBLE, + (0 != (TBS_SHOWADDRESS & windowStyle)) ? CMDSTATE_ENABLED : CMDSTATE_DISABLED)) + { + style |= ToolbarItem::stateHidden; + } + + if (CMDSTATE_ENABLED == Toolbar_GetServiceCommandState(hBrowser, serviceCommand, + &CMDGROUP_ADDRESSBAR, ADDRESSCOMMAND_READONLY, + (0 != (TBPF_READONLYADDRESS & flags) ? CMDSTATE_ENABLED : CMDSTATE_DISABLED))) + { + style |= ToolbarAddress::styleAddressReadonly; + } + + if (0 == (TBS_FANCYADDRESS & windowStyle)) + style |= ToolbarAddress::styleAddressShowReal; + + if (ITEM_ERR != Toolbar_AddItemHelper(hwnd, TOOLITEM_ADDRESSBAR, style)) + { + currentSize++; + if (0 == (ToolbarItem::stateHidden & style)) + fShowFlexSpace = FALSE; + } + + + + if (0 != currentSize) + { + Toolbar_AddItemHelper(hwnd, TOOLITEM_FLEXSPACE, ToolbarItem::stylePopup | ((FALSE == fShowFlexSpace) ? ToolbarItem::stateHidden : 0)); + } + + if (NULL != serviceCommand && 0 == (TBPF_NOSERVICECOMMANDS & flags)) + { + blockSize = toolbar->items->size(); + + // Rating + commandStatus = Toolbar_GetServiceCommandState(hBrowser, serviceCommand, &CMDGROUP_SERVICE, SVCCOMMAND_RATE, CMDSTATE_UNKNOWN); + if (SUCCEEDED(commandStatus)) + { + UINT rating; + if (NULL != service && SUCCEEDED(service->GetRating(&rating))) + { + if (ITEM_ERR != Toolbar_AddItemHelper(hwnd, TOOLITEM_USERRATING, 0)) + Toolbar_SetItemInt(hwnd, TOOLITEM_USERRATING, rating); + } + } + + // Show Info + Toolbar_AddItemHelper2(hwnd, TOOLITEM_CMDLINK_INFO, ToolbarItem::styleChevronOnly, + serviceCommand, &CMDGROUP_SERVICE, SVCCOMMAND_SHOWINFO, CMDSTATE_UNKNOWN); + + // Report + Toolbar_AddItemHelper2(hwnd, TOOLITEM_CMDLINK_REPORT, ToolbarItem::styleChevronOnly, + serviceCommand, &CMDGROUP_SERVICE, SVCCOMMAND_REPORT, CMDSTATE_UNKNOWN); + + // Remove + Toolbar_AddItemHelper2(hwnd, TOOLITEM_CMDLINK_UNSUBSCRIBE, ToolbarItem::styleChevronOnly, + serviceCommand, &CMDGROUP_SERVICE, SVCCOMMAND_UNSUBSCRIBE, CMDSTATE_UNKNOWN); + + currentSize = toolbar->items->size(); + + if (0 != currentSize && blockSize != currentSize) + Toolbar_AddItemHelper(hwnd, TOOLITEM_SEPARATOR, ToolbarItem::styleChevronOnly); + + } + + const TOOLBARITEMINSERTREC szBrowserTools[] = + { + { TOOLITEM_BUTTON_SECURECONNECTION, ToolbarItem::stateHidden | ToolbarItem::stylePopup | ToolbarItem::styleNoChevron /*| TBIS_NOREMOVE*/ }, + { TOOLITEM_BUTTON_SCRIPTERROR, ToolbarItem::stateHidden | ToolbarItem::stylePopup | ToolbarItem::styleNoChevron /*| TBIS_NOREMOVE*/}, + { TOOLITEM_DOWNLOADPROGRESS, ToolbarItem::styleNoChevron | ToolbarItem::stateDisabled /*| TBIS_NOREMOVE*/}, + }; + + for (INT i = 0; i < ARRAYSIZE(szBrowserTools); i++) + { + item = Toolbar_CreateItem(szBrowserTools[i].name, szBrowserTools[i].style); + if (NULL != item) + { + Toolbar_InsertItemInternal(toolbar, item, TBIP_LAST, hwnd); + item->Release(); + } + } + + if (0 == (TBS_LOCKUPDATE & windowStyle)) + { + Toolbar_UpdateTabstop(hwnd); + Toolbar_UpdateLayout(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + + if (NULL != serviceCommand) + serviceCommand->Release(); + + return (INT)(INT_PTR)toolbar->items->size(); + +} + +static LRESULT Toolbar_OnEnableBottomDock(HWND hwnd, BOOL fEnable) +{ + UINT windowStyle = GetWindowStyle(hwnd); + UINT newStyle = windowStyle; + + if (FALSE == fEnable) + newStyle &= ~TBS_BOTTOMDOCK; + else + newStyle |= TBS_BOTTOMDOCK; + + if(newStyle == windowStyle) + return fEnable; + + if (0 != (TBS_AUTOHIDE & windowStyle)) + { + HWND hFocus = GetFocus(); + if (hwnd == hFocus || IsChild(hwnd, hFocus)) + Toolbar_AutoHideWindow(hwnd, TRUE); + } + + SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); + + + HWND hParent = GetParent(hwnd); + if (NULL != hParent) + { + SetWindowPos(hParent, NULL, 0, 0, 0, 0, + SWP_NOSIZE |SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + } + + HWND insertAfter = HWND_TOP; + if (0 != (TBS_BOTTOMDOCK & newStyle)) + { + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar || + 0 == (TBS_AUTOHIDE & windowStyle) || + 0 != (TBS_HIDDEN & toolbar->flags)) + { + insertAfter = HWND_BOTTOM; + } + } + + SetWindowPos(hwnd, insertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW); + InvalidateRect(hwnd, NULL, TRUE); + + return !fEnable; +} + +static LRESULT Toolbar_OnEnableAutoHide(HWND hwnd, BOOL fEnable) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return 0; + + UINT windowStyle = GetWindowStyle(hwnd); + UINT newStyle = windowStyle; + + KillTimer(hwnd, TIMER_AUTOHIDE_ID); + toolbar->flags &= ~TBS_HIDETIMERSET; + + if (FALSE == fEnable) + { + newStyle &= ~TBS_AUTOHIDE; + toolbar->flags &= ~TBS_HIDDEN; + } + else + { + newStyle |= TBS_AUTOHIDE; + + HWND hFocus = GetFocus(); + if (hwnd != hFocus && FALSE == IsChild(hwnd, hFocus)) + toolbar->flags |= TBS_HIDDEN; + } + + if(newStyle == windowStyle) + return fEnable; + + + SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); + + HWND hParent = GetParent(hwnd); + if (NULL != hParent) + { + SetWindowPos(hParent, NULL, 0, 0, 0, 0, + SWP_NOSIZE |SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + } + + InvalidateRect(hwnd, NULL, TRUE); + + return !fEnable; +} + +static LRESULT Toolbar_OnEnableTabStop(HWND hwnd, BOOL fEnable) +{ + UINT windowStyle = GetWindowStyle(hwnd); + UINT newStyle = windowStyle; + + if (FALSE == fEnable) + newStyle &= ~TBS_TABSTOP; + else + newStyle |= TBS_TABSTOP; + + if(newStyle == windowStyle) + return fEnable; + + SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); + + Toolbar_UpdateTabstop(hwnd); + + return !fEnable; +} + +static LRESULT Toolbar_OnEnableForceAddress(HWND hwnd, BOOL fEnable) +{ + UINT windowStyle = GetWindowStyle(hwnd); + UINT newStyle = windowStyle; + + if (FALSE == fEnable) + newStyle &= ~TBS_FORCEADDRESS; + else + newStyle |= TBS_FORCEADDRESS; + + if(newStyle == windowStyle) + return fEnable; + + SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->items) + { + size_t index = toolbar->items->size(); + while(index--) + { + ToolbarItem *item = toolbar->items->at(index); + if (NULL != item && item->IsEqual(TOOLITEM_ADDRESSBAR, -1)) + { + UINT itemStyle = item->GetStyle(); + if (FALSE != fEnable) + { + if (0 != (ToolbarItem::stateHidden & itemStyle)) + { + Toolbar_LockUpdate(hwnd, TRUE); + if (FALSE != Toolbar_ShowItem(hwnd, MAKEINTRESOURCE(index), TRUE)) + { + size_t nextIndex = index + 1; + if (nextIndex < toolbar->items->size()) + { + ToolbarItem *nextItem = toolbar->items->at(nextIndex); + if (NULL != nextItem && nextItem->IsEqual(TOOLITEM_FLEXSPACE, -1)) + { + Toolbar_ShowItem(hwnd, MAKEINTRESOURCE(nextIndex), FALSE); + } + } + } + Toolbar_LockUpdate(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + } + else + { + HRESULT commandState = E_NOTIMPL; + HWND hBrowser = GetParent(hwnd); + ifc_omservice *service; + if (NULL != hBrowser && FALSE != BrowserControl_GetService(hBrowser, &service)) + { + ifc_omservicecommand *serviceCommand; + if (SUCCEEDED(service->QueryInterface(IFC_OmServiceCommand, (void**)&serviceCommand))) + { + commandState = serviceCommand->QueryState(hBrowser, &CMDGROUP_ADDRESSBAR, ADDRESSCOMMAND_VISIBLE); + serviceCommand->Release(); + } + service->Release(); + } + + if (E_NOTIMPL == commandState) + commandState = (0 != (TBS_SHOWADDRESS & windowStyle)) ? CMDSTATE_ENABLED : CMDSTATE_DISABLED; + + if (0 == (ToolbarItem::stateHidden & itemStyle) && CMDSTATE_ENABLED != commandState) + { + Toolbar_LockUpdate(hwnd, TRUE); + if (FALSE != Toolbar_ShowItem(hwnd, MAKEINTRESOURCE(index), FALSE)) + { + size_t nextIndex = index + 1; + if (nextIndex < toolbar->items->size()) + { + ToolbarItem *nextItem = toolbar->items->at(nextIndex); + if (NULL != nextItem && nextItem->IsEqual(TOOLITEM_FLEXSPACE, -1)) + { + Toolbar_ShowItem(hwnd, MAKEINTRESOURCE(nextIndex), TRUE); + } + } + } + Toolbar_LockUpdate(hwnd, FALSE); + InvalidateRect(hwnd, NULL, TRUE); + } + + + } + break; + } + } + } + + return !fEnable; +} + +static LRESULT Toolbar_OnEnableFancyAddress(HWND hwnd, BOOL fEnable) +{ + UINT windowStyle = GetWindowStyle(hwnd); + UINT newStyle = windowStyle; + + if (FALSE == fEnable) + newStyle &= ~TBS_FANCYADDRESS; + else + newStyle |= TBS_FANCYADDRESS; + + if(newStyle == windowStyle) + return fEnable; + + SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL != toolbar && NULL != toolbar->items) + { + size_t index = toolbar->items->size(); + while(index--) + { + ToolbarItem *item = toolbar->items->at(index); + if (NULL != item && item->IsEqual(TOOLITEM_ADDRESSBAR, -1)) + { + UINT style = (FALSE != fEnable) ? 0 : ToolbarAddress::styleAddressShowReal; + item->SetStyle(hwnd, style, ToolbarAddress::styleAddressShowReal); + break; + } + } + } + + return !fEnable; +} + +static LRESULT Toolbar_OnSetBrowserHost(HWND hwnd, HWND hBrowser) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return 0; + + toolbar->hBrowser = hBrowser; + return TRUE; +} + + +static LRESULT Toolbar_OnGetImageListHeight(HWND hwnd) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + INT iconCX, iconCY; + if (NULL == toolbar || + NULL == toolbar->imageList || + FALSE == ImageList_GetIconSize(toolbar->imageList, &iconCX, &iconCY)) + { + return 0; + } + + return iconCY/TOOLBAR_ICONSTATE_COUNT; +} + +static LRESULT Toolbar_OnGetNextTabItem(HWND hwnd, LPCSTR pszName, BOOL fPrevious) +{ + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return ITEM_ERR; + + INT index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) + return ITEM_ERR; + + if (0 == index && FALSE == fPrevious) + return ITEM_ERR; + + UINT windowStyle = GetWindowStyle(hwnd); + BOOL fTabstopOnly = (0 == (TBS_TABSTOP & windowStyle)); + INT direction = (FALSE == fPrevious) ? 1 : -1; + return Toolbar_GetFocusIndex(hwnd, index + direction, direction, fTabstopOnly); +} + +static void Toolbar_OnCheckHide(HWND hwnd, BOOL fImmediate) +{ + Toolbar_AutoHideWindow(hwnd, fImmediate); +} + +static LRESULT Toolbar_OnGetTextLength(HWND hwnd, LPCSTR pszName, size_t *textLength) +{ + if (NULL == textLength) return FALSE; + *textLength = 0; + + TOOLBAR *toolbar = GetToolbar(hwnd); + if (NULL == toolbar) return FALSE; + + size_t index = Toolbar_ResolveName(hwnd, pszName); + if (ITEM_ERR == index) return FALSE; + + ToolbarItem *item = Toolbar_GetItem(toolbar, index); + if (NULL == item) return FALSE; + + if (FAILED(item->GetTextLength(textLength))) + return FALSE; + + return TRUE; +} + +static LRESULT CALLBACK Toolbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: return Toolbar_OnCreate(hwnd, (CREATESTRUCT*)lParam); + case WM_DESTROY: Toolbar_OnDestroy(hwnd); break; + case WM_PAINT: Toolbar_OnPaint(hwnd); return 0; + case WM_PRINTCLIENT: Toolbar_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0; + case WM_ERASEBKGND: return 0; + case WM_WINDOWPOSCHANGED: Toolbar_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0; + case WM_SETREDRAW: Toolbar_OnSetRedraw(hwnd, (BOOL)wParam); return 0; + case WM_MOUSEMOVE: Toolbar_OnMouseMove(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0; + case WM_MOUSELEAVE: Toolbar_OnMouseLeave(hwnd); return 0; + case WM_LBUTTONDOWN: + Toolbar_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); + break; + case WM_LBUTTONUP: Toolbar_OnLButtonUp(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); break; + case WM_RBUTTONDOWN: Toolbar_OnRButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); break; + case WM_RBUTTONUP: Toolbar_OnRButtonUp(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); break; + case WM_MBUTTONDOWN: Toolbar_OnMButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); break; + case WM_MBUTTONUP: Toolbar_OnMButtonUp(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); break; + case WM_CAPTURECHANGED: Toolbar_OnCaptureChanged(hwnd, (HWND)lParam); return 0; + case WM_GETFONT: return Toolbar_OnGetFont(hwnd); + case WM_SETFONT: Toolbar_OnSetFont(hwnd, (HFONT)wParam, (BOOL)LOWORD(lParam)); return 0; + case WM_NOTIFY: return Toolbar_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam); + case WM_COMMAND: Toolbar_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return 0; + case WM_ENTERMENULOOP: Toolbar_OnEnterMenuLoop(hwnd, (BOOL)wParam); return 0; + case WM_EXITMENULOOP: Toolbar_OnExitMenuLoop(hwnd, (BOOL)wParam); return 0; + case WM_SETFOCUS: Toolbar_OnSetFocus(hwnd, (HWND)wParam); return 0; + case WM_KILLFOCUS: Toolbar_OnKillFocus(hwnd, (HWND)wParam); return 0; + case WM_CONTEXTMENU: Toolbar_OnContextMenu(hwnd, (HWND)wParam, MAKEPOINTS(lParam)); return 0; + case WM_KEYDOWN: Toolbar_OnKeyDown(hwnd, (INT)wParam, (UINT)lParam); return 0; + case WM_KEYUP: Toolbar_OnKeyUp(hwnd, (INT)wParam, (UINT)lParam); return 0; + case WM_GETDLGCODE: return Toolbar_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam); + case WM_UPDATEUISTATE: Toolbar_OnUpdateUiState(hwnd, LOWORD(wParam), HIWORD(wParam)); return 0; + case WM_ENABLE: Toolbar_OnEnable(hwnd, (BOOL)wParam); return 0; + case WM_SETCURSOR: return Toolbar_OnSetCursor(hwnd, (HWND)wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_CTLCOLOREDIT: return Toolbar_OnColorEdit(hwnd, (HDC)wParam, (HWND)lParam); + case WM_CTLCOLORSTATIC: return Toolbar_OnColorStatic(hwnd, (HDC)wParam, (HWND)lParam); + + case TBM_UPDATESKIN: Toolbar_OnUpdateSkin(hwnd, (BOOL)lParam); return 0; + case TBM_GETIDEALHEIGHT: return Toolbar_OnGetIdealHeight(hwnd); + case TBM_GETICONSIZE: return Toolbar_OnGetIconSize(hwnd, (INT)wParam, (SIZE*)lParam); + case TBM_SENDCOMMAND: return Toolbar_OnSendCommand(hwnd, (INT)wParam); + case TBM_DRAWICON: return Toolbar_OnDrawIcon(hwnd, (TOOLBARDRAWICONPARAM*)lParam); + case TBM_GETITEMCOUNT: return Toolbar_OnGetItemCount(hwnd); + case TBM_CLEAR: return Toolbar_OnClear(hwnd); + case TBM_INSERTITEM: return Toolbar_OnInsertItem(hwnd, (TOOLBARINSERTITEM*)lParam); + case TBM_FINDITEM: return Toolbar_OnFindItem(hwnd, (LPCSTR)lParam); + case TBM_REMOVEITEM: return Toolbar_OnRemoveItem(hwnd, (LPCSTR)lParam); + case TBM_SETITEMINT: return Toolbar_OnSetItemInt(hwnd, (LPCSTR)lParam, (INT)wParam); + case TBM_SETITEMSTRING: return Toolbar_OnSetItemString(hwnd, (LPCSTR)lParam, (LPCWSTR)wParam); + case TBM_GETBKCOLOR: return Toolbar_OnGetBkColor(hwnd); + case TBM_GETFGCOLOR: return Toolbar_OnGetFgColor(hwnd); + case TBM_GETTEXTCOLOR: return Toolbar_OnGetTextColor(hwnd); + case TBM_GETHILITECOLOR: return Toolbar_OnGetHiliteColor(hwnd); + case TBM_ENABLEITEM: return Toolbar_OnEnableItem(hwnd,(LPCSTR)lParam, (BOOL)wParam); + case TBM_SHOWITEM: return Toolbar_OnShowItem(hwnd,(LPCSTR)lParam, (BOOL)wParam); + case TBM_UPDATETIP: Toolbar_OnUpdateTip(hwnd); return 0; + case TBM_GETTEXTMETRICS: return Toolbar_OnGetTextMetrics(hwnd, (TOOLBARTEXTMETRIC*)lParam); + case TBM_GETBKBRUSH: return Toolbar_OnGetBkBrush(hwnd); + case TBM_LAYOUT: return Toolbar_OnLayout(hwnd, (TOOLBARLAYOUT*)lParam); + case TBM_NEXTITEM: return Toolbar_OnNextItem(hwnd, (LPCSTR)lParam, (BOOL)wParam); + case TBM_GETITEMSTYLE: return Toolbar_OnGetItemStyle(hwnd, (LPCSTR)lParam, (UINT)wParam); + case TBM_GETITEMCOMMAND: return Toolbar_OnGetItemCommand(hwnd, (LPCSTR)lParam); + case TBM_SETITEMDESCRIPTION:return Toolbar_OnSetItemDescription(hwnd, (LPCSTR)lParam, (LPCWSTR)wParam); + case TBM_GETITEMINFO: return Toolbar_OnGetItemInfo(hwnd, (LPCSTR)lParam, (TBITEMINFO*)wParam); + case TBM_AUTOPOPULATE: return Toolbar_OnAutoPopulate(hwnd, (ifc_omservice*)lParam, (UINT)wParam); + case TBM_ENABLEBOTTOMDOCK: return Toolbar_OnEnableBottomDock(hwnd, (BOOL)lParam); + case TBM_ENABLEAUTOHIDE: return Toolbar_OnEnableAutoHide(hwnd, (BOOL)lParam); + case TBM_ENABLETABSTOP: return Toolbar_OnEnableTabStop(hwnd, (BOOL)lParam); + case TBM_ENABLEFORCEADDRESS: return Toolbar_OnEnableForceAddress(hwnd, (BOOL)lParam); + case TBM_ENABLEFANCYADDRESS: return Toolbar_OnEnableFancyAddress(hwnd, (BOOL)lParam); + case TBM_SETBROWSERHOST: return Toolbar_OnSetBrowserHost(hwnd, (HWND)lParam); + case TBM_GETEDITCOLOR: return Toolbar_OnGetEditColor(hwnd); + case TBM_GETEDITBKCOLOR: return Toolbar_OnGetEditBkColor(hwnd); + case TBM_GETIMAGELISTHEIGHT:return Toolbar_OnGetImageListHeight(hwnd); + case TBM_GETNEXTTABITEM: return Toolbar_OnGetNextTabItem(hwnd, (LPCSTR)lParam, (BOOL)wParam); + case TBM_CHECKHIDE: Toolbar_OnCheckHide(hwnd, (BOOL)lParam); return 0; + case TBM_GETTEXTLENGTH: return Toolbar_OnGetTextLength(hwnd, (LPCSTR)lParam, (size_t*)wParam); + } + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +static LRESULT CALLBACK Toolbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam) +{ + TOOLBARMOUSEHOOK *hook = (TOOLBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex); + if (NULL == hook || NULL == hook->hHook) return FALSE; + + + if (code >= 0) + { + MOUSEHOOKSTRUCT *mouseHook = (MOUSEHOOKSTRUCT*)lParam; + if (mouseHook->hwnd != hook->hwnd) + { + TOOLBAR *toolbar = GetToolbar(hook->hwnd); + if (NULL != toolbar) + { + if (0 != (TBS_HIDDEN & toolbar->flags)) + { + Toolbar_RemoveMouseHook(hook->hwnd, TRUE); + } + else if (0 == ((TBS_MENULOOP | TBS_HIDETIMERSET) & toolbar->flags)) + { + HWND hAncestor = GetAncestor(mouseHook->hwnd, GA_ROOT); + BOOL autoHide; + if (NULL == hAncestor || FALSE == IsChild(hAncestor, hook->hwnd)) + { + autoHide = TRUE; + } + else + { + RECT toolbarRect; + if (!GetWindowRect(hook->hwnd, &toolbarRect)) + SetRectEmpty(&toolbarRect); + toolbarRect.top -= 6; + toolbarRect.bottom += 6; + autoHide = !PtInRect(&toolbarRect, mouseHook->pt); + } + + if (FALSE != autoHide) + Toolbar_AutoHideWindow(hook->hwnd, FALSE); + } + } + } + } + return CallNextHookEx(hook->hHook, code, wParam, lParam); +}
\ No newline at end of file |