From b6b84ffaf51673a3b9b2851602428ac815b680c4 Mon Sep 17 00:00:00 2001 From: Tobias Weimer Date: Sun, 25 Jan 2015 21:39:23 +0000 Subject: TabSRMM: - Fixed memory issues - Fixed translation issue (fixes #869) git-svn-id: http://svn.miranda-ng.org/main/trunk@11909 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/TabSRMM/src/ImageDataObject.h | 6 +- plugins/TabSRMM/src/buttonsbar.cpp | 5 +- plugins/TabSRMM/src/container.cpp | 16 +- plugins/TabSRMM/src/containeroptions.cpp | 46 +- plugins/TabSRMM/src/controls.cpp | 2078 +++++++++++++++--------------- plugins/TabSRMM/src/functions.h | 2 +- plugins/TabSRMM/src/globals.cpp | 4 +- plugins/TabSRMM/src/modplus.cpp | 12 +- plugins/TabSRMM/src/msgoptions.cpp | 2 +- plugins/TabSRMM/src/sidebar.cpp | 6 +- 10 files changed, 1086 insertions(+), 1091 deletions(-) (limited to 'plugins/TabSRMM/src') diff --git a/plugins/TabSRMM/src/ImageDataObject.h b/plugins/TabSRMM/src/ImageDataObject.h index f05df9fa69..2601c10dc6 100644 --- a/plugins/TabSRMM/src/ImageDataObject.h +++ b/plugins/TabSRMM/src/ImageDataObject.h @@ -68,9 +68,11 @@ public: STDMETHOD_(ULONG, Release)(void) { - m_ulRefCnt--; - if (m_ulRefCnt == 0) + m_ulRefCnt--; + if (m_ulRefCnt == 0) { delete this; + return 0; + } return m_ulRefCnt; } diff --git a/plugins/TabSRMM/src/buttonsbar.cpp b/plugins/TabSRMM/src/buttonsbar.cpp index 7925c001a0..20e13e190d 100644 --- a/plugins/TabSRMM/src/buttonsbar.cpp +++ b/plugins/TabSRMM/src/buttonsbar.cpp @@ -198,7 +198,10 @@ static INT_PTR CB_AddButton(WPARAM, LPARAM lParam) LButtonsList.insert(cbd); else if (cbd->bRSided) RButtonsList.insert(cbd); - else return 1; + else { + delete cbd; + return 1; + } if (cbd->dwButtonCID != cbd->dwButtonOrigID) LastCID++; diff --git a/plugins/TabSRMM/src/container.cpp b/plugins/TabSRMM/src/container.cpp index b4908bfca2..7cdeb10e5d 100644 --- a/plugins/TabSRMM/src/container.cpp +++ b/plugins/TabSRMM/src/container.cpp @@ -130,17 +130,14 @@ static LRESULT CALLBACK ContainerWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, break; if (CSkin::m_frameSkins) { - RECT rcWindow, rcClient; HDC dcFrame = GetDCEx(hwndDlg, 0, DCX_WINDOW|/*DCX_INTERSECTRGN|*/0x10000); // GetWindowDC(hwndDlg); - POINT pt, pt1; LONG clip_top, clip_left; - CSkinItem *item; - TCHAR szWindowText[512]; RECT rcText; HDC dcMem = CreateCompatibleDC(pContainer->cachedDC ? pContainer->cachedDC : dcFrame); - HBITMAP hbmMem, hbmOld; int i; + RECT rcWindow, rcClient; + POINT pt, pt1; GetWindowRect(hwndDlg, &rcWindow); GetClientRect(hwndDlg, &rcClient); pt.y = 0; @@ -156,15 +153,16 @@ static LRESULT CALLBACK ContainerWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, rcWindow.bottom = rcWindow.bottom - rcWindow.top; rcWindow.left = rcWindow.top = 0; - hbmMem = CreateCompatibleBitmap(dcFrame, rcWindow.right, rcWindow.bottom); - hbmOld = (HBITMAP)SelectObject(dcMem, hbmMem); + HBITMAP hbmMem = CreateCompatibleBitmap(dcFrame, rcWindow.right, rcWindow.bottom); + HBITMAP hbmOld = (HBITMAP)SelectObject(dcMem, hbmMem); ExcludeClipRect(dcFrame, clip_left, clip_top, clip_left + (pt1.x - pt.x), clip_top + (pt1.y - pt.y)); ExcludeClipRect(dcMem, clip_left, clip_top, clip_left + (pt1.x - pt.x), clip_top + (pt1.y - pt.y)); - item = pContainer->ncActive ? &SkinItems[ID_EXTBKFRAME] : &SkinItems[ID_EXTBKFRAMEINACTIVE]; + CSkinItem *item = pContainer->ncActive ? &SkinItems[ID_EXTBKFRAME] : &SkinItems[ID_EXTBKFRAMEINACTIVE]; CSkin::DrawItem(dcMem, &rcWindow, item); - + + TCHAR szWindowText[512]; GetWindowText(hwndDlg, szWindowText, SIZEOF(szWindowText)); szWindowText[511] = 0; hOldFont = (HFONT)SelectObject(dcMem, PluginConfig.hFontCaption); diff --git a/plugins/TabSRMM/src/containeroptions.cpp b/plugins/TabSRMM/src/containeroptions.cpp index 4cd595acbb..cf80aefeb4 100644 --- a/plugins/TabSRMM/src/containeroptions.cpp +++ b/plugins/TabSRMM/src/containeroptions.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // Miranda NG: the free IM client for Microsoft* Windows* // -// Copyright (ñ) 2012-15 Miranda NG project, +// Copyright (c) 2012-15 Miranda NG project, // Copyright (c) 2000-09 Miranda ICQ/IM project, // all portions of this codebase are copyrighted to the people // listed in contributors.txt. @@ -136,25 +136,21 @@ static void ShowPage(HWND hwndDlg, int iPage, BOOL fShow) INT_PTR CALLBACK DlgProcContainerOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { - TContainerData *pContainer = 0; - HWND hwndTree = GetDlgItem(hwndDlg, IDC_SECTIONTREE); - pContainer = (TContainerData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + HWND hwndTree = GetDlgItem(hwndDlg, IDC_SECTIONTREE); + TContainerData *pContainer = (TContainerData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: { - wchar_t szNewTitle[128]; - TContainerData *pContainer = 0; - int i, j; TVINSERTSTRUCT tvis = {0}; - HTREEITEM hItem; - int nr_layouts = 0; - const TSideBarLayout* sblayouts = CSideBar::getLayouts(nr_layouts); + int nr_layouts = 0; + const TSideBarLayout *sblayouts = CSideBar::getLayouts(nr_layouts); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) lParam); pContainer = (TContainerData*)lParam; pContainer->hWndOptions = hwndDlg; TranslateDialogDefault(hwndDlg); SetWindowText(hwndDlg, TranslateT("Container options")); + TCHAR szNewTitle[128]; mir_sntprintf(szNewTitle, SIZEOF(szNewTitle), TranslateT("Configure container options for\n%s"), !_tcscmp(pContainer->szName, _T("default")) ? TranslateT("Default container") : pContainer->szName); SetDlgItemText(hwndDlg, IDC_HEADERBAR, szNewTitle); @@ -166,21 +162,15 @@ INT_PTR CALLBACK DlgProcContainerOptions(HWND hwndDlg, UINT msg, WPARAM wParam, SendDlgItemMessage(hwndDlg, IDC_TABMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Switch bar on the left side")); SendDlgItemMessage(hwndDlg, IDC_TABMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Switch bar on the right side")); - SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("Globally on")); - SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("On, if present")); - SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("Globally OFF")); - SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("On, if present, always in bottom display")); - - SendDlgItemMessage(hwndDlg, IDC_OWNAVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("On, if present")); - SendDlgItemMessage(hwndDlg, IDC_OWNAVATARMODE, CB_INSERTSTRING, -1, - (LPARAM)TranslateT("Don't show them")); - - for (i=0; i < nr_layouts; i++) + SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Globally on")); + SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("On, if present")); + SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Globally OFF")); + SendDlgItemMessage(hwndDlg, IDC_AVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("On, if present, always in bottom display")); + + SendDlgItemMessage(hwndDlg, IDC_OWNAVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("On, if present")); + SendDlgItemMessage(hwndDlg, IDC_OWNAVATARMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Don't show them")); + + for (int i=0; i < nr_layouts; i++) SendDlgItemMessage(hwndDlg, IDC_SBARLAYOUT, CB_INSERTSTRING, -1, (LPARAM)TranslateTS(sblayouts[i].szName)); /* bits 24 - 31 of dwFlagsEx hold the side bar layout id */ @@ -191,16 +181,16 @@ INT_PTR CALLBACK DlgProcContainerOptions(HWND hwndDlg, UINT msg, WPARAM wParam, SendDlgItemMessage(hwndDlg, IDC_TITLEFORMAT, EM_LIMITTEXT, TITLE_FORMATLEN - 1, 0); SetDlgItemText(hwndDlg, IDC_TITLEFORMAT, pContainer->settings->szTitleFormat); SetDlgItemText(hwndDlg, IDC_THEME, pContainer->szRelThemeFile); - for (i=0; i < NR_O_PAGES; i++) { + for (int i=0; i < NR_O_PAGES; i++) { tvis.hParent = NULL; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_TEXT | TVIF_PARAM; tvis.item.pszText = TranslateTS(o_pages[i].szTitle); tvis.item.lParam = i; - hItem = TreeView_InsertItem(hwndTree, &tvis); + HTREEITEM hItem = TreeView_InsertItem(hwndTree, &tvis); if (i == 0) SendMessage(hwndTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem); - for (j = 0; j < NR_O_OPTIONSPERPAGE && o_pages[i].uIds[j] != 0; j++) + for (int j = 0; j < NR_O_OPTIONSPERPAGE && o_pages[i].uIds[j] != 0; j++) Utils::showDlgControl(hwndDlg, o_pages[i].uIds[j], SW_HIDE); ShowPage(hwndDlg, i, FALSE); } diff --git a/plugins/TabSRMM/src/controls.cpp b/plugins/TabSRMM/src/controls.cpp index 3a66bf6276..cf50bf2eac 100644 --- a/plugins/TabSRMM/src/controls.cpp +++ b/plugins/TabSRMM/src/controls.cpp @@ -1,1040 +1,1042 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-15 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// Menu and status bar control(s) for the container window. - -#include "commonheaders.h" - -static WNDPROC OldStatusBarproc = 0; - -bool CMenuBar::m_buttonsInit = false; -HHOOK CMenuBar::m_hHook = 0; -TBBUTTON CMenuBar::m_TbButtons[8] = {0}; -CMenuBar *CMenuBar::m_Owner = 0; -HBITMAP CMenuBar::m_MimIcon = 0; -int CMenuBar::m_MimIconRefCount = 0; - -static int resetLP(WPARAM, LPARAM, LPARAM obj) -{ - if (PluginConfig.g_hMenuContext) - DestroyMenu(PluginConfig.g_hMenuContext); +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-15 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// Menu and status bar control(s) for the container window. + +#include "commonheaders.h" + +static WNDPROC OldStatusBarproc = 0; + +bool CMenuBar::m_buttonsInit = false; +HHOOK CMenuBar::m_hHook = 0; +TBBUTTON CMenuBar::m_TbButtons[8] = {0}; +CMenuBar *CMenuBar::m_Owner = 0; +HBITMAP CMenuBar::m_MimIcon = 0; +int CMenuBar::m_MimIconRefCount = 0; + +static int resetLP(WPARAM, LPARAM, LPARAM obj) +{ + if (PluginConfig.g_hMenuContext) + DestroyMenu(PluginConfig.g_hMenuContext); PluginConfig.g_hMenuContext = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_TABCONTEXT)); TranslateMenu(PluginConfig.g_hMenuContext); - - ((CMenuBar*)obj)->resetLP(); - return 0; -} - -CMenuBar::CMenuBar(HWND hwndParent, const TContainerData *pContainer) -{ - m_pContainer = const_cast(pContainer); - - if (m_MimIcon == 0) { - HDC hdc = ::GetDC(m_pContainer->hwnd); - HANDLE hIcon = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA); - - HDC hdcTemp = ::CreateCompatibleDC(hdc); - - RECT rc = {0,0,16,16}; - m_MimIcon = CSkin::CreateAeroCompatibleBitmap(rc, hdcTemp); - HBITMAP hbmOld = reinterpret_cast(::SelectObject(hdcTemp, m_MimIcon)); - ::DrawIconEx(hdcTemp, 0, 0, (HICON)hIcon, 16, 16, 0, 0, DI_NORMAL); - ::SelectObject(hdcTemp, hbmOld); - - ::DeleteDC(hdcTemp); - ::ReleaseDC(m_pContainer->hwnd, hdc); - } - - m_MimIconRefCount++; - - m_hwndToolbar = ::CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL, WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_VISIBLE|TBSTYLE_FLAT|TBSTYLE_TRANSPARENT|TBSTYLE_LIST|/*CCS_NOPARENTALIGN|*/CCS_NODIVIDER|CCS_TOP, - 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL); - - ::SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - - checkButtons(); - - m_activeMenu = 0; - m_activeID = 0; - m_isAero = M.isAero(); - m_mustAutoHide = false; - m_activeSubMenu = 0; - m_fTracking = false; - m_isContactMenu = m_isMainMenu = false; - HookEventParam(ME_LANGPACK_CHANGED, &::resetLP, (LPARAM)this); - - ::SetWindowLongPtr(m_hwndToolbar, GWLP_USERDATA, (LONG_PTR)this); - mir_subclassWindow(m_hwndToolbar, wndProc); -} - -CMenuBar::~CMenuBar() -{ - ::SetWindowLongPtr(m_hwndToolbar, GWLP_USERDATA, 0); - ::DestroyWindow(m_hwndToolbar); - releaseHook(); - m_MimIconRefCount--; - if (m_MimIconRefCount == 0) { - ::DeleteObject(m_MimIcon); - m_MimIcon = 0; - } -} - -/** - * retrieves the client rectangle for the rebar control. This must be - * called once per WM_SIZE event by the parent window. getHeight() depends on it. - * - * @return RECT&: client rectangle of the rebar control - */ -const RECT& CMenuBar::getClientRect() -{ - ::GetClientRect(m_hwndToolbar, &m_rcClient); - return(m_rcClient); -} - -void CMenuBar::obtainHook() -{ - releaseHook(); - if (m_hHook == 0) - m_hHook = ::SetWindowsHookEx(WH_MSGFILTER, CMenuBar::MessageHook, 0, GetCurrentThreadId()); - m_Owner = this; -} - -void CMenuBar::releaseHook() -{ - if (m_hHook) { - ::UnhookWindowsHookEx(m_hHook); - m_hHook = 0; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Retrieve the height of the rebar control -// -// @return LONG: height of the rebar, in pixels - -LONG CMenuBar::getHeight() const -{ - return((m_pContainer->dwFlags & CNT_NOMENUBAR) ? 0 : m_size_y); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// process all relevant messages. Must be called by the parent window's -// window procedure. -// -// @param msg -// @param wParam -// @param lParam -// -// @return LRESULT: message processing result. Win32 conform. -// -1 means: nothing processed, caller should continue as usual. - -LONG_PTR CMenuBar::processMsg(const UINT msg, const WPARAM, const LPARAM lParam) -{ - if (msg == WM_NOTIFY) { - NMHDR *pNMHDR = (NMHDR*)lParam; - switch(pNMHDR->code) { - case NM_CUSTOMDRAW: - { - NMCUSTOMDRAW *nm = (NMCUSTOMDRAW*)lParam; - return customDrawWorker(nm); - } - - case TBN_DROPDOWN: - { - NMTOOLBAR *mtb = (NMTOOLBAR *)lParam; - return Handle(mtb); - } - case TBN_HOTITEMCHANGE: - { - NMTBHOTITEM *nmtb = (NMTBHOTITEM *)lParam; - if (nmtb->idNew != 0 && m_fTracking && nmtb->idNew != m_activeID && m_activeID != 0) { - cancel(); - return 0; - } - else if (m_fTracking == true && m_activeID == 0 && nmtb->idNew != 0) { - invoke(nmtb->idNew); - return 0; - } - break; - } - - default: - return -1; - } - } - else if (msg == WM_LBUTTONDOWN) { - if (m_pContainer->dwFlags & CNT_NOTITLE) { - POINT pt; - ::GetCursorPos(&pt); - return ::SendMessage(m_pContainer->hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); - } - } - return -1; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclass the toolbar control to handle some keyboard events and improve -// keyboard navigation - -LRESULT CALLBACK CMenuBar::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - CMenuBar *menuBar = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); - - switch(msg) { - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - menuBar->Cancel(); - return 0; - } - break; - } - return ::mir_callNextSubclass(hWnd, CMenuBar::wndProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Implements NM_CUSTOMDRAW for the toolbar -// -// @param nm NMCUSTOMDRAW *: sent via NM_CUSTOMDRAW message -// -// @return LONG_PTR: see Win32 NM_CUSTOMDRAW message. The function must return a valid -// message return value to indicate how Windows should continue with the drawing process. -// -// It may return zero in which case, the caller should allow default processing for -// the NM_CUSTOMDRAW message. - -LONG_PTR CMenuBar::customDrawWorker(NMCUSTOMDRAW *nm) -{ - bool fMustDraw = true; - - if (nm->hdr.hwndFrom == m_hwndToolbar) { - NMTBCUSTOMDRAW *nmtb = (NMTBCUSTOMDRAW *)(nm); - - switch(nmtb->nmcd.dwDrawStage) { - case CDDS_PREPAINT: - if (fMustDraw) { - if (nmtb->nmcd.dwItemSpec == 0) { - m_hdcDraw = ::CreateCompatibleDC(nmtb->nmcd.hdc); - //m_rcItem = nmtb->nmcd.rc; - ::GetClientRect(m_hwndToolbar, &m_rcItem); - m_rcItem.bottom -= 4; - m_hbmDraw = CSkin::CreateAeroCompatibleBitmap(m_rcItem, nmtb->nmcd.hdc); - m_hbmOld = reinterpret_cast(::SelectObject(m_hdcDraw, m_hbmDraw)); - m_hTheme = M.isAero() || M.isVSThemed() ? OpenThemeData(m_hwndToolbar, L"REBAR") : 0; - m_hOldFont = reinterpret_cast(::SelectObject(m_hdcDraw, reinterpret_cast(::GetStockObject(DEFAULT_GUI_FONT)))); - if (m_isAero) { - nm->rc.bottom--; - CSkin::ApplyAeroEffect(m_hdcDraw, &m_rcItem, CSkin::AERO_EFFECT_AREA_MENUBAR); - nm->rc.bottom++; - } - else if ((PluginConfig.m_fillColor || M.isVSThemed()) && !CSkin::m_skinEnabled) { - if (PluginConfig.m_fillColor && PluginConfig.m_tbBackgroundHigh && PluginConfig.m_tbBackgroundLow) { - ::DrawAlpha(m_hdcDraw, &m_rcItem, PluginConfig.m_tbBackgroundHigh, 100, PluginConfig.m_tbBackgroundLow, 0, - GRADIENT_TB, 0, 0, 0); - } - else { - m_rcItem.bottom--; - if (PluginConfig.m_fillColor) - CSkin::FillBack(m_hdcDraw, &m_rcItem); - else if (M.isVSThemed()) - DrawThemeBackground(m_hTheme, m_hdcDraw, 6, 1, &m_rcItem, &m_rcItem); - else - FillRect(m_hdcDraw, &m_rcItem, GetSysColorBrush(COLOR_3DFACE)); - } - } - else if (CSkin::m_MenuBGBrush) - ::FillRect(m_hdcDraw, &nm->rc, CSkin::m_MenuBGBrush); - else - ::FillRect(m_hdcDraw, &nm->rc, GetSysColorBrush(COLOR_3DFACE)); - } - return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYPOSTERASE; - } - - m_hdcDraw = 0; - return CDRF_DODEFAULT; - - case CDDS_ITEMPREPAINT: - if (fMustDraw) { - TCHAR *szText = 0; - bool fDraw = true; - - int iIndex = idToIndex(nmtb->nmcd.dwItemSpec); - if (iIndex >= 0 && iIndex < NR_BUTTONS) - szText = (TCHAR*)m_TbButtons[iIndex].iString; - - UINT uState = nmtb->nmcd.uItemState; - - nmtb->nmcd.rc.bottom--; - if (CSkin::m_skinEnabled) { - CSkinItem *item = 0; - - ::FillRect(m_hdcDraw, &nmtb->nmcd.rc, CSkin::m_MenuBGBrush); - - if (uState & CDIS_MARKED || uState & CDIS_CHECKED || uState & CDIS_SELECTED) - item = &SkinItems[ID_EXTBKBUTTONSPRESSED]; - else if (uState & CDIS_HOT) - item = &SkinItems[ID_EXTBKBUTTONSMOUSEOVER]; - - if (item) - fDraw = !CSkin::DrawItem(m_hdcDraw, &nmtb->nmcd.rc, item); - else - fDraw = false; - } - if (fDraw) { - COLORREF clr = ::GetSysColor(COLOR_HOTLIGHT); - COLORREF clrRev = clr; - if (uState & CDIS_MARKED || uState & CDIS_CHECKED) - ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); - - if (uState & CDIS_SELECTED) - ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); - - if (uState & CDIS_HOT) - ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); - } - - if (szText) { - COLORREF clr = CSkin::m_skinEnabled ? CSkin::m_DefaultFontColor : - (PluginConfig.m_fillColor ? PluginConfig.m_genericTxtColor : - (uState & (CDIS_SELECTED | CDIS_HOT | CDIS_MARKED)) ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) : ::GetSysColor(COLOR_BTNTEXT)); - - ::SetBkMode(m_hdcDraw, TRANSPARENT); - CSkin::RenderText(m_hdcDraw, m_hTheme, szText, &nmtb->nmcd.rc, DT_SINGLELINE | DT_VCENTER | DT_CENTER, CSkin::m_glowSize, clr); - } - if (iIndex == 0) - ::DrawIconEx(m_hdcDraw, (nmtb->nmcd.rc.left + nmtb->nmcd.rc.right) / 2 - 8, - (nmtb->nmcd.rc.top + nmtb->nmcd.rc.bottom) / 2 - 8, LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), - 16, 16, 0, 0, DI_NORMAL); - - return CDRF_SKIPDEFAULT; - } - else return CDRF_DODEFAULT; - - case CDDS_PREERASE: - case CDDS_ITEMPOSTERASE: - case CDDS_ITEMPOSTPAINT: - case CDDS_ITEMPREERASE: - return fMustDraw ? CDRF_SKIPDEFAULT : CDRF_DODEFAULT; - - case CDDS_POSTERASE: - return fMustDraw ? CDRF_SKIPDEFAULT : CDRF_DODEFAULT; - - case CDDS_POSTPAINT: - if (nmtb->nmcd.dwItemSpec == 0 && m_hdcDraw) { - ::BitBlt(nmtb->nmcd.hdc, 0, 0, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, - m_hdcDraw, 0, 0, SRCCOPY); - ::SelectObject(m_hdcDraw, m_hbmOld); - ::DeleteObject(m_hbmDraw); - ::SelectObject(m_hdcDraw, m_hOldFont); - ::DeleteDC(m_hdcDraw); - m_hdcDraw = 0; - if (m_hTheme) - CloseThemeData(m_hTheme); - return CDRF_SKIPDEFAULT; - } - return CDRF_DODEFAULT; - - default: - return CDRF_DODEFAULT; - } - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Handle the TBN_DROPDOWN notification message sent by the -// toolbar control. -// -// @param nmtb NMTOOLBAR *: notification message structure -// -// @return LONG_PTR: must be a valid return value. See Win32 API, TBN_DROPDOWN - -LONG_PTR CMenuBar::Handle(const NMTOOLBAR *nmtb) -{ - if (nmtb->hdr.hwndFrom != m_hwndToolbar) - return TBDDRET_NODEFAULT; - - invoke(nmtb->iItem); - return TBDDRET_DEFAULT; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Invoke the dropdown menu for the button with the given control id. -// -// @param id int: the control id of the toolbar button which has been activated - -void CMenuBar::invoke(const int id) -{ - const int index = idToIndex(id); - - HMENU hMenu; - - m_isContactMenu = m_isMainMenu = false; - - TWindowData *dat = (TWindowData*)GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); - - MCONTACT hContact = dat ? dat->hContact : 0; - - if (index == 3 && hContact != 0) { - hMenu = reinterpret_cast(::CallService(MS_CLIST_MENUBUILDCONTACT, hContact, 0)); - m_isContactMenu = true; - } else if (index == 0) { - hMenu = reinterpret_cast(::CallService(MS_CLIST_MENUBUILDMAIN, 0, 0)); - m_isMainMenu = true; - } else - hMenu = reinterpret_cast(m_TbButtons[index].dwData); - - RECT rcButton; - POINT pt; - ::SendMessage(m_hwndToolbar, TB_GETITEMRECT, (WPARAM)index, (LPARAM)&rcButton); - pt.x = rcButton.left; - pt.y = rcButton.bottom; - ::ClientToScreen(m_hwndToolbar, &pt); - - if (m_activeID) - cancel(); - - m_activeMenu = hMenu; - m_activeSubMenu = 0; - m_activeID = id; - updateState(hMenu); - obtainHook(); - m_fTracking = true; - ::SendMessage(m_hwndToolbar, TB_SETSTATE, (WPARAM)id, TBSTATE_CHECKED | TBSTATE_ENABLED); - ::TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, m_pContainer->hwnd, 0); -} - -void CMenuBar::cancel() -{ - releaseHook(); - if (m_activeID) - ::SendMessage(m_hwndToolbar, TB_SETSTATE, (WPARAM)m_activeID, TBSTATE_ENABLED); - m_activeID = 0; - m_activeMenu = 0; - m_isContactMenu = m_isMainMenu = false; - ::EndMenu(); -} - -void CMenuBar::Cancel(void) -{ - cancel(); - m_fTracking = false; - autoShow(0); -} - -void CMenuBar::updateState(const HMENU hMenu) const -{ - TWindowData *dat = (TWindowData*)GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); - if (dat) { - ::CheckMenuItem(hMenu, ID_VIEW_SHOWMENUBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOMENUBAR ? MF_UNCHECKED : MF_CHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_SHOWSTATUSBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOSTATUSBAR ? MF_UNCHECKED : MF_CHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_SHOWAVATAR, MF_BYCOMMAND | (dat->bShowAvatar ? MF_CHECKED : MF_UNCHECKED)); - ::CheckMenuItem(hMenu, ID_VIEW_SHOWTITLEBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOTITLE ? MF_UNCHECKED : MF_CHECKED); - - ::EnableMenuItem(hMenu, ID_VIEW_SHOWTITLEBAR, CSkin::m_skinEnabled && CSkin::m_frameSkins ? MF_GRAYED : MF_ENABLED); - - ::CheckMenuItem(hMenu, ID_VIEW_TABSATBOTTOM, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_TABSBOTTOM ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_VERTICALMAXIMIZE, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_VERTICALMAX ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_SHOWTOOLBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_HIDETOOLBAR ? MF_UNCHECKED : MF_CHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_BOTTOMTOOLBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? MF_CHECKED : MF_UNCHECKED); - - ::CheckMenuItem(hMenu, ID_VIEW_SHOWMULTISENDCONTACTLIST, MF_BYCOMMAND | (dat->sendMode & SMODE_MULTIPLE) ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_VIEW_STAYONTOP, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_STICKY ? MF_CHECKED : MF_UNCHECKED); - - ::EnableMenuItem(hMenu, 2, MF_BYPOSITION | (nen_options.bWindowCheck ? MF_GRAYED : MF_ENABLED)); - ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_DISABLEALLEVENTPOPUPS, MF_BYCOMMAND | m_pContainer->dwFlags & (CNT_DONTREPORT | CNT_DONTREPORTUNFOCUSED | CNT_DONTREPORTFOCUSED | CNT_ALWAYSREPORTINACTIVE) ? MF_UNCHECKED : MF_CHECKED); - ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISMINIMIZED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORT ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSFORALLINACTIVESESSIONS, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISUNFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORTFOCUSED ? MF_CHECKED : MF_UNCHECKED); - - ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_USEDEFAULTVALUES, MF_BYCOMMAND | (m_pContainer->dwFlags & (CNT_NOFLASH | CNT_FLASHALWAYS)) ? MF_UNCHECKED : MF_CHECKED); - ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_DISABLEFLASHING, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOFLASH ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_FLASHUNTILFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_FLASHALWAYS ? MF_CHECKED : MF_UNCHECKED); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// this updates the container menu bar and other window elements depending on the current -// child session (IM, chat etc.). It fully supports IEView and will disable/enable the -// message log menus depending on the configuration of IEView (e.g. when template mode -// is on, the message log settin menus have no functionality, thus can be disabled to -// improve ui feedback quality). - -void CMenuBar::configureMenu() const -{ - BOOL fDisable = FALSE; - - TWindowData *dat = (TWindowData*)::GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); - if (dat) { - bool fChat = (dat->bType == SESSIONTYPE_CHAT); - - ::SendMessage(m_hwndToolbar, TB_SETSTATE, 103, fChat ? TBSTATE_HIDDEN : TBSTATE_ENABLED); - ::SendMessage(m_hwndToolbar, TB_SETSTATE, 104, fChat ? TBSTATE_ENABLED : TBSTATE_HIDDEN); - ::SendMessage(m_hwndToolbar, TB_SETSTATE, 105, fChat ? TBSTATE_HIDDEN : TBSTATE_ENABLED); - - if (dat->bType == SESSIONTYPE_IM) - ::EnableWindow(GetDlgItem(dat->hwnd, IDC_TIME), fDisable ? FALSE : TRUE); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Automatically shows or hides the menu bar. Depends on the current state, -// used when the ALT key is hit in the message window. - -void CMenuBar::autoShow(const int showcmd) -{ - if (m_mustAutoHide && !(m_pContainer->dwFlags & CNT_NOMENUBAR)) { - m_pContainer->dwFlags |= CNT_NOMENUBAR; - m_mustAutoHide = false; - ::SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); - releaseHook(); - } - - if (showcmd == 0) { - ::SetFocus(m_pContainer->hwndActive); - return; - } - - if (m_pContainer->dwFlags & CNT_NOMENUBAR) { - m_mustAutoHide = true; - m_pContainer->dwFlags &= ~CNT_NOMENUBAR; - ::SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); - } - else // do nothing, already visible - m_mustAutoHide = false; - - ::SetFocus(m_hwndToolbar); -} - -void CMenuBar::checkButtons() -{ - if (!m_buttonsInit) { - memset(m_TbButtons, 0, sizeof(m_TbButtons)); - - m_TbButtons[0].iBitmap = 0; - m_TbButtons[0].iString = 0; - m_TbButtons[0].fsState = TBSTATE_ENABLED; - m_TbButtons[0].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[0].idCommand = 100; - m_TbButtons[0].dwData = 0; - - m_TbButtons[1].iBitmap = I_IMAGENONE; - m_TbButtons[1].iString = (INT_PTR)TranslateT("&File"); - m_TbButtons[1].fsState = TBSTATE_ENABLED; - m_TbButtons[1].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[1].idCommand = 101; - m_TbButtons[1].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 0)); - - m_TbButtons[2].iBitmap = I_IMAGENONE; - m_TbButtons[2].iString = (INT_PTR)TranslateT("&View"); - m_TbButtons[2].fsState = TBSTATE_ENABLED; - m_TbButtons[2].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[2].idCommand = 102; - m_TbButtons[2].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 1)); - - m_TbButtons[3].iBitmap = I_IMAGENONE; - m_TbButtons[3].iString = (INT_PTR)TranslateT("&User"); - m_TbButtons[3].fsState = TBSTATE_ENABLED; - m_TbButtons[3].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[3].idCommand = 103; - m_TbButtons[3].dwData = 0; // dynamically built by Clist service - - m_TbButtons[4].iBitmap = I_IMAGENONE; - m_TbButtons[4].iString = (INT_PTR)TranslateT("&Room"); - m_TbButtons[4].fsState = TBSTATE_ENABLED; - m_TbButtons[4].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[4].idCommand = 104; - m_TbButtons[4].dwData = 0; - - m_TbButtons[5].iBitmap = I_IMAGENONE; - m_TbButtons[5].iString = (INT_PTR)TranslateT("Message &log"); - m_TbButtons[5].fsState = TBSTATE_ENABLED; - m_TbButtons[5].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[5].idCommand = 105; - m_TbButtons[5].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 2)); - - m_TbButtons[6].iBitmap = I_IMAGENONE; - m_TbButtons[6].iString = (INT_PTR)TranslateT("&Container"); - m_TbButtons[6].fsState = TBSTATE_ENABLED; - m_TbButtons[6].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[6].idCommand = 106; - m_TbButtons[6].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 3)); - - m_TbButtons[7].iBitmap = I_IMAGENONE; - m_TbButtons[7].iString = (INT_PTR)TranslateT("Help"); - m_TbButtons[7].fsState = TBSTATE_ENABLED; - m_TbButtons[7].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; - m_TbButtons[7].idCommand = 107; - m_TbButtons[7].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 4)); - - m_buttonsInit = true; - } - - ::SendMessage(m_hwndToolbar, TB_ADDBUTTONS, SIZEOF(m_TbButtons), (LPARAM)m_TbButtons); - - m_size_y = HIWORD(::SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0)); - - TBADDBITMAP tb; - tb.nID = (UINT_PTR)m_MimIcon; - tb.hInst = 0; - - ::SendMessage(m_hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tb); -} - -void CMenuBar::resetLP() -{ - while ( SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0)); - - m_buttonsInit = false; - checkButtons(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Message hook function, installed by the menu handler to support -// hot-tracking and keyboard navigation for the menu bar while a modal -// popup menu is active. -// -// Hook is only active while a (modal) popup menu is processed. -// -// @params See Win32, message hooks - -LRESULT CALLBACK CMenuBar::MessageHook(int nCode, WPARAM wParam, LPARAM lParam) -{ - MSG *pMsg = reinterpret_cast(lParam); - bool fCancel = false; - POINT pt; - - if (nCode == MSGF_MENU) { - switch(pMsg->message) { - case WM_KEYDOWN: - if (pMsg->wParam == VK_ESCAPE) - fCancel = true; - break; - - case WM_SYSKEYUP: - if (pMsg->wParam == VK_MENU) - fCancel = true; - break; - - case WM_LBUTTONDOWN: - ::GetCursorPos(&pt); - if (::MenuItemFromPoint(0, m_Owner->m_activeMenu, pt) >= 0) // inside menu - break; - if (m_Owner->m_activeSubMenu && ::MenuItemFromPoint(0, m_Owner->m_activeSubMenu, pt) >= 0) - break; - else { // anywhere else, cancel the menu - ::CallNextHookEx(m_hHook, nCode, wParam, lParam); - m_Owner->Cancel(); - return 0; - } - - // allow hottracking by the toolbar control - case WM_MOUSEMOVE: - ::GetCursorPos(&pt); - ::ScreenToClient(m_Owner->m_hwndToolbar, &pt); - LPARAM newPos = MAKELONG(pt.x, pt.y); - ::SendMessage(m_Owner->m_hwndToolbar, pMsg->message, pMsg->wParam, newPos); - break; - } - - // some key event requested to cancel the menu - if (fCancel) { - int iIndex = m_Owner->idToIndex(m_Owner->m_activeID); - if (iIndex != -1) - ::SendMessage(m_Owner->m_hwndToolbar, TB_SETHOTITEM, (WPARAM)iIndex, 0); - ::SetFocus(m_Owner->m_hwndToolbar); - ::SendMessage(m_Owner->m_hwndToolbar, TB_SETSTATE, (WPARAM)m_Owner->m_activeID, TBSTATE_ENABLED | TBSTATE_PRESSED); - m_Owner->cancel(); - m_Owner->m_fTracking = false; - } - } - return ::CallNextHookEx(m_hHook, nCode, wParam, lParam); -} - -// window procedure for the status bar class. - -static int tooltip_active = FALSE; -static POINT ptMouse = {0}; -RECT rcLastStatusBarClick; // remembers click (down event) point for status bar clicks - -LONG_PTR CALLBACK StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TContainerData *pContainer = (TContainerData*)GetWindowLongPtr(GetParent(hWnd), GWLP_USERDATA); - TWindowData *dat = NULL; - POINT pt; - - if (OldStatusBarproc == 0) { - WNDCLASSEX wc = {0}; - wc.cbSize = sizeof(wc); - GetClassInfoEx(g_hInst, STATUSCLASSNAME, &wc); - OldStatusBarproc = wc.lpfnWndProc; - } - - switch (msg) { - case WM_CREATE: - LRESULT ret; - { - CREATESTRUCT *cs = (CREATESTRUCT *)lParam; - HWND hwndParent = GetParent(hWnd); - - // dirty trick to get rid of that annoying sizing gripper - SetWindowLongPtr(hwndParent, GWL_STYLE, GetWindowLongPtr(hwndParent, GWL_STYLE) & ~WS_THICKFRAME); - SetWindowLongPtr(hwndParent, GWL_EXSTYLE, GetWindowLongPtr(hwndParent, GWL_EXSTYLE) & ~WS_EX_APPWINDOW); - cs->style &= ~SBARS_SIZEGRIP; - ret = CallWindowProc(OldStatusBarproc, hWnd, msg, wParam, lParam); - SetWindowLongPtr(hwndParent, GWL_STYLE, GetWindowLongPtr(hwndParent, GWL_STYLE) | WS_THICKFRAME); - SetWindowLongPtr(hwndParent, GWL_EXSTYLE, GetWindowLongPtr(hwndParent, GWL_EXSTYLE) | WS_EX_APPWINDOW); - } - return ret; - - case WM_NCHITTEST: - RECT r; - { - LRESULT lr = SendMessage(GetParent(hWnd), WM_NCHITTEST, wParam, lParam); - int clip = CSkin::m_bClipBorder; - - GetWindowRect(hWnd, &r); - GetCursorPos(&pt); - if (pt.y <= r.bottom && pt.y >= r.bottom - clip - 3) { - if (pt.x > r.right - clip - 4) - return HTBOTTOMRIGHT; - } - if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT - || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) - return HTTRANSPARENT; - } - break; - - case WM_ERASEBKGND: - return 1; - - case WM_PAINT: - PAINTSTRUCT ps; - { - HDC hdc = BeginPaint(hWnd, &ps); - int nParts = SendMessage(hWnd, SB_GETPARTS, 0, 0); - CSkinItem *item = &SkinItems[ID_EXTBKSTATUSBARPANEL]; - - BOOL bAero = M.isAero(); - HANDLE hTheme = bAero ? OpenThemeData(hWnd, L"ButtonStyle") : 0; - - if (pContainer) - dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); - - RECT rcClient; - GetClientRect(hWnd, &rcClient); - - HBITMAP hbm, hbmOld; - HANDLE hbp = 0; - HDC hdcMem; - if (CMimAPI::m_haveBufferedPaint) { - hbp = CMimAPI::m_pfnBeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, NULL, &hdcMem); - hbm = hbmOld = 0; - } - else { - hdcMem = CreateCompatibleDC(hdc); - hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); - hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); - } - - SetBkMode(hdcMem, TRANSPARENT); - - COLORREF clr = CSkin::m_skinEnabled ? CSkin::m_DefaultFontColor : (PluginConfig.m_fillColor ? PluginConfig.m_genericTxtColor : GetSysColor(COLOR_BTNTEXT)); - - HFONT hFontOld = (HFONT)SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT)); - - if (pContainer && CSkin::m_skinEnabled) - CSkin::SkinDrawBG(hWnd, GetParent(hWnd), pContainer, &rcClient, hdcMem); - else if (bAero) { - FillRect(hdcMem, &rcClient, CSkin::m_BrushBack); - CSkin::ApplyAeroEffect(hdcMem, &rcClient, CSkin::AERO_EFFECT_AREA_STATUSBAR); - } - else { - CSkin::FillBack(hdcMem, &rcClient); - RECT rcFrame = rcClient; - if (PluginConfig.m_fillColor == 0) { - InflateRect(&rcFrame, -2, -1); - DrawEdge(hdcMem, &rcClient, BDR_RAISEDINNER | BDR_SUNKENOUTER, BF_RECT); - } - else { - CSkin::m_switchBarItem->setAlphaFormat(AC_SRC_ALPHA, 180); - CSkin::m_switchBarItem->Render(hdcMem, &rcFrame, true); - } - } - - for (int i = 0; i < nParts; i++) { - RECT itemRect; - SendMessage(hWnd, SB_GETRECT, (WPARAM)i, (LPARAM)&itemRect); - if (!item->IGNORED && !bAero && pContainer && CSkin::m_skinEnabled) - CSkin::DrawItem(hdcMem, &itemRect, item); - - if (i == 0) - itemRect.left += 2; - - // draw visual message length indicator in the leftmost status bar field - if (PluginConfig.m_visualMessageSizeIndicator && i == 0) { - if (dat && dat->bType == SESSIONTYPE_IM) { - HBRUSH br = CreateSolidBrush(RGB(0, 255, 0)); - HBRUSH brOld = (HBRUSH)SelectObject(hdcMem, br); - - RECT rc = itemRect; - rc.top = rc.bottom - 3; - rc.left = 0; - - if (!PluginConfig.m_autoSplit) { - float fMax = (float)dat->nMax; - float uPercent = (float)dat->textLen / ((fMax / (float)100.0) ? (fMax / (float)100.0) : (float)75.0); - float fx = ((float)rc.right / (float)100.0) * uPercent; - - rc.right = (LONG)fx; - FillRect(hdcMem, &rc, br); - } - else { - float baselen = (dat->textLen <= dat->nMax) ? (float)dat->textLen : (float)dat->nMax; - float fMax = (float)dat->nMax; - float uPercent = baselen / ((fMax / (float)100.0) ? (fMax / (float)100.0) : (float)75.0); - float fx; - LONG width = rc.right - rc.left; - if (dat->textLen >= dat->nMax) - rc.right = rc.right / 3; - fx = ((float)rc.right / (float)100.0) * uPercent; - rc.right = (LONG)fx; - FillRect(hdcMem, &rc, br); - if (dat->textLen >= dat->nMax) { - SelectObject(hdcMem, brOld); - DeleteObject(br); - br = CreateSolidBrush(RGB(255, 0, 0)); - brOld = (HBRUSH)SelectObject(hdcMem, br); - rc.left = width / 3; - rc.right = width; - uPercent = (float)dat->textLen / (float)200.0; - fx = ((float)(rc.right - rc.left) / (float)100.0) * uPercent; - rc.right = rc.left + (LONG)fx; - FillRect(hdcMem, &rc, br); - } - } - SelectObject(hdcMem, brOld); - DeleteObject(br); - } - } - - int height = itemRect.bottom - itemRect.top; - HICON hIcon = (HICON)SendMessage(hWnd, SB_GETICON, i, 0); - - TCHAR szText[1024]; szText[0] = 0; - LRESULT result = SendMessage(hWnd, SB_GETTEXT, i, (LPARAM)szText); - if (i == 2 && pContainer) { - TWindowData *dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); - if (dat) - DrawStatusIcons(dat, hdcMem, itemRect, 2); - } - else { - if (hIcon) { - if (LOWORD(result) > 1) { // we have a text - DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, hIcon, 16, 16, 0, 0, DI_NORMAL); - if (dat) { - if (dat->bShowTyping == 2) - DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, PluginConfig.g_iconOverlayEnabled, 16, 16, 0, 0, DI_NORMAL); - } - itemRect.left += 20; - CSkin::RenderText(hdcMem, hTheme, szText, &itemRect, DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX, - CSkin::m_glowSize, clr); - } - else DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, hIcon, 16, 16, 0, 0, DI_NORMAL); - } - else { - itemRect.left += 2; - itemRect.right -= 2; - CSkin::RenderText(hdcMem, hTheme, szText, &itemRect, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, CSkin::m_glowSize, clr); - } - } - } - - if (hbp) - CSkin::FinalizeBufferedPaint(hbp, &rcClient); - else { - BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, SRCCOPY); - SelectObject(hdcMem, hbmOld); - DeleteObject(hbm); - SelectObject(hdcMem, hFontOld); - DeleteDC(hdcMem); - } - - if (hTheme) - CloseThemeData(hTheme); - - EndPaint(hWnd, &ps); - } - return 0; - - // tell status bar to update the part layout (re-calculate part widths) - // needed when an icon is added to or removed from the icon area - case WM_USER + 101: - { - int list_icons = 0; - dat = (TWindowData*)lParam; - if (dat) - while ( Srmm_GetNthIcon(dat->hContact, list_icons)) - list_icons++; - - SendMessage(hWnd, WM_SIZE, 0, 0); - - RECT rcs; - GetWindowRect(hWnd, &rcs); - - int statwidths[5]; - statwidths[0] = (rcs.right - rcs.left) - (2 * SB_CHAR_WIDTH + 20) - (list_icons * (PluginConfig.m_smcxicon + 2)); - statwidths[1] = (rcs.right - rcs.left) - (10 + (list_icons * (PluginConfig.m_smcxicon + 2))); - statwidths[2] = -1; - SendMessage(hWnd, SB_SETPARTS, 3, (LPARAM)statwidths); - } - return 0; - - case WM_SETCURSOR: - GetCursorPos(&pt); - SendMessage(GetParent(hWnd), msg, wParam, lParam); - if (pt.x == ptMouse.x && pt.y == ptMouse.y) - return 1; - - ptMouse = pt; - if (tooltip_active) { - KillTimer(hWnd, TIMERID_HOVER); - CallService("mToolTip/HideTip", 0, 0); - tooltip_active = FALSE; - } - KillTimer(hWnd, TIMERID_HOVER); - SetTimer(hWnd, TIMERID_HOVER, 450, 0); - break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - KillTimer(hWnd, TIMERID_HOVER); - CallService("mToolTip/HideTip", 0, 0); - tooltip_active = FALSE; - GetCursorPos(&pt); - rcLastStatusBarClick.left = pt.x - 2; - rcLastStatusBarClick.right = pt.x + 2; - rcLastStatusBarClick.top = pt.y - 2; - rcLastStatusBarClick.bottom = pt.y + 2; - - if (pContainer->dwFlags & CNT_NOTITLE) { - POINT pt1 = pt; - ScreenToClient(hWnd, &pt1); - - RECT rcIconpart; - SendMessage(hWnd, SB_GETRECT, 2, (LPARAM)&rcIconpart); - if (!PtInRect(&rcIconpart, pt1)) - return SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); - } - break; - - case WM_TIMER: - if (wParam != TIMERID_HOVER) - break; - KillTimer(hWnd, TIMERID_HOVER); - GetCursorPos(&pt); - if (pt.x != ptMouse.x || pt.y != ptMouse.y) - break; - dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); - if (dat != NULL) { - RECT rc; - SIZE size; - TCHAR wBuf[512]; wBuf[0] = 0; - CLCINFOTIP ti = {0}; - ti.cbSize = sizeof(ti); - ti.ptCursor = pt; - ScreenToClient(hWnd, &pt); - SendMessage(hWnd, SB_GETRECT, 2, (LPARAM)&rc); - if ( PtInRect(&rc, pt)) { - unsigned int iconNum = (pt.x - rc.left) / (PluginConfig.m_smcxicon + 2); - StatusIconData *sid = Srmm_GetNthIcon(dat->hContact, iconNum); - if (sid == NULL) - break; - - if ( !strcmp(sid->szModule, MSG_ICON_MODULE)) { - if (sid->dwId == MSG_ICON_SOUND && pContainer) - mir_sntprintf(wBuf, SIZEOF(wBuf), TranslateT("Sounds are %s. Click to toggle status, hold SHIFT and click to set for all open containers"), - pContainer->dwFlags & CNT_NOSOUND ? TranslateT("disabled") : TranslateT("enabled")); - - else if (sid->dwId == MSG_ICON_UTN && dat && (dat->bType == SESSIONTYPE_IM || dat->si->iType == GCW_PRIVMESS)) { - int mtnStatus = db_get_b(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, M.GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); - mir_sntprintf(wBuf, SIZEOF(wBuf), TranslateT("Sending typing notifications is %s."), - mtnStatus ? TranslateT("enabled") : TranslateT("disabled")); - } - else if (sid->dwId == MSG_ICON_SESSION) - _tcsncpy_s(wBuf, TranslateT("Session list.\nClick left for a list of open sessions.\nClick right to access favorites and quickly configure message window behavior"), _TRUNCATE); - } - else if (sid->tszTooltip) - _tcsncpy(wBuf, sid->tszTooltip, SIZEOF(wBuf)); - - if (wBuf[0]) { - CallService("mToolTip/ShowTipW", (WPARAM)wBuf, (LPARAM)&ti); - tooltip_active = TRUE; - } - } - SendMessage(hWnd, SB_GETRECT, 1, (LPARAM)&rc); - if (PtInRect(&rc, pt)) { - int iLength = 0; - GETTEXTLENGTHEX gtxl = {0}; - int iQueued = db_get_dw(dat->hContact, "SendLater", "count", 0); - gtxl.codepage = CP_UTF8; - gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; - iLength = SendDlgItemMessage(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_MESSAGE : IDC_CHAT_MESSAGE, EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); - tooltip_active = TRUE; - - const TCHAR *szFormat = TranslateT("There are %d pending send jobs. Message length: %d bytes, message length limit: %d bytes\n\n%d messages are queued for later delivery"); - - mir_sntprintf(wBuf, SIZEOF(wBuf), szFormat, dat->iOpenJobs, iLength, dat->nMax ? dat->nMax : 20000, iQueued); - CallService("mToolTip/ShowTipW", (WPARAM)wBuf, (LPARAM)&ti); - } - - if (SendMessage(dat->pContainer->hwndStatus, SB_GETTEXT, 0, (LPARAM)wBuf)) { - HDC hdc; - int iLen=SendMessage(dat->pContainer->hwndStatus,SB_GETTEXTLENGTH,0,0); - SendMessage(hWnd, SB_GETRECT, 0, (LPARAM)&rc); - GetTextExtentPoint32( hdc=GetDC( dat->pContainer->hwndStatus), wBuf, iLen, &size ); - ReleaseDC (dat->pContainer->hwndStatus,hdc); - - if (PtInRect(&rc,pt)&&((rc.right-rc.left)bType == SESSIONTYPE_CHAT) - db_get_ts(dat->hContact,dat->szProto,"Topic",&dbv); - - tooltip_active = TRUE; - CallService("mToolTip/ShowTipW", (WPARAM)dbv.ptszVal, (LPARAM)&ti); - if (dbv.pszVal) - db_free(&dbv); - } - } - } - break; - - case WM_DESTROY: - KillTimer(hWnd, TIMERID_HOVER); - } - return CallWindowProc(OldStatusBarproc, hWnd, msg, wParam, lParam); -} + + ((CMenuBar*)obj)->resetLP(); + return 0; +} + +CMenuBar::CMenuBar(HWND hwndParent, const TContainerData *pContainer) +{ + m_pContainer = const_cast(pContainer); + + if (m_MimIcon == 0) { + HDC hdc = ::GetDC(m_pContainer->hwnd); + HANDLE hIcon = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA); + + HDC hdcTemp = ::CreateCompatibleDC(hdc); + + RECT rc = {0,0,16,16}; + m_MimIcon = CSkin::CreateAeroCompatibleBitmap(rc, hdcTemp); + HBITMAP hbmOld = reinterpret_cast(::SelectObject(hdcTemp, m_MimIcon)); + ::DrawIconEx(hdcTemp, 0, 0, (HICON)hIcon, 16, 16, 0, 0, DI_NORMAL); + ::SelectObject(hdcTemp, hbmOld); + + ::DeleteDC(hdcTemp); + ::ReleaseDC(m_pContainer->hwnd, hdc); + } + + m_MimIconRefCount++; + + m_hwndToolbar = ::CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL, WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_VISIBLE|TBSTYLE_FLAT|TBSTYLE_TRANSPARENT|TBSTYLE_LIST|/*CCS_NOPARENTALIGN|*/CCS_NODIVIDER|CCS_TOP, + 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL); + + ::SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + + checkButtons(); + + m_activeMenu = 0; + m_activeID = 0; + m_isAero = M.isAero(); + m_mustAutoHide = false; + m_activeSubMenu = 0; + m_fTracking = false; + m_isContactMenu = m_isMainMenu = false; + HookEventParam(ME_LANGPACK_CHANGED, &::resetLP, (LPARAM)this); + + ::SetWindowLongPtr(m_hwndToolbar, GWLP_USERDATA, (LONG_PTR)this); + mir_subclassWindow(m_hwndToolbar, wndProc); +} + +CMenuBar::~CMenuBar() +{ + ::SetWindowLongPtr(m_hwndToolbar, GWLP_USERDATA, 0); + ::DestroyWindow(m_hwndToolbar); + releaseHook(); + m_MimIconRefCount--; + if (m_MimIconRefCount == 0) { + ::DeleteObject(m_MimIcon); + m_MimIcon = 0; + } +} + +/** + * retrieves the client rectangle for the rebar control. This must be + * called once per WM_SIZE event by the parent window. getHeight() depends on it. + * + * @return RECT&: client rectangle of the rebar control + */ +const RECT& CMenuBar::getClientRect() +{ + ::GetClientRect(m_hwndToolbar, &m_rcClient); + return(m_rcClient); +} + +void CMenuBar::obtainHook() +{ + releaseHook(); + if (m_hHook == 0) + m_hHook = ::SetWindowsHookEx(WH_MSGFILTER, CMenuBar::MessageHook, 0, GetCurrentThreadId()); + m_Owner = this; +} + +void CMenuBar::releaseHook() +{ + if (m_hHook) { + ::UnhookWindowsHookEx(m_hHook); + m_hHook = 0; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Retrieve the height of the rebar control +// +// @return LONG: height of the rebar, in pixels + +LONG CMenuBar::getHeight() const +{ + return((m_pContainer->dwFlags & CNT_NOMENUBAR) ? 0 : m_size_y); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// process all relevant messages. Must be called by the parent window's +// window procedure. +// +// @param msg +// @param wParam +// @param lParam +// +// @return LRESULT: message processing result. Win32 conform. +// -1 means: nothing processed, caller should continue as usual. + +LONG_PTR CMenuBar::processMsg(const UINT msg, const WPARAM, const LPARAM lParam) +{ + if (msg == WM_NOTIFY) { + NMHDR *pNMHDR = (NMHDR*)lParam; + switch(pNMHDR->code) { + case NM_CUSTOMDRAW: + { + NMCUSTOMDRAW *nm = (NMCUSTOMDRAW*)lParam; + return customDrawWorker(nm); + } + + case TBN_DROPDOWN: + { + NMTOOLBAR *mtb = (NMTOOLBAR *)lParam; + return Handle(mtb); + } + case TBN_HOTITEMCHANGE: + { + NMTBHOTITEM *nmtb = (NMTBHOTITEM *)lParam; + if (nmtb->idNew != 0 && m_fTracking && nmtb->idNew != m_activeID && m_activeID != 0) { + cancel(); + return 0; + } + else if (m_fTracking == true && m_activeID == 0 && nmtb->idNew != 0) { + invoke(nmtb->idNew); + return 0; + } + break; + } + + default: + return -1; + } + } + else if (msg == WM_LBUTTONDOWN) { + if (m_pContainer->dwFlags & CNT_NOTITLE) { + POINT pt; + ::GetCursorPos(&pt); + return ::SendMessage(m_pContainer->hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + } + return -1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclass the toolbar control to handle some keyboard events and improve +// keyboard navigation + +LRESULT CALLBACK CMenuBar::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CMenuBar *menuBar = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); + + switch(msg) { + case WM_SYSKEYUP: + if (wParam == VK_MENU) { + menuBar->Cancel(); + return 0; + } + break; + } + return ::mir_callNextSubclass(hWnd, CMenuBar::wndProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Implements NM_CUSTOMDRAW for the toolbar +// +// @param nm NMCUSTOMDRAW *: sent via NM_CUSTOMDRAW message +// +// @return LONG_PTR: see Win32 NM_CUSTOMDRAW message. The function must return a valid +// message return value to indicate how Windows should continue with the drawing process. +// +// It may return zero in which case, the caller should allow default processing for +// the NM_CUSTOMDRAW message. + +LONG_PTR CMenuBar::customDrawWorker(NMCUSTOMDRAW *nm) +{ + bool fMustDraw = true; + + if (nm->hdr.hwndFrom == m_hwndToolbar) { + NMTBCUSTOMDRAW *nmtb = (NMTBCUSTOMDRAW *)(nm); + + switch(nmtb->nmcd.dwDrawStage) { + case CDDS_PREPAINT: + if (fMustDraw) { + if (nmtb->nmcd.dwItemSpec == 0) { + m_hdcDraw = ::CreateCompatibleDC(nmtb->nmcd.hdc); + //m_rcItem = nmtb->nmcd.rc; + ::GetClientRect(m_hwndToolbar, &m_rcItem); + m_rcItem.bottom -= 4; + m_hbmDraw = CSkin::CreateAeroCompatibleBitmap(m_rcItem, nmtb->nmcd.hdc); + m_hbmOld = reinterpret_cast(::SelectObject(m_hdcDraw, m_hbmDraw)); + m_hTheme = M.isAero() || M.isVSThemed() ? OpenThemeData(m_hwndToolbar, L"REBAR") : 0; + m_hOldFont = reinterpret_cast(::SelectObject(m_hdcDraw, reinterpret_cast(::GetStockObject(DEFAULT_GUI_FONT)))); + if (m_isAero) { + nm->rc.bottom--; + CSkin::ApplyAeroEffect(m_hdcDraw, &m_rcItem, CSkin::AERO_EFFECT_AREA_MENUBAR); + nm->rc.bottom++; + } + else if ((PluginConfig.m_fillColor || M.isVSThemed()) && !CSkin::m_skinEnabled) { + if (PluginConfig.m_fillColor && PluginConfig.m_tbBackgroundHigh && PluginConfig.m_tbBackgroundLow) { + ::DrawAlpha(m_hdcDraw, &m_rcItem, PluginConfig.m_tbBackgroundHigh, 100, PluginConfig.m_tbBackgroundLow, 0, + GRADIENT_TB, 0, 0, 0); + } + else { + m_rcItem.bottom--; + if (PluginConfig.m_fillColor) + CSkin::FillBack(m_hdcDraw, &m_rcItem); + else if (M.isVSThemed()) + DrawThemeBackground(m_hTheme, m_hdcDraw, 6, 1, &m_rcItem, &m_rcItem); + else + FillRect(m_hdcDraw, &m_rcItem, GetSysColorBrush(COLOR_3DFACE)); + } + } + else if (CSkin::m_MenuBGBrush) + ::FillRect(m_hdcDraw, &nm->rc, CSkin::m_MenuBGBrush); + else + ::FillRect(m_hdcDraw, &nm->rc, GetSysColorBrush(COLOR_3DFACE)); + } + return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYPOSTERASE; + } + + m_hdcDraw = 0; + return CDRF_DODEFAULT; + + case CDDS_ITEMPREPAINT: + if (fMustDraw) { + TCHAR *szText = 0; + bool fDraw = true; + + int iIndex = idToIndex(nmtb->nmcd.dwItemSpec); + if (iIndex >= 0 && iIndex < NR_BUTTONS) + szText = (TCHAR*)m_TbButtons[iIndex].iString; + + UINT uState = nmtb->nmcd.uItemState; + + nmtb->nmcd.rc.bottom--; + if (CSkin::m_skinEnabled) { + CSkinItem *item = 0; + + ::FillRect(m_hdcDraw, &nmtb->nmcd.rc, CSkin::m_MenuBGBrush); + + if (uState & CDIS_MARKED || uState & CDIS_CHECKED || uState & CDIS_SELECTED) + item = &SkinItems[ID_EXTBKBUTTONSPRESSED]; + else if (uState & CDIS_HOT) + item = &SkinItems[ID_EXTBKBUTTONSMOUSEOVER]; + + if (item) + fDraw = !CSkin::DrawItem(m_hdcDraw, &nmtb->nmcd.rc, item); + else + fDraw = false; + } + if (fDraw) { + COLORREF clr = ::GetSysColor(COLOR_HOTLIGHT); + COLORREF clrRev = clr; + if (uState & CDIS_MARKED || uState & CDIS_CHECKED) + ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); + + if (uState & CDIS_SELECTED) + ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); + + if (uState & CDIS_HOT) + ::DrawAlpha(m_hdcDraw, &nmtb->nmcd.rc, clrRev, 80, clrRev, 0, 9, 31, 4, 0); + } + + if (szText) { + COLORREF clr = CSkin::m_skinEnabled ? CSkin::m_DefaultFontColor : + (PluginConfig.m_fillColor ? PluginConfig.m_genericTxtColor : + (uState & (CDIS_SELECTED | CDIS_HOT | CDIS_MARKED)) ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) : ::GetSysColor(COLOR_BTNTEXT)); + + ::SetBkMode(m_hdcDraw, TRANSPARENT); + CSkin::RenderText(m_hdcDraw, m_hTheme, szText, &nmtb->nmcd.rc, DT_SINGLELINE | DT_VCENTER | DT_CENTER, CSkin::m_glowSize, clr); + } + if (iIndex == 0) + ::DrawIconEx(m_hdcDraw, (nmtb->nmcd.rc.left + nmtb->nmcd.rc.right) / 2 - 8, + (nmtb->nmcd.rc.top + nmtb->nmcd.rc.bottom) / 2 - 8, LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), + 16, 16, 0, 0, DI_NORMAL); + + return CDRF_SKIPDEFAULT; + } + else return CDRF_DODEFAULT; + + case CDDS_PREERASE: + case CDDS_ITEMPOSTERASE: + case CDDS_ITEMPOSTPAINT: + case CDDS_ITEMPREERASE: + return fMustDraw ? CDRF_SKIPDEFAULT : CDRF_DODEFAULT; + + case CDDS_POSTERASE: + return fMustDraw ? CDRF_SKIPDEFAULT : CDRF_DODEFAULT; + + case CDDS_POSTPAINT: + if (nmtb->nmcd.dwItemSpec == 0 && m_hdcDraw) { + ::BitBlt(nmtb->nmcd.hdc, 0, 0, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, + m_hdcDraw, 0, 0, SRCCOPY); + ::SelectObject(m_hdcDraw, m_hbmOld); + ::DeleteObject(m_hbmDraw); + ::SelectObject(m_hdcDraw, m_hOldFont); + ::DeleteDC(m_hdcDraw); + m_hdcDraw = 0; + if (m_hTheme) + CloseThemeData(m_hTheme); + return CDRF_SKIPDEFAULT; + } + return CDRF_DODEFAULT; + + default: + return CDRF_DODEFAULT; + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Handle the TBN_DROPDOWN notification message sent by the +// toolbar control. +// +// @param nmtb NMTOOLBAR *: notification message structure +// +// @return LONG_PTR: must be a valid return value. See Win32 API, TBN_DROPDOWN + +LONG_PTR CMenuBar::Handle(const NMTOOLBAR *nmtb) +{ + if (nmtb->hdr.hwndFrom != m_hwndToolbar) + return TBDDRET_NODEFAULT; + + invoke(nmtb->iItem); + return TBDDRET_DEFAULT; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Invoke the dropdown menu for the button with the given control id. +// +// @param id int: the control id of the toolbar button which has been activated + +void CMenuBar::invoke(const int id) +{ + const int index = idToIndex(id); + if (index == -1) + return; + + HMENU hMenu; + + m_isContactMenu = m_isMainMenu = false; + + TWindowData *dat = (TWindowData*)GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); + + MCONTACT hContact = dat ? dat->hContact : 0; + + if (index == 3 && hContact != 0) { + hMenu = reinterpret_cast(::CallService(MS_CLIST_MENUBUILDCONTACT, hContact, 0)); + m_isContactMenu = true; + } else if (index == 0) { + hMenu = reinterpret_cast(::CallService(MS_CLIST_MENUBUILDMAIN, 0, 0)); + m_isMainMenu = true; + } else + hMenu = reinterpret_cast(m_TbButtons[index].dwData); + + RECT rcButton; + POINT pt; + ::SendMessage(m_hwndToolbar, TB_GETITEMRECT, (WPARAM)index, (LPARAM)&rcButton); + pt.x = rcButton.left; + pt.y = rcButton.bottom; + ::ClientToScreen(m_hwndToolbar, &pt); + + if (m_activeID) + cancel(); + + m_activeMenu = hMenu; + m_activeSubMenu = 0; + m_activeID = id; + updateState(hMenu); + obtainHook(); + m_fTracking = true; + ::SendMessage(m_hwndToolbar, TB_SETSTATE, (WPARAM)id, TBSTATE_CHECKED | TBSTATE_ENABLED); + ::TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, m_pContainer->hwnd, 0); +} + +void CMenuBar::cancel() +{ + releaseHook(); + if (m_activeID) + ::SendMessage(m_hwndToolbar, TB_SETSTATE, (WPARAM)m_activeID, TBSTATE_ENABLED); + m_activeID = 0; + m_activeMenu = 0; + m_isContactMenu = m_isMainMenu = false; + ::EndMenu(); +} + +void CMenuBar::Cancel(void) +{ + cancel(); + m_fTracking = false; + autoShow(0); +} + +void CMenuBar::updateState(const HMENU hMenu) const +{ + TWindowData *dat = (TWindowData*)GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); + if (dat) { + ::CheckMenuItem(hMenu, ID_VIEW_SHOWMENUBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOMENUBAR ? MF_UNCHECKED : MF_CHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_SHOWSTATUSBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOSTATUSBAR ? MF_UNCHECKED : MF_CHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_SHOWAVATAR, MF_BYCOMMAND | (dat->bShowAvatar ? MF_CHECKED : MF_UNCHECKED)); + ::CheckMenuItem(hMenu, ID_VIEW_SHOWTITLEBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOTITLE ? MF_UNCHECKED : MF_CHECKED); + + ::EnableMenuItem(hMenu, ID_VIEW_SHOWTITLEBAR, CSkin::m_skinEnabled && CSkin::m_frameSkins ? MF_GRAYED : MF_ENABLED); + + ::CheckMenuItem(hMenu, ID_VIEW_TABSATBOTTOM, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_TABSBOTTOM ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_VERTICALMAXIMIZE, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_VERTICALMAX ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_SHOWTOOLBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_HIDETOOLBAR ? MF_UNCHECKED : MF_CHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_BOTTOMTOOLBAR, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? MF_CHECKED : MF_UNCHECKED); + + ::CheckMenuItem(hMenu, ID_VIEW_SHOWMULTISENDCONTACTLIST, MF_BYCOMMAND | (dat->sendMode & SMODE_MULTIPLE) ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_VIEW_STAYONTOP, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_STICKY ? MF_CHECKED : MF_UNCHECKED); + + ::EnableMenuItem(hMenu, 2, MF_BYPOSITION | (nen_options.bWindowCheck ? MF_GRAYED : MF_ENABLED)); + ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_DISABLEALLEVENTPOPUPS, MF_BYCOMMAND | m_pContainer->dwFlags & (CNT_DONTREPORT | CNT_DONTREPORTUNFOCUSED | CNT_DONTREPORTFOCUSED | CNT_ALWAYSREPORTINACTIVE) ? MF_UNCHECKED : MF_CHECKED); + ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISMINIMIZED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORT ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSFORALLINACTIVESESSIONS, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISUNFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_DONTREPORTFOCUSED ? MF_CHECKED : MF_UNCHECKED); + + ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_USEDEFAULTVALUES, MF_BYCOMMAND | (m_pContainer->dwFlags & (CNT_NOFLASH | CNT_FLASHALWAYS)) ? MF_UNCHECKED : MF_CHECKED); + ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_DISABLEFLASHING, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_NOFLASH ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, ID_WINDOWFLASHING_FLASHUNTILFOCUSED, MF_BYCOMMAND | m_pContainer->dwFlags & CNT_FLASHALWAYS ? MF_CHECKED : MF_UNCHECKED); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// this updates the container menu bar and other window elements depending on the current +// child session (IM, chat etc.). It fully supports IEView and will disable/enable the +// message log menus depending on the configuration of IEView (e.g. when template mode +// is on, the message log settin menus have no functionality, thus can be disabled to +// improve ui feedback quality). + +void CMenuBar::configureMenu() const +{ + BOOL fDisable = FALSE; + + TWindowData *dat = (TWindowData*)::GetWindowLongPtr(m_pContainer->hwndActive, GWLP_USERDATA); + if (dat) { + bool fChat = (dat->bType == SESSIONTYPE_CHAT); + + ::SendMessage(m_hwndToolbar, TB_SETSTATE, 103, fChat ? TBSTATE_HIDDEN : TBSTATE_ENABLED); + ::SendMessage(m_hwndToolbar, TB_SETSTATE, 104, fChat ? TBSTATE_ENABLED : TBSTATE_HIDDEN); + ::SendMessage(m_hwndToolbar, TB_SETSTATE, 105, fChat ? TBSTATE_HIDDEN : TBSTATE_ENABLED); + + if (dat->bType == SESSIONTYPE_IM) + ::EnableWindow(GetDlgItem(dat->hwnd, IDC_TIME), fDisable ? FALSE : TRUE); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Automatically shows or hides the menu bar. Depends on the current state, +// used when the ALT key is hit in the message window. + +void CMenuBar::autoShow(const int showcmd) +{ + if (m_mustAutoHide && !(m_pContainer->dwFlags & CNT_NOMENUBAR)) { + m_pContainer->dwFlags |= CNT_NOMENUBAR; + m_mustAutoHide = false; + ::SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); + releaseHook(); + } + + if (showcmd == 0) { + ::SetFocus(m_pContainer->hwndActive); + return; + } + + if (m_pContainer->dwFlags & CNT_NOMENUBAR) { + m_mustAutoHide = true; + m_pContainer->dwFlags &= ~CNT_NOMENUBAR; + ::SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); + } + else // do nothing, already visible + m_mustAutoHide = false; + + ::SetFocus(m_hwndToolbar); +} + +void CMenuBar::checkButtons() +{ + if (!m_buttonsInit) { + memset(m_TbButtons, 0, sizeof(m_TbButtons)); + + m_TbButtons[0].iBitmap = 0; + m_TbButtons[0].iString = 0; + m_TbButtons[0].fsState = TBSTATE_ENABLED; + m_TbButtons[0].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[0].idCommand = 100; + m_TbButtons[0].dwData = 0; + + m_TbButtons[1].iBitmap = I_IMAGENONE; + m_TbButtons[1].iString = (INT_PTR)TranslateT("&File"); + m_TbButtons[1].fsState = TBSTATE_ENABLED; + m_TbButtons[1].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[1].idCommand = 101; + m_TbButtons[1].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 0)); + + m_TbButtons[2].iBitmap = I_IMAGENONE; + m_TbButtons[2].iString = (INT_PTR)TranslateT("&View"); + m_TbButtons[2].fsState = TBSTATE_ENABLED; + m_TbButtons[2].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[2].idCommand = 102; + m_TbButtons[2].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 1)); + + m_TbButtons[3].iBitmap = I_IMAGENONE; + m_TbButtons[3].iString = (INT_PTR)TranslateT("&User"); + m_TbButtons[3].fsState = TBSTATE_ENABLED; + m_TbButtons[3].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[3].idCommand = 103; + m_TbButtons[3].dwData = 0; // dynamically built by Clist service + + m_TbButtons[4].iBitmap = I_IMAGENONE; + m_TbButtons[4].iString = (INT_PTR)TranslateT("&Room"); + m_TbButtons[4].fsState = TBSTATE_ENABLED; + m_TbButtons[4].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[4].idCommand = 104; + m_TbButtons[4].dwData = 0; + + m_TbButtons[5].iBitmap = I_IMAGENONE; + m_TbButtons[5].iString = (INT_PTR)TranslateT("Message &log"); + m_TbButtons[5].fsState = TBSTATE_ENABLED; + m_TbButtons[5].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[5].idCommand = 105; + m_TbButtons[5].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 2)); + + m_TbButtons[6].iBitmap = I_IMAGENONE; + m_TbButtons[6].iString = (INT_PTR)TranslateT("&Container"); + m_TbButtons[6].fsState = TBSTATE_ENABLED; + m_TbButtons[6].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[6].idCommand = 106; + m_TbButtons[6].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 3)); + + m_TbButtons[7].iBitmap = I_IMAGENONE; + m_TbButtons[7].iString = (INT_PTR)TranslateT("Help"); + m_TbButtons[7].fsState = TBSTATE_ENABLED; + m_TbButtons[7].fsStyle = BTNS_DROPDOWN|BTNS_AUTOSIZE; + m_TbButtons[7].idCommand = 107; + m_TbButtons[7].dwData = reinterpret_cast(::GetSubMenu(PluginConfig.getMenuBar(), 4)); + + m_buttonsInit = true; + } + + ::SendMessage(m_hwndToolbar, TB_ADDBUTTONS, SIZEOF(m_TbButtons), (LPARAM)m_TbButtons); + + m_size_y = HIWORD(::SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0)); + + TBADDBITMAP tb; + tb.nID = (UINT_PTR)m_MimIcon; + tb.hInst = 0; + + ::SendMessage(m_hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tb); +} + +void CMenuBar::resetLP() +{ + while ( SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0)); + + m_buttonsInit = false; + checkButtons(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Message hook function, installed by the menu handler to support +// hot-tracking and keyboard navigation for the menu bar while a modal +// popup menu is active. +// +// Hook is only active while a (modal) popup menu is processed. +// +// @params See Win32, message hooks + +LRESULT CALLBACK CMenuBar::MessageHook(int nCode, WPARAM wParam, LPARAM lParam) +{ + MSG *pMsg = reinterpret_cast(lParam); + bool fCancel = false; + POINT pt; + + if (nCode == MSGF_MENU) { + switch(pMsg->message) { + case WM_KEYDOWN: + if (pMsg->wParam == VK_ESCAPE) + fCancel = true; + break; + + case WM_SYSKEYUP: + if (pMsg->wParam == VK_MENU) + fCancel = true; + break; + + case WM_LBUTTONDOWN: + ::GetCursorPos(&pt); + if (::MenuItemFromPoint(0, m_Owner->m_activeMenu, pt) >= 0) // inside menu + break; + if (m_Owner->m_activeSubMenu && ::MenuItemFromPoint(0, m_Owner->m_activeSubMenu, pt) >= 0) + break; + else { // anywhere else, cancel the menu + ::CallNextHookEx(m_hHook, nCode, wParam, lParam); + m_Owner->Cancel(); + return 0; + } + + // allow hottracking by the toolbar control + case WM_MOUSEMOVE: + ::GetCursorPos(&pt); + ::ScreenToClient(m_Owner->m_hwndToolbar, &pt); + LPARAM newPos = MAKELONG(pt.x, pt.y); + ::SendMessage(m_Owner->m_hwndToolbar, pMsg->message, pMsg->wParam, newPos); + break; + } + + // some key event requested to cancel the menu + if (fCancel) { + int iIndex = m_Owner->idToIndex(m_Owner->m_activeID); + if (iIndex != -1) + ::SendMessage(m_Owner->m_hwndToolbar, TB_SETHOTITEM, (WPARAM)iIndex, 0); + ::SetFocus(m_Owner->m_hwndToolbar); + ::SendMessage(m_Owner->m_hwndToolbar, TB_SETSTATE, (WPARAM)m_Owner->m_activeID, TBSTATE_ENABLED | TBSTATE_PRESSED); + m_Owner->cancel(); + m_Owner->m_fTracking = false; + } + } + return ::CallNextHookEx(m_hHook, nCode, wParam, lParam); +} + +// window procedure for the status bar class. + +static int tooltip_active = FALSE; +static POINT ptMouse = {0}; +RECT rcLastStatusBarClick; // remembers click (down event) point for status bar clicks + +LONG_PTR CALLBACK StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TContainerData *pContainer = (TContainerData*)GetWindowLongPtr(GetParent(hWnd), GWLP_USERDATA); + TWindowData *dat = NULL; + POINT pt; + + if (OldStatusBarproc == 0) { + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + GetClassInfoEx(g_hInst, STATUSCLASSNAME, &wc); + OldStatusBarproc = wc.lpfnWndProc; + } + + switch (msg) { + case WM_CREATE: + LRESULT ret; + { + CREATESTRUCT *cs = (CREATESTRUCT *)lParam; + HWND hwndParent = GetParent(hWnd); + + // dirty trick to get rid of that annoying sizing gripper + SetWindowLongPtr(hwndParent, GWL_STYLE, GetWindowLongPtr(hwndParent, GWL_STYLE) & ~WS_THICKFRAME); + SetWindowLongPtr(hwndParent, GWL_EXSTYLE, GetWindowLongPtr(hwndParent, GWL_EXSTYLE) & ~WS_EX_APPWINDOW); + cs->style &= ~SBARS_SIZEGRIP; + ret = CallWindowProc(OldStatusBarproc, hWnd, msg, wParam, lParam); + SetWindowLongPtr(hwndParent, GWL_STYLE, GetWindowLongPtr(hwndParent, GWL_STYLE) | WS_THICKFRAME); + SetWindowLongPtr(hwndParent, GWL_EXSTYLE, GetWindowLongPtr(hwndParent, GWL_EXSTYLE) | WS_EX_APPWINDOW); + } + return ret; + + case WM_NCHITTEST: + RECT r; + { + LRESULT lr = SendMessage(GetParent(hWnd), WM_NCHITTEST, wParam, lParam); + int clip = CSkin::m_bClipBorder; + + GetWindowRect(hWnd, &r); + GetCursorPos(&pt); + if (pt.y <= r.bottom && pt.y >= r.bottom - clip - 3) { + if (pt.x > r.right - clip - 4) + return HTBOTTOMRIGHT; + } + if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT + || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) + return HTTRANSPARENT; + } + break; + + case WM_ERASEBKGND: + return 1; + + case WM_PAINT: + PAINTSTRUCT ps; + { + HDC hdc = BeginPaint(hWnd, &ps); + int nParts = SendMessage(hWnd, SB_GETPARTS, 0, 0); + CSkinItem *item = &SkinItems[ID_EXTBKSTATUSBARPANEL]; + + BOOL bAero = M.isAero(); + HANDLE hTheme = bAero ? OpenThemeData(hWnd, L"ButtonStyle") : 0; + + if (pContainer) + dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); + + RECT rcClient; + GetClientRect(hWnd, &rcClient); + + HBITMAP hbm, hbmOld; + HANDLE hbp = 0; + HDC hdcMem; + if (CMimAPI::m_haveBufferedPaint) { + hbp = CMimAPI::m_pfnBeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, NULL, &hdcMem); + hbm = hbmOld = 0; + } + else { + hdcMem = CreateCompatibleDC(hdc); + hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); + hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); + } + + SetBkMode(hdcMem, TRANSPARENT); + + COLORREF clr = CSkin::m_skinEnabled ? CSkin::m_DefaultFontColor : (PluginConfig.m_fillColor ? PluginConfig.m_genericTxtColor : GetSysColor(COLOR_BTNTEXT)); + + HFONT hFontOld = (HFONT)SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT)); + + if (pContainer && CSkin::m_skinEnabled) + CSkin::SkinDrawBG(hWnd, GetParent(hWnd), pContainer, &rcClient, hdcMem); + else if (bAero) { + FillRect(hdcMem, &rcClient, CSkin::m_BrushBack); + CSkin::ApplyAeroEffect(hdcMem, &rcClient, CSkin::AERO_EFFECT_AREA_STATUSBAR); + } + else { + CSkin::FillBack(hdcMem, &rcClient); + RECT rcFrame = rcClient; + if (PluginConfig.m_fillColor == 0) { + InflateRect(&rcFrame, -2, -1); + DrawEdge(hdcMem, &rcClient, BDR_RAISEDINNER | BDR_SUNKENOUTER, BF_RECT); + } + else { + CSkin::m_switchBarItem->setAlphaFormat(AC_SRC_ALPHA, 180); + CSkin::m_switchBarItem->Render(hdcMem, &rcFrame, true); + } + } + + for (int i = 0; i < nParts; i++) { + RECT itemRect; + SendMessage(hWnd, SB_GETRECT, (WPARAM)i, (LPARAM)&itemRect); + if (!item->IGNORED && !bAero && pContainer && CSkin::m_skinEnabled) + CSkin::DrawItem(hdcMem, &itemRect, item); + + if (i == 0) + itemRect.left += 2; + + // draw visual message length indicator in the leftmost status bar field + if (PluginConfig.m_visualMessageSizeIndicator && i == 0) { + if (dat && dat->bType == SESSIONTYPE_IM) { + HBRUSH br = CreateSolidBrush(RGB(0, 255, 0)); + HBRUSH brOld = (HBRUSH)SelectObject(hdcMem, br); + + RECT rc = itemRect; + rc.top = rc.bottom - 3; + rc.left = 0; + + if (!PluginConfig.m_autoSplit) { + float fMax = (float)dat->nMax; + float uPercent = (float)dat->textLen / ((fMax / (float)100.0) ? (fMax / (float)100.0) : (float)75.0); + float fx = ((float)rc.right / (float)100.0) * uPercent; + + rc.right = (LONG)fx; + FillRect(hdcMem, &rc, br); + } + else { + float baselen = (dat->textLen <= dat->nMax) ? (float)dat->textLen : (float)dat->nMax; + float fMax = (float)dat->nMax; + float uPercent = baselen / ((fMax / (float)100.0) ? (fMax / (float)100.0) : (float)75.0); + float fx; + LONG width = rc.right - rc.left; + if (dat->textLen >= dat->nMax) + rc.right = rc.right / 3; + fx = ((float)rc.right / (float)100.0) * uPercent; + rc.right = (LONG)fx; + FillRect(hdcMem, &rc, br); + if (dat->textLen >= dat->nMax) { + SelectObject(hdcMem, brOld); + DeleteObject(br); + br = CreateSolidBrush(RGB(255, 0, 0)); + brOld = (HBRUSH)SelectObject(hdcMem, br); + rc.left = width / 3; + rc.right = width; + uPercent = (float)dat->textLen / (float)200.0; + fx = ((float)(rc.right - rc.left) / (float)100.0) * uPercent; + rc.right = rc.left + (LONG)fx; + FillRect(hdcMem, &rc, br); + } + } + SelectObject(hdcMem, brOld); + DeleteObject(br); + } + } + + int height = itemRect.bottom - itemRect.top; + HICON hIcon = (HICON)SendMessage(hWnd, SB_GETICON, i, 0); + + TCHAR szText[1024]; szText[0] = 0; + LRESULT result = SendMessage(hWnd, SB_GETTEXT, i, (LPARAM)szText); + if (i == 2 && pContainer) { + TWindowData *dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); + if (dat) + DrawStatusIcons(dat, hdcMem, itemRect, 2); + } + else { + if (hIcon) { + if (LOWORD(result) > 1) { // we have a text + DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, hIcon, 16, 16, 0, 0, DI_NORMAL); + if (dat) { + if (dat->bShowTyping == 2) + DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, PluginConfig.g_iconOverlayEnabled, 16, 16, 0, 0, DI_NORMAL); + } + itemRect.left += 20; + CSkin::RenderText(hdcMem, hTheme, szText, &itemRect, DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX, + CSkin::m_glowSize, clr); + } + else DrawIconEx(hdcMem, itemRect.left + 3, (height / 2 - 8) + itemRect.top, hIcon, 16, 16, 0, 0, DI_NORMAL); + } + else { + itemRect.left += 2; + itemRect.right -= 2; + CSkin::RenderText(hdcMem, hTheme, szText, &itemRect, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, CSkin::m_glowSize, clr); + } + } + } + + if (hbp) + CSkin::FinalizeBufferedPaint(hbp, &rcClient); + else { + BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmOld); + DeleteObject(hbm); + SelectObject(hdcMem, hFontOld); + DeleteDC(hdcMem); + } + + if (hTheme) + CloseThemeData(hTheme); + + EndPaint(hWnd, &ps); + } + return 0; + + // tell status bar to update the part layout (re-calculate part widths) + // needed when an icon is added to or removed from the icon area + case WM_USER + 101: + { + int list_icons = 0; + dat = (TWindowData*)lParam; + if (dat) + while ( Srmm_GetNthIcon(dat->hContact, list_icons)) + list_icons++; + + SendMessage(hWnd, WM_SIZE, 0, 0); + + RECT rcs; + GetWindowRect(hWnd, &rcs); + + int statwidths[5]; + statwidths[0] = (rcs.right - rcs.left) - (2 * SB_CHAR_WIDTH + 20) - (list_icons * (PluginConfig.m_smcxicon + 2)); + statwidths[1] = (rcs.right - rcs.left) - (10 + (list_icons * (PluginConfig.m_smcxicon + 2))); + statwidths[2] = -1; + SendMessage(hWnd, SB_SETPARTS, 3, (LPARAM)statwidths); + } + return 0; + + case WM_SETCURSOR: + GetCursorPos(&pt); + SendMessage(GetParent(hWnd), msg, wParam, lParam); + if (pt.x == ptMouse.x && pt.y == ptMouse.y) + return 1; + + ptMouse = pt; + if (tooltip_active) { + KillTimer(hWnd, TIMERID_HOVER); + CallService("mToolTip/HideTip", 0, 0); + tooltip_active = FALSE; + } + KillTimer(hWnd, TIMERID_HOVER); + SetTimer(hWnd, TIMERID_HOVER, 450, 0); + break; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + KillTimer(hWnd, TIMERID_HOVER); + CallService("mToolTip/HideTip", 0, 0); + tooltip_active = FALSE; + GetCursorPos(&pt); + rcLastStatusBarClick.left = pt.x - 2; + rcLastStatusBarClick.right = pt.x + 2; + rcLastStatusBarClick.top = pt.y - 2; + rcLastStatusBarClick.bottom = pt.y + 2; + + if (pContainer->dwFlags & CNT_NOTITLE) { + POINT pt1 = pt; + ScreenToClient(hWnd, &pt1); + + RECT rcIconpart; + SendMessage(hWnd, SB_GETRECT, 2, (LPARAM)&rcIconpart); + if (!PtInRect(&rcIconpart, pt1)) + return SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + break; + + case WM_TIMER: + if (wParam != TIMERID_HOVER) + break; + KillTimer(hWnd, TIMERID_HOVER); + GetCursorPos(&pt); + if (pt.x != ptMouse.x || pt.y != ptMouse.y) + break; + dat = (TWindowData*)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA); + if (dat != NULL) { + RECT rc; + SIZE size; + TCHAR wBuf[512]; wBuf[0] = 0; + CLCINFOTIP ti = {0}; + ti.cbSize = sizeof(ti); + ti.ptCursor = pt; + ScreenToClient(hWnd, &pt); + SendMessage(hWnd, SB_GETRECT, 2, (LPARAM)&rc); + if ( PtInRect(&rc, pt)) { + unsigned int iconNum = (pt.x - rc.left) / (PluginConfig.m_smcxicon + 2); + StatusIconData *sid = Srmm_GetNthIcon(dat->hContact, iconNum); + if (sid == NULL) + break; + + if ( !strcmp(sid->szModule, MSG_ICON_MODULE)) { + if (sid->dwId == MSG_ICON_SOUND && pContainer) + mir_sntprintf(wBuf, SIZEOF(wBuf), TranslateT("Sounds are %s. Click to toggle status, hold SHIFT and click to set for all open containers"), + pContainer->dwFlags & CNT_NOSOUND ? TranslateT("disabled") : TranslateT("enabled")); + + else if (sid->dwId == MSG_ICON_UTN && dat && (dat->bType == SESSIONTYPE_IM || dat->si->iType == GCW_PRIVMESS)) { + int mtnStatus = db_get_b(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, M.GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); + mir_sntprintf(wBuf, SIZEOF(wBuf), TranslateT("Sending typing notifications is %s."), + mtnStatus ? TranslateT("enabled") : TranslateT("disabled")); + } + else if (sid->dwId == MSG_ICON_SESSION) + _tcsncpy_s(wBuf, TranslateT("Session list.\nClick left for a list of open sessions.\nClick right to access favorites and quickly configure message window behavior"), _TRUNCATE); + } + else if (sid->tszTooltip) + _tcsncpy(wBuf, sid->tszTooltip, SIZEOF(wBuf)); + + if (wBuf[0]) { + CallService("mToolTip/ShowTipW", (WPARAM)wBuf, (LPARAM)&ti); + tooltip_active = TRUE; + } + } + SendMessage(hWnd, SB_GETRECT, 1, (LPARAM)&rc); + if (PtInRect(&rc, pt)) { + int iLength = 0; + GETTEXTLENGTHEX gtxl = {0}; + int iQueued = db_get_dw(dat->hContact, "SendLater", "count", 0); + gtxl.codepage = CP_UTF8; + gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; + iLength = SendDlgItemMessage(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_MESSAGE : IDC_CHAT_MESSAGE, EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); + tooltip_active = TRUE; + + const TCHAR *szFormat = TranslateT("There are %d pending send jobs. Message length: %d bytes, message length limit: %d bytes\n\n%d messages are queued for later delivery"); + + mir_sntprintf(wBuf, SIZEOF(wBuf), szFormat, dat->iOpenJobs, iLength, dat->nMax ? dat->nMax : 20000, iQueued); + CallService("mToolTip/ShowTipW", (WPARAM)wBuf, (LPARAM)&ti); + } + + if (SendMessage(dat->pContainer->hwndStatus, SB_GETTEXT, 0, (LPARAM)wBuf)) { + HDC hdc; + int iLen=SendMessage(dat->pContainer->hwndStatus,SB_GETTEXTLENGTH,0,0); + SendMessage(hWnd, SB_GETRECT, 0, (LPARAM)&rc); + GetTextExtentPoint32( hdc=GetDC( dat->pContainer->hwndStatus), wBuf, iLen, &size ); + ReleaseDC (dat->pContainer->hwndStatus,hdc); + + if (PtInRect(&rc,pt)&&((rc.right-rc.left)bType == SESSIONTYPE_CHAT) + db_get_ts(dat->hContact,dat->szProto,"Topic",&dbv); + + tooltip_active = TRUE; + CallService("mToolTip/ShowTipW", (WPARAM)dbv.ptszVal, (LPARAM)&ti); + if (dbv.pszVal) + db_free(&dbv); + } + } + } + break; + + case WM_DESTROY: + KillTimer(hWnd, TIMERID_HOVER); + } + return CallWindowProc(OldStatusBarproc, hWnd, msg, wParam, lParam); +} diff --git a/plugins/TabSRMM/src/functions.h b/plugins/TabSRMM/src/functions.h index fa5ae612fc..bfffb4fbd6 100644 --- a/plugins/TabSRMM/src/functions.h +++ b/plugins/TabSRMM/src/functions.h @@ -36,7 +36,7 @@ int FontServiceFontsChanged(WPARAM wParam, LPARAM lParam); int SmileyAddOptionsChanged(WPARAM wParam, LPARAM lParam); int IEViewOptionsChanged(WPARAM wParam, LPARAM lParam); int ModPlus_PreShutdown(WPARAM wparam, LPARAM lparam); -int ModPlus_Init(WPARAM wparam, LPARAM lparam); +int ModPlus_Init(); void RegisterFontServiceFonts(); diff --git a/plugins/TabSRMM/src/globals.cpp b/plugins/TabSRMM/src/globals.cpp index 0db994d7bb..f5227a5ff8 100644 --- a/plugins/TabSRMM/src/globals.cpp +++ b/plugins/TabSRMM/src/globals.cpp @@ -286,7 +286,7 @@ int CGlobals::TopToolbarLoaded(WPARAM,LPARAM) ///////////////////////////////////////////////////////////////////////////////////////// // second part of the startup initialisation.All plugins are now fully loaded -int CGlobals::ModulesLoaded(WPARAM wParam, LPARAM lParam) +int CGlobals::ModulesLoaded(WPARAM, LPARAM) { M.configureCustomFolders(); @@ -312,7 +312,7 @@ int CGlobals::ModulesLoaded(WPARAM wParam, LPARAM lParam) ::BuildContainerMenu(); ::CB_InitDefaultButtons(); - ::ModPlus_Init(wParam, lParam); + ::ModPlus_Init(); ::NotifyEventHooks(hHookToolBarLoadedEvt, 0, 0); if (M.GetByte("avatarmode", -1) == -1) diff --git a/plugins/TabSRMM/src/modplus.cpp b/plugins/TabSRMM/src/modplus.cpp index 79d775501c..42dca25d9d 100644 --- a/plugins/TabSRMM/src/modplus.cpp +++ b/plugins/TabSRMM/src/modplus.cpp @@ -58,8 +58,8 @@ static int RegisterCustomButton(WPARAM, LPARAM) bbd.dwButtonID = 1; bbd.dwDefPos = 200; bbd.hIcon = PluginConfig.g_buttonBarIconHandles[3]; - bbd.pszModuleName = (char*)"Tabmodplus"; - bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]"); + bbd.pszModuleName = "Tabmodplus"; + bbd.ptszTooltip = LPGENT("Insert [img] tag / surround selected text with [img][/img]"); return CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bbd); } @@ -71,7 +71,7 @@ static int CustomButtonPressed(WPARAM wParam, LPARAM lParam) BBButton bbd = { sizeof(bbd) }; bbd.dwButtonID = 1; - bbd.pszModuleName = (char *)"Tabmodplus"; + bbd.pszModuleName = "Tabmodplus"; CallService(MS_BB_GETBUTTONSTATE, wParam, (LPARAM)&bbd); TCHAR *pszText = _T(""); @@ -139,14 +139,14 @@ static int CustomButtonPressed(WPARAM wParam, LPARAM lParam) case 3: pszFormatedText = _T("[img]"); - bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]"); + bbd.ptszTooltip = LPGENT("Insert [img] tag / surround selected text with [img][/img]"); CallService(MS_BB_SETBUTTONSTATE, wParam, (LPARAM)&bbd); break; case 4: pszFormatedText = _T("[/img]"); - bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]"); + bbd.ptszTooltip = LPGENT("Insert [img] tag / surround selected text with [img][/img]"); CallService(MS_BB_SETBUTTONSTATE, wParam, (LPARAM)&bbd); break; } @@ -162,7 +162,7 @@ static int CustomButtonPressed(WPARAM wParam, LPARAM lParam) return 1; } -int ModPlus_Init(WPARAM, LPARAM) +int ModPlus_Init() { HookEvent(ME_MSG_BUTTONPRESSED, CustomButtonPressed); HookEvent(ME_MSG_TOOLBARLOADED, RegisterCustomButton); diff --git a/plugins/TabSRMM/src/msgoptions.cpp b/plugins/TabSRMM/src/msgoptions.cpp index 530aa9375c..fd14c1a823 100644 --- a/plugins/TabSRMM/src/msgoptions.cpp +++ b/plugins/TabSRMM/src/msgoptions.cpp @@ -119,7 +119,7 @@ static int TSAPI ScanSkinDir(const TCHAR* tszFolder, HWND hwndCombobox) mir_sntprintf(tszFinalName, SIZEOF(tszFinalName), _T("%s%s"), tszFolder, fd.cFileName); - GetPrivateProfileString(_T("Global"), _T("Name"), _T("None"), szBuf, 500, tszFinalName); + GetPrivateProfileString(_T("Global"), _T("Name"), _T("None"), szBuf, SIZEOF(szBuf), tszFinalName); if (!_tcscmp(szBuf, _T("None"))) { fd.cFileName[mir_tstrlen(fd.cFileName) - 4] = 0; _tcsncpy_s(szBuf, fd.cFileName, _TRUNCATE); diff --git a/plugins/TabSRMM/src/sidebar.cpp b/plugins/TabSRMM/src/sidebar.cpp index b663bb8ac0..1f0b809d51 100644 --- a/plugins/TabSRMM/src/sidebar.cpp +++ b/plugins/TabSRMM/src/sidebar.cpp @@ -105,12 +105,12 @@ void CSideBarButton::_create() ::SendMessage(m_hwnd, BUTTONSETASTHEMEDBTN, TRUE, 0); ::SendMessage(m_hwnd, BUTTONSETCONTAINER, (LPARAM)m_sideBar->getContainer(), 0); m_buttonControl = (TSButtonCtrl *)::GetWindowLongPtr(m_hwnd, 0); + if (m_id == IDC_SIDEBARUP || m_id == IDC_SIDEBARDOWN) + ::SetParent(m_hwnd, m_sideBar->getContainer()->hwnd); } else delete this; - if (m_id == IDC_SIDEBARUP || m_id == IDC_SIDEBARDOWN) - ::SetParent(m_hwnd, m_sideBar->getContainer()->hwnd); } CSideBarButton::~CSideBarButton() @@ -344,7 +344,7 @@ void CSideBarButton::activateSession() const */ void CSideBarButton::invokeContextMenu() { - const TContainerData* pContainer = m_sideBar->getContainer(); + const TContainerData *pContainer = m_sideBar->getContainer(); if (pContainer) { TSideBarNotify tsn = {0}; -- cgit v1.2.3