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
10 WINE_DEFAULT_DEBUG_CHANNEL(msutb);
11
12 //#define ENABLE_DESKBAND
13
14 typedef struct LANGBARITEMSTATE
15 {
16 CLSID m_clsid;
17 DWORD m_dwDemoteLevel;
18 UINT_PTR m_nTimerID;
19 UINT m_uTimeOut;
20 BOOL m_bStartedIntentionally;
21 BOOL m_bDisableDemoting;
22
IsShownLANGBARITEMSTATE23 BOOL IsShown()
24 {
25 return m_dwDemoteLevel < 2;
26 }
27 } LANGBARITEMSTATE, *PLANGBARITEMSTATE;
28
29 HINSTANCE g_hInst = NULL;
30 UINT g_wmTaskbarCreated = 0;
31 UINT g_uACP = CP_ACP;
32 DWORD g_dwOSInfo = 0;
33 CRITICAL_SECTION g_cs;
34 LONG g_DllRefCount = 0;
35 BOOL g_bWinLogon = FALSE;
36 BOOL g_fInClosePopupTipbar = FALSE;
37 HWND g_hwndParent = NULL;
38 CIC_LIBTHREAD g_libTLS = { NULL, NULL };
39 #ifdef ENABLE_DESKBAND
40 BOOL g_bEnableDeskBand = TRUE;
41 #else
42 BOOL g_bEnableDeskBand = FALSE;
43 #endif
44
45 BOOL g_bShowTipbar = TRUE;
46 BOOL g_bShowDebugMenu = FALSE;
47 BOOL g_bNewLook = TRUE;
48 BOOL g_bIntelliSense = FALSE;
49 BOOL g_bShowCloseMenu = FALSE;
50 UINT g_uTimeOutNonIntentional = 60 * 1000;
51 UINT g_uTimeOutIntentional = 10 * 60 * 1000;
52 UINT g_uTimeOutMax = 60 * 60 * 1000;
53 BOOL g_bShowMinimizedBalloon = TRUE;
54 POINT g_ptTipbar = { -1, -1 };
55 BOOL g_bExcludeCaptionButtons = TRUE;
56 BOOL g_bShowShadow = FALSE;
57 BOOL g_fTaskbarTheme = TRUE;
58 BOOL g_fVertical = FALSE;
59 UINT g_uTimerElapseSTUBSTART = 100;
60 UINT g_uTimerElapseSTUBEND = 2 * 1000;
61 UINT g_uTimerElapseBACKTOALPHA = 3 * 1000;
62 UINT g_uTimerElapseONTHREADITEMCHANGE = 200;
63 UINT g_uTimerElapseSETWINDOWPOS = 100;
64 UINT g_uTimerElapseONUPDATECALLED = 50;
65 UINT g_uTimerElapseSYSCOLORCHANGED = 20;
66 UINT g_uTimerElapseDISPLAYCHANGE = 20;
67 UINT g_uTimerElapseUPDATEUI = 70;
68 UINT g_uTimerElapseSHOWWINDOW = 50;
69 UINT g_uTimerElapseMOVETOTRAY = 50;
70 UINT g_uTimerElapseTRAYWNDONDELAYMSG = 50;
71 UINT g_uTimerElapseDOACCDEFAULTACTION = 200;
72 UINT g_uTimerElapseENSUREFOCUS = 50;
73 BOOL g_bShowDeskBand = FALSE;
74 UINT g_uTimerElapseSHOWDESKBAND = 3 * 1000;
75 BOOL g_fPolicyDisableCloseButton = FALSE;
76 BOOL g_fPolicyEnableLanguagebarInFullscreen = FALSE;
77 DWORD g_dwWndStyle = 0;
78 DWORD g_dwMenuStyle = 0;
79 DWORD g_dwChildWndStyle = 0;
80 BOOL g_fRTL = FALSE;
81
82 #define TIMER_ID_DOACCDEFAULTACTION 11
83
84 class CMsUtbModule : public CComModule
85 {
86 };
87
88 CMsUtbModule gModule;
89
90 class CCicLibMenuItem;
91 class CTipbarAccItem;
92 class CUTBMenuItem;
93 class CMainIconItem;
94 class CTrayIconItem;
95 class CTipbarWnd;
96 class CButtonIconItem;
97 class CTrayIconWnd;
98
99 CTipbarWnd *g_pTipbarWnd = NULL;
100 CTrayIconWnd *g_pTrayIconWnd = NULL;
101
102 CicArray<HKL> *g_prghklSkipRedrawing = NULL;
103
IsSkipRedrawHKL(HKL hSkipKL)104 BOOL IsSkipRedrawHKL(HKL hSkipKL)
105 {
106 if (LOWORD(hSkipKL) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
107 return FALSE; // Japanese HKL will be skipped
108 if (!g_prghklSkipRedrawing)
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
IsBiDiLocalizedSystem(void)120 BOOL IsBiDiLocalizedSystem(void)
121 {
122 LOCALESIGNATURE Sig;
123 LANGID LangID = ::GetUserDefaultUILanguage();
124 if (!LangID)
125 return FALSE;
126
127 INT size = sizeof(Sig) / sizeof(WCHAR);
128 if (!::GetLocaleInfoW(LangID, LOCALE_FONTSIGNATURE, (LPWSTR)&Sig, size))
129 return FALSE;
130 return (Sig.lsUsb[3] & 0x8000000) != 0;
131 }
132
GetFontSig(HWND hWnd,HKL hKL)133 BOOL GetFontSig(HWND hWnd, HKL hKL)
134 {
135 LOCALESIGNATURE Sig;
136 INT size = sizeof(Sig) / sizeof(WCHAR);
137 if (!::GetLocaleInfoW(LOWORD(hKL), LOCALE_FONTSIGNATURE, (LPWSTR)&Sig, size))
138 return FALSE;
139
140 HDC hDC = ::GetDC(hWnd);
141 DWORD CharSet = ::GetTextCharsetInfo(hDC, NULL, 0);
142 CHARSETINFO CharSetInfo;
143 ::TranslateCharsetInfo((DWORD*)(DWORD_PTR)CharSet, &CharSetInfo, TCI_SRCCHARSET);
144 ::ReleaseDC(hWnd, hDC);
145
146 return !!(CharSetInfo.fs.fsCsb[0] & Sig.lsCsbSupported[0]);
147 }
148
InitSkipRedrawHKLArray(void)149 void InitSkipRedrawHKLArray(void)
150 {
151 g_prghklSkipRedrawing = new(cicNoThrow) CicArray<HKL>();
152 if (!g_prghklSkipRedrawing)
153 return;
154
155 if (g_bEnableDeskBand && (g_dwOSInfo & CIC_OSINFO_XPPLUS))
156 {
157 // Japanese IME will be skipped
158 g_prghklSkipRedrawing->Add((HKL)UlongToHandle(0xE0010411));
159 }
160
161 CicRegKey regKey;
162 LSTATUS error = regKey.Open(HKEY_LOCAL_MACHINE,
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
UninitSkipRedrawHKLArray(void)183 void UninitSkipRedrawHKLArray(void)
184 {
185 if (g_prghklSkipRedrawing)
186 {
187 delete g_prghklSkipRedrawing;
188 g_prghklSkipRedrawing = NULL;
189 }
190 }
191
GetGlobalCompartment(REFGUID rguid,ITfCompartment ** ppComp)192 HRESULT GetGlobalCompartment(REFGUID rguid, ITfCompartment **ppComp)
193 {
194 ITfCompartmentMgr *pCompMgr = NULL;
195 HRESULT hr = TF_GetGlobalCompartment(&pCompMgr);
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
GetGlobalCompartmentDWORD(REFGUID rguid,LPDWORD pdwValue)207 HRESULT GetGlobalCompartmentDWORD(REFGUID rguid, LPDWORD pdwValue)
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
SetGlobalCompartmentDWORD(REFGUID rguid,DWORD dwValue)223 HRESULT SetGlobalCompartmentDWORD(REFGUID rguid, DWORD dwValue)
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
TurnOffSpeechIfItsOn(void)238 void TurnOffSpeechIfItsOn(void)
239 {
240 DWORD dwValue = 0;
241 HRESULT hr = GetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, &dwValue);
242 if (SUCCEEDED(hr) && dwValue)
243 SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0);
244 }
245
DoCloseLangbar(void)246 void DoCloseLangbar(void)
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))
260 TurnOffSpeechIfItsOn();
261
262 CicRegKey regKey;
263 LSTATUS error = regKey.Open(HKEY_CURRENT_USER,
264 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
265 KEY_ALL_ACCESS);
266 if (error == ERROR_SUCCESS)
267 ::RegDeleteValue(regKey, TEXT("ctfmon.exe"));
268 }
269
GetIconIndexFromhKL(_In_ HKL hKL)270 INT GetIconIndexFromhKL(_In_ HKL hKL)
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
GethKLDesc(_In_ HKL hKL,_Out_ LPWSTR pszDesc,_In_ UINT cchDesc)287 BOOL 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
301 HRESULT
LangBarInsertMenu(_In_ ITfMenu * pMenu,_In_ UINT uId,_In_ LPCWSTR pszText,_In_ BOOL bChecked,_Inout_opt_ HICON hIcon)302 LangBarInsertMenu(
303 _In_ ITfMenu *pMenu,
304 _In_ UINT uId,
305 _In_ LPCWSTR pszText,
306 _In_ BOOL bChecked,
307 _Inout_opt_ HICON hIcon)
308 {
309 HBITMAP hbmp = NULL, hbmpMask = NULL;
310 if (hIcon)
311 {
312 HICON hIconNew = (HICON)::CopyImage(hIcon, IMAGE_ICON, 16, 16, LR_COPYFROMRESOURCE);
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);
320 ::DestroyIcon(hIcon);
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
LangBarInsertSeparator(_In_ ITfMenu * pMenu)328 HRESULT LangBarInsertSeparator(_In_ ITfMenu *pMenu)
329 {
330 return pMenu->AddMenuItem(-1, TF_LBMENUF_SEPARATOR, NULL, NULL, NULL, 0, NULL);
331 }
332
333 // Is it a Far-East language ID?
IsFELangId(LANGID LangID)334 BOOL IsFELangId(LANGID LangID)
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
CheckCloseMenuAvailable(void)348 BOOL CheckCloseMenuAvailable(void)
349 {
350 BOOL ret = FALSE;
351 ITfInputProcessorProfiles *pProfiles = NULL;
352 LANGID *pLangIds = NULL;
353 ULONG iItem, cItems;
354
355 if (g_fPolicyDisableCloseButton)
356 return FALSE;
357
358 if (g_bShowCloseMenu)
359 return TRUE;
360
361 if (SUCCEEDED(TF_CreateInputProcessorProfiles(&pProfiles)) &&
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
381 /// @unimplemented
IsTransparecyAvailable(void)382 BOOL IsTransparecyAvailable(void)
383 {
384 return FALSE;
385 }
386
387 static INT CALLBACK
FindEAEnumFontProc(ENUMLOGFONT * pLF,NEWTEXTMETRIC * pTM,INT nFontType,LPARAM lParam)388 FindEAEnumFontProc(ENUMLOGFONT *pLF, NEWTEXTMETRIC *pTM, INT nFontType, LPARAM lParam)
389 {
390 if ((nFontType != TRUETYPE_FONTTYPE) || (pLF->elfLogFont.lfFaceName[0] != '@'))
391 return TRUE;
392 *(BOOL*)lParam = TRUE;
393 return FALSE;
394 }
395
396 /// Are there East-Asian vertical fonts?
CheckEAFonts(void)397 BOOL CheckEAFonts(void)
398 {
399 BOOL bHasVertical = FALSE;
400 HDC hDC = ::GetDC(NULL);
401 ::EnumFonts(hDC, NULL, (FONTENUMPROC)FindEAEnumFontProc, (LPARAM)&bHasVertical);
402 ::ReleaseDC(NULL, hDC);
403 return bHasVertical;
404 }
405
IsDeskBandFromReg()406 BOOL IsDeskBandFromReg()
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
SetDeskBandToReg(BOOL bShow)422 void SetDeskBandToReg(BOOL bShow)
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
RegisterComCat(REFCLSID rclsid,REFCATID rcatid,BOOL bRegister)429 BOOL RegisterComCat(REFCLSID rclsid, REFCATID rcatid, BOOL bRegister)
430 {
431 if (FAILED(::CoInitialize(NULL)))
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
447 ::CoUninitialize();
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
InitFromReg(void)455 BOOL InitFromReg(void)
456 {
457 DWORD dwValue;
458 LSTATUS error;
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)
523 g_uTimerElapseBACKTOALPHA = dwValue;
524 error = regKey2.QueryDword(TEXT("TimerElapseONTHREADITEMCHANGE"), &dwValue);
525 if (error == ERROR_SUCCESS)
526 g_uTimerElapseONTHREADITEMCHANGE = dwValue;
527 error = regKey2.QueryDword(TEXT("TimerElapseSETWINDOWPOS"), &dwValue);
528 if (error == ERROR_SUCCESS)
529 g_uTimerElapseSETWINDOWPOS = dwValue;
530 error = regKey2.QueryDword(TEXT("TimerElapseONUPDATECALLED"), &dwValue);
531 if (error == ERROR_SUCCESS)
532 g_uTimerElapseONUPDATECALLED = dwValue;
533 error = regKey2.QueryDword(TEXT("TimerElapseSYSCOLORCHANGED"), &dwValue);
534 if (error == ERROR_SUCCESS)
535 g_uTimerElapseSYSCOLORCHANGED = dwValue;
536 error = regKey2.QueryDword(TEXT("TimerElapseDISPLAYCHANGE"), &dwValue);
537 if (error == ERROR_SUCCESS)
538 g_uTimerElapseDISPLAYCHANGE = dwValue;
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)
550 g_uTimerElapseTRAYWNDONDELAYMSG = dwValue;
551 error = regKey2.QueryDword(TEXT("TimerElapseDOACCDEFAULTACTION"), &dwValue);
552 if (error == ERROR_SUCCESS)
553 g_uTimerElapseDOACCDEFAULTACTION = dwValue;
554 error = regKey2.QueryDword(TEXT("TimerElapseENSUREFOCUS"), &dwValue);
555 if (error == ERROR_SUCCESS)
556 g_uTimerElapseENSUREFOCUS = dwValue;
557 if (g_bEnableDeskBand && (g_dwOSInfo & CIC_OSINFO_XPPLUS))
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)
564 g_uTimerElapseSHOWDESKBAND = dwValue;
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)
583 g_fPolicyEnableLanguagebarInFullscreen = !!dwValue;
584 }
585
586 InitSkipRedrawHKLArray();
587
588 if (g_bNewLook)
589 {
590 g_dwWndStyle = UIF_WINDOW_ENABLETHEMED | UIF_WINDOW_WORKAREA | UIF_WINDOW_TOOLTIP |
591 UIF_WINDOW_TOOLWINDOW | UIF_WINDOW_TOPMOST;
592 if (g_bShowShadow)
593 g_dwWndStyle |= UIF_WINDOW_SHADOW;
594 g_dwMenuStyle = 0x10000000 | UIF_WINDOW_MONITOR | UIF_WINDOW_SHADOW |
595 UIF_WINDOW_TOOLWINDOW | UIF_WINDOW_TOPMOST;
596 }
597 else
598 {
599 g_dwWndStyle = UIF_WINDOW_WORKAREA | UIF_WINDOW_TOOLTIP | UIF_WINDOW_DLGFRAME |
600 UIF_WINDOW_TOPMOST;
601 g_dwMenuStyle = UIF_WINDOW_MONITOR | UIF_WINDOW_DLGFRAME | UIF_WINDOW_TOPMOST;
602 }
603
604 g_dwChildWndStyle =
605 UIF_WINDOW_ENABLETHEMED | UIF_WINDOW_NOMOUSEMSG | UIF_WINDOW_TOOLTIP | UIF_WINDOW_CHILD;
606
607 if (IsBiDiLocalizedSystem())
608 {
609 g_dwWndStyle |= UIF_WINDOW_LAYOUTRTL;
610 g_dwChildWndStyle |= UIF_WINDOW_LAYOUTRTL;
611 g_dwMenuStyle |= UIF_WINDOW_LAYOUTRTL;
612 g_fRTL = TRUE;
613 }
614
615 return TRUE;
616 }
617
618 /***********************************************************************/
619
620 struct CShellWndThread
621 {
622 HWND m_hTrayWnd = NULL;
623 HWND m_hProgmanWnd = NULL;
624
GetWndTrayCShellWndThread625 HWND GetWndTray()
626 {
627 if (!m_hTrayWnd || !::IsWindow(m_hTrayWnd))
628 m_hTrayWnd = ::FindWindowW(L"Shell_TrayWnd", NULL);
629 return m_hTrayWnd;
630 }
631
GetWndProgmanCShellWndThread632 HWND GetWndProgman()
633 {
634 if (!m_hProgmanWnd || !::IsWindow(m_hProgmanWnd))
635 m_hProgmanWnd = ::FindWindowW(L"Progman", NULL);
636 return m_hProgmanWnd;
637 }
638
clearCShellWndThread639 void clear()
640 {
641 m_hTrayWnd = m_hProgmanWnd = NULL;
642 }
643 };
644
645 /***********************************************************************/
646
647 class CUTBLangBarDlg
648 {
649 protected:
650 LPTSTR m_pszDialogName;
651 LONG m_cRefs;
652
653 public:
CUTBLangBarDlg()654 CUTBLangBarDlg() { }
~CUTBLangBarDlg()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);
660 static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
661
662 BOOL StartThread();
663 LONG _Release();
664
665 STDMETHOD_(BOOL, DoModal)(HWND hDlg) = 0;
666 STDMETHOD_(BOOL, OnCommand)(HWND hDlg, WPARAM wParam, LPARAM lParam) = 0;
667 STDMETHOD_(BOOL, IsDlgShown)() = 0;
668 STDMETHOD_(void, SetDlgShown)(BOOL bShown) = 0;
669 STDMETHOD_(BOOL, ThreadProc)();
670 };
671
672 /***********************************************************************/
673
674 class CUTBCloseLangBarDlg : public CUTBLangBarDlg
675 {
676 public:
677 CUTBCloseLangBarDlg();
678
679 static BOOL s_bIsDlgShown;
680
681 STDMETHOD_(BOOL, DoModal)(HWND hDlg) override;
682 STDMETHOD_(BOOL, OnCommand)(HWND hDlg, WPARAM wParam, LPARAM lParam) override;
683 STDMETHOD_(BOOL, IsDlgShown)() override;
684 STDMETHOD_(void, SetDlgShown)(BOOL bShown) override;
685 };
686
687 BOOL CUTBCloseLangBarDlg::s_bIsDlgShown = FALSE;
688
689 /***********************************************************************/
690
691 class CUTBMinimizeLangBarDlg : public CUTBLangBarDlg
692 {
693 public:
694 CUTBMinimizeLangBarDlg();
695
696 static BOOL s_bIsDlgShown;
697
698 STDMETHOD_(BOOL, DoModal)(HWND hDlg) override;
699 STDMETHOD_(BOOL, OnCommand)(HWND hDlg, WPARAM wParam, LPARAM lParam) override;
700 STDMETHOD_(BOOL, IsDlgShown)() override;
701 STDMETHOD_(void, SetDlgShown)(BOOL bShown) override;
702 STDMETHOD_(BOOL, ThreadProc)() override;
703 };
704
705 BOOL CUTBMinimizeLangBarDlg::s_bIsDlgShown = FALSE;
706
707 /***********************************************************************/
708
709 class CCicLibMenu : public ITfMenu
710 {
711 protected:
712 CicArray<CCicLibMenuItem*> m_MenuItems;
713 LONG m_cRefs;
714
715 public:
716 CCicLibMenu();
717 virtual ~CCicLibMenu();
718
719 STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj) override;
720 STDMETHOD_(ULONG, AddRef)() override;
721 STDMETHOD_(ULONG, Release)() override;
722 STDMETHOD(AddMenuItem)(
723 UINT uId,
724 DWORD dwFlags,
725 HBITMAP hbmp,
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
736 class CCicLibMenuItem
737 {
738 protected:
739 DWORD m_uId;
740 DWORD m_dwFlags;
741 HBITMAP m_hbmp;
742 HBITMAP m_hbmpMask;
743 BSTR m_bstrText;
744 ITfMenu *m_pMenu;
745
746 public:
747 CCicLibMenuItem();
748 virtual ~CCicLibMenuItem();
749
750 BOOL Init(
751 UINT uId,
752 DWORD dwFlags,
753 HBITMAP hbmp,
754 HBITMAP hbmpMask,
755 const WCHAR *pch,
756 ULONG cch,
757 ITfMenu *pMenu);
758 HBITMAP CreateBitmap(HANDLE hBitmap);
759 };
760
761 /***********************************************************************/
762
763 class CTipbarAccessible : public IAccessible
764 {
765 protected:
766 LONG m_cRefs;
767 HWND m_hWnd;
768 IAccessible *m_pStdAccessible;
769 ITypeInfo *m_pTypeInfo;
770 BOOL m_bInitialized;
771 CicArray<CTipbarAccItem*> m_AccItems;
772 LONG m_cSelection;
773 friend class CUTBMenuWnd;
774 friend class CTipbarWnd;
775
776 public:
777 CTipbarAccessible(CTipbarAccItem *pItem);
778 virtual ~CTipbarAccessible();
779
780 HRESULT Initialize();
781
782 BOOL AddAccItem(CTipbarAccItem *pItem);
783 HRESULT RemoveAccItem(CTipbarAccItem *pItem);
784 void ClearAccItems();
785 CTipbarAccItem *AccItemFromID(INT iItem);
786 INT GetIDOfItem(CTipbarAccItem *pTarget);
787
788 LONG_PTR CreateRefToAccObj(WPARAM wParam);
789 BOOL DoDefaultActionReal(INT nID);
790 void NotifyWinEvent(DWORD event, CTipbarAccItem *pItem);
791 void SetWindow(HWND hWnd);
792
793 // IUnknown methods
794 STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
795 STDMETHOD_(ULONG, AddRef)();
796 STDMETHOD_(ULONG, Release)();
797
798 // IDispatch methods
799 STDMETHOD(GetTypeInfoCount)(UINT *pctinfo);
800 STDMETHOD(GetTypeInfo)(
801 UINT iTInfo,
802 LCID lcid,
803 ITypeInfo **ppTInfo);
804 STDMETHOD(GetIDsOfNames)(
805 REFIID riid,
806 LPOLESTR *rgszNames,
807 UINT cNames,
808 LCID lcid,
809 DISPID *rgDispId);
810 STDMETHOD(Invoke)(
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);
826 STDMETHOD(get_accDescription)(VARIANT varID, BSTR *description);
827 STDMETHOD(get_accRole)(VARIANT varID, VARIANT *role);
828 STDMETHOD(get_accState)(VARIANT varID, VARIANT *state);
829 STDMETHOD(get_accHelp)(VARIANT varID, BSTR *help);
830 STDMETHOD(get_accHelpTopic)(BSTR *helpfile, VARIANT varID, LONG *pidTopic);
831 STDMETHOD(get_accKeyboardShortcut)(VARIANT varID, BSTR *shortcut);
832 STDMETHOD(get_accFocus)(VARIANT *pvarID);
833 STDMETHOD(get_accSelection)(VARIANT *pvarID);
834 STDMETHOD(get_accDefaultAction)(VARIANT varID, BSTR *action);
835 STDMETHOD(accSelect)(LONG flagsSelect, VARIANT varID);
836 STDMETHOD(accLocation)(
837 LONG *left,
838 LONG *top,
839 LONG *width,
840 LONG *height,
841 VARIANT varID);
842 STDMETHOD(accNavigate)(LONG dir, VARIANT varStart, VARIANT *pvarEnd);
843 STDMETHOD(accHitTest)(LONG left, LONG top, VARIANT *pvarID);
844 STDMETHOD(accDoDefaultAction)(VARIANT varID);
845 STDMETHOD(put_accName)(VARIANT varID, BSTR name);
846 STDMETHOD(put_accValue)(VARIANT varID, BSTR value);
847 };
848
849 /***********************************************************************/
850
851 class CTipbarAccItem
852 {
853 public:
CTipbarAccItem()854 CTipbarAccItem() { }
~CTipbarAccItem()855 virtual ~CTipbarAccItem() { }
856
STDMETHOD_(BSTR,GetAccName)857 STDMETHOD_(BSTR, GetAccName)()
858 {
859 return SysAllocString(L"");
860 }
STDMETHOD_(BSTR,GetAccValue)861 STDMETHOD_(BSTR, GetAccValue)()
862 {
863 return NULL;
864 }
STDMETHOD_(INT,GetAccRole)865 STDMETHOD_(INT, GetAccRole)()
866 {
867 return 10;
868 }
STDMETHOD_(INT,GetAccState)869 STDMETHOD_(INT, GetAccState)()
870 {
871 return 256;
872 }
STDMETHOD_(void,GetAccLocation)873 STDMETHOD_(void, GetAccLocation)(LPRECT lprc)
874 {
875 *lprc = { 0, 0, 0, 0 };
876 }
STDMETHOD_(BSTR,GetAccDefaultAction)877 STDMETHOD_(BSTR, GetAccDefaultAction)()
878 {
879 return NULL;
880 }
STDMETHOD_(BOOL,DoAccDefaultAction)881 STDMETHOD_(BOOL, DoAccDefaultAction)()
882 {
883 return FALSE;
884 }
STDMETHOD_(BOOL,DoAccDefaultActionReal)885 STDMETHOD_(BOOL, DoAccDefaultActionReal)()
886 {
887 return FALSE;
888 }
889 };
890
891 /***********************************************************************/
892
893 class CTipbarCoInitialize
894 {
895 public:
896 BOOL m_bCoInit;
897
CTipbarCoInitialize()898 CTipbarCoInitialize() : m_bCoInit(FALSE) { }
~CTipbarCoInitialize()899 ~CTipbarCoInitialize() { CoUninit(); }
900
EnsureCoInit()901 HRESULT EnsureCoInit()
902 {
903 if (m_bCoInit)
904 return S_OK;
905 HRESULT hr = ::CoInitialize(NULL);
906 if (FAILED(hr))
907 return hr;
908 m_bCoInit = TRUE;
909 return S_OK;
910 }
911
CoUninit()912 void CoUninit()
913 {
914 if (m_bCoInit)
915 {
916 ::CoUninitialize();
917 m_bCoInit = FALSE;
918 }
919 }
920 };
921
922 /***********************************************************************/
923
924 class CUTBMenuWnd : public CTipbarAccItem, public CUIFMenu
925 {
926 protected:
927 CTipbarCoInitialize m_coInit;
928 CTipbarAccessible *m_pAccessible;
929 UINT m_nMenuWndID;
930 friend class CUTBMenuItem;
931
932 public:
933 CUTBMenuWnd(HINSTANCE hInst, DWORD style, DWORD dwUnknown14);
934
935 BOOL StartDoAccDefaultActionTimer(CUTBMenuItem *pTarget);
936
GetAccItem()937 CTipbarAccItem* GetAccItem()
938 {
939 return static_cast<CTipbarAccItem*>(this);
940 }
GetMenu()941 CUIFMenu* GetMenu()
942 {
943 return static_cast<CUIFMenu*>(this);
944 }
945
946 STDMETHOD_(BSTR, GetAccName)() override;
947 STDMETHOD_(INT, GetAccRole)() override;
948 STDMETHOD_(BOOL, Initialize)() override;
949 STDMETHOD_(void, OnCreate)(HWND hWnd) override;
950 STDMETHOD_(void, OnDestroy)(HWND hWnd) override;
951 STDMETHOD_(HRESULT, OnGetObject)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
952 STDMETHOD_(LRESULT, OnShowWindow)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
953 STDMETHOD_(void, OnTimer)(WPARAM wParam) override;
954 };
955
956 /***********************************************************************/
957
958 class CUTBMenuItem : public CTipbarAccItem, public CUIFMenuItem
959 {
960 protected:
961 CUTBMenuWnd *m_pMenuUI;
962 friend class CUTBMenuWnd;
963
964 public:
965 CUTBMenuItem(CUTBMenuWnd *pMenuUI);
966 ~CUTBMenuItem() override;
967
GetMenuItem()968 CUIFMenuItem* GetMenuItem()
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
983 class CModalMenu
984 {
985 public:
986 DWORD m_dwUnknown26;
987 CUTBMenuWnd *m_pMenuUI;
988
989 public:
CModalMenu()990 CModalMenu() { }
~CModalMenu()991 virtual ~CModalMenu() { }
992
993 CUTBMenuItem *InsertItem(CUTBMenuWnd *pMenuUI, INT nCommandId, INT nStringID);
994 void PostKey(BOOL bUp, WPARAM wParam, LPARAM lParam);
995 void CancelMenu();
996 };
997
998 /***********************************************************************/
999
1000 class CTipbarThread;
1001
1002 class CUTBContextMenu : public CModalMenu
1003 {
1004 public:
1005 CTipbarWnd *m_pTipbarWnd;
1006 CTipbarThread *m_pTipbarThread;
1007
1008 public:
1009 CUTBContextMenu(CTipbarWnd *pTipbarWnd);
1010
1011 BOOL Init();
1012 CUTBMenuWnd *CreateMenuUI(BOOL bFlag);
1013
1014 UINT ShowPopup(
1015 CUIFWindow *pWindow,
1016 POINT pt,
1017 LPCRECT prc,
1018 BOOL bFlag);
1019
1020 BOOL SelectMenuItem(UINT nCommandId);
1021 };
1022
1023 /***********************************************************************/
1024
1025 class CUTBLBarMenuItem;
1026
1027 class CUTBLBarMenu : public CCicLibMenu
1028 {
1029 protected:
1030 CUTBMenuWnd *m_pMenuUI;
1031 HINSTANCE m_hInst;
1032
1033 public:
1034 CUTBLBarMenu(HINSTANCE hInst);
1035 ~CUTBLBarMenu() override;
1036
1037 CUTBMenuWnd *CreateMenuUI();
1038 INT ShowPopup(CUIFWindow *pWindow, POINT pt, LPCRECT prcExclude);
1039
1040 STDMETHOD_(CCicLibMenuItem*, CreateMenuItem)() override;
1041 STDMETHOD_(CCicLibMenu*, CreateSubMenu)() override;
1042 };
1043
1044 /***********************************************************************/
1045
1046 class CUTBLBarMenuItem : public CCicLibMenuItem
1047 {
1048 public:
1049 CUTBLBarMenu *m_pLBarMenu;
1050
1051 public:
CUTBLBarMenuItem()1052 CUTBLBarMenuItem() { m_pLBarMenu = NULL; }
1053 BOOL InsertToUI(CUTBMenuWnd *pMenuUI);
1054 };
1055
1056 /***********************************************************************/
1057
1058 class CTipbarGripper : public CUIFGripper
1059 {
1060 protected:
1061 CTipbarWnd *m_pTipbarWnd;
1062 BOOL m_bInDebugMenu;
1063 friend class CTipbarWnd;
1064
1065 public:
1066 CTipbarGripper(CTipbarWnd *pTipbarWnd, LPCRECT prc, DWORD style);
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
1075 class CLangBarItemList : public CicArray<LANGBARITEMSTATE>
1076 {
1077 public:
1078 BOOL IsStartedIntentionally(REFCLSID rclsid);
1079
1080 LANGBARITEMSTATE *AddItem(REFCLSID rclsid);
1081 void Clear();
1082 BOOL SetDemoteLevel(REFCLSID rclsid, DWORD dwDemoteLevel);
1083
1084 LANGBARITEMSTATE *FindItem(REFCLSID rclsid);
1085 LANGBARITEMSTATE *GetItemStateFromTimerId(UINT_PTR nTimerID);
1086
1087 void Load();
1088 void SaveItem(CicRegKey *pRegKey, const LANGBARITEMSTATE *pState);
1089
1090 void StartDemotingTimer(REFCLSID rclsid, BOOL bIntentional);
1091 UINT_PTR FindDemotingTimerId();
1092 };
1093
1094 /***********************************************************************/
1095
1096 class CTrayIconWnd
1097 {
1098 protected:
1099 DWORD m_dwUnknown20;
1100 BOOL m_bBusy;
1101 UINT m_uCallbackMessage;
1102 UINT m_uMsg;
1103 HWND m_hWnd;
1104 DWORD m_dwUnknown21[2];
1105 HWND m_hTrayWnd;
1106 HWND m_hNotifyWnd;
1107 DWORD m_dwTrayWndThreadId;
1108 DWORD m_dwUnknown22;
1109 HWND m_hwndProgman;
1110 DWORD m_dwProgmanThreadId;
1111 CMainIconItem *m_pMainIconItem;
1112 CicArray<CButtonIconItem*> m_Items;
1113 UINT m_uCallbackMsg;
1114 UINT m_uNotifyIconID;
1115 friend class CTipbarWnd;
1116
1117 static BOOL CALLBACK EnumChildWndProc(HWND hWnd, LPARAM lParam);
1118 static LRESULT CALLBACK _WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
1119
1120 public:
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
1134 void RemoveAllIcon(DWORD dwFlags);
1135 void RemoveUnusedIcons(int unknown);
1136
1137 CButtonIconItem *FindIconItem(REFGUID rguid);
1138 BOOL FindTrayEtc();
1139 HWND GetNotifyWnd();
1140 BOOL OnIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
1141
1142 void CallOnDelayMsg();
1143 };
1144
1145 /***********************************************************************/
1146
1147 class CTrayIconItem
1148 {
1149 protected:
1150 HWND m_hWnd;
1151 UINT m_uCallbackMessage;
1152 UINT m_uNotifyIconID;
1153 DWORD m_dwIconAddOrModify;
1154 BOOL m_bIconAdded;
1155 CTrayIconWnd *m_pTrayIconWnd;
1156 DWORD m_dwUnknown25;
1157 GUID m_guid;
1158 RECT m_rcMenu;
1159 POINT m_ptCursor;
1160 friend class CTrayIconWnd;
1161
1162 public:
1163 CTrayIconItem(CTrayIconWnd *pTrayIconWnd);
~CTrayIconItem()1164 virtual ~CTrayIconItem() { }
1165
1166 BOOL _Init(HWND hWnd, UINT uCallbackMessage, UINT uNotifyIconID, const GUID& rguid);
1167 BOOL UpdateMenuRectPoint();
1168 BOOL RemoveIcon();
1169
1170 STDMETHOD_(BOOL, SetIcon)(HICON hIcon, LPCWSTR pszTip);
STDMETHOD_(BOOL,OnMsg)1171 STDMETHOD_(BOOL, OnMsg)(WPARAM wParam, LPARAM lParam) { return FALSE; };
STDMETHOD_(BOOL,OnDelayMsg)1172 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) { return 0; };
1173 };
1174
1175 /***********************************************************************/
1176
1177 class CButtonIconItem : public CTrayIconItem
1178 {
1179 protected:
1180 DWORD m_dwUnknown24;
1181 HKL m_hKL;
1182 friend class CTrayIconWnd;
1183
1184 public:
1185 CButtonIconItem(CTrayIconWnd *pWnd, DWORD dwUnknown24);
1186
1187 STDMETHOD_(BOOL, OnMsg)(WPARAM wParam, LPARAM lParam) override;
1188 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
1189 };
1190
1191 /***********************************************************************/
1192
1193 class CMainIconItem : public CButtonIconItem
1194 {
1195 public:
1196 CMainIconItem(CTrayIconWnd *pWnd);
1197
1198 BOOL Init(HWND hWnd);
1199 STDMETHOD_(BOOL, OnDelayMsg)(UINT uMsg) override;
1200 };
1201
1202 /***********************************************************************/
1203
1204 class CLBarItemBase
1205 {
1206 protected:
1207 DWORD m_dwItemStatus;
1208 TF_LANGBARITEMINFO m_NewUIInfo;
1209 WCHAR m_szToolTipText[256];
1210 LONG m_cRefs;
1211 ITfLangBarItemSink *m_pLangBarItemSink;
1212
1213 public:
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
1226 HRESULT GetInfo(TF_LANGBARITEMINFO *pInfo);
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
1237 class CLBarItemButtonBase
1238 : public CLBarItemBase
1239 , public ITfLangBarItem
1240 , public ITfLangBarItemButton
1241 , public ITfSource
1242 {
1243 public:
1244 HICON m_hIcon;
1245
1246 public:
CLBarItemButtonBase()1247 CLBarItemButtonBase() { m_hIcon = NULL; }
1248 ~CLBarItemButtonBase() override;
1249
1250 // IUnknown methods
1251 STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override;
1252 STDMETHOD_(ULONG, AddRef)() override;
1253 STDMETHOD_(ULONG, Release)() 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
1275 /// Language Bar international item
1276 class CLBarInatItem : public CLBarItemButtonBase
1277 {
1278 protected:
1279 HKL m_hKL;
1280 DWORD m_dwThreadId;
1281
1282 public:
1283 CLBarInatItem(DWORD dwThreadId);
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
1293 class CTipbarItem;
1294 class CTipbarBalloonItem;
1295
1296 class CTipbarThread
1297 {
1298 protected:
1299 CTipbarWnd *m_pTipbarWnd;
1300 ITfLangBarItemMgr *m_pLangBarItemMgr;
1301 CicArray<CTipbarItem*> m_UIObjects;
1302 CicArray<CUIFObject*> m_Separators;
1303 DWORD m_dwUnknown32;
1304 DWORD m_dwThreadId;
1305 DWORD m_dwFlags1;
1306 DWORD m_dwFlags2;
1307 INT m_cxGrip;
1308 INT m_cyGrip;
1309 DWORD m_dwFlags3;
1310 DWORD m_dwUnknown34;
1311 LONG m_cRefs;
1312 friend class CTipbarWnd;
1313 friend class CTipbarItem;
1314
1315 public:
1316 CTipbarThread(CTipbarWnd *pTipbarWnd);
1317 virtual ~CTipbarThread();
1318
1319 HRESULT Init(DWORD dwThreadId);
1320
1321 HRESULT InitItemList();
1322 HRESULT _UninitItemList(BOOL bUnAdvise);
1323
1324 DWORD IsDirtyItem();
1325 BOOL IsFocusThread();
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
1339 HRESULT _UnadviseItemsSink();
_AddRef()1340 LONG _AddRef() { return ++m_cRefs; }
1341 LONG _Release();
1342
1343 /// @unimplemented
SetFocus(CTipbarBalloonItem * pTarget)1344 BOOL SetFocus(CTipbarBalloonItem *pTarget)
1345 {
1346 return FALSE;
1347 }
1348
1349 /// @unimplemented
CallOnUpdateHandler()1350 HRESULT CallOnUpdateHandler()
1351 {
1352 return E_NOTIMPL;
1353 }
1354
1355 //FIXME
1356 };
1357
1358 /***********************************************************************/
1359
1360 class CTipbarItem : public CTipbarAccItem
1361 {
1362 protected:
1363 DWORD m_dwCookie;
1364 TF_LANGBARITEMINFO m_ItemInfo;
1365 DWORD m_dwUnknown16;
1366 DWORD m_dwUnknown17;
1367 CTipbarThread *m_pTipbarThread;
1368 ITfLangBarItem *m_pLangBarItem;
1369 DWORD m_dwUnknown18[2];
1370 DWORD m_dwItemFlags;
1371 DWORD m_dwDirty;
1372 DWORD m_dwUnknown19[4];
1373 friend class CTipbarThread;
1374 friend class CTipbarWnd;
1375
1376 public:
1377 CTipbarItem(
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
1393 void MyClientToScreen(LPPOINT ppt, LPRECT prc);
MyClientToScreen(LPRECT prc)1394 void MyClientToScreen(LPRECT prc) { return MyClientToScreen(NULL, prc); }
1395
1396 STDMETHOD_(BSTR, GetAccName)() override;
1397 STDMETHOD_(void, GetAccLocation)(LPRECT prc) override;
1398 STDMETHOD_(BOOL, DoAccDefaultAction)() override;
STDMETHOD(OnUnknown40)1399 STDMETHOD(OnUnknown40)() { return S_OK; }
STDMETHOD(OnUnknown41)1400 STDMETHOD(OnUnknown41)() { return S_OK; }
STDMETHOD(OnUnknown42)1401 STDMETHOD(OnUnknown42)() { return S_OK; }
STDMETHOD(OnUnknown43)1402 STDMETHOD(OnUnknown43)() { return S_OK; }
1403 STDMETHOD(OnUpdate)(DWORD dwDirty);
STDMETHOD(OnUnknown44)1404 STDMETHOD(OnUnknown44)() { return S_OK; }
STDMETHOD_(void,OnUnknown45)1405 STDMETHOD_(void, OnUnknown45)(DWORD dwDirty, DWORD dwStatus) { }
1406 STDMETHOD_(void, OnUpdateHandler)(ULONG, ULONG);
STDMETHOD(OnUnknown46)1407 STDMETHOD(OnUnknown46)(CUIFWindow *pWindow) { return S_OK; }
STDMETHOD(OnUnknown47)1408 STDMETHOD(OnUnknown47)(CUIFWindow *pWindow) { return S_OK; }
STDMETHOD(OnUnknown48)1409 STDMETHOD(OnUnknown48)() { return S_OK; }
STDMETHOD(OnUnknown49)1410 STDMETHOD(OnUnknown49)() { return S_OK; }
STDMETHOD(OnUnknown50)1411 STDMETHOD(OnUnknown50)() { return S_OK; }
STDMETHOD(OnUnknown51)1412 STDMETHOD(OnUnknown51)() { return S_OK; }
STDMETHOD(OnUnknown52)1413 STDMETHOD(OnUnknown52)() { return S_OK; }
STDMETHOD(OnUnknown53)1414 STDMETHOD(OnUnknown53)(BSTR bstr) { return S_OK; }
STDMETHOD_(LPCWSTR,OnUnknown55)1415 STDMETHOD_(LPCWSTR, OnUnknown55)() { return NULL; }
STDMETHOD(OnUnknown56)1416 STDMETHOD(OnUnknown56)() { return S_OK; }
1417 STDMETHOD_(LPCWSTR, GetToolTip)();
STDMETHOD(OnUnknown57)1418 STDMETHOD(OnUnknown57)(LPRECT prc) { return S_OK; }
STDMETHOD(OnUnknown58)1419 STDMETHOD(OnUnknown58)() { return S_OK; }
STDMETHOD_(void,OnUnknown59)1420 STDMETHOD_(void, OnUnknown59)() { }
STDMETHOD_(void,OnUnknown60)1421 STDMETHOD_(void, OnUnknown60)() { }
STDMETHOD_(void,OnUnknown61)1422 STDMETHOD_(void, OnUnknown61)(HWND) { }
STDMETHOD_(void,OnUnknown62)1423 STDMETHOD_(void, OnUnknown62)(HWND) { }
STDMETHOD(OnUnknown63)1424 STDMETHOD(OnUnknown63)() { return S_OK; }
1425 };
1426
1427 /***********************************************************************/
1428
1429 class CTipbarCtrlButtonHolder;
1430 class CDeskBand;
1431
1432 // Flags for m_dwTipbarWndFlags
1433 enum
1434 {
1435 TIPBAR_ATTACHED = 0x1,
1436 TIPBAR_CHILD = 0x2,
1437 TIPBAR_VERTICAL = 0x4,
1438 TIPBAR_HIGHCONTRAST = 0x10,
1439 TIPBAR_TRAYICON = 0x20,
1440 TIPBAR_UPDATING = 0x400,
1441 TIPBAR_ENSURING = 0x2000,
1442 TIPBAR_NODESKBAND = 0x4000,
1443 TIPBAR_TOOLBARENDED = 0x10000,
1444 TIPBAR_TOPFIT = 0x40000,
1445 TIPBAR_BOTTOMFIT = 0x80000,
1446 TIPBAR_RIGHTFIT = 0x100000,
1447 TIPBAR_LEFTFIT = 0x200000,
1448 };
1449
1450 class CTipbarWnd
1451 : public ITfLangBarEventSink
1452 , public ITfLangBarEventSink_P
1453 , public CTipbarAccItem
1454 , public CUIFWindow
1455 {
1456 CTipbarCoInitialize m_coInit;
1457 DWORD m_dwSinkCookie;
1458 CModalMenu *m_pModalMenu;
1459 CTipbarThread *m_pThread;
1460 CLangBarItemList m_LangBarItemList;
1461 DWORD m_dwUnknown20;
1462 CUIFWndFrame *m_pWndFrame;
1463 CTipbarGripper *m_pTipbarGripper;
1464 CTipbarThread *m_pFocusThread;
1465 CicArray<CTipbarThread*> m_Threads;
1466 CicArray<CTipbarThread*> m_ThreadCreatingList;
1467 DWORD m_dwAlphaValue;
1468 DWORD m_dwTipbarWndFlags;
1469 LONG m_ButtonWidth;
1470 DWORD m_dwShowType;
1471 DWORD m_dwUnknown21;
1472 INT m_cxSmallIcon;
1473 INT m_cySmallIcon;
1474 INT m_cxDlgFrameX2;
1475 INT m_cyDlgFrameX2;
1476 HFONT m_hMarlettFont;
1477 HFONT m_hTextFont;
1478 ITfLangBarMgr_P *m_pLangBarMgr;
1479 DWORD m_dwUnknown23;
1480 CTipbarCtrlButtonHolder *m_pTipbarCtrlButtonHolder;
1481 DWORD m_dwUnknown23_1[8];
1482 CUIFWindow *m_pBalloon;
1483 DWORD m_dwChangingThreadId;
1484 LONG m_bInCallOn;
1485 LONG m_X;
1486 LONG m_Y;
1487 LONG m_CX;
1488 LONG m_CY;
1489 CTipbarAccessible *m_pTipbarAccessible;
1490 INT m_nID;
1491 MARGINS m_Margins;
1492 DWORD m_dwUnknown23_5[4];
1493 CTipbarThread *m_pUnknownThread;
1494 CDeskBand *m_pDeskBand;
1495 CShellWndThread m_ShellWndThread;
1496 LONG m_cRefs;
1497 friend class CUTBContextMenu;
1498 friend class CTipbarGripper;
1499 friend class CTipbarThread;
1500 friend class CTipbarItem;
1501 friend class CLBarInatItem;
1502 friend class CMainIconItem;
1503 friend VOID WINAPI ClosePopupTipbar(VOID);
1504 friend BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand);
1505 friend LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds);
1506
1507 public:
1508 CTipbarWnd(DWORD style);
1509 ~CTipbarWnd() override;
1510
GetWindow()1511 CUIFWindow *GetWindow()
1512 {
1513 return static_cast<CUIFWindow*>(this);
1514 }
1515
GetAccItem()1516 CTipbarAccItem *GetAccItem()
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
1527 BOOL IsFullScreenWindow(HWND hWnd);
1528 BOOL IsHKLToSkipRedrawOnNoItem();
1529 BOOL IsInItemChangeOrDirty(CTipbarThread *pTarget);
1530
1531 void AddThreadToThreadCreatingList(CTipbarThread *pThread);
1532 void RemoveThredFromThreadCreatingList(CTipbarThread *pTarget);
1533
1534 void MoveToStub(BOOL bFlag);
1535 void RestoreFromStub();
1536
1537 INT GetCtrlButtonWidth();
1538 INT GetGripperWidth();
1539 INT GetTipbarHeight();
1540 BOOL AutoAdjustDeskBandSize();
1541 INT AdjustDeskBandSize(BOOL bFlag);
1542 void LocateCtrlButtons();
1543 void AdjustPosOnDisplayChange();
1544 void SetVertical(BOOL bVertical);
1545 void UpdatePosFlags();
1546
1547 void CancelMenu();
1548 BOOL CheckExcludeCaptionButtonMode(LPRECT prc1, LPCRECT prc2);
1549 void ClearLBItemList();
1550
1551 HFONT CreateVerticalFont();
1552 void UpdateVerticalFont();
1553
1554 void ShowOverScreenSizeBalloon();
1555 void DestroyOverScreenSizeBalloon();
1556 void DestroyWnd();
1557
1558 HKL GetFocusKeyboardLayout();
1559 void KillOnTheadItemChangeTimer();
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);
1569 void SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight);
1570 void SetShowText(BOOL bShow);
1571 void SetShowTrayIcon(BOOL bShow);
1572
1573 void ShowContextMenu(POINT pt, LPCRECT prc, BOOL bFlag);
1574 void StartBackToAlphaTimer();
1575 BOOL StartDoAccDefaultActionTimer(CTipbarItem *pTarget);
1576
1577 void StartModalInput(ITfLangBarEventSink *pSink, DWORD dwThreadId);
1578 void StopModalInput(DWORD dwThreadId);
1579
1580 CTipbarThread *_CreateThread(DWORD dwThreadId);
1581 CTipbarThread *_FindThread(DWORD dwThreadId);
1582 void EnsureFocusThread();
1583 HRESULT SetFocusThread(CTipbarThread *pFocusThread);
1584 HRESULT AttachFocusThread();
1585 void RestoreLastFocus(DWORD *pdwThreadId, BOOL fPrev);
1586 void CleanUpThreadPointer(CTipbarThread *pThread, BOOL bRemove);
1587 void TerminateAllThreads(BOOL bFlag);
1588 void OnTerminateToolbar();
1589 HRESULT OnThreadTerminateInternal(DWORD dwThreadId);
1590
1591 /// @unimplemented
OnThreadItemChangeInternal(DWORD dwThreadId)1592 HRESULT OnThreadItemChangeInternal(DWORD dwThreadId)
1593 {
1594 return E_NOTIMPL;
1595 }
1596
1597 // IUnknown methods
1598 STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
1599 STDMETHOD_(ULONG, AddRef)();
1600 STDMETHOD_(ULONG, Release)();
1601
1602 // ITfLangBarEventSink methods
1603 STDMETHOD(OnSetFocus)(DWORD dwThreadId) override;
1604 STDMETHOD(OnThreadTerminate)(DWORD dwThreadId) override;
1605 STDMETHOD(OnThreadItemChange)(DWORD dwThreadId) override;
1606 STDMETHOD(OnModalInput)(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1607 STDMETHOD(ShowFloating)(DWORD dwFlags) override;
1608 STDMETHOD(GetItemFloatingRect)(DWORD dwThreadId, REFGUID rguid, RECT *prc) override;
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;
1624 STDMETHOD_(void, OnTimer)(WPARAM wParam) override;
1625 STDMETHOD_(void, OnSysColorChange)() override;
1626 STDMETHOD_(void, OnEndSession)(HWND hWnd, WPARAM wParam, LPARAM lParam) override;
1627 STDMETHOD_(void, OnUser)(HWND hWnd, UINT uMsg, 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;
1630 STDMETHOD_(LRESULT, OnShowWindow)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1631 STDMETHOD_(LRESULT, OnSettingChange)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1632 STDMETHOD_(LRESULT, OnDisplayChange)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1633 STDMETHOD_(HRESULT, OnGetObject)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
1634 STDMETHOD_(BOOL, OnEraseBkGnd)(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
1643 class CDeskBand
1644 {
1645 public:
1646 // FIXME: Implement this
1647 };
1648 #endif
1649
1650 /***********************************************************************
1651 * CUTBLangBarDlg
1652 */
1653
GetThis(HWND hDlg)1654 CUTBLangBarDlg *CUTBLangBarDlg::GetThis(HWND hDlg)
1655 {
1656 return (CUTBLangBarDlg*)::GetWindowLongPtr(hDlg, DWLP_USER);
1657 }
1658
SetThis(HWND hDlg,CUTBLangBarDlg * pThis)1659 void CUTBLangBarDlg::SetThis(HWND hDlg, CUTBLangBarDlg *pThis)
1660 {
1661 ::SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pThis);
1662 }
1663
s_ThreadProc(LPVOID pParam)1664 DWORD WINAPI CUTBLangBarDlg::s_ThreadProc(LPVOID pParam)
1665 {
1666 return ((CUTBLangBarDlg *)pParam)->ThreadProc();
1667 }
1668
StartThread()1669 BOOL CUTBLangBarDlg::StartThread()
1670 {
1671 if (IsDlgShown())
1672 return FALSE;
1673
1674 SetDlgShown(TRUE);
1675
1676 DWORD dwThreadId;
1677 HANDLE hThread = ::CreateThread(NULL, 0, s_ThreadProc, this, 0, &dwThreadId);
1678 if (!hThread)
1679 {
1680 SetDlgShown(FALSE);
1681 return TRUE;
1682 }
1683
1684 ++m_cRefs;
1685 ::CloseHandle(hThread);
1686 return TRUE;
1687 }
1688
_Release()1689 LONG CUTBLangBarDlg::_Release()
1690 {
1691 if (--m_cRefs == 0)
1692 {
1693 delete this;
1694 return 0;
1695 }
1696 return m_cRefs;
1697 }
1698
STDMETHODIMP_(BOOL)1699 STDMETHODIMP_(BOOL) CUTBLangBarDlg::ThreadProc()
1700 {
1701 extern HINSTANCE g_hInst;
1702 ::DialogBoxParam(g_hInst, m_pszDialogName, NULL, DlgProc, (LPARAM)this);
1703 SetDlgShown(FALSE);
1704 _Release();
1705 return TRUE;
1706 }
1707
1708 INT_PTR CALLBACK
DlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)1709 CUTBLangBarDlg::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
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 {
1721 CUTBLangBarDlg *pThis = CUTBLangBarDlg::GetThis(hDlg);
1722 pThis->OnCommand(hDlg, wParam, lParam);
1723 return TRUE;
1724 }
1725
1726 return FALSE;
1727 }
1728
1729 /***********************************************************************
1730 * CUTBCloseLangBarDlg
1731 */
1732
CUTBCloseLangBarDlg()1733 CUTBCloseLangBarDlg::CUTBCloseLangBarDlg()
1734 {
1735 m_cRefs = 1;
1736
1737 if (!(g_dwOSInfo & CIC_OSINFO_XPPLUS))
1738 m_pszDialogName = MAKEINTRESOURCE(IDD_CLOSELANGBARNOBAND);
1739 else
1740 m_pszDialogName = MAKEINTRESOURCE(IDD_CLOSELANGBAR);
1741 }
1742
STDMETHODIMP_(BOOL)1743 STDMETHODIMP_(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
STDMETHODIMP_(BOOL)1759 STDMETHODIMP_(BOOL) CUTBCloseLangBarDlg::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
1760 {
1761 switch (LOWORD(wParam))
1762 {
1763 case IDOK:
1764 DoCloseLangbar();
1765 if (::IsDlgButtonChecked(hDlg, IDC_CLOSELANGBAR_CHECK))
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
STDMETHODIMP_(BOOL)1786 STDMETHODIMP_(BOOL) CUTBCloseLangBarDlg::IsDlgShown()
1787 {
1788 return s_bIsDlgShown;
1789 }
1790
STDMETHODIMP_(void)1791 STDMETHODIMP_(void) CUTBCloseLangBarDlg::SetDlgShown(BOOL bShown)
1792 {
1793 s_bIsDlgShown = bShown;
1794 }
1795
1796 /***********************************************************************
1797 * CUTBMinimizeLangBarDlg
1798 */
1799
CUTBMinimizeLangBarDlg()1800 CUTBMinimizeLangBarDlg::CUTBMinimizeLangBarDlg()
1801 {
1802 m_cRefs = 1;
1803 if (!(g_dwOSInfo & CIC_OSINFO_XPPLUS))
1804 m_pszDialogName = MAKEINTRESOURCE(IDD_MINIMIZELANGBARNOBAND);
1805 else
1806 m_pszDialogName = MAKEINTRESOURCE(IDD_MINIMIZELANGBAR);
1807 }
1808
STDMETHODIMP_(BOOL)1809 STDMETHODIMP_(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
STDMETHODIMP_(BOOL)1826 STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
1827 {
1828 switch (LOWORD(wParam))
1829 {
1830 case IDOK:
1831 if (::IsDlgButtonChecked(hDlg, IDC_MINIMIZELANGBAR_CHECK))
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
STDMETHODIMP_(BOOL)1850 STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::IsDlgShown()
1851 {
1852 return s_bIsDlgShown;
1853 }
1854
STDMETHODIMP_(void)1855 STDMETHODIMP_(void) CUTBMinimizeLangBarDlg::SetDlgShown(BOOL bShown)
1856 {
1857 s_bIsDlgShown = bShown;
1858 }
1859
STDMETHODIMP_(BOOL)1860 STDMETHODIMP_(BOOL) CUTBMinimizeLangBarDlg::ThreadProc()
1861 {
1862 ::Sleep(700);
1863 return CUTBLangBarDlg::ThreadProc();
1864 }
1865
1866 /***********************************************************************
1867 * CCicLibMenu
1868 */
1869
CCicLibMenu()1870 CCicLibMenu::CCicLibMenu() : m_cRefs(1)
1871 {
1872 }
1873
~CCicLibMenu()1874 CCicLibMenu::~CCicLibMenu()
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
QueryInterface(REFIID riid,LPVOID * ppvObj)1883 STDMETHODIMP CCicLibMenu::QueryInterface(REFIID riid, LPVOID *ppvObj)
1884 {
1885 static const QITAB c_tab[] =
1886 {
1887 QITABENT(CCicLibMenu, ITfMenu),
1888 { NULL }
1889 };
1890 return ::QISearch(this, c_tab, riid, ppvObj);
1891 }
1892
STDMETHODIMP_(ULONG)1893 STDMETHODIMP_(ULONG) CCicLibMenu::AddRef()
1894 {
1895 return ++m_cRefs;
1896 }
1897
STDMETHODIMP_(ULONG)1898 STDMETHODIMP_(ULONG) CCicLibMenu::Release()
1899 {
1900 if (--m_cRefs == 0)
1901 {
1902 delete this;
1903 return 0;
1904 }
1905 return m_cRefs;
1906 }
1907
STDMETHODIMP_(CCicLibMenu *)1908 STDMETHODIMP_(CCicLibMenu*) CCicLibMenu::CreateSubMenu()
1909 {
1910 return new(cicNoThrow) CCicLibMenu();
1911 }
1912
STDMETHODIMP_(CCicLibMenuItem *)1913 STDMETHODIMP_(CCicLibMenuItem*) CCicLibMenu::CreateMenuItem()
1914 {
1915 return new(cicNoThrow) CCicLibMenuItem();
1916 }
1917
AddMenuItem(UINT uId,DWORD dwFlags,HBITMAP hbmp,HBITMAP hbmpMask,const WCHAR * pch,ULONG cch,ITfMenu ** ppSubMenu)1918 STDMETHODIMP CCicLibMenu::AddMenuItem(
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;
1931 if (dwFlags & TF_LBMENUF_SUBMENU)
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
CCicLibMenuItem()1959 CCicLibMenuItem::CCicLibMenuItem()
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
~CCicLibMenuItem()1969 CCicLibMenuItem::~CCicLibMenuItem()
1970 {
1971 if (m_pMenu)
1972 {
1973 m_pMenu->Release();
1974 m_pMenu = NULL;
1975 }
1976
1977 if (m_hbmp)
1978 {
1979 ::DeleteObject(m_hbmp);
1980 m_hbmp = NULL;
1981 }
1982
1983 if (m_hbmpMask)
1984 {
1985 ::DeleteObject(m_hbmpMask);
1986 m_hbmpMask = NULL;
1987 }
1988
1989 ::SysFreeString(m_bstrText);
1990 m_bstrText = NULL;
1991 }
1992
Init(UINT uId,DWORD dwFlags,HBITMAP hbmp,HBITMAP hbmpMask,const WCHAR * pch,ULONG cch,ITfMenu * pMenu)1993 BOOL CCicLibMenuItem::Init(
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;
2003 m_dwFlags = dwFlags;
2004 m_bstrText = ::SysAllocStringLen(pch, cch);
2005 if (!m_bstrText && cch)
2006 return FALSE;
2007
2008 m_pMenu = pMenu;
2009 m_hbmp = CreateBitmap(hbmp);
2010 m_hbmpMask = CreateBitmap(hbmpMask);
2011 if (hbmp)
2012 ::DeleteObject(hbmp);
2013 if (hbmpMask)
2014 ::DeleteObject(hbmpMask);
2015
2016 return TRUE;
2017 }
2018
CreateBitmap(HANDLE hBitmap)2019 HBITMAP CCicLibMenuItem::CreateBitmap(HANDLE hBitmap)
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
CTipbarAccessible(CTipbarAccItem * pItem)2066 CTipbarAccessible::CTipbarAccessible(CTipbarAccItem *pItem)
2067 {
2068 m_cRefs = 1;
2069 m_hWnd = NULL;
2070 m_pTypeInfo = NULL;
2071 m_pStdAccessible = NULL;
2072 m_bInitialized = FALSE;
2073 m_cSelection = 1;
2074 m_AccItems.Add(pItem);
2075 ++g_DllRefCount;
2076 }
2077
~CTipbarAccessible()2078 CTipbarAccessible::~CTipbarAccessible()
2079 {
2080 m_pTypeInfo = m_pTypeInfo;
2081 if (m_pTypeInfo)
2082 {
2083 m_pTypeInfo->Release();
2084 m_pTypeInfo = NULL;
2085 }
2086 if (m_pStdAccessible)
2087 {
2088 m_pStdAccessible->Release();
2089 m_pStdAccessible = NULL;
2090 }
2091 --g_DllRefCount;
2092 }
2093
Initialize()2094 HRESULT CTipbarAccessible::Initialize()
2095 {
2096 m_bInitialized = TRUE;
2097
2098 HRESULT hr = ::CreateStdAccessibleObject(m_hWnd, OBJID_CLIENT, IID_IAccessible,
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
AddAccItem(CTipbarAccItem * pItem)2117 BOOL CTipbarAccessible::AddAccItem(CTipbarAccItem *pItem)
2118 {
2119 return m_AccItems.Add(pItem);
2120 }
2121
RemoveAccItem(CTipbarAccItem * pItem)2122 HRESULT CTipbarAccessible::RemoveAccItem(CTipbarAccItem *pItem)
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
ClearAccItems()2135 void CTipbarAccessible::ClearAccItems()
2136 {
2137 m_AccItems.clear();
2138 }
2139
AccItemFromID(INT iItem)2140 CTipbarAccItem *CTipbarAccessible::AccItemFromID(INT iItem)
2141 {
2142 if (iItem < 0 || (INT)m_AccItems.size() <= iItem)
2143 return NULL;
2144 return m_AccItems[iItem];
2145 }
2146
GetIDOfItem(CTipbarAccItem * pTarget)2147 INT CTipbarAccessible::GetIDOfItem(CTipbarAccItem *pTarget)
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
CreateRefToAccObj(WPARAM wParam)2157 LONG_PTR CTipbarAccessible::CreateRefToAccObj(WPARAM wParam)
2158 {
2159 return ::LresultFromObject(IID_IAccessible, wParam, this);
2160 }
2161
DoDefaultActionReal(INT nID)2162 BOOL CTipbarAccessible::DoDefaultActionReal(INT nID)
2163 {
2164 CTipbarAccItem *pItem = AccItemFromID(nID);
2165 if (!pItem)
2166 return FALSE;
2167 return pItem->DoAccDefaultActionReal();
2168 }
2169
NotifyWinEvent(DWORD event,CTipbarAccItem * pItem)2170 void CTipbarAccessible::NotifyWinEvent(DWORD event, CTipbarAccItem *pItem)
2171 {
2172 INT nID = GetIDOfItem(pItem);
2173 if (nID < 0)
2174 return;
2175
2176 ::NotifyWinEvent(event, m_hWnd, -4, nID);
2177 }
2178
SetWindow(HWND hWnd)2179 void CTipbarAccessible::SetWindow(HWND hWnd)
2180 {
2181 m_hWnd = hWnd;
2182 }
2183
QueryInterface(REFIID riid,void ** ppvObject)2184 STDMETHODIMP CTipbarAccessible::QueryInterface(
2185 REFIID riid,
2186 void **ppvObject)
2187 {
2188 static const QITAB c_tab[] =
2189 {
2190 QITABENT(CTipbarAccessible, IDispatch),
2191 QITABENT(CTipbarAccessible, IAccessible),
2192 { NULL }
2193 };
2194 return ::QISearch(this, c_tab, riid, ppvObject);
2195 }
2196
STDMETHODIMP_(ULONG)2197 STDMETHODIMP_(ULONG) CTipbarAccessible::AddRef()
2198 {
2199 return ::InterlockedIncrement(&m_cRefs);
2200 }
2201
STDMETHODIMP_(ULONG)2202 STDMETHODIMP_(ULONG) CTipbarAccessible::Release()
2203 {
2204 LONG count = ::InterlockedDecrement(&m_cRefs);
2205 if (count == 0)
2206 {
2207 delete this;
2208 return 0;
2209 }
2210 return count;
2211 }
2212
GetTypeInfoCount(UINT * pctinfo)2213 STDMETHODIMP CTipbarAccessible::GetTypeInfoCount(UINT *pctinfo)
2214 {
2215 if (!pctinfo)
2216 return E_INVALIDARG;
2217 *pctinfo = (m_pTypeInfo == NULL);
2218 return S_OK;
2219 }
2220
GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)2221 STDMETHODIMP CTipbarAccessible::GetTypeInfo(
2222 UINT iTInfo,
2223 LCID lcid,
2224 ITypeInfo **ppTInfo)
2225 {
2226 if (!ppTInfo)
2227 return E_INVALIDARG;
2228 *ppTInfo = NULL;
2229 if (iTInfo != 0)
2230 return TYPE_E_ELEMENTNOTFOUND;
2231 if (!m_pTypeInfo)
2232 return E_NOTIMPL;
2233 *ppTInfo = m_pTypeInfo;
2234 m_pTypeInfo->AddRef();
2235 return S_OK;
2236 }
2237
GetIDsOfNames(REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)2238 STDMETHODIMP CTipbarAccessible::GetIDsOfNames(
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
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2250 STDMETHODIMP CTipbarAccessible::Invoke(
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
get_accParent(IDispatch ** ppdispParent)2271 STDMETHODIMP CTipbarAccessible::get_accParent(IDispatch **ppdispParent)
2272 {
2273 return m_pStdAccessible->get_accParent(ppdispParent);
2274 }
2275
get_accChildCount(LONG * pcountChildren)2276 STDMETHODIMP CTipbarAccessible::get_accChildCount(LONG *pcountChildren)
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
get_accChild(VARIANT varChildID,IDispatch ** ppdispChild)2287 STDMETHODIMP CTipbarAccessible::get_accChild(
2288 VARIANT varChildID,
2289 IDispatch **ppdispChild)
2290 {
2291 if (!ppdispChild)
2292 return E_INVALIDARG;
2293 *ppdispChild = NULL;
2294 return S_FALSE;
2295 }
2296
get_accName(VARIANT varID,BSTR * pszName)2297 STDMETHODIMP CTipbarAccessible::get_accName(
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
get_accValue(VARIANT varID,BSTR * pszValue)2312 STDMETHODIMP CTipbarAccessible::get_accValue(
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
get_accDescription(VARIANT varID,BSTR * description)2327 STDMETHODIMP CTipbarAccessible::get_accDescription(
2328 VARIANT varID,
2329 BSTR *description)
2330 {
2331 if (!description)
2332 return E_INVALIDARG;
2333 return m_pStdAccessible->get_accDescription(varID, description);
2334 }
2335
get_accRole(VARIANT varID,VARIANT * role)2336 STDMETHODIMP CTipbarAccessible::get_accRole(
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
get_accState(VARIANT varID,VARIANT * state)2350 STDMETHODIMP CTipbarAccessible::get_accState(
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
get_accHelp(VARIANT varID,BSTR * help)2364 STDMETHODIMP CTipbarAccessible::get_accHelp(VARIANT varID, BSTR *help)
2365 {
2366 return DISP_E_MEMBERNOTFOUND;
2367 }
2368
get_accHelpTopic(BSTR * helpfile,VARIANT varID,LONG * pidTopic)2369 STDMETHODIMP CTipbarAccessible::get_accHelpTopic(
2370 BSTR *helpfile,
2371 VARIANT varID,
2372 LONG *pidTopic)
2373 {
2374 return DISP_E_MEMBERNOTFOUND;
2375 }
2376
get_accKeyboardShortcut(VARIANT varID,BSTR * shortcut)2377 STDMETHODIMP CTipbarAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *shortcut)
2378 {
2379 return DISP_E_MEMBERNOTFOUND;
2380 }
2381
get_accFocus(VARIANT * pvarID)2382 STDMETHODIMP CTipbarAccessible::get_accFocus(VARIANT *pvarID)
2383 {
2384 if (!pvarID)
2385 return E_INVALIDARG;
2386 V_VT(pvarID) = VT_EMPTY;
2387 return S_FALSE;
2388 }
2389
get_accSelection(VARIANT * pvarID)2390 STDMETHODIMP CTipbarAccessible::get_accSelection(VARIANT *pvarID)
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
get_accDefaultAction(VARIANT varID,BSTR * action)2410 STDMETHODIMP CTipbarAccessible::get_accDefaultAction(
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
accSelect(LONG flagsSelect,VARIANT varID)2430 STDMETHODIMP CTipbarAccessible::accSelect(
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
accLocation(LONG * left,LONG * top,LONG * width,LONG * height,VARIANT varID)2450 STDMETHODIMP CTipbarAccessible::accLocation(
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
accNavigate(LONG dir,VARIANT varStart,VARIANT * pvarEnd)2474 STDMETHODIMP CTipbarAccessible::accNavigate(
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
accHitTest(LONG left,LONG top,VARIANT * pvarID)2523 STDMETHODIMP CTipbarAccessible::accHitTest(LONG left, LONG top, VARIANT *pvarID)
2524 {
2525 if (!pvarID)
2526 return E_INVALIDARG;
2527 POINT Point = { left, top };
2528 RECT Rect;
2529 ::ScreenToClient(m_hWnd, &Point);
2530 ::GetClientRect(m_hWnd, &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
accDoDefaultAction(VARIANT varID)2558 STDMETHODIMP CTipbarAccessible::accDoDefaultAction(VARIANT varID)
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
put_accName(VARIANT varID,BSTR name)2568 STDMETHODIMP CTipbarAccessible::put_accName(VARIANT varID, BSTR name)
2569 {
2570 return S_FALSE;
2571 }
2572
put_accValue(VARIANT varID,BSTR value)2573 STDMETHODIMP CTipbarAccessible::put_accValue(VARIANT varID, BSTR value)
2574 {
2575 return S_FALSE;
2576 }
2577
2578 /***********************************************************************
2579 * CUTBMenuWnd
2580 */
2581
CUTBMenuWnd(HINSTANCE hInst,DWORD style,DWORD dwUnknown14)2582 CUTBMenuWnd::CUTBMenuWnd(HINSTANCE hInst, DWORD style, DWORD dwUnknown14)
2583 : CUIFMenu(hInst, style, dwUnknown14)
2584 {
2585 }
2586
StartDoAccDefaultActionTimer(CUTBMenuItem * pTarget)2587 BOOL CUTBMenuWnd::StartDoAccDefaultActionTimer(CUTBMenuItem *pTarget)
2588 {
2589 if (!m_pAccessible)
2590 return FALSE;
2591
2592 m_nMenuWndID = m_pAccessible->GetIDOfItem(pTarget);
2593 if (!m_nMenuWndID || m_nMenuWndID == (UINT)-1)
2594 return FALSE;
2595
2596 if (::IsWindow(m_hWnd))
2597 {
2598 ::KillTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION);
2599 ::SetTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION, g_uTimerElapseDOACCDEFAULTACTION, NULL);
2600 }
2601
2602 return TRUE;
2603 }
2604
STDMETHODIMP_(BSTR)2605 STDMETHODIMP_(BSTR) CUTBMenuWnd::GetAccName()
2606 {
2607 WCHAR szText[64];
2608 LoadStringW(g_hInst, IDS_MENUWND, szText, _countof(szText));
2609 return ::SysAllocString(szText);
2610 }
2611
STDMETHODIMP_(INT)2612 STDMETHODIMP_(INT) CUTBMenuWnd::GetAccRole()
2613 {
2614 return 9;
2615 }
2616
STDMETHODIMP_(BOOL)2617 STDMETHODIMP_(BOOL) CUTBMenuWnd::Initialize()
2618 {
2619 CTipbarAccessible *pAccessible = new(cicNoThrow) CTipbarAccessible(GetAccItem());
2620 if (pAccessible)
2621 m_pAccessible = pAccessible;
2622
2623 return CUIFObject::Initialize();
2624 }
2625
STDMETHODIMP_(void)2626 STDMETHODIMP_(void) CUTBMenuWnd::OnCreate(HWND hWnd)
2627 {
2628 if (m_pAccessible)
2629 m_pAccessible->SetWindow(hWnd);
2630 }
2631
STDMETHODIMP_(void)2632 STDMETHODIMP_(void) CUTBMenuWnd::OnDestroy(HWND hWnd)
2633 {
2634 if (m_pAccessible)
2635 {
2636 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_DESTROY, GetAccItem());
2637 m_pAccessible->ClearAccItems();
2638 m_pAccessible->Release();
2639 m_pAccessible = NULL;
2640 }
2641 m_coInit.CoUninit();
2642 }
2643
STDMETHODIMP_(HRESULT)2644 STDMETHODIMP_(HRESULT)
2645 CUTBMenuWnd::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
2653 if (m_pAccessible->m_bInitialized)
2654 return m_pAccessible->CreateRefToAccObj(wParam);
2655
2656 if (SUCCEEDED(m_coInit.EnsureCoInit()))
2657 {
2658 HRESULT hr = m_pAccessible->Initialize();
2659 if (FAILED(hr))
2660 {
2661 m_pAccessible->Release();
2662 m_pAccessible = NULL;
2663 return hr;
2664 }
2665
2666 m_pAccessible->NotifyWinEvent(EVENT_OBJECT_CREATE, GetAccItem());
2667 return m_pAccessible->CreateRefToAccObj(wParam);
2668 }
2669
2670 return S_OK;
2671 }
2672
STDMETHODIMP_(LRESULT)2673 STDMETHODIMP_(LRESULT)
2674 CUTBMenuWnd::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
STDMETHODIMP_(void)2692 STDMETHODIMP_(void) CUTBMenuWnd::OnTimer(WPARAM wParam)
2693 {
2694 if (wParam == TIMER_ID_DOACCDEFAULTACTION)
2695 {
2696 ::KillTimer(m_hWnd, TIMER_ID_DOACCDEFAULTACTION);
2697 if (m_pAccessible && m_nMenuWndID)
2698 {
2699 m_pAccessible->DoDefaultActionReal(m_nMenuWndID);
2700 m_nMenuWndID = 0;
2701 }
2702 }
2703 }
2704
2705 /***********************************************************************
2706 * CUTBMenuItem
2707 */
2708
CUTBMenuItem(CUTBMenuWnd * pMenuUI)2709 CUTBMenuItem::CUTBMenuItem(CUTBMenuWnd *pMenuUI)
2710 : CUIFMenuItem(pMenuUI ? pMenuUI->GetMenu() : NULL)
2711 {
2712 m_pMenuUI = pMenuUI;
2713 }
2714
~CUTBMenuItem()2715 CUTBMenuItem::~CUTBMenuItem()
2716 {
2717 if (m_hbmColor)
2718 {
2719 ::DeleteObject(m_hbmColor);
2720 m_hbmColor = NULL;
2721 }
2722 if (m_hbmMask)
2723 {
2724 ::DeleteObject(m_hbmMask);
2725 m_hbmMask = NULL;
2726 }
2727 }
2728
STDMETHODIMP_(BOOL)2729 STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultAction()
2730 {
2731 if (!m_pMenuUI)
2732 return FALSE;
2733
2734 m_pMenuUI->StartDoAccDefaultActionTimer(this);
2735 return TRUE;
2736 }
2737
STDMETHODIMP_(BOOL)2738 STDMETHODIMP_(BOOL) CUTBMenuItem::DoAccDefaultActionReal()
2739 {
2740 if (!m_pSubMenu)
2741 OnLButtonUp(0, 0);
2742 else
2743 ShowSubPopup();
2744 return TRUE;
2745 }
2746
STDMETHODIMP_(BSTR)2747 STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccDefaultAction()
2748 {
2749 WCHAR szText[64];
2750 ::LoadStringW(g_hInst, IDS_LEFTCLICK, szText, _countof(szText));
2751 return ::SysAllocString(szText);
2752 }
2753
STDMETHODIMP_(void)2754 STDMETHODIMP_(void) CUTBMenuItem::GetAccLocation(LPRECT lprc)
2755 {
2756 GetRect(lprc);
2757 ::ClientToScreen(m_pMenuUI->m_hWnd, (LPPOINT)lprc);
2758 ::ClientToScreen(m_pMenuUI->m_hWnd, (LPPOINT)&lprc->right);
2759 }
2760
STDMETHODIMP_(BSTR)2761 STDMETHODIMP_(BSTR) CUTBMenuItem::GetAccName()
2762 {
2763 return ::SysAllocString(m_pszMenuItemLeft);
2764 }
2765
2766 /// @unimplemented
STDMETHODIMP_(INT)2767 STDMETHODIMP_(INT) CUTBMenuItem::GetAccRole()
2768 {
2769 if (FALSE) //FIXME
2770 return 21;
2771 return 12;
2772 }
2773
2774 /***********************************************************************
2775 * CModalMenu
2776 */
2777
2778 CUTBMenuItem *
InsertItem(CUTBMenuWnd * pMenuUI,INT nCommandId,INT nStringID)2779 CModalMenu::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
PostKey(BOOL bUp,WPARAM wParam,LPARAM lParam)2799 void CModalMenu::PostKey(BOOL bUp, WPARAM wParam, LPARAM lParam)
2800 {
2801 m_pMenuUI->PostKey(bUp, wParam, lParam);
2802 }
2803
CancelMenu()2804 void CModalMenu::CancelMenu()
2805 {
2806 if (m_pMenuUI)
2807 m_pMenuUI->CancelMenu();
2808 }
2809
2810 /***********************************************************************
2811 * CUTBContextMenu
2812 */
2813
CUTBContextMenu(CTipbarWnd * pTipbarWnd)2814 CUTBContextMenu::CUTBContextMenu(CTipbarWnd *pTipbarWnd)
2815 {
2816 m_pTipbarWnd = pTipbarWnd;
2817 }
2818
2819 /// @implemented
Init()2820 BOOL CUTBContextMenu::Init()
2821 {
2822 m_pTipbarThread = m_pTipbarWnd->m_pFocusThread;
2823 return !!m_pTipbarThread;
2824 }
2825
2826 /// @unimplemented
CreateMenuUI(BOOL bFlag)2827 CUTBMenuWnd *CUTBContextMenu::CreateMenuUI(BOOL bFlag)
2828 {
2829 DWORD dwStatus = 0;
2830
2831 if (FAILED(m_pTipbarWnd->m_pLangBarMgr->GetShowFloatingStatus(&dwStatus)))
2832 return NULL;
2833
2834 CUTBMenuWnd *pMenuUI = new (cicNoThrow) CUTBMenuWnd(g_hInst, g_dwMenuStyle, 0);
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 {
2848 InsertItem(pMenuUI, ID_DESKBAND, IDS_MINIMIZE);
2849
2850 if (bFlag)
2851 {
2852 if (IsTransparecyAvailable())
2853 {
2854 if (dwStatus & TF_LBI_BALLOON)
2855 {
2856 InsertItem(pMenuUI, ID_TRANS, IDS_TRANSPARENCY);
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 {
2868 InsertItem(pMenuUI, ID_LABELS, IDS_TEXTLABELS);
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)
2879 pVertical->Check(!!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL));
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)
2912 InsertItem(pMenuUI, ID_ADJUSTDESKBAND, IDS_ADJUSTLANGBAND);
2913
2914 InsertItem(pMenuUI, ID_SETTINGS, IDS_SETTINGS);
2915
2916 if (CheckCloseMenuAvailable())
2917 InsertItem(pMenuUI, ID_CLOSELANGBAR, IDS_CLOSELANGBAR);
2918 }
2919
2920 return pMenuUI;
2921 }
2922
2923 UINT
ShowPopup(CUIFWindow * pWindow,POINT pt,LPCRECT prc,BOOL bFlag)2924 CUTBContextMenu::ShowPopup(
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
2951 /// @unimplemented
SelectMenuItem(UINT nCommandId)2952 BOOL CUTBContextMenu::SelectMenuItem(UINT nCommandId)
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 {
2974 if (!g_bEnableDeskBand || !(g_dwOSInfo & CIC_OSINFO_XPPLUS))
2975 {
2976 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_MINIMIZED);
2977 }
2978 else
2979 {
2980 DWORD dwStatus;
2981 m_pTipbarWnd->m_pLangBarMgr->GetShowFloatingStatus(&dwStatus);
2982
2983 if (dwStatus & TF_SFT_DESKBAND)
2984 break;
2985
2986 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_DESKBAND);
2987 }
2988
2989 CUTBMinimizeLangBarDlg *pDialog = new(cicNoThrow) CUTBMinimizeLangBarDlg();
2990 if (pDialog)
2991 {
2992 pDialog->DoModal(*m_pTipbarWnd->GetWindow());
2993 pDialog->_Release();
2994 }
2995 break;
2996 }
2997
2998 case ID_CLOSELANGBAR:
2999 {
3000 CUTBCloseLangBarDlg *pDialog = new(cicNoThrow) CUTBCloseLangBarDlg();
3001 if (pDialog)
3002 {
3003 BOOL bOK = pDialog->DoModal(*m_pTipbarWnd->GetWindow());
3004 pDialog->_Release();
3005 if (!bOK)
3006 DoCloseLangbar();
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:
3022 m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_LBI_ICON);
3023 break;
3024
3025 case ID_VERTICAL:
3026 m_pTipbarWnd->SetVertical(!!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL));
3027 break;
3028
3029 case ID_ADJUSTDESKBAND:
3030 m_pTipbarWnd->AdjustDeskBandSize(TRUE);
3031 break;
3032
3033 case ID_SETTINGS:
3034 TF_RunInputCPL();
3035 break;
3036
3037 default:
3038 break;
3039 }
3040
3041 return TRUE;
3042 }
3043
3044 /***********************************************************************
3045 * CTrayIconItem
3046 */
3047
CTrayIconItem(CTrayIconWnd * pTrayIconWnd)3048 CTrayIconItem::CTrayIconItem(CTrayIconWnd *pTrayIconWnd)
3049 {
3050 m_dwIconAddOrModify = NIM_ADD;
3051 m_pTrayIconWnd = pTrayIconWnd;
3052 }
3053
3054 BOOL
_Init(HWND hWnd,UINT uCallbackMessage,UINT uNotifyIconID,const GUID & rguid)3055 CTrayIconItem::_Init(
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
RemoveIcon()3068 BOOL CTrayIconItem::RemoveIcon()
3069 {
3070 if (m_dwIconAddOrModify == NIM_MODIFY)
3071 {
3072 NOTIFYICONDATAW NotifyIcon = { sizeof(NotifyIcon), m_hWnd, m_uNotifyIconID };
3073 NotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
3074 NotifyIcon.uCallbackMessage = m_uCallbackMessage;
3075 ::Shell_NotifyIconW(NIM_DELETE, &NotifyIcon);
3076 }
3077
3078 m_dwIconAddOrModify = NIM_ADD;
3079 m_bIconAdded = TRUE;
3080 return TRUE;
3081 }
3082
SetIcon(HICON hIcon,LPCWSTR pszTip)3083 BOOL 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;
3090 NotifyIcon.uCallbackMessage = m_uCallbackMessage;
3091 NotifyIcon.hIcon = hIcon;
3092 if (pszTip)
3093 {
3094 NotifyIcon.uFlags |= NIF_TIP;
3095 StringCchCopyW(NotifyIcon.szTip, _countof(NotifyIcon.szTip), pszTip);
3096 }
3097
3098 ::Shell_NotifyIconW(m_dwIconAddOrModify, &NotifyIcon);
3099
3100 m_dwIconAddOrModify = NIM_MODIFY;
3101 m_bIconAdded = NIM_MODIFY;
3102 return TRUE;
3103 }
3104
UpdateMenuRectPoint()3105 BOOL CTrayIconItem::UpdateMenuRectPoint()
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);
3111 ::GetCursorPos(&m_ptCursor);
3112 return TRUE;
3113 }
3114
3115 /***********************************************************************
3116 * CButtonIconItem
3117 */
3118
CButtonIconItem(CTrayIconWnd * pWnd,DWORD dwUnknown24)3119 CButtonIconItem::CButtonIconItem(CTrayIconWnd *pWnd, DWORD dwUnknown24)
3120 : CTrayIconItem(pWnd)
3121 {
3122 m_dwUnknown24 = dwUnknown24;
3123 }
3124
3125 /// @unimplemented
STDMETHODIMP_(BOOL)3126 STDMETHODIMP_(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
3143 /// @unimplemented
STDMETHODIMP_(BOOL)3144 STDMETHODIMP_(BOOL) CButtonIconItem::OnDelayMsg(UINT uMsg)
3145 {
3146 //FIXME
3147 return FALSE;
3148 }
3149
3150 /***********************************************************************
3151 * CMainIconItem
3152 */
3153
3154 /// @implemented
CMainIconItem(CTrayIconWnd * pWnd)3155 CMainIconItem::CMainIconItem(CTrayIconWnd *pWnd)
3156 : CButtonIconItem(pWnd, 1)
3157 {
3158 }
3159
3160 /// @implemented
Init(HWND hWnd)3161 BOOL CMainIconItem::Init(HWND hWnd)
3162 {
3163 return CTrayIconItem::_Init(hWnd, WM_USER, 0, GUID_LBI_TRAYMAIN);
3164 }
3165
3166 /// @implemented
STDMETHODIMP_(BOOL)3167 STDMETHODIMP_(BOOL) CMainIconItem::OnDelayMsg(UINT uMsg)
3168 {
3169 if (!CButtonIconItem::OnDelayMsg(uMsg))
3170 return 0;
3171
3172 if (uMsg == WM_LBUTTONDBLCLK)
3173 {
3174 if (g_pTipbarWnd->m_dwUnknown20)
3175 g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
3176 }
3177 else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
3178 {
3179 g_pTipbarWnd->ShowContextMenu(m_ptCursor, &m_rcMenu, uMsg == WM_RBUTTONDOWN);
3180 }
3181 return TRUE;
3182 }
3183
3184 /***********************************************************************
3185 * CTrayIconWnd
3186 */
3187
CTrayIconWnd()3188 CTrayIconWnd::CTrayIconWnd()
3189 {
3190 m_uCallbackMsg = WM_USER + 0x1000;
3191 m_uNotifyIconID = 0x1000;
3192 }
3193
~CTrayIconWnd()3194 CTrayIconWnd::~CTrayIconWnd()
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
CallOnDelayMsg()3207 void CTrayIconWnd::CallOnDelayMsg()
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
CreateWnd()3220 HWND CTrayIconWnd::CreateWnd()
3221 {
3222 m_hWnd = ::CreateWindowEx(0, TEXT("CTrayIconWndClass"), NULL, WS_DISABLED,
3223 0, 0, 0, 0, NULL, NULL, g_hInst, this);
3224 FindTrayEtc();
3225
3226 m_pMainIconItem = new(cicNoThrow) CMainIconItem(this);
3227 if (m_pMainIconItem)
3228 {
3229 m_pMainIconItem->Init(m_hWnd);
3230 m_Items.Add(m_pMainIconItem);
3231 }
3232
3233 return m_hWnd;
3234 }
3235
DestroyWnd()3236 void CTrayIconWnd::DestroyWnd()
3237 {
3238 ::DestroyWindow(m_hWnd);
3239 m_hWnd = NULL;
3240 }
3241
EnumChildWndProc(HWND hWnd,LPARAM lParam)3242 BOOL CALLBACK CTrayIconWnd::EnumChildWndProc(HWND hWnd, LPARAM lParam)
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
FindIconItem(REFGUID rguid)3255 CButtonIconItem *CTrayIconWnd::FindIconItem(REFGUID rguid)
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
FindTrayEtc()3266 BOOL CTrayIconWnd::FindTrayEtc()
3267 {
3268 m_hTrayWnd = ::FindWindow(TEXT("Shell_TrayWnd"), NULL);
3269 if (!m_hTrayWnd)
3270 return FALSE;
3271
3272 ::EnumChildWindows(m_hTrayWnd, EnumChildWndProc, (LPARAM)this);
3273 if (!m_hNotifyWnd)
3274 return FALSE;
3275 m_dwTrayWndThreadId = ::GetWindowThreadProcessId(m_hTrayWnd, NULL);
3276 m_hwndProgman = FindWindow(TEXT("Progman"), NULL);
3277 m_dwProgmanThreadId = ::GetWindowThreadProcessId(m_hwndProgman, NULL);
3278 return TRUE;
3279 }
3280
GetNotifyWnd()3281 HWND CTrayIconWnd::GetNotifyWnd()
3282 {
3283 if (!::IsWindow(m_hNotifyWnd))
3284 FindTrayEtc();
3285 return m_hNotifyWnd;
3286 }
3287
3288 /// @implemented
OnIconMessage(UINT uMsg,WPARAM wParam,LPARAM lParam)3289 BOOL CTrayIconWnd::OnIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
3290 {
3291 if (g_pTipbarWnd)
3292 g_pTipbarWnd->AttachFocusThread();
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
RegisterClass()3309 BOOL CTrayIconWnd::RegisterClass()
3310 {
3311 WNDCLASSEX wc = { sizeof(wc) };
3312 wc.style = CS_HREDRAW | CS_VREDRAW;
3313 wc.hInstance = g_hInst;
3314 wc.hCursor = ::LoadCursor(NULL, (LPCTSTR)IDC_ARROW);
3315 wc.lpfnWndProc = CTrayIconWnd::_WndProc;
3316 wc.lpszClassName = TEXT("CTrayIconWndClass");
3317 ::RegisterClassEx(&wc);
3318 return TRUE;
3319 }
3320
RemoveAllIcon(DWORD dwFlags)3321 void CTrayIconWnd::RemoveAllIcon(DWORD dwFlags)
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
3348 /// @unimplemented
RemoveUnusedIcons(int unknown)3349 void CTrayIconWnd::RemoveUnusedIcons(int unknown)
3350 {
3351 //FIXME
3352 }
3353
SetIcon(REFGUID rguid,DWORD dwUnknown24,HICON hIcon,LPCWSTR psz)3354 BOOL CTrayIconWnd::SetIcon(REFGUID rguid, DWORD dwUnknown24, HICON hIcon, LPCWSTR psz)
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;
3367 ++m_uNotifyIconID;
3368 m_Items.Add(pItem);
3369 }
3370
3371 if (!hIcon)
3372 return pItem->RemoveIcon();
3373
3374 return pItem->SetIcon(hIcon, psz);
3375 }
3376
SetMainIcon(HKL hKL)3377 BOOL CTrayIconWnd::SetMainIcon(HKL hKL)
3378 {
3379 if (!hKL)
3380 {
3381 m_pMainIconItem->RemoveIcon();
3382 m_pMainIconItem->m_hKL = NULL;
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);
3393 ::DestroyIcon(hIcon);
3394 }
3395 else
3396 {
3397 ::LoadStringW(g_hInst, IDS_RESTORELANGBAR, szText, _countof(szText));
3398 hIcon = ::LoadIconW(g_hInst, MAKEINTRESOURCEW(IDI_MAINICON));
3399 m_pMainIconItem->SetIcon(hIcon, szText);
3400 }
3401
3402 m_pMainIconItem->m_hKL = hKL;
3403 }
3404
3405 return TRUE;
3406 }
3407
GetThis(HWND hWnd)3408 CTrayIconWnd *CTrayIconWnd::GetThis(HWND hWnd)
3409 {
3410 return (CTrayIconWnd *)::GetWindowLongPtr(hWnd, GWL_USERDATA);
3411 }
3412
SetThis(HWND hWnd,LPCREATESTRUCT pCS)3413 void CTrayIconWnd::SetThis(HWND hWnd, LPCREATESTRUCT pCS)
3414 {
3415 if (pCS)
3416 ::SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)pCS->lpCreateParams);
3417 else
3418 ::SetWindowLongPtr(hWnd, GWL_USERDATA, 0);
3419 }
3420
3421 LRESULT CALLBACK
_WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)3422 CTrayIconWnd::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3423 {
3424 CTrayIconWnd *pThis;
3425 switch (uMsg)
3426 {
3427 case WM_CREATE:
3428 CTrayIconWnd::SetThis(hWnd, (LPCREATESTRUCT)lParam);
3429 break;
3430 case WM_DESTROY:
3431 ::SetWindowLongPtr(hWnd, GWL_USERDATA, 0);
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
CLBarItemBase()3459 CLBarItemBase::CLBarItemBase()
3460 {
3461 m_dwItemStatus = 0;
3462 m_szToolTipText[0] = 0;
3463 m_cRefs = 1;
3464 m_pLangBarItemSink = NULL;
3465 }
3466
~CLBarItemBase()3467 CLBarItemBase::~CLBarItemBase()
3468 {
3469 if (m_pLangBarItemSink)
3470 m_pLangBarItemSink->Release();
3471 }
3472
3473 HRESULT
AdviseSink(REFIID riid,IUnknown * punk,DWORD * pdwCookie)3474 CLBarItemBase::AdviseSink(
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
UnadviseSink(DWORD dwCookie)3488 HRESULT CLBarItemBase::UnadviseSink(DWORD dwCookie)
3489 {
3490 if (dwCookie != 0x80000001)
3491 return E_FAIL;
3492
3493 if (!m_pLangBarItemSink)
3494 return E_UNEXPECTED;
3495
3496 m_pLangBarItemSink->Release();
3497 m_pLangBarItemSink = NULL;
3498 return S_OK;
3499 }
3500
3501 void
InitNuiInfo(REFIID clsidService,REFGUID guidItem,DWORD dwStyle,DWORD ulSort,LPCWSTR Source)3502 CLBarItemBase::InitNuiInfo(
3503 REFIID clsidService,
3504 REFGUID guidItem,
3505 DWORD dwStyle,
3506 DWORD ulSort,
3507 LPCWSTR Source)
3508 {
3509 m_NewUIInfo.clsidService = clsidService;
3510 m_NewUIInfo.guidItem = guidItem;
3511 m_NewUIInfo.dwStyle = dwStyle;
3512 m_NewUIInfo.ulSort = ulSort;
3513 StringCchCopyW(m_NewUIInfo.szDescription, _countof(m_NewUIInfo.szDescription), Source);
3514 }
3515
3516 HRESULT
ShowInternal(BOOL bShow,BOOL bUpdate)3517 CLBarItemBase::ShowInternal(BOOL bShow, BOOL bUpdate)
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 {
3528 if (m_pLangBarItemSink)
3529 m_pLangBarItemSink->OnUpdate(TF_LBI_STATUS);
3530 }
3531
3532 return S_OK;
3533 }
3534
GetInfo(TF_LANGBARITEMINFO * pInfo)3535 HRESULT CLBarItemBase::GetInfo(TF_LANGBARITEMINFO *pInfo)
3536 {
3537 CopyMemory(pInfo, &m_NewUIInfo, sizeof(*pInfo));
3538 return S_OK;
3539 }
3540
GetStatus(DWORD * pdwStatus)3541 HRESULT CLBarItemBase::GetStatus(DWORD *pdwStatus)
3542 {
3543 *pdwStatus = m_dwItemStatus;
3544 return S_OK;
3545 }
3546
Show(BOOL fShow)3547 HRESULT CLBarItemBase::Show(BOOL fShow)
3548 {
3549 return ShowInternal(fShow, TRUE);
3550 }
3551
GetTooltipString(BSTR * pbstrToolTip)3552 HRESULT CLBarItemBase::GetTooltipString(BSTR *pbstrToolTip)
3553 {
3554 if (!pbstrToolTip)
3555 return E_INVALIDARG;
3556 BSTR bstr = ::SysAllocString(m_szToolTipText);
3557 *pbstrToolTip = bstr;
3558 return bstr ? S_OK : E_OUTOFMEMORY;
3559 }
3560
3561 /***********************************************************************
3562 * CUTBLBarMenu
3563 */
3564
CUTBLBarMenu(HINSTANCE hInst)3565 CUTBLBarMenu::CUTBLBarMenu(HINSTANCE hInst) : CCicLibMenu()
3566 {
3567 m_hInst = hInst;
3568 }
3569
~CUTBLBarMenu()3570 CUTBLBarMenu::~CUTBLBarMenu()
3571 {
3572 }
3573
STDMETHODIMP_(CCicLibMenuItem *)3574 STDMETHODIMP_(CCicLibMenuItem*) CUTBLBarMenu::CreateMenuItem()
3575 {
3576 CUTBLBarMenuItem *pItem = new(cicNoThrow) CUTBLBarMenuItem();
3577 if (!pItem)
3578 return NULL;
3579 pItem->m_pLBarMenu = this;
3580 return pItem;
3581 }
3582
CreateMenuUI()3583 CUTBMenuWnd *CUTBLBarMenu::CreateMenuUI()
3584 {
3585 CUTBMenuWnd *pMenuUI = new(cicNoThrow) CUTBMenuWnd(m_hInst, g_dwMenuStyle, 0);
3586 if (!pMenuUI)
3587 return NULL;
3588
3589 pMenuUI->Initialize();
3590 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
3591 {
3592 CUTBLBarMenuItem *pItem = (CUTBLBarMenuItem *)m_MenuItems[iItem];
3593 pItem->InsertToUI(pMenuUI);
3594 }
3595
3596 return pMenuUI;
3597 }
3598
STDMETHODIMP_(CCicLibMenu *)3599 STDMETHODIMP_(CCicLibMenu*) CUTBLBarMenu::CreateSubMenu()
3600 {
3601 return new(cicNoThrow) CUTBLBarMenu(m_hInst);
3602 }
3603
ShowPopup(CUIFWindow * pWindow,POINT pt,LPCRECT prcExclude)3604 INT CUTBLBarMenu::ShowPopup(CUIFWindow *pWindow, POINT pt, LPCRECT prcExclude)
3605 {
3606 if (m_pMenuUI)
3607 return 0;
3608
3609 m_pMenuUI = CreateMenuUI();
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
3628 /// @unimplemented
InsertToUI(CUTBMenuWnd * pMenuUI)3629 BOOL CUTBLBarMenuItem::InsertToUI(CUTBMenuWnd *pMenuUI)
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
~CLBarItemButtonBase()3651 CLBarItemButtonBase::~CLBarItemButtonBase()
3652 {
3653 if (m_hIcon)
3654 {
3655 ::DestroyIcon(m_hIcon);
3656 m_hIcon = NULL;
3657 }
3658 }
3659
QueryInterface(REFIID riid,void ** ppvObject)3660 STDMETHODIMP CLBarItemButtonBase::QueryInterface(REFIID riid, void **ppvObject)
3661 {
3662 static const QITAB c_tab[] =
3663 {
3664 QITABENT(CLBarItemButtonBase, ITfLangBarItem),
3665 QITABENT(CLBarItemButtonBase, ITfLangBarItemButton),
3666 QITABENT(CLBarItemButtonBase, ITfSource),
3667 { NULL }
3668 };
3669 return ::QISearch(this, c_tab, riid, ppvObject);
3670 }
3671
STDMETHODIMP_(ULONG)3672 STDMETHODIMP_(ULONG) CLBarItemButtonBase::AddRef()
3673 {
3674 return ++m_cRefs;
3675 }
3676
STDMETHODIMP_(ULONG)3677 STDMETHODIMP_(ULONG) CLBarItemButtonBase::Release()
3678 {
3679 if (--m_cRefs == 0)
3680 {
3681 delete this;
3682 return 0;
3683 }
3684 return m_cRefs;
3685 }
3686
3687 /// @unimplemented
OnClick(TfLBIClick click,POINT pt,LPCRECT prc)3688 STDMETHODIMP CLBarItemButtonBase::OnClick(TfLBIClick click, POINT pt, LPCRECT prc)
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
InitMenu(ITfMenu * pMenu)3701 STDMETHODIMP CLBarItemButtonBase::InitMenu(ITfMenu *pMenu)
3702 {
3703 return E_NOTIMPL;
3704 }
3705
OnMenuSelect(UINT wID)3706 STDMETHODIMP CLBarItemButtonBase::OnMenuSelect(UINT wID)
3707 {
3708 return E_NOTIMPL;
3709 }
3710
GetIcon(HICON * phIcon)3711 STDMETHODIMP CLBarItemButtonBase::GetIcon(HICON *phIcon)
3712 {
3713 return E_NOTIMPL;
3714 }
3715
GetText(BSTR * pbstr)3716 STDMETHODIMP CLBarItemButtonBase::GetText(BSTR *pbstr)
3717 {
3718 if (!pbstr)
3719 return E_INVALIDARG;
3720 *pbstr = ::SysAllocString(m_NewUIInfo.szDescription);
3721 return (*pbstr ? S_OK : E_OUTOFMEMORY);
3722 }
3723
GetInfo(TF_LANGBARITEMINFO * pInfo)3724 STDMETHODIMP CLBarItemButtonBase::GetInfo(TF_LANGBARITEMINFO *pInfo)
3725 {
3726 return CLBarItemBase::GetInfo(pInfo);
3727 }
3728
GetStatus(DWORD * pdwStatus)3729 STDMETHODIMP CLBarItemButtonBase::GetStatus(DWORD *pdwStatus)
3730 {
3731 return CLBarItemBase::GetStatus(pdwStatus);
3732 }
3733
Show(BOOL fShow)3734 STDMETHODIMP CLBarItemButtonBase::Show(BOOL fShow)
3735 {
3736 return CLBarItemBase::Show(fShow);
3737 }
3738
GetTooltipString(BSTR * pbstrToolTip)3739 STDMETHODIMP CLBarItemButtonBase::GetTooltipString(BSTR *pbstrToolTip)
3740 {
3741 return CLBarItemBase::GetTooltipString(pbstrToolTip);
3742 }
3743
AdviseSink(REFIID riid,IUnknown * punk,DWORD * pdwCookie)3744 STDMETHODIMP CLBarItemButtonBase::AdviseSink(
3745 REFIID riid,
3746 IUnknown *punk,
3747 DWORD *pdwCookie)
3748 {
3749 return CLBarItemBase::AdviseSink(riid, punk, pdwCookie);
3750 }
3751
UnadviseSink(DWORD dwCookie)3752 STDMETHODIMP CLBarItemButtonBase::UnadviseSink(DWORD dwCookie)
3753 {
3754 return CLBarItemBase::UnadviseSink(dwCookie);
3755 }
3756
3757 /***********************************************************************
3758 * CLBarInatItem
3759 */
3760
CLBarInatItem(DWORD dwThreadId)3761 CLBarInatItem::CLBarInatItem(DWORD dwThreadId)
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
3767 ::LoadStringW(g_hInst, IDS_LANGUAGEBUTTON, szText, _countof(szText));
3768 StringCchCopyW(m_szToolTipText, _countof(m_szToolTipText), szText);
3769 m_dwThreadId = dwThreadId;
3770 m_hKL = ::GetKeyboardLayout(m_dwThreadId);
3771
3772 TF_InitMlngInfo();
3773 ShowInternal(TF_MlngInfoCount() > 1, 0);
3774 }
3775
GetIcon(HICON * phIcon)3776 STDMETHODIMP CLBarInatItem::GetIcon(HICON *phIcon)
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
GetText(BSTR * pbstr)3786 STDMETHODIMP CLBarInatItem::GetText(BSTR *pbstr)
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
InitMenu(ITfMenu * pMenu)3799 STDMETHODIMP CLBarInatItem::InitMenu(ITfMenu *pMenu)
3800 {
3801 TF_InitMlngInfo();
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
3819 DWORD dwStatus;
3820 if (g_pTipbarWnd &&
3821 g_pTipbarWnd->m_pLangBarMgr &&
3822 SUCCEEDED(g_pTipbarWnd->m_pLangBarMgr->GetShowFloatingStatus(&dwStatus)) &&
3823 (dwStatus & (TF_SFT_DESKBAND | TF_SFT_MINIMIZED)))
3824 {
3825 LangBarInsertSeparator(pMenu);
3826
3827 WCHAR szText[256];
3828 ::LoadStringW(g_hInst, IDS_RESTORELANGBAR2, szText, _countof(szText));
3829 LangBarInsertMenu(pMenu, 2000, szText, FALSE, NULL);
3830 }
3831
3832 return S_OK;
3833 }
3834
OnMenuSelect(INT nCommandId)3835 STDMETHODIMP CLBarInatItem::OnMenuSelect(INT nCommandId)
3836 {
3837 HKL hKL;
3838
3839 if (nCommandId == 2000)
3840 {
3841 if (g_pTipbarWnd)
3842 {
3843 ITfLangBarMgr *pLangBarMgr = g_pTipbarWnd->m_pLangBarMgr;
3844 if (pLangBarMgr)
3845 pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
3846 }
3847 }
3848 else if (TF_GetMlngHKL(nCommandId, &hKL, NULL, 0))
3849 {
3850 g_pTipbarWnd->RestoreLastFocus(NULL, !!(g_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_CHILD));
3851 HWND hwndFore = ::GetForegroundWindow();
3852 if (m_dwThreadId == ::GetWindowThreadProcessId(hwndFore, NULL))
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
CTipbarGripper(CTipbarWnd * pTipbarWnd,LPCRECT prc,DWORD style)3866 CTipbarGripper::CTipbarGripper(CTipbarWnd *pTipbarWnd, LPCRECT prc, DWORD style)
3867 : CUIFGripper((pTipbarWnd ? pTipbarWnd->GetWindow() : NULL), prc, style)
3868 {
3869 m_bInDebugMenu = FALSE;
3870 m_pTipbarWnd = pTipbarWnd;
3871 }
3872
3873 /// @unimplemented
STDMETHODIMP_(void)3874 STDMETHODIMP_(void) CTipbarGripper::OnLButtonUp(LONG x, LONG y)
3875 {
3876 m_pTipbarWnd->RestoreFromStub();
3877
3878 if (g_bEnableDeskBand && (g_dwOSInfo & CIC_OSINFO_XPPLUS))
3879 {
3880 APPBARDATA AppBar = { sizeof(AppBar) };
3881 AppBar.hWnd = ::FindWindowW(L"Shell_TrayWnd", NULL);
3882 if (::SHAppBarMessage(ABM_GETTASKBARPOS, &AppBar))
3883 {
3884 RECT rc = AppBar.rc;
3885 POINT pt;
3886 ::GetCursorPos(&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);
3894 m_pTipbarWnd->UpdatePosFlags();
3895 }
3896
3897 /// @unimplemented
STDMETHODIMP_(void)3898 STDMETHODIMP_(void) CTipbarGripper::OnRButtonUp(LONG x, LONG y)
3899 {
3900 if (g_bShowDebugMenu)
3901 {
3902 // FIXME: Debugging feature
3903 }
3904 }
3905
STDMETHODIMP_(BOOL)3906 STDMETHODIMP_(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
IsStartedIntentionally(REFCLSID rclsid)3918 BOOL CLangBarItemList::IsStartedIntentionally(REFCLSID rclsid)
3919 {
3920 auto *pItem = FindItem(rclsid);
3921 if (!pItem)
3922 return FALSE;
3923 return pItem->m_bStartedIntentionally;
3924 }
3925
AddItem(REFCLSID rclsid)3926 LANGBARITEMSTATE *CLangBarItemList::AddItem(REFCLSID rclsid)
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 ZeroMemory(pItem, sizeof(*pItem));
3937 pItem->m_clsid = rclsid;
3938 pItem->m_dwDemoteLevel = 0;
3939 return pItem;
3940 }
3941
Clear()3942 void CLangBarItemList::Clear()
3943 {
3944 clear();
3945
3946 CicRegKey regKey;
3947 LSTATUS error;
3948 error = regKey.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar", KEY_ALL_ACCESS);
3949 if (error == ERROR_SUCCESS)
3950 regKey.RecurseDeleteKey(L"ItemState");
3951 }
3952
SetDemoteLevel(REFCLSID rclsid,DWORD dwDemoteLevel)3953 BOOL CLangBarItemList::SetDemoteLevel(REFCLSID rclsid, DWORD dwDemoteLevel)
3954 {
3955 auto *pItem = AddItem(rclsid);
3956 if (!pItem)
3957 return TRUE;
3958
3959 pItem->m_dwDemoteLevel = dwDemoteLevel;
3960 if (!pItem->IsShown())
3961 {
3962 if (pItem->m_nTimerID)
3963 {
3964 if (g_pTipbarWnd)
3965 g_pTipbarWnd->KillTimer(pItem->m_nTimerID);
3966 pItem->m_nTimerID = 0;
3967 pItem->m_uTimeOut = 0;
3968 }
3969 pItem->m_bDisableDemoting = FALSE;
3970 }
3971
3972 SaveItem(0, pItem);
3973 return TRUE;
3974 }
3975
FindItem(REFCLSID rclsid)3976 LANGBARITEMSTATE *CLangBarItemList::FindItem(REFCLSID rclsid)
3977 {
3978 for (size_t iItem = 0; iItem < size(); ++iItem)
3979 {
3980 auto& item = (*this)[iItem];
3981 if (IsEqualCLSID(item.m_clsid, rclsid))
3982 return &item;
3983 }
3984 return NULL;
3985 }
3986
GetItemStateFromTimerId(UINT_PTR nTimerID)3987 LANGBARITEMSTATE *CLangBarItemList::GetItemStateFromTimerId(UINT_PTR nTimerID)
3988 {
3989 for (size_t iItem = 0; iItem < size(); ++iItem)
3990 {
3991 auto& item = (*this)[iItem];
3992 if (item.m_nTimerID == nTimerID)
3993 return &item;
3994 }
3995 return NULL;
3996 }
3997
Load()3998 void CLangBarItemList::Load()
3999 {
4000 CicRegKey regKey;
4001 LSTATUS error;
4002 error = regKey.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar\\ItemState");
4003 if (error != ERROR_SUCCESS)
4004 return;
4005
4006 WCHAR szKeyName[MAX_PATH];
4007 for (DWORD dwIndex = 0; ; ++dwIndex)
4008 {
4009 error = ::RegEnumKeyW(regKey, dwIndex, szKeyName, _countof(szKeyName));
4010 if (error != ERROR_SUCCESS)
4011 break;
4012
4013 CLSID clsid;
4014 if (::CLSIDFromString(szKeyName, &clsid) != S_OK)
4015 continue;
4016
4017 CicRegKey regKey2;
4018 error = regKey2.Open(regKey, szKeyName);
4019 if (error != ERROR_SUCCESS)
4020 continue;
4021
4022 auto *pItem = AddItem(clsid);
4023 if (!pItem)
4024 continue;
4025
4026 DWORD Data = 0;
4027 regKey2.QueryDword(L"DemoteLevel", &Data);
4028 pItem->m_dwDemoteLevel = Data;
4029 regKey2.QueryDword(L"DisableDemoting", &Data);
4030 pItem->m_bDisableDemoting = !!Data;
4031 }
4032 }
4033
SaveItem(CicRegKey * pRegKey,const LANGBARITEMSTATE * pState)4034 void CLangBarItemList::SaveItem(CicRegKey *pRegKey, const LANGBARITEMSTATE *pState)
4035 {
4036 LSTATUS error;
4037 CicRegKey regKey;
4038
4039 if (!pRegKey)
4040 {
4041 error = regKey.Create(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar\\ItemState");
4042 if (error != ERROR_SUCCESS)
4043 return;
4044
4045 pRegKey = ®Key;
4046 }
4047
4048 WCHAR szSubKey[MAX_PATH];
4049 ::StringFromGUID2(pState->m_clsid, szSubKey, _countof(szSubKey));
4050
4051 if (pState->m_dwDemoteLevel || pState->m_bDisableDemoting)
4052 {
4053 CicRegKey regKey2;
4054 error = regKey2.Create(*pRegKey, szSubKey);
4055 if (error == ERROR_SUCCESS)
4056 {
4057 DWORD dwDemoteLevel = pState->m_dwDemoteLevel;
4058 if (dwDemoteLevel)
4059 regKey2.SetDword(L"DemoteLevel", dwDemoteLevel);
4060 else
4061 regKey2.DeleteValue(L"DemoteLevel");
4062
4063 regKey2.SetDword(L"DisableDemoting", pState->m_bDisableDemoting);
4064 }
4065 }
4066 else
4067 {
4068 pRegKey->RecurseDeleteKey(szSubKey);
4069 }
4070 }
4071
StartDemotingTimer(REFCLSID rclsid,BOOL bIntentional)4072 void CLangBarItemList::StartDemotingTimer(REFCLSID rclsid, BOOL bIntentional)
4073 {
4074 if (!g_bIntelliSense)
4075 return;
4076
4077 auto *pItem = AddItem(rclsid);
4078 if (!pItem || pItem->m_bDisableDemoting)
4079 return;
4080
4081 if (pItem->m_nTimerID)
4082 {
4083 if (!bIntentional)
4084 return;
4085
4086 if (g_pTipbarWnd)
4087 g_pTipbarWnd->KillTimer(pItem->m_nTimerID);
4088
4089 pItem->m_nTimerID = 0;
4090 }
4091
4092 pItem->m_bStartedIntentionally |= bIntentional;
4093
4094 UINT uTimeOut = (bIntentional ? g_uTimeOutIntentional : g_uTimeOutNonIntentional);
4095 pItem->m_uTimeOut += uTimeOut;
4096
4097 if (pItem->m_uTimeOut < g_uTimeOutMax)
4098 {
4099 UINT_PTR uDemotingTimerId = FindDemotingTimerId();
4100 pItem->m_nTimerID = uDemotingTimerId;
4101 if (uDemotingTimerId)
4102 {
4103 if (g_pTipbarWnd)
4104 g_pTipbarWnd->SetTimer(uDemotingTimerId, uTimeOut);
4105 }
4106 }
4107 else
4108 {
4109 pItem->m_bDisableDemoting = TRUE;
4110 }
4111 }
4112
FindDemotingTimerId()4113 UINT_PTR CLangBarItemList::FindDemotingTimerId()
4114 {
4115 UINT_PTR nTimerID = 10000;
4116
4117 if (empty())
4118 return nTimerID;
4119
4120 for (;;)
4121 {
4122 size_t iItem = 0;
4123
4124 while ((*this)[iItem].m_nTimerID != nTimerID)
4125 {
4126 ++iItem;
4127 if (iItem >= size())
4128 return nTimerID;
4129 }
4130
4131 ++nTimerID;
4132 if (nTimerID >= 10050)
4133 return 0;
4134 }
4135 }
4136
4137 /***********************************************************************
4138 * CTipbarWnd
4139 */
4140
4141 /// @unimplemented
CTipbarWnd(DWORD style)4142 CTipbarWnd::CTipbarWnd(DWORD style)
4143 : CUIFWindow(g_hInst, style)
4144 {
4145 m_dwUnknown23_1[4] = 0;
4146 m_dwUnknown23_1[5] = 0;
4147 m_dwUnknown23_1[6] = 0;
4148 m_dwUnknown23_1[7] = 0;
4149
4150 RECT rc;
4151 cicGetScreenRect(g_ptTipbar, &rc);
4152
4153 //FIXME: Fix g_ptTipbar
4154
4155 Move(g_ptTipbar.x, g_ptTipbar.y, 100, 24);
4156 UpdatePosFlags();
4157
4158 m_hMarlettFont = ::CreateFontW(8, 8, 0, 0, FW_NORMAL, 0, 0, 0,
4159 SYMBOL_CHARSET, 0, 0, 0, 0, L"Marlett");
4160
4161 ITfLangBarMgr *pLangBarMgr = NULL;
4162 if (SUCCEEDED(TF_CreateLangBarMgr(&pLangBarMgr)) && pLangBarMgr)
4163 {
4164 pLangBarMgr->QueryInterface(IID_ITfLangBarMgr_P, (void **)&m_pLangBarMgr);
4165 pLangBarMgr->Release();
4166 }
4167
4168 if (style & UIF_WINDOW_ENABLETHEMED)
4169 {
4170 if (g_fTaskbarTheme)
4171 {
4172 m_iPartId = 1;
4173 m_iStateId = 1;
4174 m_pszClassList = L"TASKBAR";
4175 }
4176 else
4177 {
4178 m_iPartId = 0;
4179 m_iStateId = 1;
4180 m_pszClassList = L"REBAR";
4181 }
4182 }
4183
4184 SetVertical(g_fVertical);
4185
4186 m_cRefs = 1;
4187 }
4188
~CTipbarWnd()4189 CTipbarWnd::~CTipbarWnd()
4190 {
4191 UnInit();
4192
4193 if (m_hMarlettFont)
4194 ::DeleteObject(m_hMarlettFont);
4195 if (m_hTextFont)
4196 ::DeleteObject(m_hTextFont);
4197
4198 TFUninitLib_Thread(&g_libTLS);
4199 }
4200
4201 /// @unimplemented
Init(BOOL bChild,CDeskBand * pDeskBand)4202 void CTipbarWnd::Init(BOOL bChild, CDeskBand *pDeskBand)
4203 {
4204 if (bChild)
4205 m_dwTipbarWndFlags |= TIPBAR_CHILD;
4206 else
4207 m_dwTipbarWndFlags &= ~TIPBAR_CHILD;
4208
4209 if (m_dwTipbarWndFlags & TIPBAR_CHILD)
4210 m_dwTipbarWndFlags &= TIPBAR_HIGHCONTRAST;
4211
4212 m_pDeskBand = pDeskBand;
4213
4214 RECT rc = { 0, 0, 0, 0 };
4215
4216 if (g_bNewLook && !m_pWndFrame && (m_style & 0x20000000))
4217 {
4218 CUIFWndFrame *pWndFrame = new(cicNoThrow) CUIFWndFrame(GetWindow(), &rc, 0);
4219 if (pWndFrame)
4220 {
4221 pWndFrame->Initialize();
4222 AddUIObj(m_pWndFrame);
4223 }
4224 }
4225
4226 if (!m_pTipbarGripper && !(m_dwTipbarWndFlags & TIPBAR_CHILD))
4227 {
4228 m_pTipbarGripper =
4229 new(cicNoThrow) CTipbarGripper(this, &rc, !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL));
4230 if (m_pTipbarGripper)
4231 {
4232 m_pTipbarGripper->Initialize();
4233 AddUIObj(m_pTipbarGripper);
4234 }
4235 }
4236
4237 //FIXME: CTipbarCtrlButtonHolder
4238
4239 if (m_dwTipbarWndFlags & TIPBAR_VERTICAL)
4240 {
4241 Move(m_nLeft, m_nTop, GetTipbarHeight(), 0);
4242 }
4243 else
4244 {
4245 Move(m_nLeft, m_nTop, 0, GetTipbarHeight());
4246 }
4247 }
4248
InitHighContrast()4249 void CTipbarWnd::InitHighContrast()
4250 {
4251 m_dwTipbarWndFlags &= ~TIPBAR_HIGHCONTRAST;
4252
4253 HIGHCONTRAST HiCon = { sizeof(HiCon) };
4254 if (::SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HiCon), &HiCon, 0))
4255 {
4256 if (HiCon.dwFlags & HCF_HIGHCONTRASTON)
4257 m_dwTipbarWndFlags |= TIPBAR_HIGHCONTRAST;
4258 }
4259 }
4260
InitMetrics()4261 void CTipbarWnd::InitMetrics()
4262 {
4263 m_cxSmallIcon = ::GetSystemMetrics(SM_CXSMICON);
4264 m_cySmallIcon = ::GetSystemMetrics(SM_CYSMICON);
4265
4266 DWORD_PTR style = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
4267 if (style & WS_DLGFRAME)
4268 {
4269 m_cxDlgFrameX2 = 2 * ::GetSystemMetrics(SM_CXDLGFRAME);
4270 m_cyDlgFrameX2 = 2 * ::GetSystemMetrics(SM_CYDLGFRAME);
4271 }
4272 else if (style & WS_BORDER)
4273 {
4274 m_cxDlgFrameX2 = 2 * ::GetSystemMetrics(SM_CXBORDER);
4275 m_cyDlgFrameX2 = 2 * ::GetSystemMetrics(SM_CYBORDER);
4276 }
4277 else
4278 {
4279 m_cxDlgFrameX2 = m_cyDlgFrameX2 = 0;
4280 }
4281 }
4282
InitThemeMargins()4283 void CTipbarWnd::InitThemeMargins()
4284 {
4285 ZeroMemory(&m_Margins, sizeof(m_Margins));
4286
4287 CUIFTheme theme;
4288 m_dwUnknown23_5[0] = 6;
4289 m_dwUnknown23_5[1] = 6;
4290 m_dwUnknown23_5[2] = 0;
4291 m_ButtonWidth = GetSystemMetrics(SM_CXSIZE);
4292
4293 theme.m_iPartId = 1;
4294 theme.m_iStateId = 0;
4295 theme.m_pszClassList = L"TOOLBAR";
4296 if (SUCCEEDED(theme.InternalOpenThemeData(m_hWnd)))
4297 {
4298 ::GetThemeMargins(theme.m_hTheme, NULL, theme.m_iPartId, 1, 3602, NULL, &m_Margins);
4299 m_dwUnknown23_5[0] = 4;
4300 m_dwUnknown23_5[1] = 2;
4301 m_dwUnknown23_5[2] = 1;
4302 }
4303 theme.CloseThemeData();
4304
4305 theme.m_iPartId = 18;
4306 theme.m_iStateId = 0;
4307 theme.m_pszClassList = L"WINDOW";
4308 if (SUCCEEDED(theme.InternalOpenThemeData(m_hWnd)))
4309 {
4310 SIZE partSize;
4311 ::GetThemePartSize(theme.m_hTheme, NULL, theme.m_iPartId, 1, 0, TS_TRUE, &partSize);
4312 INT size = ::GetThemeSysSize(theme.m_hTheme, 31);
4313 m_ButtonWidth = MulDiv(size, partSize.cx, partSize.cy);
4314 }
4315 theme.CloseThemeData();
4316 }
4317
UnInit()4318 void CTipbarWnd::UnInit()
4319 {
4320 SetFocusThread(NULL);
4321 for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem)
4322 {
4323 CTipbarThread* pThread = m_Threads[iItem];
4324 if (pThread)
4325 {
4326 pThread->_UninitItemList(TRUE);
4327 pThread->m_pTipbarWnd = NULL;
4328 pThread->_Release();
4329 }
4330 }
4331 m_Threads.clear();
4332
4333 if (m_pLangBarMgr)
4334 m_pLangBarMgr->UnAdviseEventSink(m_dwSinkCookie);
4335
4336 if (m_pLangBarMgr)
4337 {
4338 m_pLangBarMgr->Release();
4339 m_pLangBarMgr = NULL;
4340 }
4341 }
4342
IsFullScreenWindow(HWND hWnd)4343 BOOL CTipbarWnd::IsFullScreenWindow(HWND hWnd)
4344 {
4345 if (g_fPolicyEnableLanguagebarInFullscreen)
4346 return FALSE;
4347
4348 DWORD_PTR style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
4349 if (!(style & WS_VISIBLE) || (style & WS_CAPTION))
4350 return FALSE;
4351
4352 DWORD_PTR exstyle = ::GetWindowLongPtr(hWnd, GWL_EXSTYLE);
4353 if (exstyle & WS_EX_LAYERED)
4354 return FALSE;
4355
4356 if ((exstyle & WS_EX_TOOLWINDOW) && (hWnd == m_ShellWndThread.GetWndProgman()))
4357 return FALSE;
4358
4359 return !!cicIsFullScreenSize(hWnd);
4360 }
4361
IsHKLToSkipRedrawOnNoItem()4362 BOOL CTipbarWnd::IsHKLToSkipRedrawOnNoItem()
4363 {
4364 HKL hKL = GetFocusKeyboardLayout();
4365 return IsSkipRedrawHKL(hKL);
4366 }
4367
IsInItemChangeOrDirty(CTipbarThread * pTarget)4368 BOOL CTipbarWnd::IsInItemChangeOrDirty(CTipbarThread *pTarget)
4369 {
4370 if (pTarget->m_dwThreadId == m_dwChangingThreadId)
4371 return TRUE;
4372 return pTarget->IsDirtyItem();
4373 }
4374
AddThreadToThreadCreatingList(CTipbarThread * pThread)4375 void CTipbarWnd::AddThreadToThreadCreatingList(CTipbarThread *pThread)
4376 {
4377 m_ThreadCreatingList.Add(pThread);
4378 }
4379
RemoveThredFromThreadCreatingList(CTipbarThread * pTarget)4380 void CTipbarWnd::RemoveThredFromThreadCreatingList(CTipbarThread *pTarget)
4381 {
4382 ssize_t iItem = m_ThreadCreatingList.Find(pTarget);
4383 if (iItem >= 0)
4384 m_ThreadCreatingList.Remove(iItem);
4385 }
4386
MoveToStub(BOOL bFlag)4387 void CTipbarWnd::MoveToStub(BOOL bFlag)
4388 {
4389 m_dwTipbarWndFlags |= 0x40;
4390
4391 RECT rcWorkArea;
4392 ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
4393
4394 if (bFlag)
4395 {
4396 m_nLeft = rcWorkArea.right - 38;
4397 m_dwTipbarWndFlags &= ~0x80;
4398 }
4399 else
4400 {
4401 RECT Rect;
4402 ::GetWindowRect(m_hWnd, &Rect);
4403 m_nLeft = rcWorkArea.right + Rect.left - Rect.right;
4404 m_dwTipbarWndFlags |= 0x80;
4405 }
4406
4407 m_nTop = rcWorkArea.bottom - m_cyDlgFrameX2 - GetTipbarHeight();
4408
4409 if (m_pFocusThread)
4410 m_pFocusThread->MyMoveWnd(0, 0);
4411 }
4412
RestoreFromStub()4413 void CTipbarWnd::RestoreFromStub()
4414 {
4415 m_dwTipbarWndFlags &= 0x3F;
4416 KillTimer(1);
4417 KillTimer(2);
4418 }
4419
4420 /// @unimplemented
GetCtrlButtonWidth()4421 INT CTipbarWnd::GetCtrlButtonWidth()
4422 {
4423 return 0;
4424 }
4425
GetGripperWidth()4426 INT CTipbarWnd::GetGripperWidth()
4427 {
4428 if (m_dwTipbarWndFlags & 2)
4429 return 0;
4430
4431 if (!m_pTipbarGripper || FAILED(m_pTipbarGripper->EnsureThemeData(m_hWnd)))
4432 return 5;
4433
4434 INT width = -1;
4435 SIZE partSize;
4436 HDC hDC = ::GetDC(m_hWnd);
4437 if (SUCCEEDED(m_pTipbarGripper->GetThemePartSize(hDC, 1, 0, TS_TRUE, &partSize)))
4438 {
4439 INT cx = partSize.cx;
4440 if (m_dwTipbarWndFlags & 4)
4441 cx = partSize.cy;
4442 width = cx + 4;
4443 }
4444 ::ReleaseDC(m_hWnd, hDC);
4445
4446 return ((width < 0) ? 5 : width);
4447 }
4448
GetTipbarHeight()4449 INT CTipbarWnd::GetTipbarHeight()
4450 {
4451 SIZE size = { 0, 0 };
4452 if (m_pWndFrame)
4453 m_pWndFrame->GetFrameSize(&size);
4454 INT cy = m_Margins.cyBottomHeight + m_Margins.cyTopHeight + 2;
4455 if (cy < 6)
4456 cy = 6;
4457 return m_cySmallIcon + cy + (2 * size.cy);
4458 }
4459
AutoAdjustDeskBandSize()4460 BOOL CTipbarWnd::AutoAdjustDeskBandSize()
4461 {
4462 if ((m_dwTipbarWndFlags & TIPBAR_NODESKBAND) ||
4463 !m_pFocusThread ||
4464 (m_pFocusThread->m_dwFlags1 & 0x800))
4465 {
4466 return FALSE;
4467 }
4468
4469 DWORD dwOldWndFlags = m_dwTipbarWndFlags;
4470 m_dwTipbarWndFlags &= ~0x8000;
4471
4472 if (!AdjustDeskBandSize(!(dwOldWndFlags & 0x8000)))
4473 return FALSE;
4474
4475 m_dwTipbarWndFlags |= TIPBAR_NODESKBAND;
4476 return TRUE;
4477 }
4478
4479 /// @unimplemented
AdjustDeskBandSize(BOOL bFlag)4480 INT CTipbarWnd::AdjustDeskBandSize(BOOL bFlag)
4481 {
4482 return 0;
4483 }
4484
4485 /// @unimplemented
LocateCtrlButtons()4486 void CTipbarWnd::LocateCtrlButtons()
4487 {
4488 }
4489
AdjustPosOnDisplayChange()4490 void CTipbarWnd::AdjustPosOnDisplayChange()
4491 {
4492 RECT rcWorkArea;
4493 RECT rc = { m_nLeft, m_nTop, m_nLeft + m_nWidth, m_nTop + m_nHeight };
4494 if (!GetWorkArea(&rc, &rcWorkArea))
4495 return;
4496
4497 INT x = m_nLeft, y = m_nTop;
4498 if (m_dwTipbarWndFlags & TIPBAR_LEFTFIT)
4499 x = rcWorkArea.left;
4500 if (m_dwTipbarWndFlags & TIPBAR_TOPFIT)
4501 y = rcWorkArea.top;
4502 if (m_dwTipbarWndFlags & TIPBAR_RIGHTFIT)
4503 x = rcWorkArea.right - m_nWidth;
4504 if (m_dwTipbarWndFlags & TIPBAR_BOTTOMFIT)
4505 y = rcWorkArea.bottom - m_nHeight;
4506 if (x != m_nLeft || y != m_nTop)
4507 Move(x, y, m_nWidth, m_nHeight);
4508 }
4509
SetVertical(BOOL bVertical)4510 void CTipbarWnd::SetVertical(BOOL bVertical)
4511 {
4512 if (bVertical)
4513 m_dwTipbarWndFlags |= TIPBAR_VERTICAL;
4514 else
4515 m_dwTipbarWndFlags &= ~TIPBAR_VERTICAL;
4516
4517 if (m_pTipbarGripper)
4518 {
4519 DWORD style = m_pTipbarGripper->m_style;
4520 if (bVertical)
4521 style |= 0x1;
4522 else
4523 style &= 0x1;
4524 m_pTipbarGripper->SetStyle(style);
4525 }
4526
4527 if (g_fTaskbarTheme)
4528 SetActiveTheme(L"TASKBAR", !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL), 1);
4529
4530 if (!(m_dwTipbarWndFlags & TIPBAR_CHILD))
4531 {
4532 if (m_dwTipbarWndFlags & TIPBAR_VERTICAL)
4533 {
4534 Move(m_nLeft, m_nTop, GetTipbarHeight(), 0);
4535 }
4536 else
4537 {
4538 Move(m_nLeft, m_nTop, 0, GetTipbarHeight());
4539 }
4540 }
4541
4542 if (m_hWnd)
4543 {
4544 KillTimer(7);
4545 SetTimer(7, g_uTimerElapseSYSCOLORCHANGED);
4546 }
4547 }
4548
UpdatePosFlags()4549 void CTipbarWnd::UpdatePosFlags()
4550 {
4551 if (m_dwTipbarWndFlags & TIPBAR_CHILD)
4552 return;
4553
4554 RECT rc = { m_nLeft, m_nTop, m_nLeft + m_nWidth, m_nTop + m_nHeight }, rcWorkArea;
4555 if (!GetWorkArea(&rc, &rcWorkArea))
4556 return;
4557
4558 if (rcWorkArea.left + 2 < m_nLeft)
4559 m_dwTipbarWndFlags &= ~TIPBAR_LEFTFIT;
4560 else
4561 m_dwTipbarWndFlags |= TIPBAR_LEFTFIT;
4562
4563 if (rcWorkArea.top + 2 < m_nTop)
4564 m_dwTipbarWndFlags &= ~TIPBAR_TOPFIT;
4565 else
4566 m_dwTipbarWndFlags |= TIPBAR_TOPFIT;
4567
4568 if (m_nLeft + m_nWidth < rcWorkArea.right - 2)
4569 m_dwTipbarWndFlags &= ~TIPBAR_RIGHTFIT;
4570 else
4571 m_dwTipbarWndFlags |= TIPBAR_RIGHTFIT;
4572
4573 if (m_nTop + m_nHeight < rcWorkArea.bottom - 2)
4574 m_dwTipbarWndFlags &= ~TIPBAR_BOTTOMFIT;
4575 else
4576 m_dwTipbarWndFlags |= TIPBAR_BOTTOMFIT;
4577 }
4578
CancelMenu()4579 void CTipbarWnd::CancelMenu()
4580 {
4581 if (!m_pThread)
4582 return;
4583
4584 CTipbarWnd *pTipbarWnd = m_pThread->m_pTipbarWnd;
4585 if (pTipbarWnd)
4586 {
4587 if (pTipbarWnd->m_pLangBarMgr)
4588 pTipbarWnd->StartModalInput(NULL, m_pThread->m_dwThreadId);
4589 }
4590
4591 m_pModalMenu->CancelMenu();
4592 StartBackToAlphaTimer();
4593 }
4594
CheckExcludeCaptionButtonMode(LPRECT prc1,LPCRECT prc2)4595 BOOL CTipbarWnd::CheckExcludeCaptionButtonMode(LPRECT prc1, LPCRECT prc2)
4596 {
4597 return (prc1->top < prc2->top + 5) && (prc2->right <= prc1->right + (5 * m_ButtonWidth));
4598 }
4599
ClearLBItemList()4600 void CTipbarWnd::ClearLBItemList()
4601 {
4602 m_LangBarItemList.Clear();
4603 if (m_pFocusThread)
4604 OnThreadItemChange(m_pFocusThread->m_dwThreadId);
4605 }
4606
CreateVerticalFont()4607 HFONT CTipbarWnd::CreateVerticalFont()
4608 {
4609 if (!m_hWnd)
4610 return NULL;
4611
4612 CUIFTheme theme;
4613 theme.m_iPartId = 1;
4614 theme.m_iStateId = 0;
4615 theme.m_pszClassList = L"TOOLBAR";
4616
4617 LOGFONTW lf;
4618 if (FAILED(theme.InternalOpenThemeData(m_hWnd)) ||
4619 FAILED(::GetThemeFont(theme.m_hTheme, NULL, theme.m_iPartId, 0, 210, &lf)))
4620 {
4621 ::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
4622 }
4623
4624 lf.lfEscapement = lf.lfOrientation = 2700;
4625 lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
4626
4627 if (CheckEAFonts())
4628 {
4629 WCHAR szText[LF_FACESIZE];
4630 szText[0] = L'@';
4631 StringCchCopyW(&szText[1], _countof(szText) - 1, lf.lfFaceName);
4632 StringCchCopyW(lf.lfFaceName, _countof(lf.lfFaceName), szText);
4633 }
4634
4635 return ::CreateFontIndirectW(&lf);
4636 }
4637
UpdateVerticalFont()4638 void CTipbarWnd::UpdateVerticalFont()
4639 {
4640 if (m_dwTipbarWndFlags & TIPBAR_VERTICAL)
4641 {
4642 if (m_hTextFont)
4643 {
4644 ::DeleteObject(m_hTextFont);
4645 SetFontToThis(NULL);
4646 m_hTextFont = NULL;
4647 }
4648 m_hTextFont = CreateVerticalFont();
4649 SetFontToThis(m_hTextFont);
4650 }
4651 else
4652 {
4653 SetFontToThis(NULL);
4654 }
4655 }
4656
4657 /// @unimplemented
ShowOverScreenSizeBalloon()4658 void CTipbarWnd::ShowOverScreenSizeBalloon()
4659 {
4660 //FIXME: CTipbarCtrlButtonHolder
4661 }
4662
DestroyOverScreenSizeBalloon()4663 void CTipbarWnd::DestroyOverScreenSizeBalloon()
4664 {
4665 if (m_pBalloon)
4666 {
4667 if (::IsWindow(*m_pBalloon))
4668 ::DestroyWindow(*m_pBalloon);
4669 delete m_pBalloon;
4670 m_pBalloon = NULL;
4671 }
4672 }
4673
DestroyWnd()4674 void CTipbarWnd::DestroyWnd()
4675 {
4676 if (::IsWindow(m_hWnd))
4677 ::DestroyWindow(m_hWnd);
4678 }
4679
GetFocusKeyboardLayout()4680 HKL CTipbarWnd::GetFocusKeyboardLayout()
4681 {
4682 DWORD dwThreadId = 0;
4683 if (m_pFocusThread)
4684 dwThreadId = m_pFocusThread->m_dwThreadId;
4685 return ::GetKeyboardLayout(dwThreadId);
4686 }
4687
KillOnTheadItemChangeTimer()4688 void CTipbarWnd::KillOnTheadItemChangeTimer()
4689 {
4690 DWORD dwChangingThreadId = m_dwChangingThreadId;
4691 m_dwChangingThreadId = 0;
4692 KillTimer(4);
4693
4694 if (dwChangingThreadId)
4695 {
4696 CTipbarThread *pThread = _FindThread(dwChangingThreadId);
4697 if (pThread)
4698 pThread->m_dwUnknown34 |= 0x1;
4699 }
4700 }
4701
SetTimer(UINT_PTR nIDEvent,UINT uElapse)4702 UINT_PTR CTipbarWnd::SetTimer(UINT_PTR nIDEvent, UINT uElapse)
4703 {
4704 if (::IsWindow(m_hWnd))
4705 return ::SetTimer(m_hWnd, nIDEvent, uElapse, NULL);
4706 return 0;
4707 }
4708
KillTimer(UINT_PTR uIDEvent)4709 BOOL CTipbarWnd::KillTimer(UINT_PTR uIDEvent)
4710 {
4711 if (::IsWindow(m_hWnd))
4712 return ::KillTimer(m_hWnd, uIDEvent);
4713 return FALSE;
4714 }
4715
4716 /// @unimplemented
MoveToTray()4717 void CTipbarWnd::MoveToTray()
4718 {
4719 if (!g_bEnableDeskBand || !(g_dwOSInfo & CIC_OSINFO_XPPLUS))
4720 {
4721 //FIXME
4722 }
4723 }
4724
MyClientToScreen(LPPOINT lpPoint,LPRECT prc)4725 void CTipbarWnd::MyClientToScreen(LPPOINT lpPoint, LPRECT prc)
4726 {
4727 if (lpPoint)
4728 ::ClientToScreen(m_hWnd, lpPoint);
4729
4730 if (prc)
4731 {
4732 ::ClientToScreen(m_hWnd, (LPPOINT)prc);
4733 ::ClientToScreen(m_hWnd, (LPPOINT)&prc->right);
4734 }
4735 }
4736
SavePosition()4737 void CTipbarWnd::SavePosition()
4738 {
4739 CicRegKey regKey;
4740 if (regKey.Create(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\")))
4741 {
4742 POINT pt = { 0, 0 };
4743 ::ClientToScreen(m_hWnd, &pt);
4744 regKey.SetDword(TEXT("Left"), pt.x);
4745 regKey.SetDword(TEXT("Top"), pt.y);
4746 regKey.SetDword(TEXT("Vertical"), !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL));
4747 }
4748 }
4749
4750 /// @unimplemented
SetAlpha(BYTE bAlpha,BOOL bFlag)4751 void CTipbarWnd::SetAlpha(BYTE bAlpha, BOOL bFlag)
4752 {
4753 }
4754
SetLangBand(BOOL bDeskBand,BOOL bFlag2)4755 BOOL CTipbarWnd::SetLangBand(BOOL bDeskBand, BOOL bFlag2)
4756 {
4757 if (bDeskBand == !!(m_dwShowType & TF_SFT_DESKBAND))
4758 return TRUE;
4759
4760 BOOL ret = TRUE;
4761 HWND hwndTray = m_ShellWndThread.GetWndTray();
4762 if (bFlag2 && hwndTray)
4763 {
4764 DWORD_PTR dwResult;
4765 HWND hImeWnd = ::ImmGetDefaultIMEWnd(hwndTray);
4766 if (hImeWnd)
4767 ::SendMessageTimeout(hImeWnd, WM_IME_SYSTEM, 0x24 - bDeskBand, (LPARAM)hwndTray,
4768 (SMTO_BLOCK | SMTO_ABORTIFHUNG), 5000, &dwResult);
4769 else
4770 ::SendMessageTimeout(hwndTray, 0x505, 0, bDeskBand,
4771 (SMTO_BLOCK | SMTO_ABORTIFHUNG), 5000, &dwResult);
4772 }
4773 else
4774 {
4775 ret = FALSE;
4776 }
4777
4778 if (!(m_dwTipbarWndFlags & TIPBAR_CHILD) && bDeskBand)
4779 {
4780 KillTimer(7);
4781 SetTimer(7, g_uTimerElapseSYSCOLORCHANGED);
4782 }
4783
4784 return ret;
4785 }
4786
SetMoveRect(INT X,INT Y,INT nWidth,INT nHeight)4787 void CTipbarWnd::SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight)
4788 {
4789 if (m_dwTipbarWndFlags & TIPBAR_CHILD)
4790 {
4791 m_nWidth = nWidth;
4792 m_nHeight = nHeight;
4793 return;
4794 }
4795
4796 ++m_bInCallOn;
4797
4798 m_dwTipbarWndFlags |= TIPBAR_UPDATING;
4799
4800 m_X = X;
4801 m_Y = Y;
4802 m_CX = nWidth;
4803 m_CY = nHeight;
4804
4805 RECT rc;
4806 SIZE size = { 0, 0 };
4807 if (m_pWndFrame)
4808 {
4809 ::SetRect(&rc, 0, 0, nWidth - m_cxDlgFrameX2, nHeight - m_cyDlgFrameX2);
4810 m_pWndFrame->SetRect(&rc);
4811 m_pWndFrame->GetFrameSize(&size);
4812 }
4813
4814 if (m_pTipbarGripper)
4815 {
4816 if (m_dwTipbarWndFlags & TIPBAR_VERTICAL)
4817 {
4818 INT GripperWidth = GetGripperWidth();
4819 ::SetRect(&rc, size.cx, size.cy, nWidth - m_cxDlgFrameX2 - size.cx, size.cy + GripperWidth);
4820 }
4821 else
4822 {
4823 INT GripperWidth = GetGripperWidth();
4824 INT y1 = nHeight - m_cyDlgFrameX2 - size.cy;
4825 ::SetRect(&rc, size.cx, size.cy, size.cx + GripperWidth, y1);
4826 }
4827 m_pTipbarGripper->SetRect(&rc);
4828 }
4829
4830 --m_bInCallOn;
4831 }
4832
SetShowText(BOOL bShow)4833 void CTipbarWnd::SetShowText(BOOL bShow)
4834 {
4835 if (bShow)
4836 m_dwTipbarWndFlags |= TIPBAR_HIGHCONTRAST;
4837 else
4838 m_dwTipbarWndFlags &= ~TIPBAR_HIGHCONTRAST;
4839
4840 if (m_pFocusThread)
4841 OnThreadItemChange(m_pFocusThread->m_dwThreadId);
4842
4843 TerminateAllThreads(FALSE);
4844 }
4845
SetShowTrayIcon(BOOL bShow)4846 void CTipbarWnd::SetShowTrayIcon(BOOL bShow)
4847 {
4848 if (m_dwTipbarWndFlags & TIPBAR_TRAYICON)
4849 m_dwTipbarWndFlags &= ~TIPBAR_TRAYICON;
4850 else
4851 m_dwTipbarWndFlags |= TIPBAR_TRAYICON;
4852
4853 if ((m_dwTipbarWndFlags & TIPBAR_TRAYICON) && m_pFocusThread)
4854 {
4855 KillTimer(10);
4856 SetTimer(10, g_uTimerElapseMOVETOTRAY);
4857 }
4858 else if (g_pTrayIconWnd)
4859 {
4860 g_pTrayIconWnd->SetMainIcon(NULL);
4861 g_pTrayIconWnd->RemoveAllIcon(0);
4862 }
4863 }
4864
ShowContextMenu(POINT pt,LPCRECT prc,BOOL bFlag)4865 void CTipbarWnd::ShowContextMenu(POINT pt, LPCRECT prc, BOOL bFlag)
4866 {
4867 AddRef();
4868
4869 RECT rc;
4870 if (!prc)
4871 {
4872 rc = { pt.x, pt.y, pt.x, pt.y };
4873 prc = &rc;
4874 }
4875
4876 if (m_pFocusThread)
4877 {
4878 CUTBContextMenu *pContextMenu = new(cicNoThrow) CUTBContextMenu(this);
4879 if (pContextMenu)
4880 {
4881 if (pContextMenu->Init())
4882 {
4883 m_pThread = m_pFocusThread;
4884 StartModalInput(this, m_pFocusThread->m_dwThreadId);
4885
4886 m_pModalMenu = pContextMenu;
4887 DWORD dwCommandId = pContextMenu->ShowPopup(GetWindow(), pt, prc, bFlag);
4888 m_pModalMenu = NULL;
4889
4890 if (m_pThread)
4891 StopModalInput(m_pThread->m_dwThreadId);
4892
4893 m_pThread = NULL;
4894
4895 if (dwCommandId != (DWORD)-1)
4896 pContextMenu->SelectMenuItem(dwCommandId);
4897 }
4898
4899 delete pContextMenu;
4900 }
4901 }
4902
4903 Release();
4904 }
4905
StartBackToAlphaTimer()4906 void CTipbarWnd::StartBackToAlphaTimer()
4907 {
4908 UINT uTime = ::GetDoubleClickTime();
4909 ::SetTimer(m_hWnd, 3, 3 * uTime, NULL);
4910 }
4911
StartDoAccDefaultActionTimer(CTipbarItem * pTarget)4912 BOOL CTipbarWnd::StartDoAccDefaultActionTimer(CTipbarItem *pTarget)
4913 {
4914 if (!m_pTipbarAccessible)
4915 return FALSE;
4916 INT IDOfItem = m_pTipbarAccessible->GetIDOfItem(pTarget);
4917 m_nID = IDOfItem;
4918 if (!IDOfItem || IDOfItem == -1)
4919 return FALSE;
4920 KillTimer(11);
4921 SetTimer(11, g_uTimerElapseDOACCDEFAULTACTION);
4922 return TRUE;
4923 }
4924
StartModalInput(ITfLangBarEventSink * pSink,DWORD dwThreadId)4925 void CTipbarWnd::StartModalInput(ITfLangBarEventSink *pSink, DWORD dwThreadId)
4926 {
4927 if (!m_pLangBarMgr)
4928 return;
4929
4930 m_pLangBarMgr->SetModalInput(pSink, dwThreadId, 0);
4931 if (g_pTrayIconWnd)
4932 m_pLangBarMgr->SetModalInput(pSink, g_pTrayIconWnd->m_dwTrayWndThreadId, 0);
4933
4934 DWORD dwCurThreadId = ::GetCurrentThreadId();
4935 m_pLangBarMgr->SetModalInput(pSink, dwCurThreadId, 1);
4936 }
4937
StopModalInput(DWORD dwThreadId)4938 void CTipbarWnd::StopModalInput(DWORD dwThreadId)
4939 {
4940 if (!m_pLangBarMgr)
4941 return;
4942
4943 m_pLangBarMgr->SetModalInput(NULL, dwThreadId, 0);
4944 if (g_pTrayIconWnd)
4945 m_pLangBarMgr->SetModalInput(NULL, g_pTrayIconWnd->m_dwTrayWndThreadId, 0);
4946
4947 DWORD dwCurThreadId = ::GetCurrentThreadId();
4948 m_pLangBarMgr->SetModalInput(NULL, dwCurThreadId, 0);
4949 }
4950
MyWaitForInputIdle(DWORD dwThreadId,DWORD dwMilliseconds)4951 LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds)
4952 {
4953 if (g_pTipbarWnd && (g_pTipbarWnd->m_dwShowType & TF_SFT_DESKBAND))
4954 return 0;
4955
4956 if (TF_IsInMarshaling(dwThreadId))
4957 return STATUS_TIMEOUT;
4958
4959 DWORD dwFlags1 = 0, dwFlags2 = 0;
4960 if (!TF_GetThreadFlags(dwThreadId, &dwFlags1, &dwFlags2, NULL) && dwFlags2)
4961 return -1;
4962
4963 return TF_CheckThreadInputIdle(dwThreadId, dwMilliseconds);
4964 }
4965
_CreateThread(DWORD dwThreadId)4966 CTipbarThread *CTipbarWnd::_CreateThread(DWORD dwThreadId)
4967 {
4968 CTipbarThread *pTarget = _FindThread(dwThreadId);
4969 if (pTarget)
4970 return pTarget;
4971
4972 MyWaitForInputIdle(dwThreadId, 2000);
4973
4974 pTarget = new(cicNoThrow) CTipbarThread(this);
4975 if (!pTarget)
4976 return NULL;
4977
4978 AddThreadToThreadCreatingList(pTarget);
4979
4980 HRESULT hr = pTarget->Init(dwThreadId);
4981
4982 RemoveThredFromThreadCreatingList(pTarget);
4983
4984 if (SUCCEEDED(hr) && !m_Threads.Add(pTarget))
4985 {
4986 pTarget->_UninitItemList(TRUE);
4987 pTarget->m_pTipbarWnd = NULL;
4988 pTarget->_Release();
4989 return NULL;
4990 }
4991
4992 return pTarget;
4993 }
4994
_FindThread(DWORD dwThreadId)4995 CTipbarThread *CTipbarWnd::_FindThread(DWORD dwThreadId)
4996 {
4997 if (g_bWinLogon)
4998 return NULL;
4999
5000 CTipbarThread *pTarget = NULL;
5001 for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem)
5002 {
5003 CTipbarThread *pThread = m_Threads[iItem];
5004 if (pThread && pThread->m_dwThreadId == dwThreadId)
5005 {
5006 pTarget = pThread;
5007 break;
5008 }
5009 }
5010
5011 if (!pTarget)
5012 return NULL;
5013
5014 DWORD dwFlags1, dwFlags2, dwFlags3;
5015 TF_GetThreadFlags(dwThreadId, &dwFlags1, &dwFlags2, &dwFlags3);
5016
5017 if (!dwFlags2 || (dwFlags2 != pTarget->m_dwFlags2) || (dwFlags3 != pTarget->m_dwFlags3))
5018 {
5019 OnThreadTerminateInternal(dwThreadId);
5020 return NULL;
5021 }
5022
5023 return pTarget;
5024 }
5025
EnsureFocusThread()5026 void CTipbarWnd::EnsureFocusThread()
5027 {
5028 if (m_pFocusThread || (m_dwTipbarWndFlags & (TIPBAR_TOOLBARENDED | TIPBAR_ENSURING)))
5029 return;
5030
5031 m_dwTipbarWndFlags |= TIPBAR_ENSURING;
5032
5033 HWND hwndFore = ::GetForegroundWindow();
5034 if (!hwndFore)
5035 return;
5036
5037 DWORD dwThreadId = ::GetWindowThreadProcessId(hwndFore, NULL);
5038 if (dwThreadId)
5039 OnSetFocus(dwThreadId);
5040
5041 m_dwTipbarWndFlags &= ~TIPBAR_ENSURING;
5042 }
5043
SetFocusThread(CTipbarThread * pFocusThread)5044 HRESULT CTipbarWnd::SetFocusThread(CTipbarThread *pFocusThread)
5045 {
5046 if (pFocusThread == m_pFocusThread)
5047 return S_OK;
5048
5049 DWORD dwThreadId = ::GetCurrentThreadId();
5050 DestroyOverScreenSizeBalloon();
5051
5052 if (m_pFocusThread)
5053 {
5054 m_pFocusThread->SetFocus(NULL);
5055 ::AttachThreadInput(dwThreadId, m_pFocusThread->m_dwThreadId, FALSE);
5056 }
5057
5058 m_dwTipbarWndFlags &= ~TIPBAR_ATTACHED;
5059 m_pFocusThread = pFocusThread;
5060 return S_OK;
5061 }
5062
AttachFocusThread()5063 HRESULT CTipbarWnd::AttachFocusThread()
5064 {
5065 if (m_dwTipbarWndFlags & TIPBAR_ATTACHED)
5066 return S_FALSE;
5067
5068 if (m_pFocusThread)
5069 {
5070 DWORD dwThreadId = ::GetCurrentThreadId();
5071 ::AttachThreadInput(dwThreadId, m_pFocusThread->m_dwThreadId, TRUE);
5072 m_dwTipbarWndFlags |= TIPBAR_ATTACHED;
5073 }
5074
5075 return S_OK;
5076 }
5077
RestoreLastFocus(DWORD * pdwThreadId,BOOL fPrev)5078 void CTipbarWnd::RestoreLastFocus(DWORD *pdwThreadId, BOOL fPrev)
5079 {
5080 if (m_pLangBarMgr)
5081 m_pLangBarMgr->RestoreLastFocus(pdwThreadId, fPrev);
5082 }
5083
CleanUpThreadPointer(CTipbarThread * pThread,BOOL bRemove)5084 void CTipbarWnd::CleanUpThreadPointer(CTipbarThread *pThread, BOOL bRemove)
5085 {
5086 if (bRemove)
5087 {
5088 ssize_t iItem = m_Threads.Find(pThread);
5089 if (iItem >= 0)
5090 m_Threads.Remove(iItem);
5091 }
5092
5093 if (pThread == m_pFocusThread)
5094 SetFocusThread(NULL);
5095
5096 if (pThread == m_pThread)
5097 m_pThread = NULL;
5098
5099 if (pThread == m_pUnknownThread)
5100 m_pUnknownThread = NULL;
5101 }
5102
TerminateAllThreads(BOOL bFlag)5103 void CTipbarWnd::TerminateAllThreads(BOOL bFlag)
5104 {
5105 const size_t cItems = m_Threads.size();
5106
5107 DWORD *pdwThreadIds = new(cicNoThrow) DWORD[cItems];
5108 if (!pdwThreadIds)
5109 return;
5110
5111 for (size_t iItem = 0; iItem < cItems; ++iItem)
5112 {
5113 pdwThreadIds[iItem] = 0;
5114 CTipbarThread* pThread = m_Threads[iItem];
5115 if (pThread && (bFlag || (pThread != m_pFocusThread)))
5116 {
5117 pdwThreadIds[iItem] = pThread->m_dwThreadId;
5118 }
5119 }
5120
5121 for (size_t iItem = 0; iItem < cItems; ++iItem)
5122 {
5123 if (pdwThreadIds[iItem])
5124 OnThreadTerminateInternal(pdwThreadIds[iItem]);
5125 }
5126
5127 delete[] pdwThreadIds;
5128 }
5129
QueryInterface(REFIID riid,void ** ppvObj)5130 STDMETHODIMP CTipbarWnd::QueryInterface(REFIID riid, void **ppvObj)
5131 {
5132 static const QITAB c_tab[] =
5133 {
5134 QITABENT(CTipbarWnd, ITfLangBarEventSink),
5135 QITABENT(CTipbarWnd, ITfLangBarEventSink_P),
5136 { NULL }
5137 };
5138 return ::QISearch(this, c_tab, riid, ppvObj);
5139 }
5140
STDMETHODIMP_(ULONG)5141 STDMETHODIMP_(ULONG) CTipbarWnd::AddRef()
5142 {
5143 return ++m_cRefs;
5144 }
5145
STDMETHODIMP_(ULONG)5146 STDMETHODIMP_(ULONG) CTipbarWnd::Release()
5147 {
5148 if (--m_cRefs == 0)
5149 {
5150 delete this;
5151 return 0;
5152 }
5153 return m_cRefs;
5154 }
5155
5156 /// @unimplemented
OnSetFocus(DWORD dwThreadId)5157 STDMETHODIMP CTipbarWnd::OnSetFocus(DWORD dwThreadId)
5158 {
5159 return E_NOTIMPL;
5160 }
5161
OnThreadTerminate(DWORD dwThreadId)5162 STDMETHODIMP CTipbarWnd::OnThreadTerminate(DWORD dwThreadId)
5163 {
5164 HRESULT hr;
5165 ++m_bInCallOn;
5166 AddRef();
5167 {
5168 hr = OnThreadTerminateInternal(dwThreadId);
5169 if (!m_pFocusThread)
5170 EnsureFocusThread();
5171 }
5172 --m_bInCallOn;
5173 Release();
5174 return hr;
5175 }
5176
OnThreadTerminateInternal(DWORD dwThreadId)5177 HRESULT CTipbarWnd::OnThreadTerminateInternal(DWORD dwThreadId)
5178 {
5179 for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem)
5180 {
5181 CTipbarThread *pThread = m_Threads[iItem];
5182 if (pThread && pThread->m_dwThreadId == dwThreadId)
5183 {
5184 m_Threads.Remove(iItem);
5185 pThread->RemoveUIObjs();
5186 CleanUpThreadPointer(pThread, FALSE);
5187 pThread->_UninitItemList(TRUE);
5188 pThread->m_pTipbarWnd = NULL;
5189 pThread->_Release();
5190 break;
5191 }
5192 }
5193
5194 return S_OK;
5195 }
5196
OnThreadItemChange(DWORD dwThreadId)5197 STDMETHODIMP CTipbarWnd::OnThreadItemChange(DWORD dwThreadId)
5198 {
5199 if (m_dwTipbarWndFlags & TIPBAR_TOOLBARENDED)
5200 return S_OK;
5201 if (!(m_dwTipbarWndFlags & TIPBAR_CHILD) && (m_dwShowType & TF_SFT_DESKBAND))
5202 return S_OK;
5203
5204 CTipbarThread *pThread = _FindThread(dwThreadId);
5205 if (pThread)
5206 {
5207 if ((!m_dwUnknown23 || m_dwUnknown23 == dwThreadId) && pThread == m_pFocusThread)
5208 {
5209 KillOnTheadItemChangeTimer();
5210 m_dwChangingThreadId = dwThreadId;
5211 KillTimer(6);
5212 SetTimer(4, g_uTimerElapseONTHREADITEMCHANGE);
5213 }
5214 else
5215 {
5216 pThread->m_dwUnknown34 |= 0x1;
5217 }
5218 }
5219 else
5220 {
5221 for (size_t iItem = 0; iItem < m_ThreadCreatingList.size(); ++iItem)
5222 {
5223 CTipbarThread *pItem = m_ThreadCreatingList[iItem];
5224 if (pItem && pItem->m_dwThreadId == dwThreadId)
5225 {
5226 pItem->m_dwUnknown34 |= 0x1;
5227 }
5228 }
5229 }
5230
5231 return S_OK;
5232 }
5233
OnModalInput(DWORD dwThreadId,UINT uMsg,WPARAM wParam,LPARAM lParam)5234 STDMETHODIMP CTipbarWnd::OnModalInput(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam)
5235 {
5236 switch (uMsg)
5237 {
5238 case WM_NCLBUTTONDOWN:
5239 case WM_NCRBUTTONDOWN:
5240 case WM_NCMBUTTONDOWN:
5241 case WM_LBUTTONUP:
5242 case WM_RBUTTONUP:
5243 case WM_MBUTTONUP:
5244 break;
5245
5246 case WM_NCLBUTTONUP:
5247 case WM_NCRBUTTONUP:
5248 case WM_NCMBUTTONUP:
5249 if (m_pThread)
5250 {
5251 CUTBMenuWnd *pMenuUI = m_pModalMenu->m_pMenuUI;
5252 if (pMenuUI)
5253 {
5254 HWND hWnd = *pMenuUI;
5255 if (hWnd)
5256 {
5257 POINT pt = { (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) };
5258 ::ScreenToClient(hWnd, &pt);
5259 uMsg += WM_LBUTTONUP - WM_NCLBUTTONUP;
5260 ::PostMessage(m_hWnd, uMsg, wParam, MAKELPARAM(pt.x, pt.y));
5261 }
5262 }
5263 }
5264 break;
5265
5266 default:
5267 {
5268 if (uMsg == WM_KEYDOWN || uMsg == WM_KEYUP)
5269 {
5270 if (m_pThread)
5271 m_pModalMenu->PostKey(uMsg == WM_KEYUP, wParam, lParam);
5272 }
5273 else
5274 {
5275 CancelMenu();
5276 }
5277 break;
5278 }
5279 }
5280
5281 return 0;
5282 }
5283
5284 /// @unimplemented
ShowFloating(DWORD dwFlags)5285 STDMETHODIMP CTipbarWnd::ShowFloating(DWORD dwFlags)
5286 {
5287 return E_NOTIMPL;
5288 }
5289
GetItemFloatingRect(DWORD dwThreadId,REFGUID rguid,RECT * prc)5290 STDMETHODIMP CTipbarWnd::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
5291 {
5292 if (m_dwTipbarWndFlags & TIPBAR_TRAYICON)
5293 return E_UNEXPECTED;
5294
5295 if (!m_pFocusThread || (m_pFocusThread->m_dwThreadId != dwThreadId))
5296 return E_FAIL;
5297
5298 for (size_t iItem = 0; iItem < m_pFocusThread->m_UIObjects.size(); ++iItem)
5299 {
5300 CTipbarItem* pItem = m_pFocusThread->m_UIObjects[iItem];
5301 if (pItem)
5302 {
5303 if ((pItem->m_dwItemFlags & 0x8) && IsEqualGUID(pItem->m_ItemInfo.guidItem, rguid))
5304 {
5305 pItem->OnUnknown57(prc);
5306 return S_OK;
5307 }
5308 }
5309 }
5310
5311 return E_FAIL;
5312 }
5313
5314 /// @unimplemented
OnLangBarUpdate(TfLBIClick click,BOOL bFlag)5315 STDMETHODIMP CTipbarWnd::OnLangBarUpdate(TfLBIClick click, BOOL bFlag)
5316 {
5317 return E_NOTIMPL;
5318 }
5319
STDMETHODIMP_(BSTR)5320 STDMETHODIMP_(BSTR) CTipbarWnd::GetAccName()
5321 {
5322 WCHAR szText[256];
5323 ::LoadStringW(g_hInst, IDS_LANGUAGEBAR, szText, _countof(szText));
5324 return ::SysAllocString(szText);
5325 }
5326
STDMETHODIMP_(void)5327 STDMETHODIMP_(void) CTipbarWnd::GetAccLocation(LPRECT lprc)
5328 {
5329 GetRect(lprc);
5330 }
5331
STDMETHODIMP_(void)5332 STDMETHODIMP_(void) CTipbarWnd::PaintObject(HDC hDC, LPCRECT prc)
5333 {
5334 if (m_dwTipbarWndFlags & TIPBAR_UPDATING)
5335 {
5336 Move(m_X, m_Y, m_CX, m_CY);
5337 m_dwTipbarWndFlags &= ~TIPBAR_UPDATING;
5338 }
5339
5340 if (!m_pFocusThread || !m_pFocusThread->IsDirtyItem())
5341 {
5342 m_pFocusThread->CallOnUpdateHandler();
5343 if (g_pTipbarWnd)
5344 CUIFWindow::PaintObject(hDC, prc);
5345 }
5346 }
5347
STDMETHODIMP_(DWORD)5348 STDMETHODIMP_(DWORD) CTipbarWnd::GetWndStyle()
5349 {
5350 return CUIFWindow::GetWndStyle() & ~WS_BORDER;
5351 }
5352
STDMETHODIMP_(void)5353 STDMETHODIMP_(void) CTipbarWnd::Move(INT x, INT y, INT nWidth, INT nHeight)
5354 {
5355 CUIFWindow::Move(x, y, nWidth, nHeight);
5356 }
5357
STDMETHODIMP_(void)5358 STDMETHODIMP_(void) CTipbarWnd::OnMouseOutFromWindow(LONG x, LONG y)
5359 {
5360 StartBackToAlphaTimer();
5361 if ((m_dwTipbarWndFlags & 0x40) && (m_dwTipbarWndFlags & 0x80))
5362 SetTimer(2, g_uTimerElapseSTUBEND);
5363 }
5364
5365 /// @unimplemented
STDMETHODIMP_(void)5366 STDMETHODIMP_(void) CTipbarWnd::OnCreate(HWND hWnd)
5367 {
5368 }
5369
STDMETHODIMP_(void)5370 STDMETHODIMP_(void) CTipbarWnd::OnDestroy(HWND hWnd)
5371 {
5372 CancelMenu();
5373
5374 if (m_pTipbarAccessible)
5375 m_pTipbarAccessible->NotifyWinEvent(EVENT_OBJECT_DESTROY, GetAccItem());
5376
5377 OnTerminateToolbar();
5378 if (m_pTipbarAccessible)
5379 {
5380 m_pTipbarAccessible->ClearAccItems();
5381 m_pTipbarAccessible->Release();
5382 m_pTipbarAccessible = NULL;
5383 }
5384
5385 m_coInit.CoUninit();
5386
5387 if (m_pLangBarMgr)
5388 m_pLangBarMgr->UnAdviseEventSink(m_dwSinkCookie);
5389 }
5390
5391 /// @unimplemented
STDMETHODIMP_(void)5392 STDMETHODIMP_(void) CTipbarWnd::OnTimer(WPARAM wParam)
5393 {
5394 AddRef();
5395 switch (wParam)
5396 {
5397 case 1:
5398 KillTimer(1);
5399 MoveToStub(FALSE);
5400 break;
5401 case 2:
5402 KillTimer(2);
5403 MoveToStub(TRUE);
5404 break;
5405 case 3:
5406 KillTimer(3);
5407 SetAlpha((BYTE)m_dwAlphaValue, TRUE);
5408 break;
5409 case 4:
5410 {
5411 LONG status = MyWaitForInputIdle(m_dwChangingThreadId, 2000);
5412 if (status)
5413 {
5414 if (status != STATUS_TIMEOUT)
5415 {
5416 KillTimer(4);
5417 m_dwChangingThreadId = 0;
5418 }
5419 }
5420 else if (!m_pThread)
5421 {
5422 KillTimer(4);
5423 DWORD dwOldThreadId = m_dwChangingThreadId;
5424 m_dwChangingThreadId = 0;
5425 OnThreadItemChangeInternal(dwOldThreadId);
5426 }
5427 break;
5428 }
5429 case 5:
5430 KillTimer(5);
5431 ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
5432 break;
5433 case 6:
5434 KillTimer(6);
5435 if (m_pFocusThread)
5436 {
5437 if (m_pFocusThread->m_dwThreadId != m_dwChangingThreadId &&
5438 !m_pFocusThread->CallOnUpdateHandler())
5439 {
5440 if (m_pFocusThread)
5441 OnThreadItemChange(m_pFocusThread->m_dwThreadId);
5442 }
5443 }
5444 break;
5445 case 7:
5446 {
5447 DWORD dwThreadId = 0;
5448 if (KillTimer(7))
5449 {
5450 if (m_pFocusThread)
5451 dwThreadId = m_pFocusThread->m_dwThreadId;
5452
5453 TerminateAllThreads(TRUE);
5454 UpdateVerticalFont();
5455
5456 if (dwThreadId)
5457 OnSetFocus(dwThreadId);
5458
5459 InitMetrics();
5460 // FIXME: CTipbarCtrlButtonHolder
5461
5462 InitHighContrast();
5463 SetAlpha(0xFF, TRUE);
5464 ::RedrawWindow(m_hWnd, NULL, NULL, (RDW_FRAME | RDW_UPDATENOW | RDW_INVALIDATE));
5465 }
5466 break;
5467 }
5468 case 8:
5469 KillTimer(8);
5470 UpdateUI(NULL);
5471 break;
5472 case 9:
5473 KillTimer(9);
5474 //FIXME
5475 if (m_pUnknownThread == m_pFocusThread)
5476 Show(!!(m_dwUnknown23_5[3] & 0x80000000));
5477 m_pUnknownThread = NULL;
5478 if ((m_dwUnknown23_5[3] & 0x2))
5479 ShowOverScreenSizeBalloon();
5480 break;
5481 case 10:
5482 KillTimer(10);
5483 MoveToTray();
5484 break;
5485 case 11:
5486 KillTimer(11);
5487 if (m_pTipbarAccessible)
5488 {
5489 if (m_nID)
5490 {
5491 m_pTipbarAccessible->DoDefaultActionReal(m_nID);
5492 m_nID = 0;
5493 }
5494 }
5495 break;
5496 case 12:
5497 KillTimer(12);
5498 AdjustPosOnDisplayChange();
5499 break;
5500 case 13:
5501 #ifdef ENABLE_DESKBAND
5502 if (!m_pDeskBand || !m_pDeskBand->m_dwUnknown19)
5503 {
5504 KillTimer(13);
5505 if (!m_pFocusThread)
5506 EnsureFocusThread();
5507 }
5508 #endif
5509 break;
5510 case 14:
5511 if (SetLangBand(TRUE, TRUE))
5512 {
5513 m_dwShowType = TF_SFT_DESKBAND;
5514 KillTimer(14);
5515 }
5516 break;
5517 default:
5518 {
5519 if (10000 <= wParam && wParam < 10050)
5520 {
5521 auto *pItem = m_LangBarItemList.GetItemStateFromTimerId(wParam);
5522 if (pItem)
5523 {
5524 auto& clsid = pItem->m_clsid;
5525 m_LangBarItemList.SetDemoteLevel(pItem->m_clsid, 2);
5526 if (m_pFocusThread)
5527 {
5528 auto *pThreadItem = m_pFocusThread->GetItem(clsid);
5529 if (pThreadItem)
5530 pThreadItem->AddRemoveMeToUI(FALSE);
5531 }
5532 }
5533 }
5534 break;
5535 }
5536 }
5537
5538 Release();
5539 }
5540
STDMETHODIMP_(void)5541 STDMETHODIMP_(void) CTipbarWnd::OnSysColorChange()
5542 {
5543 KillTimer(7);
5544 SetTimer(7, g_uTimerElapseSYSCOLORCHANGED);
5545 }
5546
OnTerminateToolbar()5547 void CTipbarWnd::OnTerminateToolbar()
5548 {
5549 m_dwTipbarWndFlags |= TIPBAR_TOOLBARENDED;
5550 DestroyOverScreenSizeBalloon();
5551 TerminateAllThreads(TRUE);
5552 if (!(m_dwTipbarWndFlags & TIPBAR_CHILD))
5553 SavePosition();
5554 }
5555
STDMETHODIMP_(void)5556 STDMETHODIMP_(void) CTipbarWnd::OnEndSession(HWND hWnd, WPARAM wParam, LPARAM lParam)
5557 {
5558 if (!g_bWinLogon)
5559 OnTerminateToolbar();
5560
5561 if (wParam) // End session?
5562 {
5563 if (lParam & ENDSESSION_LOGOFF)
5564 {
5565 KillTimer(9);
5566 Show(FALSE);
5567 }
5568 else
5569 {
5570 OnTerminateToolbar();
5571
5572 AddRef();
5573 ::DestroyWindow(hWnd);
5574 Release();
5575 }
5576 }
5577 }
5578
STDMETHODIMP_(void)5579 STDMETHODIMP_(void) CTipbarWnd::OnUser(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5580 {
5581 if (uMsg == WM_USER + 1)
5582 {
5583 POINT pt = { (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) };
5584 ::ClientToScreen(m_hWnd, &pt);
5585 ShowContextMenu(pt, NULL, TRUE);
5586 }
5587 else if (uMsg == g_wmTaskbarCreated)
5588 {
5589 m_ShellWndThread.clear();
5590 }
5591 }
5592
STDMETHODIMP_(LRESULT)5593 STDMETHODIMP_(LRESULT)
5594 CTipbarWnd::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5595 {
5596 if (m_pFocusThread)
5597 {
5598 for (size_t iItem = 0; iItem < m_pFocusThread->m_UIObjects.size(); ++iItem)
5599 {
5600 CTipbarItem *pItem = m_pFocusThread->m_UIObjects[iItem];
5601 if (pItem)
5602 pItem->OnUnknown44();
5603 }
5604 }
5605
5606 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
5607 }
5608
STDMETHODIMP_(LRESULT)5609 STDMETHODIMP_(LRESULT)
5610 CTipbarWnd::OnWindowPosChanging(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5611 {
5612 LPWINDOWPOS pWP = (LPWINDOWPOS)lParam;
5613 if (!(pWP->flags & SWP_NOZORDER))
5614 {
5615 if (!m_pThread && (!m_pToolTip || !m_pToolTip->m_bShowToolTip))
5616 pWP->hwndInsertAfter = NULL;
5617 }
5618 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
5619 }
5620
STDMETHODIMP_(LRESULT)5621 STDMETHODIMP_(LRESULT)
5622 CTipbarWnd::OnShowWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5623 {
5624 if (m_pTipbarAccessible)
5625 {
5626 if (wParam) // Show?
5627 {
5628 m_pTipbarAccessible->NotifyWinEvent(EVENT_OBJECT_SHOW, GetAccItem());
5629 m_pTipbarAccessible->NotifyWinEvent(EVENT_OBJECT_FOCUS, GetAccItem());
5630 }
5631 else
5632 {
5633 m_pTipbarAccessible->NotifyWinEvent(EVENT_OBJECT_HIDE, GetAccItem());
5634 }
5635 }
5636 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
5637 }
5638
STDMETHODIMP_(LRESULT)5639 STDMETHODIMP_(LRESULT)
5640 CTipbarWnd::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5641 {
5642 if (!wParam || wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETHIGHCONTRAST)
5643 {
5644 KillTimer(7);
5645 SetTimer(7, g_uTimerElapseSYSCOLORCHANGED);
5646 }
5647 return 0;
5648 }
5649
STDMETHODIMP_(LRESULT)5650 STDMETHODIMP_(LRESULT)
5651 CTipbarWnd::OnDisplayChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5652 {
5653 if (!(m_dwTipbarWndFlags & TIPBAR_CHILD))
5654 {
5655 KillTimer(12);
5656 SetTimer(12, g_uTimerElapseDISPLAYCHANGE);
5657 }
5658 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
5659 }
5660
STDMETHODIMP_(HRESULT)5661 STDMETHODIMP_(HRESULT)
5662 CTipbarWnd::OnGetObject(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5663 {
5664 if (lParam != -4)
5665 return S_OK;
5666 if (!m_pTipbarAccessible)
5667 return E_OUTOFMEMORY;
5668
5669 if (m_pTipbarAccessible->m_bInitialized)
5670 return m_pTipbarAccessible->CreateRefToAccObj(wParam);
5671
5672 HRESULT hr = S_OK;
5673 if (SUCCEEDED(m_coInit.EnsureCoInit()))
5674 {
5675 hr = m_pTipbarAccessible->Initialize();
5676 if (FAILED(hr))
5677 {
5678 m_pTipbarAccessible->Release();
5679 m_pTipbarAccessible = NULL;
5680 return hr;
5681 }
5682
5683 m_pTipbarAccessible->NotifyWinEvent(EVENT_OBJECT_CREATE, GetAccItem());
5684 return m_pTipbarAccessible->CreateRefToAccObj(wParam);
5685 }
5686
5687 return hr;
5688 }
5689
STDMETHODIMP_(BOOL)5690 STDMETHODIMP_(BOOL) CTipbarWnd::OnEraseBkGnd(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5691 {
5692 return TRUE;
5693 }
5694
STDMETHODIMP_(void)5695 STDMETHODIMP_(void) CTipbarWnd::OnThemeChanged(HWND hWnd, WPARAM wParam, LPARAM lParam)
5696 {
5697 CUIFWindow::OnThemeChanged(hWnd, wParam, lParam);
5698 }
5699
STDMETHODIMP_(void)5700 STDMETHODIMP_(void) CTipbarWnd::UpdateUI(LPCRECT prc)
5701 {
5702 KillTimer(8);
5703
5704 if (m_dwChangingThreadId || m_bInCallOn || (m_pFocusThread && m_pFocusThread->IsDirtyItem()))
5705 {
5706 SetTimer(8, g_uTimerElapseUPDATEUI);
5707 return;
5708 }
5709
5710 if (m_dwTipbarWndFlags & TIPBAR_UPDATING)
5711 {
5712 ++m_bInCallOn;
5713 Move(m_X, m_Y, m_CX, m_CY);
5714 m_dwTipbarWndFlags &= ~TIPBAR_UPDATING;
5715 --m_bInCallOn;
5716 }
5717
5718 CUIFWindow::UpdateUI(NULL);
5719 }
5720
5721 /// @unimplemented
STDMETHODIMP_(void)5722 STDMETHODIMP_(void) CTipbarWnd::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
5723 {
5724 }
5725
5726 /***********************************************************************
5727 * CTipbarThread
5728 */
5729
CTipbarThread(CTipbarWnd * pTipbarWnd)5730 CTipbarThread::CTipbarThread(CTipbarWnd *pTipbarWnd)
5731 {
5732 m_pTipbarWnd = pTipbarWnd;
5733 m_dwThreadId = 0;
5734 m_pLangBarItemMgr = NULL;
5735 m_cRefs = 1;
5736 }
5737
~CTipbarThread()5738 CTipbarThread::~CTipbarThread()
5739 {
5740 if (m_pTipbarWnd)
5741 {
5742 RemoveUIObjs();
5743 m_pTipbarWnd->CleanUpThreadPointer(this, 1);
5744 }
5745
5746 _UninitItemList(1);
5747
5748 if (m_pLangBarItemMgr)
5749 {
5750 m_pLangBarItemMgr->Release();
5751 m_pLangBarItemMgr = NULL;
5752 }
5753 }
5754
Init(DWORD dwThreadId)5755 HRESULT CTipbarThread::Init(DWORD dwThreadId)
5756 {
5757 m_dwThreadId = dwThreadId;
5758 if (!TF_GetThreadFlags(dwThreadId, &m_dwFlags1, &m_dwFlags2, &m_dwFlags3))
5759 return E_FAIL;
5760 if (m_dwFlags1 & 0x8)
5761 return S_OK;
5762 return m_pTipbarWnd->m_pLangBarMgr->GetThreadLangBarItemMgr(m_dwThreadId,
5763 &m_pLangBarItemMgr,
5764 &dwThreadId);
5765 }
5766
5767 /// @unimplemented
InitItemList()5768 HRESULT CTipbarThread::InitItemList()
5769 {
5770 return E_NOTIMPL;
5771 }
5772
_UninitItemList(BOOL bUnAdvise)5773 HRESULT CTipbarThread::_UninitItemList(BOOL bUnAdvise)
5774 {
5775 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5776 {
5777 CTipbarItem* pItem = m_UIObjects[iItem];
5778 if (pItem)
5779 pItem->m_dwItemFlags |= 0x10;
5780 }
5781
5782 HRESULT hr = S_OK;
5783 if (bUnAdvise)
5784 {
5785 if (m_dwThreadId == ::GetCurrentThreadId() || !MyWaitForInputIdle(m_dwThreadId, 2000))
5786 hr = _UnadviseItemsSink();
5787 }
5788
5789 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5790 {
5791 CTipbarItem* pItem = m_UIObjects[iItem];
5792 if (pItem)
5793 {
5794 if (m_pTipbarWnd)
5795 pItem->OnUnknown47(m_pTipbarWnd->GetWindow());
5796
5797 pItem->ClearConnections();
5798
5799 if (m_pTipbarWnd)
5800 pItem->OnUnknown50();
5801 else
5802 pItem->OnUnknown51();
5803
5804 pItem->OnUnknown59();
5805 pItem->OnUnknown42();
5806 }
5807 }
5808
5809 m_UIObjects.clear();
5810
5811 RemoveAllSeparators();
5812
5813 return hr;
5814 }
5815
AddAllSeparators()5816 void CTipbarThread::AddAllSeparators()
5817 {
5818 for (size_t iItem = 0; iItem < m_Separators.size(); ++iItem)
5819 {
5820 CUIFObject *pItem = m_Separators[iItem];
5821 if (pItem)
5822 m_pTipbarWnd->AddUIObj(pItem);
5823 }
5824 }
5825
RemoveAllSeparators()5826 void CTipbarThread::RemoveAllSeparators()
5827 {
5828 for (size_t iItem = 0; iItem < m_Separators.size(); ++iItem)
5829 {
5830 CUIFObject *pItem = m_Separators[iItem];
5831 if (pItem)
5832 {
5833 if (m_pTipbarWnd)
5834 m_pTipbarWnd->RemoveUIObj(pItem);
5835 delete pItem;
5836 }
5837 }
5838 m_Separators.clear();
5839 }
5840
AddUIObjs()5841 void CTipbarThread::AddUIObjs()
5842 {
5843 _AddRef();
5844
5845 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5846 {
5847 CTipbarItem* pItem = m_UIObjects[iItem];
5848 if (pItem && (pItem->m_dwItemFlags & 0x8))
5849 {
5850 pItem->OnUnknown46(m_pTipbarWnd ? m_pTipbarWnd->GetWindow() : NULL);
5851 }
5852 }
5853
5854 AddAllSeparators();
5855 MyMoveWnd(0, 0);
5856
5857 _Release();
5858 }
5859
RemoveUIObjs()5860 void CTipbarThread::RemoveUIObjs()
5861 {
5862 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5863 {
5864 CTipbarItem* pItem = m_UIObjects[iItem];
5865 if (pItem)
5866 {
5867 pItem->OnUnknown47(m_pTipbarWnd ? m_pTipbarWnd->GetWindow() : NULL);
5868 }
5869 }
5870 RemoveAllSeparators();
5871 }
5872
GetItem(REFCLSID rclsid)5873 CTipbarItem *CTipbarThread::GetItem(REFCLSID rclsid)
5874 {
5875 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5876 {
5877 auto *pItem = m_UIObjects[iItem];
5878 if (pItem && IsEqualCLSID(pItem->m_ItemInfo.guidItem, rclsid))
5879 return pItem;
5880 }
5881 return NULL;
5882 }
5883
GetTextSize(BSTR bstr,LPSIZE pSize)5884 void CTipbarThread::GetTextSize(BSTR bstr, LPSIZE pSize)
5885 {
5886 HWND hWnd = *m_pTipbarWnd->GetWindow();
5887
5888 HGDIOBJ hFontOld = NULL;
5889
5890 HDC hDC = ::GetDC(hWnd);
5891 if (FAILED(m_pTipbarWnd->EnsureThemeData(*m_pTipbarWnd->GetWindow())))
5892 {
5893 HFONT hFont = m_pTipbarWnd->m_hFont;
5894 if (hFont)
5895 hFontOld = ::SelectObject(hDC, hFont);
5896 INT cch = ::SysStringLen(bstr);
5897 ::GetTextExtentPoint32W(hDC, bstr, cch, pSize);
5898 if (hFontOld)
5899 ::SelectObject(hDC, hFontOld);
5900 }
5901 else
5902 {
5903 CUIFTheme theme;
5904 theme.m_iPartId = 1;
5905 theme.m_iStateId = 0;
5906 theme.m_pszClassList = L"TOOLBAR";
5907
5908 HFONT hFont = NULL;
5909
5910 if (SUCCEEDED(theme.InternalOpenThemeData(hWnd)))
5911 {
5912 LOGFONTW lf;
5913 if (SUCCEEDED(::GetThemeFont(theme.m_hTheme, NULL, theme.m_iPartId, 0, 210, &lf)))
5914 {
5915 hFont = ::CreateFontIndirectW(&lf);
5916 if (hFont)
5917 hFontOld = ::SelectObject(hDC, hFont);
5918 }
5919
5920 RECT rc;
5921 INT cch = ::SysStringLen(bstr);
5922 ::GetThemeTextExtent(theme.m_hTheme, hDC, theme.m_iPartId, 0, bstr, cch, 0, NULL, &rc);
5923
5924 pSize->cx = rc.right;
5925 pSize->cy = rc.bottom;
5926 }
5927
5928 if (hFontOld)
5929 ::SelectObject(hDC, hFontOld);
5930 if (hFont)
5931 ::DeleteObject(hFont);
5932 }
5933
5934 ::ReleaseDC(hWnd, hDC);
5935 }
5936
IsDirtyItem()5937 DWORD CTipbarThread::IsDirtyItem()
5938 {
5939 DWORD dwDirty = 0;
5940 for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
5941 {
5942 CTipbarItem* pItem = m_UIObjects[iItem];
5943 if (pItem)
5944 dwDirty |= pItem->m_dwDirty;
5945 }
5946 return dwDirty;
5947 }
5948
IsFocusThread()5949 BOOL CTipbarThread::IsFocusThread()
5950 {
5951 if (!m_pTipbarWnd)
5952 return FALSE;
5953 return this == m_pTipbarWnd->m_pFocusThread;
5954 }
5955
IsVertical()5956 BOOL CTipbarThread::IsVertical()
5957 {
5958 if (!m_pTipbarWnd)
5959 return FALSE;
5960 return !!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL);
5961 }
5962
5963 /// @unimplemented
LocateItems()5964 void CTipbarThread::LocateItems()
5965 {
5966 }
5967
_Release()5968 LONG CTipbarThread::_Release()
5969 {
5970 if (--m_cRefs == 0)
5971 {
5972 delete this;
5973 return 0;
5974 }
5975 return m_cRefs;
5976 }
5977
_UnadviseItemsSink()5978 HRESULT CTipbarThread::_UnadviseItemsSink()
5979 {
5980 if (!m_pLangBarItemMgr)
5981 return E_FAIL;
5982
5983 DWORD *pdwCoolkies = new(cicNoThrow) DWORD[m_UIObjects.size()];
5984 if (!pdwCoolkies)
5985 return E_OUTOFMEMORY;
5986
5987 const size_t cItems = m_UIObjects.size();
5988 for (size_t iItem = 0; iItem < cItems; ++iItem)
5989 {
5990 CTipbarItem* pItem = m_UIObjects[iItem];
5991 if (pItem)
5992 pdwCoolkies[iItem] = pItem->m_dwCookie;
5993 }
5994
5995 HRESULT hr = m_pLangBarItemMgr->UnadviseItemsSink((LONG)cItems, pdwCoolkies);
5996
5997 delete[] pdwCoolkies;
5998
5999 return hr;
6000 }
6001
MyMoveWnd(LONG xDelta,LONG yDelta)6002 void CTipbarThread::MyMoveWnd(LONG xDelta, LONG yDelta)
6003 {
6004 if (!m_pTipbarWnd || (m_pTipbarWnd->m_pFocusThread != this))
6005 return;
6006
6007 RECT Rect, rcWorkArea;
6008 m_pTipbarWnd->GetRect(&Rect);
6009 POINT pt = { Rect.left, Rect.top };
6010 cicGetWorkAreaRect(pt, &rcWorkArea);
6011
6012 ::GetWindowRect(*m_pTipbarWnd->GetWindow(), &Rect);
6013
6014 LONG X0 = Rect.left + xDelta, Y0 = Rect.top + yDelta;
6015 if (m_pTipbarWnd->m_dwTipbarWndFlags & 0x1000)
6016 {
6017 if (m_pTipbarWnd->CheckExcludeCaptionButtonMode(&Rect, &rcWorkArea))
6018 {
6019 X0 = rcWorkArea.right - (3 * m_pTipbarWnd->m_ButtonWidth +
6020 m_pTipbarWnd->m_cxDlgFrameX2 + m_cxGrip);
6021 Y0 = 0;
6022 }
6023 else
6024 {
6025 m_pTipbarWnd->m_dwTipbarWndFlags &= ~0x1000;
6026 }
6027 }
6028
6029 if (IsVertical())
6030 {
6031 LONG width = m_pTipbarWnd->m_cxDlgFrameX2 + m_pTipbarWnd->GetTipbarHeight();
6032 LONG height = m_cyGrip + m_pTipbarWnd->m_cyDlgFrameX2;
6033 m_pTipbarWnd->SetMoveRect(X0, Y0, width, height);
6034 }
6035 else
6036 {
6037 LONG width = m_cxGrip + m_pTipbarWnd->m_cxDlgFrameX2;
6038 LONG height = m_pTipbarWnd->m_cyDlgFrameX2 + m_pTipbarWnd->GetTipbarHeight();
6039 m_pTipbarWnd->SetMoveRect(X0, Y0, width, height);
6040 }
6041
6042 SIZE frameSize = { 0, 0 };
6043 if (m_pTipbarWnd->m_pWndFrame)
6044 m_pTipbarWnd->m_pWndFrame->GetFrameSize(&frameSize);
6045
6046 m_pTipbarWnd->LocateCtrlButtons();
6047 m_pTipbarWnd->AutoAdjustDeskBandSize();
6048 }
6049
6050 /***********************************************************************
6051 * CTipbarItem
6052 */
6053
CTipbarItem(CTipbarThread * pThread,ITfLangBarItem * pLangBarItem,TF_LANGBARITEMINFO * pItemInfo,DWORD dwUnknown16)6054 CTipbarItem::CTipbarItem(
6055 CTipbarThread *pThread,
6056 ITfLangBarItem *pLangBarItem,
6057 TF_LANGBARITEMINFO *pItemInfo,
6058 DWORD dwUnknown16)
6059 {
6060 m_dwUnknown19[1] = 0;
6061 m_dwUnknown19[2] = 0;
6062 m_dwUnknown19[3] = 0;
6063 m_pTipbarThread = pThread;
6064 m_ItemInfo = *pItemInfo;
6065 m_pLangBarItem = pLangBarItem;
6066 m_pLangBarItem->AddRef();
6067 m_dwItemFlags = 0;
6068 m_dwUnknown16 = dwUnknown16;
6069 m_dwDirty = 0x1001F;
6070 }
6071
~CTipbarItem()6072 CTipbarItem::~CTipbarItem()
6073 {
6074 if (g_pTipbarWnd)
6075 {
6076 if (g_pTipbarWnd->m_pTipbarAccessible)
6077 g_pTipbarWnd->m_pTipbarAccessible->RemoveAccItem(this);
6078 }
6079
6080 if (m_pLangBarItem)
6081 m_pLangBarItem->Release();
6082 }
6083
_AddedToUI()6084 void CTipbarItem::_AddedToUI()
6085 {
6086 if (!IsConnected())
6087 return;
6088
6089 OnUnknown41();
6090
6091 m_dwItemFlags |= 0x2;
6092
6093 DWORD dwStatus;
6094 if (m_dwDirty)
6095 {
6096 if (m_dwDirty & 0x10000)
6097 m_pLangBarItem->GetStatus(&dwStatus);
6098 else
6099 dwStatus = 0;
6100 OnUnknown45(m_dwDirty, dwStatus);
6101 m_dwDirty = 0;
6102 }
6103
6104 if (m_pTipbarThread)
6105 {
6106 CTipbarWnd *pTipbarWnd = m_pTipbarThread->m_pTipbarWnd;
6107 if (pTipbarWnd)
6108 {
6109 CTipbarAccessible *pTipbarAccessible = pTipbarWnd->m_pTipbarAccessible;
6110 if (pTipbarAccessible)
6111 pTipbarAccessible->AddAccItem(this);
6112 }
6113 }
6114
6115 OnUnknown42();
6116 }
6117
_RemovedToUI()6118 void CTipbarItem::_RemovedToUI()
6119 {
6120 m_dwItemFlags &= ~0x2;
6121
6122 if (g_pTipbarWnd)
6123 {
6124 CTipbarAccessible *pAccessible = g_pTipbarWnd->m_pTipbarAccessible;
6125 if (pAccessible)
6126 pAccessible->RemoveAccItem(this);
6127 }
6128 }
6129
AddRemoveMeToUI(BOOL bFlag)6130 void CTipbarItem::AddRemoveMeToUI(BOOL bFlag)
6131 {
6132 if (!IsConnected())
6133 return;
6134
6135 m_pTipbarThread->LocateItems();
6136
6137 if (!IsConnected())
6138 return;
6139
6140 m_pTipbarThread->AddAllSeparators();
6141
6142 CTipbarWnd *pTipbarWnd = m_pTipbarThread->m_pTipbarWnd;
6143 if (bFlag)
6144 OnUnknown46(pTipbarWnd ? pTipbarWnd->GetWindow() : NULL);
6145 else
6146 OnUnknown47(pTipbarWnd ? pTipbarWnd->GetWindow() : NULL);
6147 }
6148
IsConnected()6149 BOOL CTipbarItem::IsConnected()
6150 {
6151 return (!(m_dwItemFlags & 0x10) && m_pTipbarThread && m_pTipbarThread->m_pTipbarWnd &&
6152 m_pLangBarItem);
6153 }
6154
ClearConnections()6155 void CTipbarItem::ClearConnections()
6156 {
6157 m_pTipbarThread = NULL;
6158 if (m_pLangBarItem)
6159 {
6160 m_pLangBarItem->Release();
6161 m_pLangBarItem = NULL;
6162 }
6163 }
6164
6165 /// @unimplemented
StartDemotingTimer(BOOL bStarted)6166 void CTipbarItem::StartDemotingTimer(BOOL bStarted)
6167 {
6168 if (!g_bIntelliSense)
6169 return;
6170
6171 if (!m_pTipbarThread)
6172 return;
6173
6174 CTipbarWnd *pTipbarWnd = m_pTipbarThread->m_pTipbarWnd;
6175 if (!pTipbarWnd)
6176 return;
6177
6178 //FIXME
6179 }
6180
STDMETHODIMP_(BOOL)6181 STDMETHODIMP_(BOOL) CTipbarItem::DoAccDefaultAction()
6182 {
6183 if (!m_pTipbarThread)
6184 return FALSE;
6185 CTipbarWnd *pTipbarWnd = m_pTipbarThread->m_pTipbarWnd;
6186 if (!pTipbarWnd)
6187 return FALSE;
6188 pTipbarWnd->StartDoAccDefaultActionTimer(this);
6189 return TRUE;
6190 }
6191
6192 /// @unimplemented
STDMETHODIMP_(void)6193 STDMETHODIMP_(void) CTipbarItem::OnUpdateHandler(ULONG, ULONG)
6194 {
6195 }
6196
STDMETHODIMP_(void)6197 STDMETHODIMP_(void) CTipbarItem::GetAccLocation(LPRECT prc)
6198 {
6199 OnUnknown57(prc);
6200 }
6201
STDMETHODIMP_(BSTR)6202 STDMETHODIMP_(BSTR) CTipbarItem::GetAccName()
6203 {
6204 return ::SysAllocString(m_ItemInfo.szDescription);
6205 }
6206
STDMETHODIMP_(LPCWSTR)6207 STDMETHODIMP_(LPCWSTR) CTipbarItem::GetToolTip()
6208 {
6209 OnUnknown41();
6210
6211 if (!(m_dwItemFlags & 0x1))
6212 {
6213 m_dwItemFlags |= 0x1;
6214
6215 BSTR bstrString;
6216 if (FAILED(m_pLangBarItem->GetTooltipString(&bstrString)))
6217 return NULL;
6218
6219 if (bstrString)
6220 {
6221 OnUnknown53(bstrString);
6222 ::SysFreeString(bstrString);
6223 }
6224 }
6225
6226 LPCWSTR pszToolTip = OnUnknown55();
6227
6228 OnUnknown42();
6229
6230 return pszToolTip;
6231 }
6232
OnUpdate(DWORD dwDirty)6233 HRESULT CTipbarItem::OnUpdate(DWORD dwDirty)
6234 {
6235 if (!IsConnected())
6236 return S_OK;
6237
6238 m_dwDirty |= dwDirty;
6239 m_dwItemFlags |= 0x20;
6240
6241 if ((dwDirty & 0x10000) || (m_dwItemFlags & 0x6))
6242 {
6243 if (m_pTipbarThread)
6244 {
6245 CTipbarWnd *pTipBarWnd = m_pTipbarThread->m_pTipbarWnd;
6246 if (pTipBarWnd && *pTipBarWnd)
6247 {
6248 pTipBarWnd->KillTimer(6);
6249 pTipBarWnd->SetTimer(6, g_uTimerElapseONUPDATECALLED);
6250 }
6251 }
6252 }
6253
6254 return S_OK;
6255 }
6256
MyClientToScreen(LPPOINT ppt,LPRECT prc)6257 void CTipbarItem::MyClientToScreen(LPPOINT ppt, LPRECT prc)
6258 {
6259 if (!m_pTipbarThread)
6260 return;
6261 if (m_pTipbarThread->m_pTipbarWnd)
6262 m_pTipbarThread->m_pTipbarWnd->MyClientToScreen(ppt, prc);
6263 }
6264
6265 /***********************************************************************
6266 * GetTipbarInternal
6267 */
GetTipbarInternal(HWND hWnd,DWORD dwFlags,CDeskBand * pDeskBand)6268 BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand)
6269 {
6270 BOOL bParent = !!(dwFlags & 0x80000000);
6271 g_bWinLogon = !!(dwFlags & 0x1);
6272
6273 InitFromReg();
6274
6275 if (!g_bShowTipbar)
6276 return FALSE;
6277
6278 if (bParent)
6279 {
6280 g_pTrayIconWnd = new(cicNoThrow) CTrayIconWnd();
6281 if (!g_pTrayIconWnd)
6282 return FALSE;
6283 g_pTrayIconWnd->CreateWnd();
6284 }
6285
6286 g_pTipbarWnd = new(cicNoThrow) CTipbarWnd(bParent ? g_dwWndStyle : g_dwChildWndStyle);
6287 if (!g_pTipbarWnd || !g_pTipbarWnd->Initialize())
6288 return FALSE;
6289
6290 g_pTipbarWnd->Init(!bParent, pDeskBand);
6291 g_pTipbarWnd->CreateWnd(hWnd);
6292
6293 ::SetWindowText(*g_pTipbarWnd, TEXT("TF_FloatingLangBar_WndTitle"));
6294
6295 DWORD dwOldStatus = 0;
6296 if (!bParent)
6297 {
6298 g_pTipbarWnd->m_pLangBarMgr->GetPrevShowFloatingStatus(&dwOldStatus);
6299 g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_DESKBAND);
6300 }
6301
6302 DWORD dwStatus;
6303 g_pTipbarWnd->m_pLangBarMgr->GetShowFloatingStatus(&dwStatus);
6304 g_pTipbarWnd->ShowFloating(dwStatus);
6305
6306 if (!bParent && (dwOldStatus & TF_SFT_DESKBAND))
6307 g_pTipbarWnd->m_dwTipbarWndFlags |= TIPBAR_NODESKBAND;
6308
6309 g_hwndParent = hWnd;
6310 return TRUE;
6311 }
6312
6313 /***********************************************************************
6314 * GetLibTls (MSUTB.@)
6315 *
6316 * @implemented
6317 */
6318 EXTERN_C PCIC_LIBTHREAD WINAPI
GetLibTls(VOID)6319 GetLibTls(VOID)
6320 {
6321 TRACE("()\n");
6322 return &g_libTLS;
6323 }
6324
6325 /***********************************************************************
6326 * GetPopupTipbar (MSUTB.@)
6327 *
6328 * @implemented
6329 */
6330 EXTERN_C BOOL WINAPI
GetPopupTipbar(HWND hWnd,BOOL fWinLogon)6331 GetPopupTipbar(HWND hWnd, BOOL fWinLogon)
6332 {
6333 TRACE("(%p, %d)\n", hWnd, fWinLogon);
6334
6335 if (!fWinLogon)
6336 TurnOffSpeechIfItsOn();
6337
6338 return GetTipbarInternal(hWnd, fWinLogon | 0x80000000, NULL);
6339 }
6340
6341 /***********************************************************************
6342 * SetRegisterLangBand (MSUTB.@)
6343 *
6344 * @implemented
6345 */
6346 EXTERN_C HRESULT WINAPI
SetRegisterLangBand(BOOL bRegister)6347 SetRegisterLangBand(BOOL bRegister)
6348 {
6349 TRACE("(%d)\n", bRegister);
6350
6351 if (!g_bEnableDeskBand || !(g_dwOSInfo & CIC_OSINFO_XPPLUS)) // Desk band is for XP+
6352 return E_FAIL;
6353
6354 BOOL bDeskBand = IsDeskBandFromReg();
6355 if (bDeskBand == bRegister)
6356 return S_OK;
6357
6358 SetDeskBandToReg(bRegister);
6359
6360 if (!RegisterComCat(CLSID_MSUTBDeskBand, CATID_DeskBand, bRegister))
6361 return TF_E_NOLOCK;
6362
6363 return S_OK;
6364 }
6365
6366 /***********************************************************************
6367 * ClosePopupTipbar (MSUTB.@)
6368 *
6369 * @implemented
6370 */
6371 EXTERN_C VOID WINAPI
ClosePopupTipbar(VOID)6372 ClosePopupTipbar(VOID)
6373 {
6374 TRACE("()\n");
6375
6376 if (g_fInClosePopupTipbar)
6377 return;
6378
6379 g_fInClosePopupTipbar = TRUE;
6380
6381 if (g_pTipbarWnd)
6382 {
6383 g_pTipbarWnd->m_pDeskBand = NULL;
6384 g_pTipbarWnd->DestroyWnd();
6385 g_pTipbarWnd->Release();
6386 g_pTipbarWnd = NULL;
6387 }
6388
6389 if (g_pTrayIconWnd)
6390 {
6391 g_pTrayIconWnd->DestroyWnd();
6392 delete g_pTrayIconWnd;
6393 g_pTrayIconWnd = NULL;
6394 }
6395
6396 UninitSkipRedrawHKLArray();
6397
6398 g_fInClosePopupTipbar = FALSE;
6399 }
6400
6401 /***********************************************************************
6402 * DllRegisterServer (MSUTB.@)
6403 *
6404 * @implemented
6405 */
DllRegisterServer(VOID)6406 STDAPI DllRegisterServer(VOID)
6407 {
6408 TRACE("()\n");
6409 return gModule.DllRegisterServer(FALSE);
6410 }
6411
6412 /***********************************************************************
6413 * DllUnregisterServer (MSUTB.@)
6414 *
6415 * @implemented
6416 */
DllUnregisterServer(VOID)6417 STDAPI DllUnregisterServer(VOID)
6418 {
6419 TRACE("()\n");
6420 return gModule.DllUnregisterServer(FALSE);
6421 }
6422
6423 /***********************************************************************
6424 * DllCanUnloadNow (MSUTB.@)
6425 *
6426 * @implemented
6427 */
DllCanUnloadNow(VOID)6428 STDAPI DllCanUnloadNow(VOID)
6429 {
6430 TRACE("()\n");
6431 return gModule.DllCanUnloadNow() && (g_DllRefCount == 0);
6432 }
6433
6434 /***********************************************************************
6435 * DllGetClassObject (MSUTB.@)
6436 *
6437 * @implemented
6438 */
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)6439 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
6440 {
6441 TRACE("()\n");
6442 return gModule.DllGetClassObject(rclsid, riid, ppv);
6443 }
6444
6445 /// @implemented
6446 HRESULT APIENTRY
MsUtbCoCreateInstance(REFCLSID rclsid,LPUNKNOWN pUnkOuter,DWORD dwClsContext,REFIID iid,LPVOID * ppv)6447 MsUtbCoCreateInstance(
6448 REFCLSID rclsid,
6449 LPUNKNOWN pUnkOuter,
6450 DWORD dwClsContext,
6451 REFIID iid,
6452 LPVOID *ppv)
6453 {
6454 if (IsEqualCLSID(rclsid, CLSID_TF_CategoryMgr))
6455 return TF_CreateCategoryMgr((ITfCategoryMgr**)ppv);
6456 if (IsEqualCLSID(rclsid, CLSID_TF_DisplayAttributeMgr))
6457 return TF_CreateDisplayAttributeMgr((ITfDisplayAttributeMgr **)ppv);
6458 return cicRealCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
6459 }
6460
6461 BEGIN_OBJECT_MAP(ObjectMap)
6462 #ifdef ENABLE_DESKBAND
OBJECT_ENTRY(CLSID_MSUTBDeskBand,CDeskBand)6463 OBJECT_ENTRY(CLSID_MSUTBDeskBand, CDeskBand) // FIXME: Implement this
6464 #endif
6465 END_OBJECT_MAP()
6466
6467 EXTERN_C VOID TFUninitLib(VOID)
6468 {
6469 // Do nothing
6470 }
6471
6472 /// @implemented
ProcessAttach(HINSTANCE hinstDLL)6473 BOOL ProcessAttach(HINSTANCE hinstDLL)
6474 {
6475 ::InitializeCriticalSectionAndSpinCount(&g_cs, 0);
6476
6477 g_hInst = hinstDLL;
6478
6479 cicGetOSInfo(&g_uACP, &g_dwOSInfo);
6480
6481 TFInitLib(MsUtbCoCreateInstance);
6482 cicInitUIFLib();
6483
6484 CTrayIconWnd::RegisterClass();
6485
6486 g_wmTaskbarCreated = RegisterWindowMessageW(L"TaskbarCreated");
6487
6488 gModule.Init(ObjectMap, hinstDLL, NULL);
6489 ::DisableThreadLibraryCalls(hinstDLL);
6490
6491 return TRUE;
6492 }
6493
6494 /// @implemented
ProcessDetach(HINSTANCE hinstDLL)6495 VOID ProcessDetach(HINSTANCE hinstDLL)
6496 {
6497 cicDoneUIFLib();
6498 TFUninitLib();
6499 ::DeleteCriticalSection(&g_cs);
6500 gModule.Term();
6501 }
6502
6503 /// @implemented
6504 EXTERN_C BOOL WINAPI
DllMain(_In_ HINSTANCE hinstDLL,_In_ DWORD dwReason,_Inout_opt_ LPVOID lpvReserved)6505 DllMain(
6506 _In_ HINSTANCE hinstDLL,
6507 _In_ DWORD dwReason,
6508 _Inout_opt_ LPVOID lpvReserved)
6509 {
6510 switch (dwReason)
6511 {
6512 case DLL_PROCESS_ATTACH:
6513 {
6514 TRACE("(%p, %lu, %p)\n", hinstDLL, dwReason, lpvReserved);
6515 if (!ProcessAttach(hinstDLL))
6516 {
6517 ProcessDetach(hinstDLL);
6518 return FALSE;
6519 }
6520 break;
6521 }
6522 case DLL_PROCESS_DETACH:
6523 {
6524 ProcessDetach(hinstDLL);
6525 break;
6526 }
6527 }
6528 return TRUE;
6529 }
6530