[MSCTF][MSUTB][SDK] Add CTrayIconWnd and CMainIconItem (#6424)

Supporting Language Bar...
JIRA issue: CORE-19363
- Add CTrayIconWnd, CMainIconItem,
  and CButtonIconItem classes.
- Modify msctf.spec for TF_GetLangIcon
  function.
- Add main icon IDI_MAINICON
  ("res/earth.ico").
This commit is contained in:
Katayama Hirofumi MZ 2024-01-31 16:52:02 +09:00 committed by GitHub
parent 1311537435
commit 5e4fe2cf40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 455 additions and 20 deletions

View file

@ -18,7 +18,7 @@
@ stdcall -stub TF_DllDetachInOther()
@ stdcall -stub TF_GetGlobalCompartment(ptr)
@ stub TF_GetInputScope
@ stub TF_GetLangIcon
@ stdcall -stub TF_GetLangIcon(long ptr long)
@ stub TF_GetMlngHKL
@ stub TF_GetMlngIconIndex
@ stub TF_GetThreadFlags

View file

@ -16,6 +16,8 @@ BEGIN
IDS_IGNORE "&Ignore"
IDS_YES "&Yes"
IDS_NO "&No"
IDS_RESTORELANGBAR "Restore Language Bar"
IDS_MENUWND "Menu Window"
IDS_LEFTCLICK "Left Click"
END

View file

@ -16,6 +16,10 @@ DWORD g_dwOSInfo = 0;
CRITICAL_SECTION g_cs;
LONG g_DllRefCount = 0;
UINT g_uTimerElapseDOACCDEFAULTACTION = 200;
#define TIMER_ID_DOACCDEFAULTACTION 11
EXTERN_C void __cxa_pure_virtual(void)
{
ERR("__cxa_pure_virtual\n");
@ -34,6 +38,12 @@ CMsUtbModule gModule;
class CCicLibMenuItem;
class CTipbarAccItem;
class CUTBMenuItem;
class CMainIconItem;
class CTrayIconItem;
class CTipbarWnd;
class CButtonIconItem;
CTipbarWnd *g_pTipbarWnd = NULL;
HRESULT GetGlobalCompartment(REFGUID rguid, ITfCompartment **ppComp)
{
@ -98,9 +108,8 @@ void DoCloseLangbar(void)
if (pLangBarMgr)
{
hr = pLangBarMgr->ShowFloating(8);
hr = pLangBarMgr->ShowFloating(TF_SFT_HIDDEN);
pLangBarMgr->Release();
pLangBarMgr = NULL;
}
if (SUCCEEDED(hr))
@ -453,9 +462,50 @@ public:
class CTrayIconWnd
{
protected:
DWORD m_dwUnknown20;
BOOL m_bBusy;
UINT m_uCallbackMessage;
UINT m_uMsg;
HWND m_hWnd;
DWORD m_dwUnknown21[2];
HWND m_hTrayWnd;
HWND m_hNotifyWnd;
DWORD m_dwTrayWndThreadId;
DWORD m_dwUnknown22;
HWND m_hwndProgman;
DWORD m_dwProgmanThreadId;
CMainIconItem *m_pMainIconItem;
CicArray<CButtonIconItem*> m_Items;
UINT m_uCallbackMsg;
UINT m_uNotifyIconID;
static BOOL CALLBACK EnumChildWndProc(HWND hWnd, LPARAM lParam);
static LRESULT CALLBACK _WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
//FIXME
HWND GetNotifyWnd() { return NULL; };
CTrayIconWnd();
~CTrayIconWnd();
BOOL RegisterClass();
HWND CreateWnd();
void DestroyWnd();
BOOL SetMainIcon(HKL hKL);
BOOL SetIcon(REFGUID rguid, DWORD dwUnknown24, HICON hIcon, LPCWSTR psz);
void RemoveAllIcon(DWORD dwFlags);
void RemoveUnusedIcons(int unknown);
CButtonIconItem *FindIconItem(REFGUID rguid);
BOOL FindTrayEtc();
HWND GetNotifyWnd();
BOOL OnIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
static CTrayIconWnd *GetThis(HWND hWnd);
static void SetThis(HWND hWnd, LPCREATESTRUCT pCS);
void CallOnDelayMsg();
};
/***********************************************************************/
@ -469,20 +519,50 @@ protected:
DWORD m_dwIconAddOrModify;
BOOL m_bIconAdded;
CTrayIconWnd *m_pTrayIconWnd;
DWORD m_dw;
DWORD m_dwUnknown25;
GUID m_guid;
RECT m_rcMenu;
POINT m_ptCursor;
friend class CTrayIconWnd;
public:
CTrayIconItem(CTrayIconWnd *pTrayIconWnd);
virtual ~CTrayIconItem() { }
BOOL _Init(HWND hWnd, UINT uCallbackMessage, UINT uNotifyIconID, const GUID& rguid);
BOOL UpdateMenuRectPoint();
BOOL RemoveIcon();
STDMETHOD_(BOOL, SetIcon)(HICON hIcon, LPCTSTR pszTip);
STDMETHOD_(LRESULT, OnMsg)(WPARAM wParam, LPARAM lParam) { return 0; };
STDMETHOD_(LRESULT, OnDelayMsg)(LPARAM lParam) { return 0; };
STDMETHOD_(BOOL, SetIcon)(HICON hIcon, LPCWSTR pszTip);
STDMETHOD_(BOOL, OnMsg)(WPARAM wParam, LPARAM lParam) { return FALSE; };
STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) { return 0; };
};
/***********************************************************************/
class CButtonIconItem : public CTrayIconItem
{
protected:
DWORD m_dwUnknown24;
HKL m_hKL;
friend class CTrayIconWnd;
public:
CButtonIconItem(CTrayIconWnd *pWnd, DWORD dwUnknown24);
STDMETHOD_(BOOL, OnMsg)(WPARAM wParam, LPARAM lParam) override;
STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
};
/***********************************************************************/
class CMainIconItem : public CButtonIconItem
{
public:
CMainIconItem(CTrayIconWnd *pWnd);
BOOL Init(HWND hWnd);
STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
};
/***********************************************************************
@ -780,7 +860,7 @@ STDMETHODIMP CCicLibMenu::AddMenuItem(
pSubMenu->AddRef();
}
*m_MenuItems.Append(1) = pMenuItem;
m_MenuItems.Add(pMenuItem);
return S_OK;
}
@ -1429,8 +1509,8 @@ BOOL CUTBMenuWnd::StartDoAccDefaultActionTimer(CUTBMenuItem *pTarget)
if (::IsWindow(m_hWnd))
{
::KillTimer(m_hWnd, 11);
::SetTimer(m_hWnd, 11, 200, NULL);
::KillTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION);
::SetTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION, g_uTimerElapseDOACCDEFAULTACTION, NULL);
}
return TRUE;
@ -1525,9 +1605,9 @@ CUTBMenuWnd::OnShowWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
STDMETHODIMP_(void) CUTBMenuWnd::OnTimer(WPARAM wParam)
{
if (wParam == 11)
if (wParam == TIMER_ID_DOACCDEFAULTACTION)
{
::KillTimer(m_hWnd, 11);
::KillTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION);
if (m_pAccessible && m_nMenuWndID)
{
m_pAccessible->DoDefaultActionReal(m_nMenuWndID);
@ -1633,10 +1713,10 @@ BOOL CTrayIconItem::RemoveIcon()
{
if (m_dwIconAddOrModify == NIM_MODIFY)
{
NOTIFYICONDATA NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
NOTIFYICONDATAW NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
NotifyIcon.uCallbackMessage = m_uCallbackMessage;
::Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);
::Shell_NotifyIconW(NIM_DELETE, &NotifyIcon);
}
m_dwIconAddOrModify = NIM_ADD;
@ -1644,22 +1724,22 @@ BOOL CTrayIconItem::RemoveIcon()
return TRUE;
}
BOOL CTrayIconItem::SetIcon(HICON hIcon, LPCTSTR pszTip)
BOOL CTrayIconItem::SetIcon(HICON hIcon, LPCWSTR pszTip)
{
if (!hIcon)
return FALSE;
NOTIFYICONDATA NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
NOTIFYICONDATAW NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE;
NotifyIcon.uCallbackMessage = m_uCallbackMessage;
NotifyIcon.hIcon = hIcon;
if (pszTip)
{
NotifyIcon.uFlags |= NIF_TIP;
StringCchCopy(NotifyIcon.szTip, _countof(NotifyIcon.szTip), pszTip);
StringCchCopyW(NotifyIcon.szTip, _countof(NotifyIcon.szTip), pszTip);
}
::Shell_NotifyIcon(m_dwIconAddOrModify, &NotifyIcon);
::Shell_NotifyIconW(m_dwIconAddOrModify, &NotifyIcon);
m_dwIconAddOrModify = NIM_MODIFY;
m_bIconAdded = NIM_MODIFY;
@ -1676,6 +1756,347 @@ BOOL CTrayIconItem::UpdateMenuRectPoint()
return TRUE;
}
/***********************************************************************
* CButtonIconItem
*/
CButtonIconItem::CButtonIconItem(CTrayIconWnd *pWnd, DWORD dwUnknown24)
: CTrayIconItem(pWnd)
{
m_dwUnknown24 = dwUnknown24;
}
/// @unimplemented
STDMETHODIMP_(BOOL) CButtonIconItem::OnMsg(WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
break;
default:
return TRUE;
}
//FIXME
return TRUE;
}
/// @unimplemented
STDMETHODIMP_(BOOL) CButtonIconItem::OnDelayMsg(UINT uMsg)
{
//FIXME
return FALSE;
}
/***********************************************************************
* CMainIconItem
*/
CMainIconItem::CMainIconItem(CTrayIconWnd *pWnd)
: CButtonIconItem(pWnd, 1)
{
}
BOOL CMainIconItem::Init(HWND hWnd)
{
return CTrayIconItem::_Init(hWnd, WM_USER, 0, GUID_LBI_TRAYMAIN);
}
/// @unimplemented
STDMETHODIMP_(BOOL) CMainIconItem::OnDelayMsg(UINT uMsg)
{
if (!CButtonIconItem::OnDelayMsg(uMsg))
return 0;
if (uMsg == WM_LBUTTONDBLCLK)
{
//FIXME
//if (g_pTipbarWnd->m_dwUnknown20)
// g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
}
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
{
//FIXME
//g_pTipbarWnd->ShowContextMenu(m_ptCursor, &m_rcClient, uMsg == WM_RBUTTONDOWN);
}
return TRUE;
}
/***********************************************************************
* CTrayIconWnd
*/
CTrayIconWnd::CTrayIconWnd()
{
m_uCallbackMsg = WM_USER + 0x1000;
m_uNotifyIconID = 0x1000;
}
CTrayIconWnd::~CTrayIconWnd()
{
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
auto& pItem = m_Items[iItem];
if (pItem)
{
delete pItem;
pItem = NULL;
}
}
}
void CTrayIconWnd::CallOnDelayMsg()
{
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
auto pItem = m_Items[iItem];
if (pItem && m_uCallbackMessage == pItem->m_uCallbackMessage)
{
pItem->OnDelayMsg(m_uMsg);
break;
}
}
}
HWND CTrayIconWnd::CreateWnd()
{
m_hWnd = ::CreateWindowEx(0, TEXT("CTrayIconWndClass"), NULL, WS_DISABLED,
0, 0, 0, 0, NULL, NULL, g_hInst, this);
FindTrayEtc();
m_pMainIconItem = new(cicNoThrow) CMainIconItem(this);
if (m_pMainIconItem)
{
m_pMainIconItem->Init(m_hWnd);
m_Items.Add(m_pMainIconItem);
}
return m_hWnd;
}
void CTrayIconWnd::DestroyWnd()
{
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
}
BOOL CALLBACK CTrayIconWnd::EnumChildWndProc(HWND hWnd, LPARAM lParam)
{
CTrayIconWnd *pWnd = (CTrayIconWnd *)lParam;
TCHAR ClassName[60];
::GetClassName(hWnd, ClassName, _countof(ClassName));
if (lstrcmp(ClassName, TEXT("TrayNotifyWnd")) != 0)
return TRUE;
pWnd->m_hNotifyWnd = hWnd;
return FALSE;
}
CButtonIconItem *CTrayIconWnd::FindIconItem(REFGUID rguid)
{
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
auto pItem = m_Items[iItem];
if (IsEqualGUID(rguid, pItem->m_guid))
return pItem;
}
return NULL;
}
BOOL CTrayIconWnd::FindTrayEtc()
{
m_hTrayWnd = ::FindWindow(TEXT("Shell_TrayWnd"), NULL);
if (!m_hTrayWnd)
return FALSE;
::EnumChildWindows(m_hTrayWnd, EnumChildWndProc, (LPARAM)this);
if (!m_hNotifyWnd)
return FALSE;
m_dwTrayWndThreadId = ::GetWindowThreadProcessId(m_hTrayWnd, NULL);
m_hwndProgman = FindWindow(TEXT("Progman"), NULL);
m_dwProgmanThreadId = ::GetWindowThreadProcessId(m_hwndProgman, NULL);
return TRUE;
}
HWND CTrayIconWnd::GetNotifyWnd()
{
if (!::IsWindow(m_hNotifyWnd))
FindTrayEtc();
return m_hNotifyWnd;
}
/// @unimplemented
BOOL CTrayIconWnd::OnIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//FIXME
//if (g_pTipbarWnd)
// g_pTipbarWnd->AttachFocusThread();
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
auto pItem = m_Items[iItem];
if (pItem)
{
if (uMsg == pItem->m_uCallbackMessage)
{
pItem->OnMsg(wParam, lParam);
return TRUE;
}
}
}
return FALSE;
}
BOOL CTrayIconWnd::RegisterClass()
{
WNDCLASSEX wc = { sizeof(wc) };
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = g_hInst;
wc.hCursor = ::LoadCursor(NULL, (LPCTSTR)IDC_ARROW);
wc.lpfnWndProc = CTrayIconWnd::_WndProc;
wc.lpszClassName = TEXT("CTrayIconWndClass");
::RegisterClassEx(&wc);
return TRUE;
}
void CTrayIconWnd::RemoveAllIcon(DWORD dwFlags)
{
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
auto pItem = m_Items[iItem];
if (dwFlags & 0x1)
{
if (IsEqualGUID(pItem->m_guid, GUID_LBI_INATITEM) ||
IsEqualGUID(pItem->m_guid, GUID_LBI_CTRL))
{
continue;
}
}
if (dwFlags & 0x2)
{
if (IsEqualGUID(pItem->m_guid, GUID_TFCAT_TIP_KEYBOARD))
continue;
}
if (pItem->m_uNotifyIconID < 0x1000)
continue;
pItem->RemoveIcon();
}
}
/// @unimplemented
void CTrayIconWnd::RemoveUnusedIcons(int unknown)
{
//FIXME
}
BOOL CTrayIconWnd::SetIcon(REFGUID rguid, DWORD dwUnknown24, HICON hIcon, LPCWSTR psz)
{
CButtonIconItem *pItem = FindIconItem(rguid);
if (!pItem)
{
if (!hIcon)
return FALSE;
pItem = new(cicNoThrow) CButtonIconItem(this, dwUnknown24);
if (!pItem)
return FALSE;
pItem->_Init(m_hWnd, m_uCallbackMsg, m_uNotifyIconID, rguid);
m_uCallbackMsg += 2;
++m_uNotifyIconID;
m_Items.Add(pItem);
}
if (!hIcon)
return pItem->RemoveIcon();
return pItem->SetIcon(hIcon, psz);
}
BOOL CTrayIconWnd::SetMainIcon(HKL hKL)
{
if (!hKL)
{
m_pMainIconItem->RemoveIcon();
m_pMainIconItem->m_hKL = NULL;
return TRUE;
}
if (hKL != m_pMainIconItem->m_hKL)
{
WCHAR szText[64];
HICON hIcon = TF_GetLangIcon(LOWORD(hKL), szText, _countof(szText));
if (hIcon)
{
m_pMainIconItem->SetIcon(hIcon, szText);
::DestroyIcon(hIcon);
}
else
{
::LoadStringW(g_hInst, IDS_RESTORELANGBAR, szText, _countof(szText));
hIcon = ::LoadIconW(g_hInst, MAKEINTRESOURCEW(IDI_MAINICON));
m_pMainIconItem->SetIcon(hIcon, szText);
}
m_pMainIconItem->m_hKL = hKL;
}
return TRUE;
}
CTrayIconWnd *CTrayIconWnd::GetThis(HWND hWnd)
{
return (CTrayIconWnd *)::GetWindowLongPtr(hWnd, GWL_USERDATA);
}
void CTrayIconWnd::SetThis(HWND hWnd, LPCREATESTRUCT pCS)
{
if (pCS)
::SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)pCS->lpCreateParams);
else
::SetWindowLongPtr(hWnd, GWL_USERDATA, 0);
}
LRESULT CALLBACK
CTrayIconWnd::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CTrayIconWnd *pThis;
switch (uMsg)
{
case WM_CREATE:
CTrayIconWnd::SetThis(hWnd, (LPCREATESTRUCT)lParam);
break;
case WM_DESTROY:
::SetWindowLongPtr(hWnd, GWL_USERDATA, 0);
break;
case WM_TIMER:
if (wParam == 100)
{
::KillTimer(hWnd, 100);
pThis = CTrayIconWnd::GetThis(hWnd);
if (pThis)
pThis->CallOnDelayMsg();
}
break;
default:
{
if (uMsg < WM_USER)
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
pThis = CTrayIconWnd::GetThis(hWnd);
if (pThis && pThis->OnIconMessage(uMsg, wParam, lParam))
break;
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return 0;
}
/***********************************************************************
* GetLibTls (MSUTB.@)
*

View file

@ -20,6 +20,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include <reactos/manifest_hosted.rc>
IDI_MAINICON ICON "res/earth.ico"
/* UTF-8 */
#pragma code_page(65001)

View file

@ -20,6 +20,7 @@
#include <cguid.h>
#include <msctf.h>
#include <ctffunc.h>
#include <ctfutb.h>
#include <shlwapi.h>
#include <atlbase.h>
#include <atlcom.h>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -7,6 +7,10 @@
#define IDS_IGNORE 104
#define IDS_YES 105
#define IDS_NO 106
#define IDI_MAINICON 100
#define IDS_RESTORELANGBAR 308
#define IDS_MENUWND 322
#define IDS_LEFTCLICK 323

View file

@ -43,6 +43,7 @@ cpp_quote("EXTERN_C HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist(VOID);")
cpp_quote("EXTERN_C HRESULT WINAPI TF_DllDetachInOther(VOID);")
cpp_quote("EXTERN_C HRESULT WINAPI TF_CreateCategoryMgr(ITfCategoryMgr **ppcat);")
cpp_quote("EXTERN_C HRESULT WINAPI TF_CreateDisplayAttributeMgr(ITfDisplayAttributeMgr **ppdam);")
cpp_quote("EXTERN_C HICON WINAPI TF_GetLangIcon(LANGID LangID, LPWSTR pszText, INT cchText);")
cpp_quote("EXTERN_C const GUID GUID_PROP_TEXTOWNER;")
cpp_quote("EXTERN_C const GUID GUID_PROP_ATTRIBUTE;")

View file

@ -8,6 +8,10 @@
#pragma once
DEFINE_GUID(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0x544D6A63, 0xE2E8, 0x4752, 0xBB, 0xD1, 0x00, 0x09, 0x60, 0xBC, 0xA0, 0x83);
DEFINE_GUID(GUID_LBI_TRAYMAIN, 0xE0B724E9, 0x6F76, 0x45F7, 0xB4, 0xC1, 0xB1, 0xC0, 0xFA, 0xBC, 0xE2, 0x3E);
DEFINE_GUID(GUID_LBI_INATITEM, 0xCDBC683A, 0x55CE, 0x4717, 0xBA, 0xC0, 0x50, 0xBF, 0x44, 0xA3, 0x27, 0x0C);
DEFINE_GUID(GUID_LBI_CTRL, 0x58C99D96, 0x2F9B, 0x42CE, 0x91, 0xBE, 0x37, 0xEF, 0x18, 0x60, 0xF8, 0x82);
DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745C63, 0xB2F0, 0x4784, 0x8B, 0x67, 0x5E, 0x12, 0xC8, 0x70, 0x1A, 0x31);
EXTERN_C LPVOID WINAPI GetLibTls(VOID);
EXTERN_C BOOL WINAPI GetPopupTipbar(HWND hWnd, BOOL fWinLogon);