https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d6caac30567dfee433d1c5ef8dce182b4106e97f

commit d6caac30567dfee433d1c5ef8dce182b4106e97f
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Sat Jan 27 14:06:25 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Sat Jan 27 14:06:25 2024 +0900

    [MSUTB] Add CCicLibMenu and CCicLibMenuItem (#6414)
    
    Supporting Language Bar...
    JIRA issue: CORE-19363
    - Implement CCicLibMenu and
      CCicLibMenuItem classes.
---
 dll/win32/msutb/msutb.cpp | 253 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 253 insertions(+)

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<CCicLibMenuItem*> 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
  */

Reply via email to