diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp index ec7e1ea24cb..1283165d078 100644 --- a/dll/win32/msutb/msutb.cpp +++ b/dll/win32/msutb/msutb.cpp @@ -30,6 +30,62 @@ END_OBJECT_MAP() CMsUtbModule gModule; +class CCicLibMenuItem; + +/***********************************************************************/ + +class CCicLibMenu : public ITfMenu +{ +public: + CicArray m_MenuItems; + LONG m_cRefs; + +public: + CCicLibMenu(); + virtual ~CCicLibMenu(); + + STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj) override; + STDMETHOD_(ULONG, AddRef)() override; + STDMETHOD_(ULONG, Release)() override; + STDMETHOD(AddMenuItem)( + UINT uId, + DWORD dwFlags, + HBITMAP hbmp, + HBITMAP hbmpMask, + const WCHAR *pch, + ULONG cch, + ITfMenu **ppSubMenu) override; + STDMETHOD_(CCicLibMenu*, CreateSubMenu)(); + STDMETHOD_(CCicLibMenuItem*, CreateMenuItem)(); +}; + +/***********************************************************************/ + +class CCicLibMenuItem +{ +public: + DWORD m_uId; + DWORD m_dwFlags; + HBITMAP m_hbmp; + HBITMAP m_hbmpMask; + BSTR m_bstrText; + ITfMenu *m_pMenu; + +public: + CCicLibMenuItem(); + virtual ~CCicLibMenuItem(); + + BOOL Init( + UINT uId, + DWORD dwFlags, + HBITMAP hbmp, + HBITMAP hbmpMask, + const WCHAR *pch, + ULONG cch, + ITfMenu *pMenu); + HBITMAP CreateBitmap(HANDLE hBitmap); +}; + /***********************************************************************/ class CTrayIconWnd @@ -66,6 +122,203 @@ protected: STDMETHOD_(LRESULT, OnDelayMsg)(LPARAM lParam) { return 0; }; }; +/*********************************************************************** + * CCicLibMenu + */ + +CCicLibMenu::CCicLibMenu() : m_cRefs(1) +{ +} + +CCicLibMenu::~CCicLibMenu() +{ + for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem) + { + delete m_MenuItems[iItem]; + m_MenuItems[iItem] = NULL; + } +} + +STDMETHODIMP CCicLibMenu::QueryInterface(REFIID riid, LPVOID *ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfMenu)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CCicLibMenu::AddRef() +{ + return ++m_cRefs; +} + +STDMETHODIMP_(ULONG) CCicLibMenu::Release() +{ + if (--m_cRefs == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +STDMETHODIMP_(CCicLibMenu*) CCicLibMenu::CreateSubMenu() +{ + return new(cicNoThrow) CCicLibMenu(); +} + +STDMETHODIMP_(CCicLibMenuItem*) CCicLibMenu::CreateMenuItem() +{ + return new(cicNoThrow) CCicLibMenuItem(); +} + +STDMETHODIMP CCicLibMenu::AddMenuItem( + UINT uId, + DWORD dwFlags, + HBITMAP hbmp, + HBITMAP hbmpMask, + const WCHAR *pch, + ULONG cch, + ITfMenu **ppSubMenu) +{ + if (ppSubMenu) + *ppSubMenu = NULL; + + CCicLibMenu *pSubMenu = NULL; + if (dwFlags & TF_LBMENUF_SUBMENU) + { + if (!ppSubMenu) + return E_INVALIDARG; + pSubMenu = CreateSubMenu(); + } + + CCicLibMenuItem *pMenuItem = CreateMenuItem(); + if (!pMenuItem) + return E_OUTOFMEMORY; + + if (!pMenuItem->Init(uId, dwFlags, hbmp, hbmpMask, pch, cch, pSubMenu)) + return E_FAIL; + + if (ppSubMenu && pSubMenu) + { + *ppSubMenu = pSubMenu; + pSubMenu->AddRef(); + } + + *m_MenuItems.Append(1) = pMenuItem; + return S_OK; +} + +/*********************************************************************** + * CCicLibMenuItem + */ + +CCicLibMenuItem::CCicLibMenuItem() +{ + m_uId = 0; + m_dwFlags = 0; + m_hbmp = NULL; + m_hbmpMask = NULL; + m_bstrText = NULL; + m_pMenu = NULL; +} + +CCicLibMenuItem::~CCicLibMenuItem() +{ + if (m_pMenu) + { + m_pMenu->Release(); + m_pMenu = NULL; + } + + if (m_hbmp) + { + ::DeleteObject(m_hbmp); + m_hbmp = NULL; + } + + if (m_hbmpMask) + { + ::DeleteObject(m_hbmpMask); + m_hbmpMask = NULL; + } + + ::SysFreeString(m_bstrText); + m_bstrText = NULL; +} + +BOOL CCicLibMenuItem::Init( + UINT uId, + DWORD dwFlags, + HBITMAP hbmp, + HBITMAP hbmpMask, + const WCHAR *pch, + ULONG cch, + ITfMenu *pMenu) +{ + m_uId = uId; + m_dwFlags = dwFlags; + m_bstrText = ::SysAllocStringLen(pch, cch); + if (!m_bstrText && cch) + return FALSE; + + m_pMenu = pMenu; + m_hbmp = CreateBitmap(hbmp); + m_hbmpMask = CreateBitmap(hbmpMask); + if (hbmp) + ::DeleteObject(hbmp); + if (hbmpMask) + ::DeleteObject(hbmpMask); + + return TRUE; +} + +HBITMAP CCicLibMenuItem::CreateBitmap(HANDLE hBitmap) +{ + if (!hBitmap) + return NULL; + + HDC hDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); + if (!hDC) + return NULL; + + HBITMAP hbmMem = NULL; + + BITMAP bm; + ::GetObject(hBitmap, sizeof(bm), &bm); + + HGDIOBJ hbmOld1 = NULL; + HDC hdcMem1 = ::CreateCompatibleDC(hDC); + if (hdcMem1) + hbmOld1 = ::SelectObject(hdcMem1, hBitmap); + + HGDIOBJ hbmOld2 = NULL; + HDC hdcMem2 = ::CreateCompatibleDC(hDC); + if (hdcMem2) + { + hbmMem = ::CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); + hbmOld2 = ::SelectObject(hdcMem2, hbmMem); + } + + ::BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY); + + if (hbmOld1) + ::SelectObject(hdcMem1, hbmOld1); + if (hbmOld2) + ::SelectObject(hdcMem2, hbmOld2); + + ::DeleteDC(hDC); + if (hdcMem1) + ::DeleteDC(hdcMem1); + if (hdcMem2) + ::DeleteDC(hdcMem2); + + return hbmMem; +} + /*********************************************************************** * CTrayIconItem */