From 1001b59a06ae73f39a5dc779e8ba81c06bd2389d Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Mon, 29 Jan 2024 18:38:59 +0900 Subject: [PATCH] [MSUTB][SDK] Add CUTBMenuWnd and CUTBMenuItem (#6420) Supporting Language Bar... JIRA issue: CORE-19363 - Implement CUTBMenuWnd and CUTBMenuItem classes. - Add IDS_MENUWND and IDS_LEFTCLICK resource strings. --- dll/win32/msutb/lang/en-US.rc | 2 + dll/win32/msutb/msutb.cpp | 294 +++++++++++++++++++++++++++- dll/win32/msutb/precomp.h | 4 +- dll/win32/msutb/resource.h | 2 + sdk/include/reactos/cicero/cicuif.h | 48 ++--- 5 files changed, 317 insertions(+), 33 deletions(-) diff --git a/dll/win32/msutb/lang/en-US.rc b/dll/win32/msutb/lang/en-US.rc index 646ca61f2c1..c45c6e28438 100644 --- a/dll/win32/msutb/lang/en-US.rc +++ b/dll/win32/msutb/lang/en-US.rc @@ -16,4 +16,6 @@ BEGIN IDS_IGNORE "&Ignore" IDS_YES "&Yes" IDS_NO "&No" + IDS_MENUWND "Menu Window" + IDS_LEFTCLICK "Left Click" END diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp index 6ab8eb45b21..615e7c47450 100644 --- a/dll/win32/msutb/msutb.cpp +++ b/dll/win32/msutb/msutb.cpp @@ -33,6 +33,7 @@ CMsUtbModule gModule; class CCicLibMenuItem; class CTipbarAccItem; +class CUTBMenuItem; /***********************************************************************/ @@ -100,6 +101,7 @@ protected: BOOL m_bInitialized; CicArray m_AccItems; LONG m_cSelection; + friend class CUTBMenuWnd; public: CTipbarAccessible(CTipbarAccItem *pItem); @@ -206,9 +208,9 @@ public: { return NULL; } - STDMETHOD(DoAccDefaultAction)() + STDMETHOD_(BOOL, DoAccDefaultAction)() { - return S_OK; + return FALSE; } STDMETHOD_(BOOL, DoAccDefaultActionReal)() { @@ -218,6 +220,96 @@ public: /***********************************************************************/ +class CTipbarCoInitialize +{ +public: + BOOL m_bCoInit; + + CTipbarCoInitialize() : m_bCoInit(FALSE) { } + ~CTipbarCoInitialize() { CoUninit(); } + + HRESULT EnsureCoInit() + { + if (m_bCoInit) + return S_OK; + HRESULT hr = ::CoInitialize(NULL); + if (FAILED(hr)) + return hr; + m_bCoInit = TRUE; + return S_OK; + } + + void CoUninit() + { + if (m_bCoInit) + { + ::CoUninitialize(); + m_bCoInit = FALSE; + } + } +}; + +/***********************************************************************/ + +class CUTBMenuWnd : public CTipbarAccItem, public CUIFMenu +{ +protected: + CTipbarCoInitialize m_coInit; + CTipbarAccessible *m_pAccessible; + UINT m_nMenuWndID; + friend class CUTBMenuItem; + +public: + CUTBMenuWnd(HINSTANCE hInst, DWORD style, DWORD dwUnknown14); + + BOOL StartDoAccDefaultActionTimer(CUTBMenuItem *pTarget); + + CTipbarAccItem* GetAccItem() + { + return static_cast(this); + } + CUIFMenu* GetMenu() + { + return static_cast(this); + } + + STDMETHOD_(BSTR, GetAccName)() override; + STDMETHOD_(INT, GetAccRole)() override; + STDMETHOD_(void, Initialize)() override; + STDMETHOD_(void, OnCreate)(HWND hWnd) override; + STDMETHOD_(void, OnDestroy)(HWND hWnd) override; + STDMETHOD_(HRESULT, OnGetObject)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override; + STDMETHOD_(LRESULT, OnShowWindow)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override; + STDMETHOD_(void, OnTimer)(WPARAM wParam) override; +}; + +/***********************************************************************/ + +class CUTBMenuItem : public CTipbarAccItem, public CUIFMenuItem +{ +protected: + CUTBMenuWnd *m_pMenuWnd; + friend class CUTBMenuWnd; + +public: + CUTBMenuItem(CUTBMenuWnd *pMenuWnd); + ~CUTBMenuItem() override; + + CUIFMenuItem* GetMenuItem() + { + return static_cast(this); + } + + STDMETHOD_(BOOL, DoAccDefaultAction)() override; + STDMETHOD_(BOOL, DoAccDefaultActionReal)() override; + STDMETHOD_(BSTR, GetAccDefaultAction)() override; + STDMETHOD_(void, GetAccLocation)(LPRECT lprc) override; + STDMETHOD_(BSTR, GetAccName)() override; + STDMETHOD_(INT, GetAccRole)() override; +}; + +/***********************************************************************/ + class CTrayIconWnd { public: @@ -954,7 +1046,7 @@ STDMETHODIMP CTipbarAccessible::accDoDefaultAction(VARIANT varID) CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID)); if (!pItem) return DISP_E_MEMBERNOTFOUND; - return pItem->DoAccDefaultAction() == 0; + return (pItem->DoAccDefaultAction() ? S_OK : S_FALSE); } STDMETHODIMP CTipbarAccessible::put_accName(VARIANT varID, BSTR name) @@ -967,6 +1059,202 @@ STDMETHODIMP CTipbarAccessible::put_accValue(VARIANT varID, BSTR value) return S_FALSE; } +/*********************************************************************** + * CUTBMenuWnd + */ + +CUTBMenuWnd::CUTBMenuWnd(HINSTANCE hInst, DWORD style, DWORD dwUnknown14) + : CUIFMenu(hInst, style, dwUnknown14) +{ +} + +BOOL CUTBMenuWnd::StartDoAccDefaultActionTimer(CUTBMenuItem *pTarget) +{ + if (!m_pAccessible) + return FALSE; + + m_nMenuWndID = m_pAccessible->GetIDOfItem(pTarget); + if (!m_nMenuWndID || m_nMenuWndID == (UINT)-1) + return FALSE; + + if (::IsWindow(m_hWnd)) + { + ::KillTimer(m_hWnd, 11); + ::SetTimer(m_hWnd, 11, 200, NULL); + } + + return TRUE; +} + +STDMETHODIMP_(BSTR) CUTBMenuWnd::GetAccName() +{ + WCHAR szText[64]; + LoadStringW(g_hInst, IDS_MENUWND, szText, _countof(szText)); + return ::SysAllocString(szText); +} + +STDMETHODIMP_(INT) CUTBMenuWnd::GetAccRole() +{ + return 9; +} + +STDMETHODIMP_(void) CUTBMenuWnd::Initialize() +{ + CTipbarAccessible *pAccessible = new(cicNoThrow) CTipbarAccessible(GetAccItem()); + if (pAccessible) + m_pAccessible = pAccessible; + + return CUIFObject::Initialize(); +} + +STDMETHODIMP_(void) CUTBMenuWnd::OnCreate(HWND hWnd) +{ + if (m_pAccessible) + m_pAccessible->SetWindow(hWnd); +} + +STDMETHODIMP_(void) CUTBMenuWnd::OnDestroy(HWND hWnd) +{ + if (m_pAccessible) + { + m_pAccessible->NotifyWinEvent(EVENT_OBJECT_DESTROY, GetAccItem()); + m_pAccessible->ClearAccItems(); + m_pAccessible->Release(); + m_pAccessible = NULL; + } + m_coInit.CoUninit(); +} + +STDMETHODIMP_(HRESULT) +CUTBMenuWnd::OnGetObject(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (lParam != -4) + return S_OK; + + if (!m_pAccessible) + return E_OUTOFMEMORY; + + if (m_pAccessible->m_bInitialized) + return m_pAccessible->CreateRefToAccObj(wParam); + + if (SUCCEEDED(m_coInit.EnsureCoInit())) + { + HRESULT hr = m_pAccessible->Initialize(); + if (FAILED(hr)) + { + m_pAccessible->Release(); + m_pAccessible = NULL; + return hr; + } + + m_pAccessible->NotifyWinEvent(EVENT_OBJECT_CREATE, GetAccItem()); + return m_pAccessible->CreateRefToAccObj(wParam); + } + + return S_OK; +} + +STDMETHODIMP_(LRESULT) +CUTBMenuWnd::OnShowWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_pAccessible) + { + if (wParam) + { + m_pAccessible->NotifyWinEvent(EVENT_OBJECT_SHOW, GetAccItem()); + m_pAccessible->NotifyWinEvent(EVENT_OBJECT_FOCUS, GetAccItem()); + } + else + { + m_pAccessible->NotifyWinEvent(EVENT_OBJECT_HIDE, GetAccItem()); + } + } + + return ::DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +STDMETHODIMP_(void) CUTBMenuWnd::OnTimer(WPARAM wParam) +{ + if (wParam == 11) + { + ::KillTimer(m_hWnd, 11); + if (m_pAccessible && m_nMenuWndID) + { + m_pAccessible->DoDefaultActionReal(m_nMenuWndID); + m_nMenuWndID = 0; + } + } +} + +/*********************************************************************** + * CUTBMenuItem + */ + +CUTBMenuItem::CUTBMenuItem(CUTBMenuWnd *pMenuWnd) + : CUIFMenuItem(pMenuWnd ? pMenuWnd->GetMenu() : NULL) +{ + m_pMenuWnd = pMenuWnd; +} + +CUTBMenuItem::~CUTBMenuItem() +{ + if (m_hbmColor) + { + ::DeleteObject(m_hbmColor); + m_hbmColor = NULL; + } + if (m_hbmMask) + { + ::DeleteObject(m_hbmMask); + m_hbmMask = NULL; + } +} + +STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultAction() +{ + if (!m_pMenuWnd) + return FALSE; + + m_pMenuWnd->StartDoAccDefaultActionTimer(this); + return TRUE; +} + +STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultActionReal() +{ + if (!m_pSubMenu) + OnLButtonUp(0, 0); + else + ShowSubPopup(); + return TRUE; +} + +STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccDefaultAction() +{ + WCHAR szText[64]; + ::LoadStringW(g_hInst, IDS_LEFTCLICK, szText, _countof(szText)); + return ::SysAllocString(szText); +} + +STDMETHODIMP_(void) CUTBMenuItem::GetAccLocation(LPRECT lprc) +{ + GetRect(lprc); + ::ClientToScreen(m_pMenuWnd->m_hWnd, (LPPOINT)lprc); + ::ClientToScreen(m_pMenuWnd->m_hWnd, (LPPOINT)&lprc->right); +} + +STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccName() +{ + return ::SysAllocString(m_pszMenuItemLeft); +} + +/// @unimplemented +STDMETHODIMP_(INT) CUTBMenuItem::GetAccRole() +{ + if (FALSE) //FIXME + return 21; + return 12; +} + /*********************************************************************** * CTrayIconItem */ diff --git a/dll/win32/msutb/precomp.h b/dll/win32/msutb/precomp.h index 7e880a30d57..2f3ca726f7b 100644 --- a/dll/win32/msutb/precomp.h +++ b/dll/win32/msutb/precomp.h @@ -25,8 +25,8 @@ #include #include #undef STATUS_NO_MEMORY + +#include "resource.h" #include #include - -#include "resource.h" diff --git a/dll/win32/msutb/resource.h b/dll/win32/msutb/resource.h index c91662cb293..65532689e47 100644 --- a/dll/win32/msutb/resource.h +++ b/dll/win32/msutb/resource.h @@ -7,3 +7,5 @@ #define IDS_IGNORE 104 #define IDS_YES 105 #define IDS_NO 106 +#define IDS_MENUWND 322 +#define IDS_LEFTCLICK 323 diff --git a/sdk/include/reactos/cicero/cicuif.h b/sdk/include/reactos/cicero/cicuif.h index b4715f93263..218587d3296 100644 --- a/sdk/include/reactos/cicero/cicuif.h +++ b/sdk/include/reactos/cicero/cicuif.h @@ -617,8 +617,8 @@ public: STDMETHOD_(LRESULT, OnSettingChange)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); STDMETHOD_(LRESULT, OnDisplayChange)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return 0; } - STDMETHOD_(LRESULT, OnGetObject)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { return 0; } + STDMETHOD_(HRESULT, OnGetObject)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { return S_OK; } STDMETHOD_(LRESULT, WindowProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); STDMETHOD_(BOOL, OnEraseBkGnd)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; } @@ -786,7 +786,7 @@ protected: void DrawUnderline(HDC hDC, INT xText, INT yText, HBRUSH hbr); public: - CUIFMenuItem(CUIFMenu *pMenu, BOOL bDisabled); + CUIFMenuItem(CUIFMenu *pMenu, BOOL bDisabled = FALSE); ~CUIFMenuItem() override; BOOL Init(UINT nMenuItemID, LPCWSTR pszText); @@ -2484,7 +2484,6 @@ inline BOOL cicGetIconBitmaps(HICON hIcon, HBITMAP *hbm1, HBITMAP *hbm2, const S if (!CUIFBitmapDC::s_fInitBitmapDCs) return NULL; - LONG cx, cy; SIZE size; if (pSize) { @@ -2496,8 +2495,8 @@ inline BOOL cicGetIconBitmaps(HICON hIcon, HBITMAP *hbm1, HBITMAP *hbm2, const S return FALSE; } - CUIFBitmapDC::s_phdcSrc->SetDIB(cx, cy, 1, 32); - CUIFBitmapDC::s_phdcMask->SetBitmap(cx, cy, 1, 1); + CUIFBitmapDC::s_phdcSrc->SetDIB(size.cx, size.cy, 1, 32); + CUIFBitmapDC::s_phdcMask->SetBitmap(size.cx, size.cy, 1, 1); RECT rc = { 0, 0, size.cx, size.cy }; ::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); @@ -5177,31 +5176,24 @@ CUIFBalloonWindow::AddButton(UINT nCommandId) pButton->Initialize(); pButton->m_nCommandID = nCommandId; - LPCWSTR pszText; // FIXME: Use resource strings + LPCWSTR pszText; +#ifdef IDS_OK + extern HINSTANCE g_hInst; + WCHAR szText[64]; + ::LoadStringW(g_hInst, IDS_OK + nCommandId, szText, _countof(szText)); + pszText = szText; +#else switch (nCommandId) { - case IDOK: - pszText = L"OK"; - break; - case IDCANCEL: - pszText = L"Cancel"; - break; - case IDABORT: - pszText = L"&Abort"; - break; - case IDRETRY: - pszText = L"&Retry"; - break; - case IDIGNORE: - pszText = L"&Ignore"; - break; - case IDYES: - pszText = L"&Yes"; - break; - default: - pszText = L"&No"; - break; + case IDOK: pszText = L"OK"; break; + case IDCANCEL: pszText = L"Cancel"; break; + case IDABORT: pszText = L"&Abort"; break; + case IDRETRY: pszText = L"&Retry"; break; + case IDIGNORE: pszText = L"&Ignore"; break; + case IDYES: pszText = L"&Yes"; break; + default: pszText = L"&No"; break; } +#endif pButton->SetText(pszText);