ReactOS 0.4.16-dev-319-g6cf4263
msutb.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS msutb.dll
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Language Bar (Tipbar)
5 * COPYRIGHT: Copyright 2023-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9
11
12//#define ENABLE_DESKBAND
13
14typedef struct LANGBARITEMSTATE
15{
22
24 {
25 return m_dwDemoteLevel < 2;
26 }
28
39#ifdef ENABLE_DESKBAND
41#else
43#endif
44
51UINT g_uTimeOutIntentional = 10 * 60 * 1000;
52UINT g_uTimeOutMax = 60 * 60 * 1000;
54POINT g_ptTipbar = { -1, -1 };
81
82#define TIMER_ID_DOACCDEFAULTACTION 11
83
84class CMsUtbModule : public CComModule
85{
86};
87
89
90class CCicLibMenuItem;
91class CTipbarAccItem;
92class CUTBMenuItem;
93class CMainIconItem;
94class CTrayIconItem;
95class CTipbarWnd;
96class CButtonIconItem;
97class CTrayIconWnd;
98
101
103
105{
107 return FALSE; // Japanese HKL will be skipped
109 return FALSE;
110
111 for (size_t iItem = 0; iItem < g_prghklSkipRedrawing->size(); ++iItem)
112 {
113 if ((*g_prghklSkipRedrawing)[iItem] == hSkipKL)
114 return TRUE; // To be skipped
115 }
116
117 return FALSE; // To be not skipped
118}
119
121{
122 LOCALESIGNATURE Sig;
124 if (!LangID)
125 return FALSE;
126
127 INT size = sizeof(Sig) / sizeof(WCHAR);
129 return FALSE;
130 return (Sig.lsUsb[3] & 0x8000000) != 0;
131}
132
134{
135 LOCALESIGNATURE Sig;
136 INT size = sizeof(Sig) / sizeof(WCHAR);
138 return FALSE;
139
140 HDC hDC = ::GetDC(hWnd);
142 CHARSETINFO CharSetInfo;
145
146 return !!(CharSetInfo.fs.fsCsb[0] & Sig.lsCsbSupported[0]);
147}
148
150{
153 return;
154
156 {
157 // Japanese IME will be skipped
158 g_prghklSkipRedrawing->Add((HKL)UlongToHandle(0xE0010411));
159 }
160
161 CicRegKey regKey;
163 TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\SkipRedrawHKL"));
164 if (error != ERROR_SUCCESS)
165 return;
166
167 TCHAR szValueName[256];
168 for (DWORD dwIndex = 0; ; ++dwIndex)
169 {
170 error = regKey.EnumValue(dwIndex, szValueName, _countof(szValueName));
171 if (error != ERROR_SUCCESS)
172 break;
173
174 if (szValueName[0] == TEXT('0') &&
175 (szValueName[1] == TEXT('x') || szValueName[1] == TEXT('X')))
176 {
177 HKL hKL = (HKL)UlongToHandle(_tcstoul(szValueName, NULL, 16));
178 g_prghklSkipRedrawing->Add(hKL); // This hKL will be skipped
179 }
180 }
181}
182
184{
186 {
189 }
190}
191
193{
196 if (FAILED(hr))
197 return hr;
198
199 if (!pCompMgr)
200 return E_FAIL;
201
202 hr = pCompMgr->GetCompartment(rguid, ppComp);
203 pCompMgr->Release();
204 return hr;
205}
206
208{
209 *pdwValue = 0;
210 ITfCompartment *pComp;
211 HRESULT hr = GetGlobalCompartment(rguid, &pComp);
212 if (SUCCEEDED(hr))
213 {
214 VARIANT vari;
215 hr = pComp->GetValue(&vari);
216 if (hr == S_OK)
217 *pdwValue = V_I4(&vari);
218 pComp->Release();
219 }
220 return hr;
221}
222
224{
225 VARIANT vari;
226 ITfCompartment *pComp;
227 HRESULT hr = GetGlobalCompartment(rguid, &pComp);
228 if (SUCCEEDED(hr))
229 {
230 V_VT(&vari) = VT_I4;
231 V_I4(&vari) = dwValue;
232 hr = pComp->SetValue(0, &vari);
233 pComp->Release();
234 }
235 return hr;
236}
237
239{
240 DWORD dwValue = 0;
242 if (SUCCEEDED(hr) && dwValue)
244}
245
247{
248 ITfLangBarMgr *pLangBarMgr = NULL;
249 HRESULT hr = TF_CreateLangBarMgr(&pLangBarMgr);
250 if (FAILED(hr))
251 return;
252
253 if (pLangBarMgr)
254 {
255 hr = pLangBarMgr->ShowFloating(TF_SFT_HIDDEN);
256 pLangBarMgr->Release();
257 }
258
259 if (SUCCEEDED(hr))
261
262 CicRegKey regKey;
264 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
266 if (error == ERROR_SUCCESS)
267 ::RegDeleteValue(regKey, TEXT("ctfmon.exe"));
268}
269
271{
272 HKL hGotKL;
273
274 INT iKL, cKLs = TF_MlngInfoCount();
275 for (iKL = 0; iKL < cKLs; ++iKL)
276 {
277 if (TF_GetMlngHKL(iKL, &hGotKL, NULL, 0) && hKL == hGotKL)
278 return TF_GetMlngIconIndex(iKL);
279 }
280
281 if (!TF_GetMlngHKL(0, &hGotKL, NULL, 0))
282 return -1;
283
284 return TF_GetMlngIconIndex(0);
285}
286
287BOOL GethKLDesc(_In_ HKL hKL, _Out_ LPWSTR pszDesc, _In_ UINT cchDesc)
288{
289 HKL hGotKL;
290
291 INT iKL, cKLs = TF_MlngInfoCount();
292 for (iKL = 0; iKL < cKLs; ++iKL)
293 {
294 if (TF_GetMlngHKL(iKL, &hGotKL, pszDesc, cchDesc) && hKL == hGotKL)
295 return TRUE;
296 }
297
298 return TF_GetMlngHKL(0, &hGotKL, pszDesc, cchDesc);
299}
300
303 _In_ ITfMenu *pMenu,
304 _In_ UINT uId,
305 _In_ LPCWSTR pszText,
306 _In_ BOOL bChecked,
308{
309 HBITMAP hbmp = NULL, hbmpMask = NULL;
310 if (hIcon)
311 {
313 SIZE iconSize = { 16, 16 };
314 if (!hIconNew)
315 hIconNew = hIcon;
316 if (!cicGetIconBitmaps(hIconNew, &hbmp, &hbmpMask, &iconSize))
317 return E_FAIL;
318 if (hIconNew)
319 ::DestroyIcon(hIconNew);
321 }
322
323 INT cchText = lstrlenW(pszText);
324 DWORD dwFlags = (bChecked ? TF_LBMENUF_CHECKED : 0);
325 return pMenu->AddMenuItem(uId, dwFlags, hbmp, hbmpMask, pszText, cchText, NULL);
326}
327
329{
330 return pMenu->AddMenuItem(-1, TF_LBMENUF_SEPARATOR, NULL, NULL, NULL, 0, NULL);
331}
332
333// Is it a Far-East language ID?
335{
336 switch (LangID)
337 {
338 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): // Chinese (Simplified)
339 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): // Chinese (Traditional)
340 case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): // Japanese
341 case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): // Korean
342 return TRUE;
343 default:
344 return FALSE;
345 }
346}
347
349{
350 BOOL ret = FALSE;
351 ITfInputProcessorProfiles *pProfiles = NULL;
352 LANGID *pLangIds = NULL;
353 ULONG iItem, cItems;
354
356 return FALSE;
357
359 return TRUE;
360
362 SUCCEEDED(pProfiles->GetLanguageList(&pLangIds, &cItems)))
363 {
364 for (iItem = 0; iItem < cItems; ++iItem)
365 {
366 if (IsFELangId(pLangIds[iItem]))
367 break;
368 }
369
370 ret = (iItem == cItems);
371 }
372
373 if (pLangIds)
374 CoTaskMemFree(pLangIds);
375 if (pProfiles)
376 pProfiles->Release();
377
378 return ret;
379}
380
383{
384 return FALSE;
385}
386
387static INT CALLBACK
389{
390 if ((nFontType != TRUETYPE_FONTTYPE) || (pLF->elfLogFont.lfFaceName[0] != '@'))
391 return TRUE;
392 *(BOOL*)lParam = TRUE;
393 return FALSE;
394}
395
398{
399 BOOL bHasVertical = FALSE;
400 HDC hDC = ::GetDC(NULL);
403 return bHasVertical;
404}
405
407{
408 if (!g_bEnableDeskBand || !(g_dwOSInfo & CIC_OSINFO_XPPLUS)) // Desk band is for XP+
409 return FALSE;
410
411 CicRegKey regKey;
412 if (regKey.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\")))
413 {
414 DWORD dwValue = 0;
415 regKey.QueryDword(TEXT("ShowDeskBand"), &dwValue);
416 return !!dwValue;
417 }
418
419 return FALSE;
420}
421
423{
424 CicRegKey regKey;
425 if (regKey.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"), KEY_ALL_ACCESS))
426 regKey.SetDword(TEXT("ShowDeskBand"), bShow);
427}
428
429BOOL RegisterComCat(REFCLSID rclsid, REFCATID rcatid, BOOL bRegister)
430{
432 return FALSE;
433
434 ICatRegister *pCat;
435 HRESULT hr = ::CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
436 IID_ICatRegister, (void**)&pCat);
437 if (SUCCEEDED(hr))
438 {
439 if (bRegister)
440 hr = pCat->RegisterClassImplCategories(rclsid, 1, const_cast<CATID*>(&rcatid));
441 else
442 hr = pCat->UnRegisterClassImplCategories(rclsid, 1, const_cast<CATID*>(&rcatid));
443
444 pCat->Release();
445 }
446
448
449 //if (IsIE5())
450 // ::RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("Component Categories\\{00021492-0000-0000-C000-000000000046}\\Enum"));
451
452 return SUCCEEDED(hr);
453}
454
456{
457 DWORD dwValue;
459
460 CicRegKey regKey1;
461 error = regKey1.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\"));
462 if (error == ERROR_SUCCESS)
463 {
464 error = regKey1.QueryDword(TEXT("ShowTipbar"), &dwValue);
465 if (error == ERROR_SUCCESS)
466 g_bShowTipbar = !!dwValue;
467 }
468
469 CicRegKey regKey2;
470 error = regKey2.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"));
471 if (error == ERROR_SUCCESS)
472 {
473 error = regKey2.QueryDword(TEXT("ShowDebugMenu"), &dwValue);
474 if (error == ERROR_SUCCESS)
475 g_bShowDebugMenu = !!dwValue;
476 error = regKey2.QueryDword(TEXT("NewLook"), &dwValue);
477 if (error == ERROR_SUCCESS)
478 g_bNewLook = !!dwValue;
479 error = regKey2.QueryDword(TEXT("IntelliSense"), &dwValue);
480 if (error == ERROR_SUCCESS)
481 g_bIntelliSense = !!dwValue;
482 error = regKey2.QueryDword(TEXT("ShowCloseMenu"), &dwValue);
483 if (error == ERROR_SUCCESS)
484 g_bShowCloseMenu = !!dwValue;
485 error = regKey2.QueryDword(TEXT("TimeOutNonIntentional"), &dwValue);
486 if (error == ERROR_SUCCESS)
487 g_uTimeOutNonIntentional = 1000 * dwValue;
488 error = regKey2.QueryDword(TEXT("TimeOutIntentional"), &dwValue);
489 if (error == ERROR_SUCCESS)
490 {
491 g_uTimeOutIntentional = 1000 * dwValue;
492 g_uTimeOutMax = 6000 * dwValue;
493 }
494 error = regKey2.QueryDword(TEXT("ShowMinimizedBalloon"), &dwValue);
495 if (error == ERROR_SUCCESS)
496 g_bShowMinimizedBalloon = !!dwValue;
497 error = regKey2.QueryDword(TEXT("Left"), &dwValue);
498 if (error == ERROR_SUCCESS)
499 g_ptTipbar.x = dwValue;
500 error = regKey2.QueryDword(TEXT("Top"), &dwValue);
501 if (error == ERROR_SUCCESS)
502 g_ptTipbar.y = dwValue;
503 error = regKey2.QueryDword(TEXT("ExcludeCaptionButtons"), &dwValue);
504 if (error == ERROR_SUCCESS)
505 g_bExcludeCaptionButtons = !!dwValue;
506 error = regKey2.QueryDword(TEXT("ShowShadow"), &dwValue);
507 if (error == ERROR_SUCCESS)
508 g_bShowShadow = !!dwValue;
509 error = regKey2.QueryDword(TEXT("TaskbarTheme"), &dwValue);
510 if (error == ERROR_SUCCESS)
511 g_fTaskbarTheme = !!dwValue;
512 error = regKey2.QueryDword(TEXT("Vertical"), &dwValue);
513 if (error == ERROR_SUCCESS)
514 g_fVertical = !!dwValue;
515 error = regKey2.QueryDword(TEXT("TimerElapseSTUBSTART"), &dwValue);
516 if (error == ERROR_SUCCESS)
517 g_uTimerElapseSTUBSTART = dwValue;
518 error = regKey2.QueryDword(TEXT("TimerElapseSTUBEND"), &dwValue);
519 if (error == ERROR_SUCCESS)
520 g_uTimerElapseSTUBEND = dwValue;
521 error = regKey2.QueryDword(TEXT("TimerElapseBACKTOALPHA"), &dwValue);
522 if (error == ERROR_SUCCESS)
524 error = regKey2.QueryDword(TEXT("TimerElapseONTHREADITEMCHANGE"), &dwValue);
525 if (error == ERROR_SUCCESS)
527 error = regKey2.QueryDword(TEXT("TimerElapseSETWINDOWPOS"), &dwValue);
528 if (error == ERROR_SUCCESS)
530 error = regKey2.QueryDword(TEXT("TimerElapseONUPDATECALLED"), &dwValue);
531 if (error == ERROR_SUCCESS)
533 error = regKey2.QueryDword(TEXT("TimerElapseSYSCOLORCHANGED"), &dwValue);
534 if (error == ERROR_SUCCESS)
536 error = regKey2.QueryDword(TEXT("TimerElapseDISPLAYCHANGE"), &dwValue);
537 if (error == ERROR_SUCCESS)
539 error = regKey2.QueryDword(TEXT("TimerElapseUPDATEUI"), &dwValue);
540 if (error == ERROR_SUCCESS)
541 g_uTimerElapseUPDATEUI = dwValue;
542 error = regKey2.QueryDword(TEXT("TimerElapseSHOWWINDOW"), &dwValue);
543 if (error == ERROR_SUCCESS)
544 g_uTimerElapseSHOWWINDOW = dwValue;
545 error = regKey2.QueryDword(TEXT("TimerElapseMOVETOTRAY"), &dwValue);
546 if (error == ERROR_SUCCESS)
547 g_uTimerElapseMOVETOTRAY = dwValue;
548 error = regKey2.QueryDword(TEXT("TimerElapseTRAYWNDONDELAYMSG"), &dwValue);
549 if (error == ERROR_SUCCESS)
551 error = regKey2.QueryDword(TEXT("TimerElapseDOACCDEFAULTACTION"), &dwValue);
552 if (error == ERROR_SUCCESS)
554 error = regKey2.QueryDword(TEXT("TimerElapseENSUREFOCUS"), &dwValue);
555 if (error == ERROR_SUCCESS)
558 {
559 error = regKey2.QueryDword(TEXT("ShowDeskBand"), &dwValue);
560 if (error == ERROR_SUCCESS)
561 g_bShowDeskBand = !!dwValue;
562 error = regKey2.QueryDword(TEXT("TimerElapseSHOWWDESKBAND"), &dwValue);
563 if (error == ERROR_SUCCESS)
565 }
566 }
567
568 CicRegKey regKey3;
569 error = regKey3.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Policies\\Microsoft\\MSCTF"));
570 if (error == ERROR_SUCCESS)
571 {
572 error = regKey3.QueryDword(TEXT("DisableCloseButton"), &dwValue);
573 if (error == ERROR_SUCCESS)
574 g_fPolicyDisableCloseButton = !!dwValue;
575 }
576
577 CicRegKey regKey4;
578 error = regKey4.Open(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Policies\\Microsoft\\MSCTF"));
579 if (error == ERROR_SUCCESS)
580 {
581 error = regKey4.QueryDword(TEXT("EnableLanguagebarInFullscreen"), &dwValue);
582 if (error == ERROR_SUCCESS)
584 }
585
587
588 if (g_bNewLook)
589 {
592 if (g_bShowShadow)
596 }
597 else
598 {
602 }
603
606
608 {
612 g_fRTL = TRUE;
613 }
614
615 return TRUE;
616}
617
618/***********************************************************************/
619
621{
624
626 {
628 m_hTrayWnd = ::FindWindowW(L"Shell_TrayWnd", NULL);
629 return m_hTrayWnd;
630 }
631
633 {
635 m_hProgmanWnd = ::FindWindowW(L"Progman", NULL);
636 return m_hProgmanWnd;
637 }
638
639 void clear()
640 {
642 }
643};
644
645/***********************************************************************/
646
648{
649protected:
652
653public:
655 virtual ~CUTBLangBarDlg() { }
656
657 static CUTBLangBarDlg *GetThis(HWND hDlg);
658 static void SetThis(HWND hDlg, CUTBLangBarDlg *pThis);
659 static DWORD WINAPI s_ThreadProc(LPVOID pParam);
661
663 LONG _Release();
664
665 STDMETHOD_(BOOL, DoModal)(HWND hDlg) = 0;
667 STDMETHOD_(BOOL, IsDlgShown)() = 0;
668 STDMETHOD_(void, SetDlgShown)(BOOL bShown) = 0;
670};
671
672/***********************************************************************/
673
675{
676public:
678
680
681 STDMETHOD_(BOOL, DoModal)(HWND hDlg) override;
683 STDMETHOD_(BOOL, IsDlgShown)() override;
684 STDMETHOD_(void, SetDlgShown)(BOOL bShown) override;
685};
686
688
689/***********************************************************************/
690
692{
693public:
695
697
698 STDMETHOD_(BOOL, DoModal)(HWND hDlg) override;
700 STDMETHOD_(BOOL, IsDlgShown)() override;
701 STDMETHOD_(void, SetDlgShown)(BOOL bShown) override;
703};
704
706
707/***********************************************************************/
708
709class CCicLibMenu : public ITfMenu
710{
711protected:
714
715public:
716 CCicLibMenu();
717 virtual ~CCicLibMenu();
718
719 STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj) override;
720 STDMETHOD_(ULONG, AddRef)() override;
723 UINT uId,
726 HBITMAP hbmpMask,
727 const WCHAR *pch,
728 ULONG cch,
729 ITfMenu **ppSubMenu) override;
730 STDMETHOD_(CCicLibMenu*, CreateSubMenu)();
731 STDMETHOD_(CCicLibMenuItem*, CreateMenuItem)();
732};
733
734/***********************************************************************/
735
737{
738protected:
745
746public:
748 virtual ~CCicLibMenuItem();
749
750 BOOL Init(
751 UINT uId,
754 HBITMAP hbmpMask,
755 const WCHAR *pch,
756 ULONG cch,
757 ITfMenu *pMenu);
759};
760
761/***********************************************************************/
762
764{
765protected:
773 friend class CUTBMenuWnd;
774 friend class CTipbarWnd;
775
776public:
778 virtual ~CTipbarAccessible();
779
781
784 void ClearAccItems();
787
791 void SetWindow(HWND hWnd);
792
793 // IUnknown methods
797
798 // IDispatch methods
801 UINT iTInfo,
802 LCID lcid,
803 ITypeInfo **ppTInfo);
805 REFIID riid,
806 LPOLESTR *rgszNames,
807 UINT cNames,
808 LCID lcid,
809 DISPID *rgDispId);
811 DISPID dispIdMember,
812 REFIID riid,
813 LCID lcid,
814 WORD wFlags,
815 DISPPARAMS *pDispParams,
816 VARIANT *pVarResult,
817 EXCEPINFO *pExcepInfo,
818 UINT *puArgErr);
819
820 // IAccessible methods
821 STDMETHOD(get_accParent)(IDispatch **ppdispParent);
822 STDMETHOD(get_accChildCount)(LONG *pcountChildren);
823 STDMETHOD(get_accChild)(VARIANT varChildID, IDispatch **ppdispChild);
824 STDMETHOD(get_accName)(VARIANT varID, BSTR *pszName);
825 STDMETHOD(get_accValue)(VARIANT varID, BSTR *pszValue);
827 STDMETHOD(get_accRole)(VARIANT varID, VARIANT *role);
830 STDMETHOD(get_accHelpTopic)(BSTR *helpfile, VARIANT varID, LONG *pidTopic);
835 STDMETHOD(accSelect)(LONG flagsSelect, VARIANT varID);
837 LONG *left,
838 LONG *top,
839 LONG *width,
840 LONG *height,
841 VARIANT varID);
842 STDMETHOD(accNavigate)(LONG dir, VARIANT varStart, VARIANT *pvarEnd);
847};
848
849/***********************************************************************/
850
852{
853public:
855 virtual ~CTipbarAccItem() { }
856
857 STDMETHOD_(BSTR, GetAccName)()
858 {
859 return SysAllocString(L"");
860 }
861 STDMETHOD_(BSTR, GetAccValue)()
862 {
863 return NULL;
864 }
865 STDMETHOD_(INT, GetAccRole)()
866 {
867 return 10;
868 }
869 STDMETHOD_(INT, GetAccState)()
870 {
871 return 256;
872 }
873 STDMETHOD_(void, GetAccLocation)(LPRECT lprc)
874 {
875 *lprc = { 0, 0, 0, 0 };
876 }
877 STDMETHOD_(BSTR, GetAccDefaultAction)()
878 {
879 return NULL;
880 }
881 STDMETHOD_(BOOL, DoAccDefaultAction)()
882 {
883 return FALSE;
884 }
885 STDMETHOD_(BOOL, DoAccDefaultActionReal)()
886 {
887 return FALSE;
888 }
889};
890
891/***********************************************************************/
892
894{
895public:
897
900
902 {
903 if (m_bCoInit)
904 return S_OK;
906 if (FAILED(hr))
907 return hr;
908 m_bCoInit = TRUE;
909 return S_OK;
910 }
911
912 void CoUninit()
913 {
914 if (m_bCoInit)
915 {
918 }
919 }
920};
921
922/***********************************************************************/
923
924class CUTBMenuWnd : public CTipbarAccItem, public CUIFMenu
925{
926protected:
930 friend class CUTBMenuItem;
931
932public:
934
936
938 {
939 return static_cast<CTipbarAccItem*>(this);
940 }
942 {
943 return static_cast<CUIFMenu*>(this);
944 }
945
946 STDMETHOD_(BSTR, GetAccName)() override;
947 STDMETHOD_(INT, GetAccRole)() override;
949 STDMETHOD_(void, OnCreate)(HWND hWnd) override;
950 STDMETHOD_(void, OnDestroy)(HWND hWnd) override;
953 STDMETHOD_(void, OnTimer)(WPARAM wParam) override;
954};
955
956/***********************************************************************/
957
959{
960protected:
962 friend class CUTBMenuWnd;
963
964public:
965 CUTBMenuItem(CUTBMenuWnd *pMenuUI);
966 ~CUTBMenuItem() override;
967
969 {
970 return static_cast<CUIFMenuItem*>(this);
971 }
972
973 STDMETHOD_(BOOL, DoAccDefaultAction)() override;
974 STDMETHOD_(BOOL, DoAccDefaultActionReal)() override;
975 STDMETHOD_(BSTR, GetAccDefaultAction)() override;
976 STDMETHOD_(void, GetAccLocation)(LPRECT lprc) override;
977 STDMETHOD_(BSTR, GetAccName)() override;
978 STDMETHOD_(INT, GetAccRole)() override;
979};
980
981/***********************************************************************/
982
984{
985public:
988
989public:
991 virtual ~CModalMenu() { }
992
993 CUTBMenuItem *InsertItem(CUTBMenuWnd *pMenuUI, INT nCommandId, INT nStringID);
995 void CancelMenu();
996};
997
998/***********************************************************************/
999
1000class CTipbarThread;
1001
1003{
1004public:
1007
1008public:
1009 CUTBContextMenu(CTipbarWnd *pTipbarWnd);
1010
1011 BOOL Init();
1013
1015 CUIFWindow *pWindow,
1016 POINT pt,
1017 LPCRECT prc,
1018 BOOL bFlag);
1019
1020 BOOL SelectMenuItem(UINT nCommandId);
1021};
1022
1023/***********************************************************************/
1024
1025class CUTBLBarMenuItem;
1026
1028{
1029protected:
1032
1033public:
1035 ~CUTBLBarMenu() override;
1036
1038 INT ShowPopup(CUIFWindow *pWindow, POINT pt, LPCRECT prcExclude);
1039
1040 STDMETHOD_(CCicLibMenuItem*, CreateMenuItem)() override;
1041 STDMETHOD_(CCicLibMenu*, CreateSubMenu)() override;
1042};
1043
1044/***********************************************************************/
1045
1047{
1048public:
1050
1051public:
1053 BOOL InsertToUI(CUTBMenuWnd *pMenuUI);
1054};
1055
1056/***********************************************************************/
1057
1059{
1060protected:
1063 friend class CTipbarWnd;
1064
1065public:
1067
1068 STDMETHOD_(void, OnLButtonUp)(LONG x, LONG y) override;
1069 STDMETHOD_(void, OnRButtonUp)(LONG x, LONG y) override;
1070 STDMETHOD_(BOOL, OnSetCursor)(UINT uMsg, LONG x, LONG y) override;
1071};
1072
1073/***********************************************************************/
1074
1075class CLangBarItemList : public CicArray<LANGBARITEMSTATE>
1076{
1077public:
1079
1081 void Clear();
1082 BOOL SetDemoteLevel(REFCLSID rclsid, DWORD dwDemoteLevel);
1083
1086
1087 void Load();
1088 void SaveItem(CicRegKey *pRegKey, const LANGBARITEMSTATE *pState);
1089
1090 void StartDemotingTimer(REFCLSID rclsid, BOOL bIntentional);
1092};
1093
1094/***********************************************************************/
1095
1097{
1098protected:
1115 friend class CTipbarWnd;
1116
1119
1120public:
1121 CTrayIconWnd();
1122 ~CTrayIconWnd();
1123
1124 static BOOL RegisterClass();
1125 static CTrayIconWnd *GetThis(HWND hWnd);
1126 static void SetThis(HWND hWnd, LPCREATESTRUCT pCS);
1127
1128 HWND CreateWnd();
1129 void DestroyWnd();
1130
1131 BOOL SetMainIcon(HKL hKL);
1132 BOOL SetIcon(REFGUID rguid, DWORD dwUnknown24, HICON hIcon, LPCWSTR psz);
1133
1135 void RemoveUnusedIcons(int unknown);
1136
1138 BOOL FindTrayEtc();
1141
1142 void CallOnDelayMsg();
1143};
1144
1145/***********************************************************************/
1146
1148{
1149protected:
1160 friend class CTrayIconWnd;
1161
1162public:
1163 CTrayIconItem(CTrayIconWnd *pTrayIconWnd);
1164 virtual ~CTrayIconItem() { }
1165
1166 BOOL _Init(HWND hWnd, UINT uCallbackMessage, UINT uNotifyIconID, const GUID& rguid);
1168 BOOL RemoveIcon();
1169
1172 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) { return 0; };
1173};
1174
1175/***********************************************************************/
1176
1178{
1179protected:
1182 friend class CTrayIconWnd;
1183
1184public:
1185 CButtonIconItem(CTrayIconWnd *pWnd, DWORD dwUnknown24);
1186
1188 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
1189};
1190
1191/***********************************************************************/
1192
1194{
1195public:
1197
1198 BOOL Init(HWND hWnd);
1199 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
1200};
1201
1202/***********************************************************************/
1203
1205{
1206protected:
1212
1213public:
1214 CLBarItemBase();
1215 virtual ~CLBarItemBase();
1216
1217 HRESULT ShowInternal(BOOL bShow, BOOL bUpdate);
1218
1219 void InitNuiInfo(
1220 REFIID clsidService,
1221 REFGUID guidItem,
1222 DWORD dwStyle,
1223 DWORD ulSort,
1224 LPCWSTR Source);
1225
1227 HRESULT GetStatus(DWORD *pdwStatus);
1228 HRESULT Show(BOOL fShow);
1229 HRESULT GetTooltipString(BSTR *pbstrToolTip);
1230
1231 HRESULT AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie);
1232 HRESULT UnadviseSink(DWORD dwCookie);
1233};
1234
1235/***********************************************************************/
1236
1238 : public CLBarItemBase
1239 , public ITfLangBarItem
1240 , public ITfLangBarItemButton
1241 , public ITfSource
1242{
1243public:
1245
1246public:
1248 ~CLBarItemButtonBase() override;
1249
1250 // IUnknown methods
1251 STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override;
1254
1255 // ITfLangBarItem methods
1256 STDMETHOD(GetInfo)(TF_LANGBARITEMINFO *pInfo) override;
1257 STDMETHOD(GetStatus)(DWORD *pdwStatus) override;
1258 STDMETHOD(Show)(BOOL fShow) override;
1259 STDMETHOD(GetTooltipString)(BSTR *pbstrToolTip) override;
1260
1261 // ITfLangBarItemButton methods
1262 STDMETHOD(OnClick)(TfLBIClick click, POINT pt, LPCRECT prc) override;
1263 STDMETHOD(InitMenu)(ITfMenu *pMenu) override;
1264 STDMETHOD(OnMenuSelect)(UINT wID) override;
1265 STDMETHOD(GetIcon)(HICON *phIcon) override;
1266 STDMETHOD(GetText)(BSTR *pbstr) override;
1267
1268 // ITfSource methods
1269 STDMETHOD(AdviseSink)(REFIID riid, IUnknown *punk, DWORD *pdwCookie) override;
1270 STDMETHOD(UnadviseSink)(DWORD dwCookie) override;
1271};
1272
1273/***********************************************************************/
1274
1277{
1278protected:
1281
1282public:
1284
1285 STDMETHOD(InitMenu)(ITfMenu *pMenu) override;
1286 STDMETHOD(OnMenuSelect)(INT nCommandId);
1287 STDMETHOD(GetIcon)(HICON *phIcon) override;
1288 STDMETHOD(GetText)(BSTR *pbstr) override;
1289};
1290
1291/***********************************************************************/
1292
1293class CTipbarItem;
1294class CTipbarBalloonItem;
1295
1297{
1298protected:
1312 friend class CTipbarWnd;
1313 friend class CTipbarItem;
1314
1315public:
1316 CTipbarThread(CTipbarWnd *pTipbarWnd);
1317 virtual ~CTipbarThread();
1318
1320
1322 HRESULT _UninitItemList(BOOL bUnAdvise);
1323
1326 BOOL IsVertical();
1327
1328 void AddAllSeparators();
1329 void RemoveAllSeparators();
1330
1331 void AddUIObjs();
1332 void RemoveUIObjs();
1333
1334 CTipbarItem *GetItem(REFCLSID rclsid);
1335 void GetTextSize(BSTR bstr, LPSIZE pSize);
1336 void LocateItems();
1337 void MyMoveWnd(LONG xDelta, LONG yDelta);
1338
1340 LONG _AddRef() { return ++m_cRefs; }
1341 LONG _Release();
1342
1344 BOOL SetFocus(CTipbarBalloonItem *pTarget)
1345 {
1346 return FALSE;
1347 }
1348
1351 {
1352 return E_NOTIMPL;
1353 }
1354
1355 //FIXME
1356};
1357
1358/***********************************************************************/
1359
1361{
1362protected:
1373 friend class CTipbarThread;
1374 friend class CTipbarWnd;
1375
1376public:
1378 CTipbarThread *pThread,
1379 ITfLangBarItem *pLangBarItem,
1380 TF_LANGBARITEMINFO *pItemInfo,
1381 DWORD dwUnknown16);
1382 ~CTipbarItem() override;
1383
1384 void _AddedToUI();
1385 void _RemovedToUI();
1386 void AddRemoveMeToUI(BOOL bFlag);
1387
1388 BOOL IsConnected();
1389 void ClearConnections();
1390
1391 void StartDemotingTimer(BOOL bStarted);
1392
1395
1396 STDMETHOD_(BSTR, GetAccName)() override;
1397 STDMETHOD_(void, GetAccLocation)(LPRECT prc) override;
1398 STDMETHOD_(BOOL, DoAccDefaultAction)() override;
1403 STDMETHOD(OnUpdate)(DWORD dwDirty);
1405 STDMETHOD_(void, OnUnknown45)(DWORD dwDirty, DWORD dwStatus) { }
1406 STDMETHOD_(void, OnUpdateHandler)(ULONG, ULONG);
1407 STDMETHOD(OnUnknown46)(CUIFWindow *pWindow) { return S_OK; }
1408 STDMETHOD(OnUnknown47)(CUIFWindow *pWindow) { return S_OK; }
1414 STDMETHOD(OnUnknown53)(BSTR bstr) { return S_OK; }
1415 STDMETHOD_(LPCWSTR, OnUnknown55)() { return NULL; }
1417 STDMETHOD_(LPCWSTR, GetToolTip)();
1420 STDMETHOD_(void, OnUnknown59)() { }
1421 STDMETHOD_(void, OnUnknown60)() { }
1422 STDMETHOD_(void, OnUnknown61)(HWND) { }
1423 STDMETHOD_(void, OnUnknown62)(HWND) { }
1425};
1426
1427/***********************************************************************/
1428
1429class CTipbarCtrlButtonHolder;
1430class CDeskBand;
1431
1432// Flags for m_dwTipbarWndFlags
1433enum
1434{
1444 TIPBAR_TOPFIT = 0x40000,
1447 TIPBAR_LEFTFIT = 0x200000,
1448};
1449
1451 : public ITfLangBarEventSink
1452 , public ITfLangBarEventSink_P
1453 , public CTipbarAccItem
1454 , public CUIFWindow
1455{
1480 CTipbarCtrlButtonHolder *m_pTipbarCtrlButtonHolder;
1494 CDeskBand *m_pDeskBand;
1497 friend class CUTBContextMenu;
1498 friend class CTipbarGripper;
1499 friend class CTipbarThread;
1500 friend class CTipbarItem;
1501 friend class CLBarInatItem;
1502 friend class CMainIconItem;
1504 friend BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand);
1505 friend LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds);
1506
1507public:
1509 ~CTipbarWnd() override;
1510
1512 {
1513 return static_cast<CUIFWindow*>(this);
1514 }
1515
1517 {
1518 return static_cast<CTipbarAccItem*>(this);
1519 }
1520
1521 void Init(BOOL bChild, CDeskBand *pDeskBand);
1522 void InitHighContrast();
1523 void InitMetrics();
1524 void InitThemeMargins();
1525 void UnInit();
1526
1530
1533
1534 void MoveToStub(BOOL bFlag);
1535 void RestoreFromStub();
1536
1542 void LocateCtrlButtons();
1544 void SetVertical(BOOL bVertical);
1545 void UpdatePosFlags();
1546
1547 void CancelMenu();
1549 void ClearLBItemList();
1550
1552 void UpdateVerticalFont();
1553
1556 void DestroyWnd();
1557
1560
1561 UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT uElapse);
1562 BOOL KillTimer(UINT_PTR uIDEvent);
1563
1564 void MoveToTray();
1565 void MyClientToScreen(LPPOINT lpPoint, LPRECT prc);
1566 void SavePosition();
1567 void SetAlpha(BYTE bAlpha, BOOL bFlag);
1568 BOOL SetLangBand(BOOL bDeskBand, BOOL bFlag2);
1570 void SetShowText(BOOL bShow);
1571 void SetShowTrayIcon(BOOL bShow);
1572
1573 void ShowContextMenu(POINT pt, LPCRECT prc, BOOL bFlag);
1574 void StartBackToAlphaTimer();
1576
1579
1582 void EnsureFocusThread();
1583 HRESULT SetFocusThread(CTipbarThread *pFocusThread);
1585 void RestoreLastFocus(DWORD *pdwThreadId, BOOL fPrev);
1586 void CleanUpThreadPointer(CTipbarThread *pThread, BOOL bRemove);
1587 void TerminateAllThreads(BOOL bFlag);
1588 void OnTerminateToolbar();
1590
1593 {
1594 return E_NOTIMPL;
1595 }
1596
1597 // IUnknown methods
1598 STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
1601
1602 // ITfLangBarEventSink methods
1609
1610 // ITfLangBarEventSink_P methods
1611 STDMETHOD(OnLangBarUpdate)(TfLBIClick click, BOOL bFlag) override;
1612
1613 // CTipbarAccItem methods
1614 STDMETHOD_(BSTR, GetAccName)() override;
1615 STDMETHOD_(void, GetAccLocation)(LPRECT lprc) override;
1616
1617 // CUIFWindow methods
1618 STDMETHOD_(void, PaintObject)(HDC hDC, LPCRECT prc) override;
1619 STDMETHOD_(DWORD, GetWndStyle)() override;
1620 STDMETHOD_(void, Move)(INT x, INT y, INT nWidth, INT nHeight) override;
1621 STDMETHOD_(void, OnMouseOutFromWindow)(LONG x, LONG y) override;
1622 STDMETHOD_(void, OnCreate)(HWND hWnd) override;
1623 STDMETHOD_(void, OnDestroy)(HWND hWnd) override;
1625 STDMETHOD_(void, OnSysColorChange)() override;
1626 STDMETHOD_(void, OnEndSession)(HWND hWnd, WPARAM wParam, LPARAM lParam) override;
1628 STDMETHOD_(LRESULT, OnWindowPosChanged)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1629 STDMETHOD_(LRESULT, OnWindowPosChanging)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1632 STDMETHOD_(LRESULT, OnDisplayChange)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1635 STDMETHOD_(void, OnThemeChanged)(HWND hWnd, WPARAM wParam, LPARAM lParam) override;
1636 STDMETHOD_(void, UpdateUI)(LPCRECT prc) override;
1637 STDMETHOD_(void, HandleMouseMsg)(UINT uMsg, LONG x, LONG y) override;
1638};
1639
1640/***********************************************************************/
1641
1642#ifdef ENABLE_DESKBAND
1643class CDeskBand
1644{
1645public:
1646 // FIXME: Implement this
1647};
1648#endif
1649
1650/***********************************************************************
1651 * CUTBLangBarDlg
1652 */
1653
1655{
1657}
1658
1660{
1661 ::SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pThis);
1662}
1663
1665{
1666 return ((CUTBLangBarDlg *)pParam)->ThreadProc();
1667}
1668
1670{
1671 if (IsDlgShown())
1672 return FALSE;
1673
1674 SetDlgShown(TRUE);
1675
1678 if (!hThread)
1679 {
1680 SetDlgShown(FALSE);
1681 return TRUE;
1682 }
1683
1684 ++m_cRefs;
1686 return TRUE;
1687}
1688
1690{
1691 if (--m_cRefs == 0)
1692 {
1693 delete this;
1694 return 0;
1695 }
1696 return m_cRefs;
1697}
1698
1699STDMETHODIMP_(BOOL) CUTBLangBarDlg::ThreadProc()
1700{
1701 extern HINSTANCE g_hInst;
1703 SetDlgShown(FALSE);
1704 _Release();
1705 return TRUE;
1706}
1707
1710{
1711 if (uMsg == WM_INITDIALOG)
1712 {
1713 SetThis(hDlg, (CUTBLangBarDlg *)lParam);
1714 ::ShowWindow(hDlg, SW_RESTORE);
1715 ::UpdateWindow(hDlg);
1716 return TRUE;
1717 }
1718
1719 if (uMsg == WM_COMMAND)
1720 {
1722 pThis->OnCommand(hDlg, wParam, lParam);
1723 return TRUE;
1724 }
1725
1726 return FALSE;
1727}
1728
1729/***********************************************************************
1730 * CUTBCloseLangBarDlg
1731 */
1732
1734{
1735 m_cRefs = 1;
1736
1739 else
1741}
1742
1743STDMETHODIMP_(BOOL) CUTBCloseLangBarDlg::DoModal(HWND hDlg)
1744{
1745 CicRegKey regKey;
1746 LSTATUS error;
1747 DWORD dwValue = FALSE;
1748 error = regKey.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"));
1749 if (error == ERROR_SUCCESS)
1750 regKey.QueryDword(TEXT("DontShowCloseLangBarDlg"), &dwValue);
1751
1752 if (dwValue)
1753 return FALSE;
1754
1755 StartThread();
1756 return TRUE;
1757}
1758
1759STDMETHODIMP_(BOOL) CUTBCloseLangBarDlg::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
1760{
1761 switch (LOWORD(wParam))
1762 {
1763 case IDOK:
1766 {
1767 CicRegKey regKey;
1768 LSTATUS error;
1769 error = regKey.Create(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"));
1770 if (error == ERROR_SUCCESS)
1771 regKey.SetDword(TEXT("DontShowCloseLangBarDlg"), TRUE);
1772 }
1773 ::EndDialog(hDlg, TRUE);
1774 break;
1775
1776 case IDCANCEL:
1777 ::EndDialog(hDlg, FALSE);
1778 break;
1779
1780 default:
1781 return FALSE;
1782 }
1783 return TRUE;
1784}
1785
1786STDMETHODIMP_(BOOL) CUTBCloseLangBarDlg::IsDlgShown()
1787{
1788 return s_bIsDlgShown;
1789}
1790
1791STDMETHODIMP_(void) CUTBCloseLangBarDlg::SetDlgShown(BOOL bShown)
1792{
1793 s_bIsDlgShown = bShown;
1794}
1795
1796/***********************************************************************
1797 * CUTBMinimizeLangBarDlg
1798 */
1799
1801{
1802 m_cRefs = 1;
1805 else
1807}
1808
1809STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::DoModal(HWND hDlg)
1810{
1811 CicRegKey regKey;
1812 LSTATUS error;
1813
1814 DWORD dwValue = FALSE;
1815 error = regKey.Open(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"));
1816 if (error == ERROR_SUCCESS)
1817 regKey.QueryDword(TEXT("DontShowMinimizeLangBarDlg"), &dwValue);
1818
1819 if (dwValue)
1820 return FALSE;
1821
1822 StartThread();
1823 return TRUE;
1824}
1825
1826STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
1827{
1828 switch (LOWORD(wParam))
1829 {
1830 case IDOK:
1832 {
1833 LSTATUS error;
1834 CicRegKey regKey;
1835 error = regKey.Create(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\"));
1836 if (error == ERROR_SUCCESS)
1837 regKey.SetDword(TEXT("DontShowMinimizeLangBarDlg"), TRUE);
1838 }
1839 ::EndDialog(hDlg, TRUE);
1840 break;
1841 case IDCANCEL:
1842 ::EndDialog(hDlg, FALSE);
1843 break;
1844 default:
1845 return FALSE;
1846 }
1847 return TRUE;
1848}
1849
1850STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::IsDlgShown()
1851{
1852 return s_bIsDlgShown;
1853}
1854
1855STDMETHODIMP_(void) CUTBMinimizeLangBarDlg::SetDlgShown(BOOL bShown)
1856{
1857 s_bIsDlgShown = bShown;
1858}
1859
1860STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::ThreadProc()
1861{
1862 ::Sleep(700);
1863 return CUTBLangBarDlg::ThreadProc();
1864}
1865
1866/***********************************************************************
1867 * CCicLibMenu
1868 */
1869
1871{
1872}
1873
1875{
1876 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
1877 {
1878 delete m_MenuItems[iItem];
1879 m_MenuItems[iItem] = NULL;
1880 }
1881}
1882
1884{
1885 static const QITAB c_tab[] =
1886 {
1888 { NULL }
1889 };
1890 return ::QISearch(this, c_tab, riid, ppvObj);
1891}
1892
1894{
1895 return ++m_cRefs;
1896}
1897
1899{
1900 if (--m_cRefs == 0)
1901 {
1902 delete this;
1903 return 0;
1904 }
1905 return m_cRefs;
1906}
1907
1908STDMETHODIMP_(CCicLibMenu*) CCicLibMenu::CreateSubMenu()
1909{
1910 return new(cicNoThrow) CCicLibMenu();
1911}
1912
1913STDMETHODIMP_(CCicLibMenuItem*) CCicLibMenu::CreateMenuItem()
1914{
1915 return new(cicNoThrow) CCicLibMenuItem();
1916}
1917
1919 UINT uId,
1920 DWORD dwFlags,
1921 HBITMAP hbmp,
1922 HBITMAP hbmpMask,
1923 const WCHAR *pch,
1924 ULONG cch,
1925 ITfMenu **ppSubMenu)
1926{
1927 if (ppSubMenu)
1928 *ppSubMenu = NULL;
1929
1930 CCicLibMenu *pSubMenu = NULL;
1932 {
1933 if (!ppSubMenu)
1934 return E_INVALIDARG;
1935 pSubMenu = CreateSubMenu();
1936 }
1937
1938 CCicLibMenuItem *pMenuItem = CreateMenuItem();
1939 if (!pMenuItem)
1940 return E_OUTOFMEMORY;
1941
1942 if (!pMenuItem->Init(uId, dwFlags, hbmp, hbmpMask, pch, cch, pSubMenu))
1943 return E_FAIL;
1944
1945 if (ppSubMenu && pSubMenu)
1946 {
1947 *ppSubMenu = pSubMenu;
1948 pSubMenu->AddRef();
1949 }
1950
1951 m_MenuItems.Add(pMenuItem);
1952 return S_OK;
1953}
1954
1955/***********************************************************************
1956 * CCicLibMenuItem
1957 */
1958
1960{
1961 m_uId = 0;
1962 m_dwFlags = 0;
1963 m_hbmp = NULL;
1964 m_hbmpMask = NULL;
1965 m_bstrText = NULL;
1966 m_pMenu = NULL;
1967}
1968
1970{
1971 if (m_pMenu)
1972 {
1973 m_pMenu->Release();
1974 m_pMenu = NULL;
1975 }
1976
1977 if (m_hbmp)
1978 {
1980 m_hbmp = NULL;
1981 }
1982
1983 if (m_hbmpMask)
1984 {
1986 m_hbmpMask = NULL;
1987 }
1988
1990 m_bstrText = NULL;
1991}
1992
1994 UINT uId,
1995 DWORD dwFlags,
1996 HBITMAP hbmp,
1997 HBITMAP hbmpMask,
1998 const WCHAR *pch,
1999 ULONG cch,
2000 ITfMenu *pMenu)
2001{
2002 m_uId = uId;
2005 if (!m_bstrText && cch)
2006 return FALSE;
2007
2008 m_pMenu = pMenu;
2010 m_hbmpMask = CreateBitmap(hbmpMask);
2011 if (hbmp)
2013 if (hbmpMask)
2014 ::DeleteObject(hbmpMask);
2015
2016 return TRUE;
2017}
2018
2020{
2021 if (!hBitmap)
2022 return NULL;
2023
2024 HDC hDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
2025 if (!hDC)
2026 return NULL;
2027
2028 HBITMAP hbmMem = NULL;
2029
2030 BITMAP bm;
2031 ::GetObject(hBitmap, sizeof(bm), &bm);
2032
2033 HGDIOBJ hbmOld1 = NULL;
2034 HDC hdcMem1 = ::CreateCompatibleDC(hDC);
2035 if (hdcMem1)
2036 hbmOld1 = ::SelectObject(hdcMem1, hBitmap);
2037
2038 HGDIOBJ hbmOld2 = NULL;
2039 HDC hdcMem2 = ::CreateCompatibleDC(hDC);
2040 if (hdcMem2)
2041 {
2042 hbmMem = ::CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight);
2043 hbmOld2 = ::SelectObject(hdcMem2, hbmMem);
2044 }
2045
2046 ::BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);
2047
2048 if (hbmOld1)
2049 ::SelectObject(hdcMem1, hbmOld1);
2050 if (hbmOld2)
2051 ::SelectObject(hdcMem2, hbmOld2);
2052
2053 ::DeleteDC(hDC);
2054 if (hdcMem1)
2055 ::DeleteDC(hdcMem1);
2056 if (hdcMem2)
2057 ::DeleteDC(hdcMem2);
2058
2059 return hbmMem;
2060}
2061
2062/***********************************************************************
2063 * CTipbarAccessible
2064 */
2065
2067{
2068 m_cRefs = 1;
2069 m_hWnd = NULL;
2070 m_pTypeInfo = NULL;
2073 m_cSelection = 1;
2074 m_AccItems.Add(pItem);
2075 ++g_DllRefCount;
2076}
2077
2079{
2081 if (m_pTypeInfo)
2082 {
2084 m_pTypeInfo = NULL;
2085 }
2086 if (m_pStdAccessible)
2087 {
2090 }
2091 --g_DllRefCount;
2092}
2093
2095{
2097
2099 (void **)&m_pStdAccessible);
2100 if (FAILED(hr))
2101 return hr;
2102
2103 ITypeLib *pTypeLib;
2104 hr = ::LoadRegTypeLib(LIBID_Accessibility, 1, 0, 0, &pTypeLib);
2105 if (FAILED(hr))
2106 hr = ::LoadTypeLib(L"OLEACC.DLL", &pTypeLib);
2107
2108 if (SUCCEEDED(hr))
2109 {
2110 hr = pTypeLib->GetTypeInfoOfGuid(IID_IAccessible, &m_pTypeInfo);
2111 pTypeLib->Release();
2112 }
2113
2114 return hr;
2115}
2116
2118{
2119 return m_AccItems.Add(pItem);
2120}
2121
2123{
2124 for (size_t iItem = 0; iItem < m_AccItems.size(); ++iItem)
2125 {
2126 if (m_AccItems[iItem] == pItem)
2127 {
2128 m_AccItems.Remove(iItem, 1);
2129 break;
2130 }
2131 }
2132 return S_OK;
2133}
2134
2136{
2137 m_AccItems.clear();
2138}
2139
2141{
2142 if (iItem < 0 || (INT)m_AccItems.size() <= iItem)
2143 return NULL;
2144 return m_AccItems[iItem];
2145}
2146
2148{
2149 for (size_t iItem = 0; iItem < m_AccItems.size(); ++iItem)
2150 {
2151 if (pTarget == m_AccItems[iItem])
2152 return (INT)iItem;
2153 }
2154 return -1;
2155}
2156
2158{
2159 return ::LresultFromObject(IID_IAccessible, wParam, this);
2160}
2161
2163{
2164 CTipbarAccItem *pItem = AccItemFromID(nID);
2165 if (!pItem)
2166 return FALSE;
2167 return pItem->DoAccDefaultActionReal();
2168}
2169
2171{
2172 INT nID = GetIDOfItem(pItem);
2173 if (nID < 0)
2174 return;
2175
2176 ::NotifyWinEvent(event, m_hWnd, -4, nID);
2177}
2178
2180{
2181 m_hWnd = hWnd;
2182}
2183
2185 REFIID riid,
2186 void **ppvObject)
2187{
2188 static const QITAB c_tab[] =
2189 {
2192 { NULL }
2193 };
2194 return ::QISearch(this, c_tab, riid, ppvObject);
2195}
2196
2198{
2199 return ::InterlockedIncrement(&m_cRefs);
2200}
2201
2203{
2205 if (count == 0)
2206 {
2207 delete this;
2208 return 0;
2209 }
2210 return count;
2211}
2212
2214{
2215 if (!pctinfo)
2216 return E_INVALIDARG;
2217 *pctinfo = (m_pTypeInfo == NULL);
2218 return S_OK;
2219}
2220
2222 UINT iTInfo,
2223 LCID lcid,
2224 ITypeInfo **ppTInfo)
2225{
2226 if (!ppTInfo)
2227 return E_INVALIDARG;
2228 *ppTInfo = NULL;
2229 if (iTInfo != 0)
2231 if (!m_pTypeInfo)
2232 return E_NOTIMPL;
2233 *ppTInfo = m_pTypeInfo;
2235 return S_OK;
2236}
2237
2239 REFIID riid,
2240 LPOLESTR *rgszNames,
2241 UINT cNames,
2242 LCID lcid,
2243 DISPID *rgDispId)
2244{
2245 if (!m_pTypeInfo)
2246 return E_NOTIMPL;
2247 return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId);
2248}
2249
2251 DISPID dispIdMember,
2252 REFIID riid,
2253 LCID lcid,
2254 WORD wFlags,
2255 DISPPARAMS *pDispParams,
2256 VARIANT *pVarResult,
2257 EXCEPINFO *pExcepInfo,
2258 UINT *puArgErr)
2259{
2260 if (!m_pTypeInfo)
2261 return E_NOTIMPL;
2262 return m_pTypeInfo->Invoke(this,
2263 dispIdMember,
2264 wFlags,
2265 pDispParams,
2266 pVarResult,
2267 pExcepInfo,
2268 puArgErr);
2269}
2270
2272{
2273 return m_pStdAccessible->get_accParent(ppdispParent);
2274}
2275
2277{
2278 if (!pcountChildren)
2279 return E_INVALIDARG;
2280 INT cItems = (INT)m_AccItems.size();
2281 if (!cItems)
2282 return E_FAIL;
2283 *pcountChildren = cItems - 1;
2284 return S_OK;
2285}
2286
2288 VARIANT varChildID,
2289 IDispatch **ppdispChild)
2290{
2291 if (!ppdispChild)
2292 return E_INVALIDARG;
2293 *ppdispChild = NULL;
2294 return S_FALSE;
2295}
2296
2298 VARIANT varID,
2299 BSTR *pszName)
2300{
2301 if (!pszName)
2302 return E_INVALIDARG;
2303 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2304 if (!pItem)
2305 return E_INVALIDARG;
2306 *pszName = pItem->GetAccName();
2307 if (!*pszName)
2308 return DISP_E_MEMBERNOTFOUND;
2309 return S_OK;
2310}
2311
2313 VARIANT varID,
2314 BSTR *pszValue)
2315{
2316 if (!pszValue)
2317 return E_INVALIDARG;
2318 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2319 if (!pItem)
2320 return E_INVALIDARG;
2321 *pszValue = pItem->GetAccValue();
2322 if (!*pszValue)
2323 return DISP_E_MEMBERNOTFOUND;
2324 return S_OK;
2325}
2326
2328 VARIANT varID,
2330{
2331 if (!description)
2332 return E_INVALIDARG;
2333 return m_pStdAccessible->get_accDescription(varID, description);
2334}
2335
2337 VARIANT varID,
2338 VARIANT *role)
2339{
2340 if (!role)
2341 return E_INVALIDARG;
2342 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2343 if (!pItem)
2344 return E_INVALIDARG;
2345 V_VT(role) = VT_I4;
2346 V_I4(role) = pItem->GetAccRole();
2347 return S_OK;
2348}
2349
2351 VARIANT varID,
2352 VARIANT *state)
2353{
2354 if (!state)
2355 return E_INVALIDARG;
2356 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2357 if (!pItem)
2358 return E_INVALIDARG;
2359 V_VT(state) = VT_I4;
2360 V_I4(state) = pItem->GetAccState();
2361 return S_OK;
2362}
2363
2365{
2366 return DISP_E_MEMBERNOTFOUND;
2367}
2368
2370 BSTR *helpfile,
2371 VARIANT varID,
2372 LONG *pidTopic)
2373{
2374 return DISP_E_MEMBERNOTFOUND;
2375}
2376
2378{
2379 return DISP_E_MEMBERNOTFOUND;
2380}
2381
2383{
2384 if (!pvarID)
2385 return E_INVALIDARG;
2386 V_VT(pvarID) = VT_EMPTY;
2387 return S_FALSE;
2388}
2389
2391{
2392 if (!pvarID)
2393 return E_INVALIDARG;
2394
2395 V_VT(pvarID) = VT_EMPTY;
2396
2397 INT cItems = (INT)m_AccItems.size();
2398 if (cItems < m_cSelection)
2399 return S_FALSE;
2400
2401 if (cItems > m_cSelection)
2402 {
2403 V_VT(pvarID) = VT_I4;
2404 V_I4(pvarID) = m_cSelection;
2405 }
2406
2407 return S_OK;
2408}
2409
2411 VARIANT varID,
2412 BSTR *action)
2413{
2414 if (!action)
2415 return E_INVALIDARG;
2416 *action = NULL;
2417
2418 if (V_VT(&varID) != VT_I4)
2419 return E_INVALIDARG;
2420
2421 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2422 if (!pItem)
2423 return DISP_E_MEMBERNOTFOUND;
2424 *action = pItem->GetAccDefaultAction();
2425 if (!*action)
2426 return S_FALSE;
2427 return S_OK;
2428}
2429
2431 LONG flagsSelect,
2432 VARIANT varID)
2433{
2434 if ((flagsSelect & SELFLAG_ADDSELECTION) && (flagsSelect & SELFLAG_REMOVESELECTION))
2435 return E_INVALIDARG;
2436 if (flagsSelect & (SELFLAG_TAKEFOCUS | SELFLAG_ADDSELECTION | SELFLAG_EXTENDSELECTION))
2437 return S_FALSE;
2438 if (flagsSelect & SELFLAG_REMOVESELECTION)
2439 return S_OK;
2440 if (V_VT(&varID) != VT_I4)
2441 return E_INVALIDARG;
2442 if (flagsSelect & SELFLAG_TAKESELECTION)
2443 {
2444 m_cSelection = V_I4(&varID);
2445 return S_OK;
2446 }
2447 return S_FALSE;
2448}
2449
2451 LONG *left,
2452 LONG *top,
2453 LONG *width,
2454 LONG *height,
2455 VARIANT varID)
2456{
2457 if (!left || !top || !width || !height)
2458 return E_INVALIDARG;
2459
2460 if (!V_I4(&varID))
2461 return m_pStdAccessible->accLocation(left, top, width, height, varID);
2462
2463 RECT rc;
2464 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2465 pItem->GetAccLocation(&rc);
2466
2467 *left = rc.left;
2468 *top = rc.top;
2469 *width = rc.right - rc.left;
2470 *height = rc.bottom - rc.top;
2471 return S_OK;
2472}
2473
2475 LONG dir,
2476 VARIANT varStart,
2477 VARIANT *pvarEnd)
2478{
2479 if (m_AccItems.size() <= 1)
2480 {
2481 V_VT(pvarEnd) = VT_EMPTY;
2482 return S_OK;
2483 }
2484
2485 switch (dir)
2486 {
2487 case NAVDIR_UP:
2488 case NAVDIR_LEFT:
2489 case NAVDIR_PREVIOUS:
2490 V_VT(pvarEnd) = VT_I4;
2491 V_I4(pvarEnd) = V_I4(&varStart) - 1;
2492 if (V_I4(&varStart) - 1 <= 0)
2493 V_I4(pvarEnd) = (INT)(m_AccItems.size() - 1);
2494 return S_OK;
2495
2496 case NAVDIR_DOWN:
2497 case NAVDIR_RIGHT:
2498 case NAVDIR_NEXT:
2499 V_VT(pvarEnd) = VT_I4;
2500 V_I4(pvarEnd) = V_I4(&varStart) + 1;
2501 if ((INT)m_AccItems.size() <= V_I4(&varStart) + 1)
2502 V_I4(pvarEnd) = 1;
2503 return S_OK;
2504
2505 case NAVDIR_FIRSTCHILD:
2506 V_VT(pvarEnd) = VT_I4;
2507 V_I4(pvarEnd) = 1;
2508 return S_OK;
2509
2510 case NAVDIR_LASTCHILD:
2511 V_VT(pvarEnd) = VT_I4;
2512 V_I4(pvarEnd) = (INT)(m_AccItems.size() - 1);
2513 return S_OK;
2514
2515 default:
2516 break;
2517 }
2518
2519 V_VT(pvarEnd) = VT_EMPTY;
2520 return S_OK;
2521}
2522
2524{
2525 if (!pvarID)
2526 return E_INVALIDARG;
2527 POINT Point = { left, top };
2528 RECT Rect;
2531
2532 if (!::PtInRect(&Rect, Point))
2533 {
2534 V_VT(pvarID) = VT_EMPTY;
2535 return S_OK;
2536 }
2537
2538 V_VT(pvarID) = VT_I4;
2539 V_I4(pvarID) = 0;
2540
2541 for (size_t iItem = 1; iItem < m_AccItems.size(); ++iItem)
2542 {
2543 CTipbarAccItem *pItem = m_AccItems[iItem];
2544 if (pItem)
2545 {
2546 pItem->GetAccLocation(&Rect);
2547 if (::PtInRect(&Rect, Point))
2548 {
2549 V_I4(pvarID) = iItem;
2550 break;
2551 }
2552 }
2553 }
2554
2555 return S_OK;
2556}
2557
2559{
2560 if (V_VT(&varID) != VT_I4)
2561 return E_INVALIDARG;
2562 CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
2563 if (!pItem)
2564 return DISP_E_MEMBERNOTFOUND;
2565 return (pItem->DoAccDefaultAction() ? S_OK : S_FALSE);
2566}
2567
2569{
2570 return S_FALSE;
2571}
2572
2574{
2575 return S_FALSE;
2576}
2577
2578/***********************************************************************
2579 * CUTBMenuWnd
2580 */
2581
2583 : CUIFMenu(hInst, style, dwUnknown14)
2584{
2585}
2586
2588{
2589 if (!m_pAccessible)
2590 return FALSE;
2591
2593 if (!m_nMenuWndID || m_nMenuWndID == (UINT)-1)
2594 return FALSE;
2595
2596 if (::IsWindow(m_hWnd))
2597 {
2600 }
2601
2602 return TRUE;
2603}
2604
2605STDMETHODIMP_(BSTR) CUTBMenuWnd::GetAccName()
2606{
2607 WCHAR szText[64];
2608 LoadStringW(g_hInst, IDS_MENUWND, szText, _countof(szText));
2609 return ::SysAllocString(szText);
2610}
2611
2612STDMETHODIMP_(INT) CUTBMenuWnd::GetAccRole()
2613{
2614 return 9;
2615}
2616
2617STDMETHODIMP_(BOOL) CUTBMenuWnd::Initialize()
2618{
2620 if (pAccessible)
2621 m_pAccessible = pAccessible;
2622
2623 return CUIFObject::Initialize();
2624}
2625
2626STDMETHODIMP_(void) CUTBMenuWnd::OnCreate(HWND hWnd)
2627{
2628 if (m_pAccessible)
2630}
2631
2632STDMETHODIMP_(void) CUTBMenuWnd::OnDestroy(HWND hWnd)
2633{
2634 if (m_pAccessible)
2635 {
2636 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_DESTROY, GetAccItem());
2640 }
2642}
2643
2645CUTBMenuWnd::OnGetObject(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2646{
2647 if (lParam != -4)
2648 return S_OK;
2649
2650 if (!m_pAccessible)
2651 return E_OUTOFMEMORY;
2652
2655
2657 {
2659 if (FAILED(hr))
2660 {
2663 return hr;
2664 }
2665
2666 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_CREATE, GetAccItem());
2668 }
2669
2670 return S_OK;
2671}
2672
2674CUTBMenuWnd::OnShowWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2675{
2676 if (m_pAccessible)
2677 {
2678 if (wParam)
2679 {
2680 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_SHOW, GetAccItem());
2681 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_FOCUS, GetAccItem());
2682 }
2683 else
2684 {
2685 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_HIDE, GetAccItem());
2686 }
2687 }
2688
2689 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
2690}
2691
2692STDMETHODIMP_(void) CUTBMenuWnd::OnTimer(WPARAM wParam)
2693{
2695 {
2698 {
2700 m_nMenuWndID = 0;
2701 }
2702 }
2703}
2704
2705/***********************************************************************
2706 * CUTBMenuItem
2707 */
2708
2710 : CUIFMenuItem(pMenuUI ? pMenuUI->GetMenu() : NULL)
2711{
2712 m_pMenuUI = pMenuUI;
2713}
2714
2716{
2717 if (m_hbmColor)
2718 {
2720 m_hbmColor = NULL;
2721 }
2722 if (m_hbmMask)
2723 {
2725 m_hbmMask = NULL;
2726 }
2727}
2728
2729STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultAction()
2730{
2731 if (!m_pMenuUI)
2732 return FALSE;
2733
2735 return TRUE;
2736}
2737
2738STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultActionReal()
2739{
2740 if (!m_pSubMenu)
2741 OnLButtonUp(0, 0);
2742 else
2743 ShowSubPopup();
2744 return TRUE;
2745}
2746
2747STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccDefaultAction()
2748{
2749 WCHAR szText[64];
2750 ::LoadStringW(g_hInst, IDS_LEFTCLICK, szText, _countof(szText));
2751 return ::SysAllocString(szText);
2752}
2753
2754STDMETHODIMP_(void) CUTBMenuItem::GetAccLocation(LPRECT lprc)
2755{
2756 GetRect(lprc);
2759}
2760
2761STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccName()
2762{
2763 return ::SysAllocString(m_pszMenuItemLeft);
2764}
2765
2767STDMETHODIMP_(INT) CUTBMenuItem::GetAccRole()
2768{
2769 if (FALSE) //FIXME
2770 return 21;
2771 return 12;
2772}
2773
2774/***********************************************************************
2775 * CModalMenu
2776 */
2777
2779CModalMenu::InsertItem(CUTBMenuWnd *pMenuUI, INT nCommandId, INT nStringID)
2780{
2781 CUTBMenuItem *pMenuItem = new(cicNoThrow) CUTBMenuItem(pMenuUI);
2782 if (!pMenuItem)
2783 return NULL;
2784
2785 WCHAR szText[256];
2786 ::LoadStringW(g_hInst, nStringID, szText, _countof(szText));
2787
2788 if (pMenuItem->Initialize() &&
2789 pMenuItem->Init(nCommandId, szText) &&
2790 pMenuUI->InsertItem(pMenuItem))
2791 {
2792 return pMenuItem;
2793 }
2794
2795 delete pMenuItem;
2796 return NULL;
2797}
2798
2800{
2802}
2803
2805{
2806 if (m_pMenuUI)
2808}
2809
2810/***********************************************************************
2811 * CUTBContextMenu
2812 */
2813
2815{
2816 m_pTipbarWnd = pTipbarWnd;
2817}
2818
2821{
2823 return !!m_pTipbarThread;
2824}
2825
2828{
2829 DWORD dwStatus = 0;
2830
2832 return NULL;
2833
2835 if (!pMenuUI)
2836 return NULL;
2837
2838 pMenuUI->Initialize();
2839
2840 if (dwStatus & (TF_SFT_DESKBAND | TF_SFT_MINIMIZED))
2841 {
2842 CUTBMenuItem *pRestoreLangBar = InsertItem(pMenuUI, ID_RESTORELANGBAR, IDS_RESTORELANGBAR2);
2843 if (pRestoreLangBar && !m_pTipbarWnd->m_dwUnknown20)
2844 pRestoreLangBar->Gray(TRUE);
2845 }
2846 else
2847 {
2849
2850 if (bFlag)
2851 {
2853 {
2854 if (dwStatus & TF_LBI_BALLOON)
2855 {
2857 }
2858 else
2859 {
2860 CUTBMenuItem *pTransparency = InsertItem(pMenuUI, ID_NOTRANS, IDS_TRANSPARENCY);
2861 if (pTransparency)
2862 pTransparency->Check(TRUE);
2863 }
2864 }
2865
2866 if (!(dwStatus & TF_SFT_LABELS))
2867 {
2869 }
2870 else
2871 {
2872 CUTBMenuItem *pTextLabels = InsertItem(pMenuUI, ID_NOLABELS, IDS_TEXTLABELS);
2873 if (pTextLabels)
2874 pTextLabels->Check(TRUE);
2875 }
2876
2877 CUTBMenuItem *pVertical = InsertItem(pMenuUI, ID_VERTICAL, IDS_VERTICAL);
2878 if (pVertical)
2880 }
2881 }
2882
2883 if (bFlag)
2884 {
2885 CUTBMenuItem *pExtraIcons = NULL;
2886
2887 if (dwStatus & TF_SFT_EXTRAICONSONMINIMIZED)
2888 {
2889 pExtraIcons = InsertItem(pMenuUI, ID_NOEXTRAICONS, IDS_EXTRAICONS);
2890 if (pExtraIcons)
2891 pExtraIcons->Check(TRUE);
2892 }
2893 else
2894 {
2895 pExtraIcons = CModalMenu::InsertItem(pMenuUI, ID_EXTRAICONS, IDS_EXTRAICONS);
2896 }
2897
2898 if (pExtraIcons)
2899 {
2900 if (::GetKeyboardLayoutList(0, NULL) == 1)
2901 {
2902 pExtraIcons->Check(TRUE);
2903 pExtraIcons->Gray(TRUE);
2904 }
2905 else
2906 {
2907 pExtraIcons->Gray(FALSE);
2908 }
2909 }
2910
2911 if (dwStatus & TF_SFT_DESKBAND)
2913
2915
2918 }
2919
2920 return pMenuUI;
2921}
2922
2923UINT
2925 CUIFWindow *pWindow,
2926 POINT pt,
2927 LPCRECT prc,
2928 BOOL bFlag)
2929{
2930 if (g_bWinLogon)
2931 return 0;
2932
2933 if (m_pMenuUI)
2934 return -1;
2935
2936 m_pMenuUI = CreateMenuUI(bFlag);
2937 if (!m_pMenuUI)
2938 return 0;
2939
2940 UINT nCommandId = m_pMenuUI->ShowModalPopup(pWindow, prc, TRUE);
2941
2942 if (m_pMenuUI)
2943 {
2944 delete m_pMenuUI;
2945 m_pMenuUI = NULL;
2946 }
2947
2948 return nCommandId;
2949}
2950
2953{
2954 switch (nCommandId)
2955 {
2956 case ID_TRANS:
2957 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_LOWTRANSPARENCY);
2958 break;
2959
2960 case ID_NOTRANS:
2961 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_NOTRANSPARENCY);
2962 break;
2963
2964 case ID_LABELS:
2965 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_LABELS);
2966 break;
2967
2968 case ID_NOLABELS:
2969 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_NOLABELS);
2970 break;
2971
2972 case ID_DESKBAND:
2973 {
2975 {
2976 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_MINIMIZED);
2977 }
2978 else
2979 {
2982
2983 if (dwStatus & TF_SFT_DESKBAND)
2984 break;
2985
2986 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_DESKBAND);
2987 }
2988
2990 if (pDialog)
2991 {
2992 pDialog->DoModal(*m_pTipbarWnd->GetWindow());
2993 pDialog->_Release();
2994 }
2995 break;
2996 }
2997
2998 case ID_CLOSELANGBAR:
2999 {
3001 if (pDialog)
3002 {
3003 BOOL bOK = pDialog->DoModal(*m_pTipbarWnd->GetWindow());
3004 pDialog->_Release();
3005 if (!bOK)
3007 }
3008 break;
3009 }
3010
3011 case ID_EXTRAICONS:
3012 m_pTipbarWnd->m_dwTipbarWndFlags &= ~TIPBAR_NODESKBAND;
3013 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_EXTRAICONSONMINIMIZED);
3014 break;
3015
3016 case ID_NOEXTRAICONS:
3017 m_pTipbarWnd->m_dwTipbarWndFlags &= ~TIPBAR_NODESKBAND;
3018 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_NOEXTRAICONSONMINIMIZED);
3019 break;
3020
3021 case ID_RESTORELANGBAR:
3023 break;
3024
3025 case ID_VERTICAL:
3027 break;
3028
3029 case ID_ADJUSTDESKBAND:
3031 break;
3032
3033 case ID_SETTINGS:
3035 break;
3036
3037 default:
3038 break;
3039 }
3040
3041 return TRUE;
3042}
3043
3044/***********************************************************************
3045 * CTrayIconItem
3046 */
3047
3049{
3051 m_pTrayIconWnd = pTrayIconWnd;
3052}
3053
3054BOOL
3056 HWND hWnd,
3057 UINT uCallbackMessage,
3058 UINT uNotifyIconID,
3059 const GUID& rguid)
3060{
3061 m_hWnd = hWnd;
3062 m_uCallbackMessage = uCallbackMessage;
3063 m_uNotifyIconID = uNotifyIconID;
3064 m_guid = rguid;
3065 return TRUE;
3066}
3067
3069{
3071 {
3072 NOTIFYICONDATAW NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
3073 NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
3075 ::Shell_NotifyIconW(NIM_DELETE, &NotifyIcon);
3076 }
3077
3080 return TRUE;
3081}
3082
3083BOOL CTrayIconItem::SetIcon(HICON hIcon, LPCWSTR pszTip)
3084{
3085 if (!hIcon)
3086 return FALSE;
3087
3088 NOTIFYICONDATAW NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
3089 NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE;
3091 NotifyIcon.hIcon = hIcon;
3092 if (pszTip)
3093 {
3094 NotifyIcon.uFlags |= NIF_TIP;
3095 StringCchCopyW(NotifyIcon.szTip, _countof(NotifyIcon.szTip), pszTip);
3096 }
3097
3099
3102 return TRUE;
3103}
3104
3106{
3107 HWND hNotifyWnd = m_pTrayIconWnd->GetNotifyWnd();
3108 ::GetClientRect(hNotifyWnd, &m_rcMenu);
3109 ::ClientToScreen(hNotifyWnd, (LPPOINT)&m_rcMenu);
3110 ::ClientToScreen(hNotifyWnd, (LPPOINT)&m_rcMenu.right);
3112 return TRUE;
3113}
3114
3115/***********************************************************************
3116 * CButtonIconItem
3117 */
3118
3120 : CTrayIconItem(pWnd)
3121{
3122 m_dwUnknown24 = dwUnknown24;
3123}
3124
3126STDMETHODIMP_(BOOL) CButtonIconItem::OnMsg(WPARAM wParam, LPARAM lParam)
3127{
3128 switch (lParam)
3129 {
3130 case WM_LBUTTONDOWN:
3131 case WM_RBUTTONDOWN:
3132 case WM_LBUTTONDBLCLK:
3133 case WM_RBUTTONDBLCLK:
3134 break;
3135 default:
3136 return TRUE;
3137 }
3138
3139 //FIXME
3140 return TRUE;
3141}
3142
3144STDMETHODIMP_(BOOL) CButtonIconItem::OnDelayMsg(UINT uMsg)
3145{
3146 //FIXME
3147 return FALSE;
3148}
3149
3150/***********************************************************************
3151 * CMainIconItem
3152 */
3153
3156 : CButtonIconItem(pWnd, 1)
3157{
3158}
3159
3162{
3163 return CTrayIconItem::_Init(hWnd, WM_USER, 0, GUID_LBI_TRAYMAIN);
3164}
3165
3167STDMETHODIMP_(BOOL) CMainIconItem::OnDelayMsg(UINT uMsg)
3168{
3169 if (!CButtonIconItem::OnDelayMsg(uMsg))
3170 return 0;
3171
3172 if (uMsg == WM_LBUTTONDBLCLK)
3173 {
3175 g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
3176 }
3177 else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
3178 {
3180 }
3181 return TRUE;
3182}
3183
3184/***********************************************************************
3185 * CTrayIconWnd
3186 */
3187
3189{
3190 m_uCallbackMsg = WM_USER + 0x1000;
3191 m_uNotifyIconID = 0x1000;
3192}
3193
3195{
3196 for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
3197 {
3198 auto& pItem = m_Items[iItem];
3199 if (pItem)
3200 {
3201 delete pItem;
3202 pItem = NULL;
3203 }
3204 }
3205}
3206
3208{
3209 for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
3210 {
3211 auto pItem = m_Items[iItem];
3212 if (pItem && m_uCallbackMessage == pItem->m_uCallbackMessage)
3213 {
3214 pItem->OnDelayMsg(m_uMsg);
3215 break;
3216 }
3217 }
3218}
3219
3221{
3222 m_hWnd = ::CreateWindowEx(0, TEXT("CTrayIconWndClass"), NULL, WS_DISABLED,
3223 0, 0, 0, 0, NULL, NULL, g_hInst, this);
3224 FindTrayEtc();
3225
3227 if (m_pMainIconItem)
3228 {
3231 }
3232
3233 return m_hWnd;
3234}
3235
3237{
3239 m_hWnd = NULL;
3240}
3241
3243{
3244 CTrayIconWnd *pWnd = (CTrayIconWnd *)lParam;
3245
3246 TCHAR ClassName[60];
3247 ::GetClassName(hWnd, ClassName, _countof(ClassName));
3248 if (lstrcmp(ClassName, TEXT("TrayNotifyWnd")) != 0)
3249 return TRUE;
3250
3251 pWnd->m_hNotifyWnd = hWnd;
3252 return FALSE;
3253}
3254
3256{
3257 for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
3258 {
3259 auto pItem = m_Items[iItem];
3260 if (IsEqualGUID(rguid, pItem->m_guid))
3261 return pItem;
3262 }
3263 return NULL;
3264}
3265
3267{
3268 m_hTrayWnd = ::FindWindow(TEXT("Shell_TrayWnd"), NULL);
3269 if (!m_hTrayWnd)
3270 return FALSE;
3271
3273 if (!m_hNotifyWnd)
3274 return FALSE;
3276 m_hwndProgman = FindWindow(TEXT("Progman"), NULL);
3278 return TRUE;
3279}
3280
3282{
3284 FindTrayEtc();
3285 return m_hNotifyWnd;
3286}
3287
3290{
3291 if (g_pTipbarWnd)
3293
3294 for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
3295 {
3296 auto *pItem = m_Items[iItem];
3297 if (pItem)
3298 {
3299 if (uMsg == pItem->m_uCallbackMessage)
3300 {
3301 pItem->OnMsg(wParam, lParam);
3302 return TRUE;
3303 }
3304 }
3305 }
3306 return FALSE;
3307}
3308
3310{
3311 WNDCLASSEX wc = { sizeof(wc) };
3313 wc.hInstance = g_hInst;
3316 wc.lpszClassName = TEXT("CTrayIconWndClass");
3317 ::RegisterClassEx(&wc);
3318 return TRUE;
3319}
3320
3322{
3323 for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
3324 {
3325 auto pItem = m_Items[iItem];
3326 if (dwFlags & 0x1)
3327 {
3328 if (IsEqualGUID(pItem->m_guid, GUID_LBI_INATITEM) ||
3329 IsEqualGUID(pItem->m_guid, GUID_LBI_CTRL))
3330 {
3331 continue;
3332 }
3333 }
3334
3335 if (dwFlags & 0x2)
3336 {
3337 if (IsEqualGUID(pItem->m_guid, GUID_TFCAT_TIP_KEYBOARD))
3338 continue;
3339 }
3340
3341 if (pItem->m_uNotifyIconID < 0x1000)
3342 continue;
3343
3344 pItem->RemoveIcon();
3345 }
3346}
3347
3350{
3351 //FIXME
3352}
3353
3355{
3356 CButtonIconItem *pItem = FindIconItem(rguid);
3357 if (!pItem)
3358 {
3359 if (!hIcon)
3360 return FALSE;
3361 pItem = new(cicNoThrow) CButtonIconItem(this, dwUnknown24);
3362 if (!pItem)
3363 return FALSE;
3364
3365 pItem->_Init(m_hWnd, m_uCallbackMsg, m_uNotifyIconID, rguid);
3366 m_uCallbackMsg += 2;
3368 m_Items.Add(pItem);
3369 }
3370
3371 if (!hIcon)
3372 return pItem->RemoveIcon();
3373
3374 return pItem->SetIcon(hIcon, psz);
3375}
3376
3378{
3379 if (!hKL)
3380 {
3383 return TRUE;
3384 }
3385
3386 if (hKL != m_pMainIconItem->m_hKL)
3387 {
3388 WCHAR szText[64];
3389 HICON hIcon = TF_GetLangIcon(LOWORD(hKL), szText, _countof(szText));
3390 if (hIcon)
3391 {
3392 m_pMainIconItem->SetIcon(hIcon, szText);
3394 }
3395 else
3396 {
3399 m_pMainIconItem->SetIcon(hIcon, szText);
3400 }
3401
3402 m_pMainIconItem->m_hKL = hKL;
3403 }
3404
3405 return TRUE;
3406}
3407
3409{
3411}
3412
3414{
3415 if (pCS)
3417 else
3418 ::SetWindowLongPtr(hWnd, GWL_USERDATA, 0);
3419}
3420
3423{
3424 CTrayIconWnd *pThis;
3425 switch (uMsg)
3426 {
3427 case WM_CREATE:
3429 break;
3430 case WM_DESTROY:
3432 break;
3433 case WM_TIMER:
3434 if (wParam == 100)
3435 {
3436 ::KillTimer(hWnd, 100);
3437 pThis = CTrayIconWnd::GetThis(hWnd);
3438 if (pThis)
3439 pThis->CallOnDelayMsg();
3440 }
3441 break;
3442 default:
3443 {
3444 if (uMsg < WM_USER)
3445 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
3446 pThis = CTrayIconWnd::GetThis(hWnd);
3447 if (pThis && pThis->OnIconMessage(uMsg, wParam, lParam))
3448 break;
3449 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
3450 }
3451 }
3452 return 0;
3453}
3454
3455/***********************************************************************
3456 * CLBarItemBase
3457 */
3458
3460{
3461 m_dwItemStatus = 0;
3462 m_szToolTipText[0] = 0;
3463 m_cRefs = 1;
3465}
3466
3468{
3471}
3472
3473HRESULT
3475 REFIID riid,
3476 IUnknown *punk,
3477 DWORD *pdwCookie)
3478{
3479 if (IsEqualIID(riid, IID_ITfLangBarItemSink) || m_pLangBarItemSink)
3480 return TF_E_NOOBJECT;
3481
3482 HRESULT hr = punk->QueryInterface(IID_ITfLangBarItemSink, (void **)&m_pLangBarItemSink);
3483 if (SUCCEEDED(hr))
3484 *pdwCookie = 0x80000001;
3485 return hr;
3486}
3487
3489{
3490 if (dwCookie != 0x80000001)
3491 return E_FAIL;
3492
3493 if (!m_pLangBarItemSink)
3494 return E_UNEXPECTED;
3495
3498 return S_OK;
3499}
3500
3501void
3503 REFIID clsidService,
3504 REFGUID guidItem,
3505 DWORD dwStyle,
3506 DWORD ulSort,
3508{
3509 m_NewUIInfo.clsidService = clsidService;
3510 m_NewUIInfo.guidItem = guidItem;
3511 m_NewUIInfo.dwStyle = dwStyle;
3512 m_NewUIInfo.ulSort = ulSort;
3514}
3515
3516HRESULT
3518{
3519 DWORD dwOldStatus = m_dwItemStatus;
3520
3521 if (bShow)
3522 m_dwItemStatus &= ~TF_LBI_STATUS_HIDDEN;
3523 else
3524 m_dwItemStatus |= TF_LBI_STATUS_HIDDEN;
3525
3526 if (bUpdate && (dwOldStatus != m_dwItemStatus))
3527 {
3529 m_pLangBarItemSink->OnUpdate(TF_LBI_STATUS);
3530 }
3531
3532 return S_OK;
3533}
3534
3536{
3537 CopyMemory(pInfo, &m_NewUIInfo, sizeof(*pInfo));
3538 return S_OK;
3539}
3540
3542{
3543 *pdwStatus = m_dwItemStatus;
3544 return S_OK;
3545}
3546
3548{
3549 return ShowInternal(fShow, TRUE);
3550}
3551
3553{
3554 if (!pbstrToolTip)
3555 return E_INVALIDARG;
3557 *pbstrToolTip = bstr;
3558 return bstr ? S_OK : E_OUTOFMEMORY;
3559}
3560
3561/***********************************************************************
3562 * CUTBLBarMenu
3563 */
3564
3566{
3567 m_hInst = hInst;
3568}
3569
3571{
3572}
3573
3574STDMETHODIMP_(CCicLibMenuItem*) CUTBLBarMenu::CreateMenuItem()
3575{
3577 if (!pItem)
3578 return NULL;
3579 pItem->m_pLBarMenu = this;
3580 return pItem;
3581}
3582
3584{
3586 if (!pMenuUI)
3587 return NULL;
3588
3589 pMenuUI->Initialize();
3590 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
3591 {
3593 pItem->InsertToUI(pMenuUI);
3594 }
3595
3596 return pMenuUI;
3597}
3598
3599STDMETHODIMP_(CCicLibMenu*) CUTBLBarMenu::CreateSubMenu()
3600{
3601 return new(cicNoThrow) CUTBLBarMenu(m_hInst);
3602}
3603
3605{
3606 if (m_pMenuUI)
3607 return 0;
3608
3610 if (!m_pMenuUI)
3611 return -1;
3612
3613 INT nCommandId = m_pMenuUI->ShowModalPopup(pWindow, prcExclude, TRUE);
3614
3615 if (m_pMenuUI)
3616 {
3617 delete m_pMenuUI;
3618 m_pMenuUI = NULL;
3619 }
3620
3621 return nCommandId;
3622}
3623
3624/***********************************************************************
3625 * CUTBLBarMenuItem
3626 */
3627
3630{
3631 if ((m_dwFlags & 4) != 0)
3632 {
3633 pMenuUI->InsertSeparator();
3634 return TRUE;
3635 }
3636 if (m_dwFlags & 2)
3637 {
3638 //FIXME
3639 }
3640 else
3641 {
3642 //FIXME
3643 }
3644 return FALSE;
3645}
3646
3647/***********************************************************************
3648 * CLBarItemButtonBase
3649 */
3650
3652{
3653 if (m_hIcon)
3654 {
3656 m_hIcon = NULL;
3657 }
3658}
3659
3661{
3662 static const QITAB c_tab[] =
3663 {
3667 { NULL }
3668 };
3669 return ::QISearch(this, c_tab, riid, ppvObject);
3670}
3671
3673{
3674 return ++m_cRefs;
3675}
3676
3678{
3679 if (--m_cRefs == 0)
3680 {
3681 delete this;
3682 return 0;
3683 }
3684 return m_cRefs;
3685}
3686
3689{
3690 if (click == TF_LBI_CLK_RIGHT)
3691 {
3692 return E_NOTIMPL; //FIXME
3693 }
3694 if (click == TF_LBI_CLK_LEFT)
3695 {
3696 return E_NOTIMPL; //FIXME
3697 }
3698 return E_NOTIMPL;
3699}
3700
3702{
3703 return E_NOTIMPL;
3704}
3705
3707{
3708 return E_NOTIMPL;
3709}
3710
3712{
3713 return E_NOTIMPL;
3714}
3715
3717{
3718 if (!pbstr)
3719 return E_INVALIDARG;
3721 return (*pbstr ? S_OK : E_OUTOFMEMORY);
3722}
3723
3725{
3726 return CLBarItemBase::GetInfo(pInfo);
3727}
3728
3730{
3731 return CLBarItemBase::GetStatus(pdwStatus);
3732}
3733
3735{
3736 return CLBarItemBase::Show(fShow);
3737}
3738
3740{
3741 return CLBarItemBase::GetTooltipString(pbstrToolTip);
3742}
3743
3745 REFIID riid,
3746 IUnknown *punk,
3747 DWORD *pdwCookie)
3748{
3749 return CLBarItemBase::AdviseSink(riid, punk, pdwCookie);
3750}
3751
3753{
3754 return CLBarItemBase::UnadviseSink(dwCookie);
3755}
3756
3757/***********************************************************************
3758 * CLBarInatItem
3759 */
3760
3762{
3763 WCHAR szText[256];
3764 ::LoadStringW(g_hInst, IDS_LANGUAGE, szText, _countof(szText));
3765 InitNuiInfo(CLSID_SYSTEMLANGBARITEM, GUID_LBI_INATITEM, 0x20001, 0, szText);
3766
3771
3774}
3775
3777{
3778 HICON hIcon = NULL;
3779 INT iIndex = GetIconIndexFromhKL(m_hKL);
3780 if (iIndex != -1)
3781 hIcon = TF_InatExtractIcon(iIndex);
3782 *phIcon = hIcon;
3783 return S_OK;
3784}
3785
3787{
3788 if (!pbstr)
3789 return E_INVALIDARG;
3790
3791 WCHAR szText[256];
3792 if (!GethKLDesc(m_hKL, szText, _countof(szText)))
3793 return GetText(pbstr);
3794
3795 *pbstr = ::SysAllocString(szText);
3796 return S_OK;
3797}
3798
3800{
3802
3803 INT iKL, cKLs = TF_MlngInfoCount();
3804 for (iKL = 0; iKL < cKLs; ++iKL)
3805 {
3806 HKL hKL;
3807 WCHAR szDesc[128];
3808 if (TF_GetMlngHKL(iKL, &hKL, szDesc, _countof(szDesc)))
3809 {
3810 HICON hIcon = NULL;
3811 INT iIndex = GetIconIndexFromhKL(hKL);
3812 if (iIndex != -1)
3813 hIcon = TF_InatExtractIcon(iIndex);
3814
3815 LangBarInsertMenu(pMenu, iKL, szDesc, (hKL == m_hKL), hIcon);
3816 }
3817 }
3818
3820 if (g_pTipbarWnd &&
3823 (dwStatus & (TF_SFT_DESKBAND | TF_SFT_MINIMIZED)))
3824 {
3826
3827 WCHAR szText[256];
3829 LangBarInsertMenu(pMenu, 2000, szText, FALSE, NULL);
3830 }
3831
3832 return S_OK;
3833}
3834
3836{
3837 HKL hKL;
3838
3839 if (nCommandId == 2000)
3840 {
3841 if (g_pTipbarWnd)
3842 {
3844 if (pLangBarMgr)
3845 pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
3846 }
3847 }
3848 else if (TF_GetMlngHKL(nCommandId, &hKL, NULL, 0))
3849 {
3851 HWND hwndFore = ::GetForegroundWindow();
3853 {
3854 BOOL FontSig = GetFontSig(hwndFore, hKL);
3855 ::PostMessage(hwndFore, WM_INPUTLANGCHANGEREQUEST, FontSig, (LPARAM)hKL);
3856 }
3857 }
3858
3859 return S_OK;
3860}
3861
3862/***********************************************************************
3863 * CTipbarGripper
3864 */
3865
3867 : CUIFGripper((pTipbarWnd ? pTipbarWnd->GetWindow() : NULL), prc, style)
3868{
3870 m_pTipbarWnd = pTipbarWnd;
3871}
3872
3874STDMETHODIMP_(void) CTipbarGripper::OnLButtonUp(LONG x, LONG y)
3875{
3877
3879 {
3880 APPBARDATA AppBar = { sizeof(AppBar) };
3881 AppBar.hWnd = ::FindWindowW(L"Shell_TrayWnd", NULL);
3883 {
3884 RECT rc = AppBar.rc;
3885 POINT pt;
3887 if (g_pTipbarWnd && ::PtInRect(&rc, pt))
3888 g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_DESKBAND |
3889 TF_SFT_EXTRAICONSONMINIMIZED);
3890 }
3891 }
3892
3893 CUIFGripper::OnLButtonUp(x, y);
3895}
3896
3898STDMETHODIMP_(void) CTipbarGripper::OnRButtonUp(LONG x, LONG y)
3899{
3900 if (g_bShowDebugMenu)
3901 {
3902 // FIXME: Debugging feature
3903 }
3904}
3905
3906STDMETHODIMP_(BOOL) CTipbarGripper::OnSetCursor(UINT uMsg, LONG x, LONG y)
3907{
3908 if (m_bInDebugMenu)
3909 return FALSE;
3910
3911 return CUIFGripper::OnSetCursor(uMsg, x, y);
3912}
3913
3914/***********************************************************************
3915 * CLangBarItemList
3916 */
3917
3919{
3920 auto *pItem = FindItem(rclsid);
3921 if (!pItem)
3922 return FALSE;
3923 return pItem->m_bStartedIntentionally;
3924}
3925
3927{
3928 auto *pItem = FindItem(rclsid);
3929 if (pItem)
3930 return pItem;
3931
3932 pItem = Append(1);
3933 if (!pItem)
3934 return NULL;
3935
3936