You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8025 lines
208 KiB
8025 lines
208 KiB
//
|
|
// tipbar.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include <initguid.h>
|
|
#include "tipbar.h"
|
|
#include "helpers.h"
|
|
#include "xstring.h"
|
|
#include "commctrl.h"
|
|
#include "resource.h"
|
|
#include "inatlib.h"
|
|
#include "thdutil.h"
|
|
#include "catutil.h"
|
|
#include "immxutil.h"
|
|
#include "utbmenu.h"
|
|
#include "balloon.h"
|
|
#include "cregkey.h"
|
|
#include "cuimenu.h"
|
|
#include "cuishadw.h"
|
|
#include "cuischem.h"
|
|
#include "cmydc.h"
|
|
#include "intlmenu.h"
|
|
#include "utbtray.h"
|
|
#include "catenum.h"
|
|
#include "asynccal.h"
|
|
#include "fontlink.h"
|
|
#include "cresstr.h"
|
|
#include "nuiinat.h"
|
|
#include "tlapi.h"
|
|
#include "cuiutil.h"
|
|
#include "cuischem.h"
|
|
#include "cuitip.h"
|
|
#include "utbdlgs.h"
|
|
#include <shlapip.h>
|
|
#include "deskband.h"
|
|
#include "lmcons.h" // for UNLEN
|
|
#include "sddl.h"
|
|
|
|
#include "winuserp.h"
|
|
|
|
const DWORD TF_LBESF_GLOBAL = 0x0001;
|
|
const DWORD TF_LBSMI_FILTERCURRENTTHREAD = 0x0001;
|
|
|
|
extern HINSTANCE g_hInst;
|
|
const TCHAR c_szTipbarWndClass[] = TEXT("TipbarWndClass");
|
|
const TCHAR c_szTipbarWndName[] = TEXT("Cicload Tipbar");
|
|
|
|
const TCHAR c_szCicKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\");
|
|
const TCHAR c_szUTBKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\");
|
|
const TCHAR c_szSkipRedrawHKL[] = TEXT("SOFTWARE\\Microsoft\\CTF\\MSUTB\\SkipRedrawHKL");
|
|
const TCHAR c_szShowTipbar[] = TEXT("ShowTipbar");
|
|
const TCHAR c_szDontShowCloseLangBarDlg[] = TEXT("DontShowCloseLangBarDlg");
|
|
const TCHAR c_szDontShowMinimizeLangBarDlg[] = TEXT("DontShowMinimizeLangBarDlg");
|
|
const TCHAR c_szShowDebugMenu[] = TEXT("ShowDebugMenu");
|
|
const TCHAR c_szShowDeskBand[] = TEXT("ShowDeskBand");
|
|
const TCHAR c_szNewLook[] = TEXT("NewLook");
|
|
const TCHAR c_szIntelliSense[] = TEXT("IntelliSense");
|
|
const TCHAR c_szTimeOutNonIntentional[] = TEXT("TimeOutNonIntentional");
|
|
const TCHAR c_szTimeOutIntentional[] = TEXT("TimeOutIntentional");
|
|
const TCHAR c_szShowCloseMenu[] = TEXT("ShowCloseMenu");
|
|
const TCHAR c_szShowMinimizedBalloon[] = TEXT("ShowMinimizedBalloon");
|
|
const TCHAR c_szLeft[] = TEXT("Left");
|
|
const TCHAR c_szTop[] = TEXT("Top");
|
|
const TCHAR c_szExcludeCaptionButtons[] = TEXT("ExcludeCaptionButtons");
|
|
const TCHAR c_szShowShadow[] = TEXT("ShowShadow");
|
|
const TCHAR c_szTaskbarTheme[] = TEXT("TaskbarTheme");
|
|
const TCHAR c_szVertical[] = TEXT("Vertical");
|
|
// const TCHAR c_szMoveToTray[] = TEXT("MoveToTray");
|
|
|
|
BOOL g_bNewLook = TRUE;
|
|
BOOL g_bIntelliSense = FALSE;
|
|
BOOL g_bShowTipbar = TRUE;
|
|
BOOL g_bShowDebugMenu = FALSE;
|
|
BOOL g_bShowCloseMenu = FALSE;
|
|
BOOL g_bShowMinimizedBalloon = TRUE;
|
|
BOOL g_bExcludeCaptionButtons = TRUE;
|
|
BOOL g_bShowShadow = FALSE;
|
|
BOOL g_bShowDeskBand = FALSE;
|
|
BOOL g_nLeft = -1;
|
|
BOOL g_nTop = -1;
|
|
DWORD g_dwWndStyle = 0;
|
|
DWORD g_dwChildWndStyle = 0;
|
|
DWORD g_dwMenuStyle = 0;
|
|
CTipbarWnd *g_pTipbarWnd;
|
|
CTrayIconWnd *g_pTrayIconWnd;
|
|
HWND g_hwndParent;
|
|
BOOL g_bWinLogon = FALSE;
|
|
BOOL g_fTaskbarTheme = TRUE;
|
|
BOOL g_fVertical = FALSE;
|
|
BOOL g_fInClosePopupTipbar = FALSE;
|
|
BOOL g_fRTL = FALSE;
|
|
|
|
const TCHAR c_szTimerElapseSTUBSTART[] = TEXT("TimerElapseSTUBSTART");
|
|
const TCHAR c_szTimerElapseSTUBEND[] = TEXT("TimerElapseSTUBEND");
|
|
const TCHAR c_szTimerElapseBACKTOALPHA[] = TEXT("TimerElapseBACKTOALPHA");
|
|
const TCHAR c_szTimerElapseONTHREADITEMCHANGE[] = TEXT("TimerElapseONTHREADITEMCHANGE");
|
|
const TCHAR c_szTimerElapseSETWINDOWPOS[] = TEXT("TimerElapseSETWINDOWPOS");
|
|
const TCHAR c_szTimerElapseONUPDATECALLED[] = TEXT("TimerElapseONUPDATECALLED");
|
|
const TCHAR c_szTimerElapseSYSCOLORCHANGED[] = TEXT("TimerElapseSYSCOLORCHANGED");
|
|
const TCHAR c_szTimerElapseDISPLAYCHANGE[] = TEXT("TimerElapseDISPLAYCHANGE");
|
|
const TCHAR c_szTimerElapseUPDATEUI[] = TEXT("TimerElapseUPDATEUI");
|
|
const TCHAR c_szTimerElapseSHOWWINDOW[] = TEXT("TimerElapseSHOWWINDOW");
|
|
const TCHAR c_szTimerElapseMOVETOTRAY[] = TEXT("TimerElapseMOVETOTRAY");
|
|
const TCHAR c_szTimerElapseTRAYWNDONDELAYMSG[] = TEXT("TimerElapseTRAYWNDONDELAYMSG");
|
|
const TCHAR c_szTimerElapseDOACCDEFAULTACTION[] = TEXT("TimerElapseDOACCDEFAULTACTION");
|
|
const TCHAR c_szTimerElapseENSUREFOCUS[] = TEXT("TimerElapseENSUREFOCUS");
|
|
const TCHAR c_szTimerElapseSHOWDESKBAND[] = TEXT("TimerElapseSHOWWDESKBAND");
|
|
|
|
UINT g_uTimerElapseSTUBSTART = 100;
|
|
UINT g_uTimerElapseSTUBEND = 2000;
|
|
UINT g_uTimerElapseBACKTOALPHA = 3000;
|
|
UINT g_uTimerElapseONTHREADITEMCHANGE = 200;
|
|
UINT g_uTimerElapseSETWINDOWPOS = 100;
|
|
UINT g_uTimerElapseONUPDATECALLED = 50; // Satori tune up 20,50,100 or 200
|
|
UINT g_uTimerElapseSYSCOLORCHANGED = 20;
|
|
UINT g_uTimerElapseDISPLAYCHANGE = 20;
|
|
UINT g_uTimerElapseUPDATEUI = 70; // MSIME2002 JP needs 70ms.
|
|
UINT g_uTimerElapseSHOWWINDOW = 50;
|
|
UINT g_uTimerElapseMOVETOTRAY = 50;
|
|
UINT g_uTimerElapseTRAYWNDONDELAYMSG = 50;
|
|
UINT g_uTimerElapseDOACCDEFAULTACTION = 200;
|
|
UINT g_uTimerElapseENSUREFOCUS = 50;
|
|
UINT g_uTimerElapseSHOWDESKBAND = 3000;
|
|
|
|
|
|
//
|
|
// from bandobjs.cpp
|
|
//
|
|
extern UINT g_wmTaskbarCreated;
|
|
|
|
//
|
|
// from itemlist.cpp
|
|
//
|
|
extern UINT g_uTimeOutNonIntentional;
|
|
extern UINT g_uTimeOutIntentional;
|
|
extern UINT g_uTimeOutMax;
|
|
|
|
|
|
//
|
|
// SkipRedrawing Hack HKL list.
|
|
//
|
|
CStructArray<HKL> *g_prghklSkipRedrawing = NULL;
|
|
void UninitSkipRedrawHKLArray();
|
|
|
|
#define WM_LBWND_SHOWCONTEXTMENU (WM_USER + 1)
|
|
|
|
// TM_LANGUAGEBAND is defined in "shell\inc\trayp.h"
|
|
#define TM_LANGUAGEBAND WM_USER+0x105
|
|
|
|
/* 142b6d42-955d-4488-97c0-b23b23e6b048 */
|
|
const IID IID_PRIV_BUTTONITEM = {
|
|
0x142b6d42,
|
|
0x955d,
|
|
0x4488,
|
|
{0x97, 0xc0, 0xb2, 0x3b, 0x23, 0xe6, 0xb0, 0x48}
|
|
};
|
|
|
|
/* 8dd1cc81-fca0-4dd5-b848-2b85732d2fc4 */
|
|
const IID IID_PRIV_BITMAPBUTTONITEM = {
|
|
0x8dd1cc81,
|
|
0xfca0,
|
|
0x4dd5,
|
|
{0xb8, 0x48, 0x2b, 0x85, 0x73, 0x2d, 0x2f, 0xc4}
|
|
};
|
|
|
|
/* 36b40e05-7b3e-4a4a-bda7-2249ba17d3c4 */
|
|
const IID IID_PRIV_BITMAPITEM = {
|
|
0x36b40e05,
|
|
0x7b3e,
|
|
0x4a4a,
|
|
{0xbd, 0xa7, 0x22, 0x49, 0xba, 0x17, 0xd3, 0xc4}
|
|
};
|
|
|
|
/* 68831a74-6f86-447a-b2b8-634250ac445e */
|
|
const IID IID_PRIV_BALLOONITEM = {
|
|
0x68831a74,
|
|
0x6f86,
|
|
0x447a,
|
|
{0xb2, 0xb8, 0x63, 0x42, 0x50, 0xac, 0x44, 0x5e}
|
|
};
|
|
|
|
//
|
|
// from MSCTF.DLL.
|
|
//
|
|
extern "C" BOOL WINAPI TF_IsFullScreenWindowAcitvated();
|
|
extern "C" DWORD WINAPI TF_CheckThreadInputIdle(DWORD dwThreadId, DWORD dwTimeOut);
|
|
|
|
//
|
|
// from intlmenu.cpp
|
|
//
|
|
extern BOOL IsFELangId(LANGID langid);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// predefined control buttons
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static CTRLBTNMAP g_cbCtrlBtn[NUM_CTRLBUTTONS] = {
|
|
{ID_CBTN_CAPSKEY, UIBUTTON_CENTER | UIBUTTON_VCENTER | UIBUTTON_TOGGLE,
|
|
0, 0, CTRL_ICONFROMRES | CTRL_TOGGLEBUTTON, {0x0, 0x0}},
|
|
{ID_CBTN_KANAKEY, UIBUTTON_CENTER | UIBUTTON_VCENTER | UIBUTTON_TOGGLE,
|
|
0, 1, CTRL_ICONFROMRES | CTRL_TOGGLEBUTTON, {0x0, 0x0}},
|
|
{ID_CBTN_MINIMIZE, UIBUTTON_CENTER | UIBUTTON_VCENTER,
|
|
1, 0, CTRL_USEMARLETT | CTRL_DISABLEONWINLOGON, {0x0030, 0x0000}},
|
|
{ID_CBTN_EXTMENU, UIBUTTON_CENTER | UIBUTTON_VCENTER,
|
|
1, 1, CTRL_USEMARLETT | CTRL_DISABLEONWINLOGON, {0x0075, 0x0000}},
|
|
};
|
|
|
|
static CTRLBTNMAP g_cbCtrlBtnDeskBand[NUM_CTRLBUTTONS] = {
|
|
{ID_CBTN_CAPSKEY, UIBUTTON_CENTER | UIBUTTON_VCENTER | UIBUTTON_TOGGLE,
|
|
0, 0, CTRL_ICONFROMRES | CTRL_TOGGLEBUTTON, {0x0, 0x0}},
|
|
{ID_CBTN_KANAKEY, UIBUTTON_CENTER | UIBUTTON_VCENTER | UIBUTTON_TOGGLE,
|
|
0, 1, CTRL_ICONFROMRES | CTRL_TOGGLEBUTTON, {0x0, 0x0}},
|
|
{ID_CBTN_RESTORE, UIBUTTON_CENTER | UIBUTTON_VCENTER,
|
|
1, 0, CTRL_USEMARLETT | CTRL_DISABLEONWINLOGON, {0x0032, 0x0000}},
|
|
{ID_CBTN_EXTMENU, UIBUTTON_CENTER | UIBUTTON_VCENTER,
|
|
1, 1, CTRL_USEMARLETT | CTRL_DISABLEONWINLOGON, {0x0075, 0x0000}},
|
|
};
|
|
|
|
static int c_nColumnStart[] = {0, CX_COLUMN0, CX_COLUMN1};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// APIs
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
extern "C" BOOL WINAPI GetPopupTipbar(HWND hwndParent, DWORD dwFlags)
|
|
{
|
|
if ( !(dwFlags & UTB_GTI_WINLOGON) )
|
|
{
|
|
TurnOffSpeechIfItsOn( );
|
|
}
|
|
|
|
return GetTipbarInternal(hwndParent, UTB_GTI_POPUP | dwFlags, NULL);
|
|
}
|
|
|
|
BOOL GetTipbarInternal(HWND hwndParent, DWORD dwFlags, CDeskBand *pDeskBand)
|
|
{
|
|
DWORD dwSFSFlags;
|
|
BOOL fPopup = (dwFlags & UTB_GTI_POPUP) ? TRUE : FALSE;
|
|
|
|
g_bWinLogon = (dwFlags & UTB_GTI_WINLOGON) ? TRUE : FALSE;
|
|
|
|
//
|
|
// MSAA support
|
|
//
|
|
InitTipbarAcc();
|
|
|
|
InitFromReg();
|
|
|
|
if (!g_bShowTipbar)
|
|
return NULL;
|
|
|
|
//
|
|
// we don't have to create TrayIconWnd under explorer's desk band.
|
|
//
|
|
if (fPopup)
|
|
{
|
|
g_pTrayIconWnd = new CTrayIconWnd();
|
|
if (!g_pTrayIconWnd)
|
|
return FALSE;
|
|
|
|
g_pTrayIconWnd->CreateWnd();
|
|
}
|
|
|
|
g_pTipbarWnd = new CTipbarWnd(fPopup ? g_dwWndStyle : g_dwChildWndStyle);
|
|
if (!g_pTipbarWnd)
|
|
return FALSE;
|
|
|
|
if (!g_pTipbarWnd->Initialize())
|
|
return FALSE;
|
|
|
|
g_pTipbarWnd->Init(!fPopup, pDeskBand);
|
|
|
|
|
|
g_pTipbarWnd->CreateWnd(hwndParent);
|
|
SetWindowText(g_pTipbarWnd->GetWnd(), TF_FLOATINGLANGBAR_WNDTITLE);
|
|
|
|
DWORD dwPrevFlags = 0;
|
|
if (!fPopup)
|
|
{
|
|
g_pTipbarWnd->GetLangBarMgr()->GetPrevShowFloatingStatus(&dwPrevFlags);
|
|
|
|
g_pTipbarWnd->GetLangBarMgr()->ShowFloating(TF_SFT_DESKBAND);
|
|
}
|
|
|
|
g_pTipbarWnd->GetLangBarMgr()->GetShowFloatingStatus(&dwSFSFlags);
|
|
g_pTipbarWnd->ShowFloating(dwSFSFlags);
|
|
|
|
//
|
|
// get the previous show floating status.
|
|
// if it does not have TF_SFT_DESKBAND, the floating toolbar
|
|
// was minimized.
|
|
// if it has TF_SFT_DESKBAND, exploere just started. Then we don't
|
|
// want to adjust the deskband and use the default size.
|
|
// (Explorer remembers the position of the previous logon.)
|
|
//
|
|
if (!fPopup && (dwPrevFlags & TF_SFT_DESKBAND))
|
|
g_pTipbarWnd->SetDeskbandSizeAdjusted();
|
|
|
|
g_hwndParent = hwndParent;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern "C" void WINAPI ClosePopupTipbar()
|
|
{
|
|
if (g_fInClosePopupTipbar)
|
|
return;
|
|
|
|
g_fInClosePopupTipbar = TRUE;
|
|
|
|
if (g_pTipbarWnd)
|
|
{
|
|
g_pTipbarWnd->ClearDeskBandPointer();
|
|
g_pTipbarWnd->DestroyWnd();
|
|
g_pTipbarWnd->Release();
|
|
g_pTipbarWnd = NULL;
|
|
}
|
|
|
|
if (g_pTrayIconWnd)
|
|
{
|
|
g_pTrayIconWnd->DestroyWnd();
|
|
delete g_pTrayIconWnd;
|
|
g_pTrayIconWnd = NULL;
|
|
}
|
|
|
|
UninitSkipRedrawHKLArray();
|
|
|
|
g_fInClosePopupTipbar = FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// misc func
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
extern "C" HRESULT WINAPI TF_GetGlobalCompartment(ITfCompartmentMgr **pCompMgr);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCompartment
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT GetGlobalCompartment(REFGUID rguidComp, ITfCompartment **ppComp)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ITfCompartmentMgr *pCompMgr = NULL;
|
|
|
|
if (FAILED(hr = TF_GetGlobalCompartment(&pCompMgr)))
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && pCompMgr)
|
|
{
|
|
hr = pCompMgr->GetCompartment(rguidComp, ppComp);
|
|
pCompMgr->Release();
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetCompartmentDWORD
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT SetGlobalCompartmentDWORD(REFGUID rguidComp, DWORD dw)
|
|
{
|
|
HRESULT hr;
|
|
ITfCompartment *pComp;
|
|
VARIANT var;
|
|
|
|
if (SUCCEEDED(hr = GetGlobalCompartment(rguidComp, &pComp)))
|
|
{
|
|
var.vt = VT_I4;
|
|
var.lVal = dw;
|
|
hr = pComp->SetValue(0, &var);
|
|
pComp->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetGlobalCompartmentDWORD
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT GetGlobalCompartmentDWORD(REFGUID rguidComp, DWORD *pdw)
|
|
{
|
|
HRESULT hr;
|
|
ITfCompartment *pComp;
|
|
VARIANT var;
|
|
|
|
*pdw = 0;
|
|
if (SUCCEEDED(hr = GetGlobalCompartment(rguidComp, &pComp)))
|
|
{
|
|
if ((hr = pComp->GetValue(&var)) == S_OK)
|
|
{
|
|
Assert(var.vt == VT_I4);
|
|
*pdw = var.lVal;
|
|
}
|
|
pComp->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// TurnOffSpeechIfItsOn
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void TurnOffSpeechIfItsOn()
|
|
{
|
|
// turn off the mic here only if someone set speech on
|
|
DWORD dw = 0;
|
|
HRESULT hr = GetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, &dw);
|
|
if (SUCCEEDED(hr) && dw > 0)
|
|
{
|
|
SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitSkipRedrawHKLArray
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void InitSkipRedrawHKLArray()
|
|
{
|
|
CMyRegKey key;
|
|
HKL *phkl;
|
|
|
|
Assert(!g_prghklSkipRedrawing);
|
|
g_prghklSkipRedrawing = new CStructArray<HKL>;
|
|
if (!g_prghklSkipRedrawing)
|
|
return;
|
|
|
|
if (IsOnNT51())
|
|
{
|
|
phkl = g_prghklSkipRedrawing->Append(1);
|
|
if (phkl)
|
|
*phkl = (HKL)IntToPtr(0xe0010411);
|
|
}
|
|
|
|
if (key.Open(HKEY_LOCAL_MACHINE, c_szSkipRedrawHKL, KEY_READ) == S_OK)
|
|
{
|
|
char szValue[255];
|
|
DWORD dwIndex = 0;
|
|
while (key.EnumValue(dwIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
|
|
{
|
|
if ((szValue[0] == '0') &&
|
|
((szValue[1] == 'X') || (szValue[1] == 'x')))
|
|
{
|
|
phkl = g_prghklSkipRedrawing->Append(1);
|
|
if (phkl)
|
|
*phkl = (HKL)IntToPtr(AsciiToNum(&szValue[2]));
|
|
}
|
|
dwIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UninitSkipRedrawHKLArray
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void UninitSkipRedrawHKLArray()
|
|
{
|
|
if (!g_prghklSkipRedrawing)
|
|
return;
|
|
|
|
delete g_prghklSkipRedrawing;
|
|
g_prghklSkipRedrawing = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsSkipRedrawHKL
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL IsSkipRedrawHKL(HKL hkl)
|
|
{
|
|
int i;
|
|
|
|
if (0x0411 != LANGID(LOWORD(HandleToLong(hkl))))
|
|
return FALSE;
|
|
|
|
if (!g_prghklSkipRedrawing)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < g_prghklSkipRedrawing->Count(); i++)
|
|
{
|
|
HKL *phkl = g_prghklSkipRedrawing->GetPtr(i);
|
|
if (phkl && (*phkl == hkl))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitFromReg
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL InitFromReg()
|
|
{
|
|
CMyRegKey key;
|
|
CMyRegKey keyUTB;
|
|
DWORD dwValue;
|
|
LANGID langID = 0;
|
|
|
|
if (key.Open(HKEY_CURRENT_USER, c_szCicKey, KEY_READ) == S_OK)
|
|
{
|
|
if (key.QueryValue(dwValue, c_szShowTipbar) == S_OK)
|
|
g_bShowTipbar = dwValue ? TRUE : FALSE;
|
|
}
|
|
|
|
if (keyUTB.Open(HKEY_CURRENT_USER, c_szUTBKey, KEY_READ) == S_OK)
|
|
{
|
|
if (keyUTB.QueryValue(dwValue, c_szShowDebugMenu) == S_OK)
|
|
g_bShowDebugMenu = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szNewLook) == S_OK)
|
|
g_bNewLook = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szIntelliSense) == S_OK)
|
|
g_bIntelliSense = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szShowCloseMenu) == S_OK)
|
|
g_bShowCloseMenu = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimeOutNonIntentional) == S_OK)
|
|
g_uTimeOutNonIntentional = dwValue * 1000;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimeOutIntentional) == S_OK)
|
|
{
|
|
g_uTimeOutIntentional = dwValue * 1000;
|
|
g_uTimeOutMax = g_uTimeOutIntentional * 6;
|
|
}
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szShowMinimizedBalloon) == S_OK)
|
|
g_bShowMinimizedBalloon = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szLeft) == S_OK)
|
|
g_nLeft = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTop) == S_OK)
|
|
g_nTop = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szExcludeCaptionButtons) == S_OK)
|
|
g_bExcludeCaptionButtons = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szShowShadow) == S_OK)
|
|
g_bShowShadow = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTaskbarTheme) == S_OK)
|
|
g_fTaskbarTheme = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szVertical) == S_OK)
|
|
g_fVertical = dwValue ? TRUE : FALSE;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseSTUBSTART) == S_OK)
|
|
g_uTimerElapseSTUBSTART = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseSTUBEND) == S_OK)
|
|
g_uTimerElapseSTUBEND = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseBACKTOALPHA) == S_OK)
|
|
g_uTimerElapseBACKTOALPHA = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseONTHREADITEMCHANGE) == S_OK)
|
|
g_uTimerElapseONTHREADITEMCHANGE = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseSETWINDOWPOS) == S_OK)
|
|
g_uTimerElapseSETWINDOWPOS = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseONUPDATECALLED) == S_OK)
|
|
g_uTimerElapseONUPDATECALLED = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseSYSCOLORCHANGED) == S_OK)
|
|
g_uTimerElapseSYSCOLORCHANGED = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseDISPLAYCHANGE) == S_OK)
|
|
g_uTimerElapseDISPLAYCHANGE = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseUPDATEUI) == S_OK)
|
|
g_uTimerElapseUPDATEUI = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseSHOWWINDOW) == S_OK)
|
|
g_uTimerElapseSHOWWINDOW = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseMOVETOTRAY) == S_OK)
|
|
g_uTimerElapseMOVETOTRAY = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseTRAYWNDONDELAYMSG) == S_OK)
|
|
g_uTimerElapseTRAYWNDONDELAYMSG = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseDOACCDEFAULTACTION) == S_OK)
|
|
g_uTimerElapseDOACCDEFAULTACTION = dwValue;
|
|
|
|
if (keyUTB.QueryValue(dwValue, c_szTimerElapseENSUREFOCUS) == S_OK)
|
|
g_uTimerElapseENSUREFOCUS = dwValue;
|
|
|
|
if (IsOnNT51() && keyUTB.QueryValue(dwValue, c_szShowDeskBand) == S_OK)
|
|
g_bShowDeskBand = dwValue ? TRUE : FALSE;
|
|
|
|
if (IsOnNT51() && keyUTB.QueryValue(dwValue, c_szTimerElapseSHOWDESKBAND) == S_OK)
|
|
g_uTimerElapseSHOWDESKBAND = dwValue;
|
|
}
|
|
|
|
|
|
InitSkipRedrawHKLArray();
|
|
|
|
if (g_bNewLook)
|
|
{
|
|
g_dwWndStyle = UIWINDOW_TOPMOST |
|
|
// UIWINDOW_WSDLGFRAME |
|
|
UIWINDOW_HASTOOLTIP |
|
|
UIWINDOW_HABITATINWORKAREA |
|
|
UIWINDOW_OFC10TOOLBAR |
|
|
UIWINDOW_TOOLWINDOW;
|
|
|
|
if (IsOnNT51())
|
|
{
|
|
g_dwWndStyle &= ~UIWINDOW_OFC10TOOLBAR;
|
|
g_dwWndStyle |= UIWINDOW_WHISTLERLOOK;
|
|
// g_dwWndStyle |= UIWINDOW_WSBORDER;
|
|
}
|
|
|
|
if (g_bShowShadow)
|
|
g_dwWndStyle |= UIWINDOW_HASSHADOW;
|
|
|
|
g_dwMenuStyle = UIWINDOW_TOPMOST |
|
|
UIWINDOW_TOOLWINDOW |
|
|
UIWINDOW_OFC10MENU |
|
|
UIWINDOW_HASSHADOW |
|
|
UIWINDOW_HABITATINSCREEN;
|
|
}
|
|
else
|
|
{
|
|
g_dwWndStyle = UIWINDOW_TOPMOST |
|
|
UIWINDOW_HASTOOLTIP |
|
|
UIWINDOW_WSDLGFRAME |
|
|
UIWINDOW_HABITATINWORKAREA;
|
|
g_dwMenuStyle = UIWINDOW_TOPMOST |
|
|
UIWINDOW_WSDLGFRAME |
|
|
UIWINDOW_HABITATINSCREEN;
|
|
}
|
|
|
|
g_dwChildWndStyle = UIWINDOW_CHILDWND;
|
|
|
|
if (IsOnNT51())
|
|
{
|
|
g_dwChildWndStyle |= UIWINDOW_WHISTLERLOOK |
|
|
UIWINDOW_HASTOOLTIP |
|
|
UIWINDOW_NOMOUSEMSGFROMSETCURSOR;
|
|
}
|
|
|
|
langID = GetPlatformResourceLangID();
|
|
if (PRIMARYLANGID(langID) == LANG_ARABIC || PRIMARYLANGID(langID) == LANG_HEBREW)
|
|
{
|
|
g_dwWndStyle |= UIWINDOW_LAYOUTRTL;
|
|
g_dwChildWndStyle |= UIWINDOW_LAYOUTRTL;
|
|
g_dwMenuStyle |= UIWINDOW_LAYOUTRTL;
|
|
g_fRTL = TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetTopLevelWindow
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HWND GetTopLevelWindow(HWND hwnd)
|
|
{
|
|
HWND hwndT,hwndRet;
|
|
HWND hwndDsktop = GetDesktopWindow();
|
|
|
|
hwndT = hwndRet = hwnd;
|
|
|
|
while (hwndT && hwndT != hwndDsktop)
|
|
{
|
|
HWND hwndT0;
|
|
hwndRet = hwndT;
|
|
hwndT0 = GetParent(hwndT);
|
|
|
|
if (IsOn98() && !hwndT0)
|
|
{
|
|
//
|
|
// GetLastActivePopup() returns hwnd->hwndLastActive.
|
|
// But top level owner's hwndLastActive is used.
|
|
// We need to find a top level owner.
|
|
//
|
|
hwndT0 = GetWindow(hwndT, GW_OWNER);
|
|
}
|
|
hwndT = hwndT0;
|
|
}
|
|
|
|
return(hwndRet);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MyWaitForInputIdle
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
#define UTB_INPUTIDLETIMEOUT 2000
|
|
|
|
DWORD MyWaitForInputIdle(DWORD dwThreadId, DWORD dwTimeOut)
|
|
{
|
|
DWORD dwRet = -1;
|
|
DWORD dwProcessId = 0;
|
|
DWORD dwThreadFlags;
|
|
|
|
if (g_pTipbarWnd && g_pTipbarWnd->IsSFDeskband())
|
|
{
|
|
//
|
|
// Skip it on the Deskband that is belong to Explorer process.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// If the target thread is in marshaling call, we can behave as it's busy.
|
|
//
|
|
if (TF_IsInMarshaling(dwThreadId))
|
|
return WAIT_TIMEOUT;
|
|
|
|
if (TF_GetThreadFlags(dwThreadId, &dwThreadFlags, &dwProcessId, NULL) && dwProcessId)
|
|
{
|
|
dwRet = 0;
|
|
|
|
if (IsOnNT() &&
|
|
Is16bitThread(dwProcessId, dwThreadId))
|
|
{
|
|
//
|
|
// we need to do something here to detect 16bit idle.
|
|
//
|
|
}
|
|
else if (IsOnNT() || !(dwThreadFlags & TLF_NOWAITFORINPUTIDLEONWIN9X))
|
|
{
|
|
#if 0
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
|
|
FALSE, dwProcessId);
|
|
if (hProcess)
|
|
{
|
|
dwRet = WaitForInputIdle(hProcess, dwTimeOut);
|
|
CloseHandle(hProcess);
|
|
}
|
|
else
|
|
dwRet = -1;
|
|
#else
|
|
dwRet = TF_CheckThreadInputIdle(dwThreadId, dwTimeOut);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ClearMsgQueue
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void ClearMsgQueue()
|
|
{
|
|
MSG msg;
|
|
ULONG ulQuitCode;
|
|
BOOL fQuitReceived = FALSE;
|
|
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
|
|
{
|
|
if (msg.message == WM_QUIT)
|
|
{
|
|
ulQuitCode = (ULONG)(msg.wParam);
|
|
fQuitReceived = TRUE;
|
|
}
|
|
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
if (fQuitReceived)
|
|
PostQuitMessage(ulQuitCode);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsFullScreenSize
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL IsFullScreenSize(HWND hwnd)
|
|
{
|
|
RECT rc;
|
|
GetWindowRect(hwnd, &rc);
|
|
if ((rc.left <= 0) &&
|
|
(rc.top <= 0)&&
|
|
(rc.right >= GetSystemMetrics(SM_CXFULLSCREEN)) &&
|
|
(rc.bottom >= GetSystemMetrics(SM_CYFULLSCREEN)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitUniqueString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL GetUserSIDString(DWORD dwProcessId, char *pch, UINT cch)
|
|
{
|
|
HANDLE hToken = NULL;
|
|
char *pszStringSid = NULL;
|
|
HANDLE hProcess;
|
|
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
|
|
|
|
if (hProcess)
|
|
OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
|
|
|
|
if (hToken)
|
|
{
|
|
DWORD dwReturnLength = 0;
|
|
void *pvUserBuffer = NULL;
|
|
|
|
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwReturnLength);
|
|
|
|
pvUserBuffer = cicMemAllocClear(dwReturnLength);
|
|
if (pvUserBuffer &&
|
|
GetTokenInformation(hToken,
|
|
TokenUser,
|
|
pvUserBuffer,
|
|
dwReturnLength,
|
|
&dwReturnLength))
|
|
{
|
|
if (!ConvertSidToStringSid(((TOKEN_USER*)(pvUserBuffer))->User.Sid,
|
|
&pszStringSid))
|
|
{
|
|
if (pszStringSid)
|
|
LocalFree(pszStringSid);
|
|
|
|
pszStringSid = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
if (pvUserBuffer)
|
|
{
|
|
cicMemFree(pvUserBuffer);
|
|
}
|
|
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
if (hProcess)
|
|
CloseHandle(hProcess);
|
|
|
|
if (pszStringSid)
|
|
{
|
|
StringCchCopy(pch, cch, pszStringSid);
|
|
LocalFree(pszStringSid);
|
|
return TRUE;
|
|
}
|
|
|
|
*pch = '\0';
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitCurrentProcessSid
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL g_fSidInit = FALSE;
|
|
char g_szSid[UNLEN + 1];
|
|
|
|
BOOL InitCurrentProcessSid()
|
|
{
|
|
if (g_fSidInit)
|
|
return TRUE;
|
|
|
|
if (GetUserSIDString(GetCurrentProcessId(), g_szSid, ARRAYSIZE(g_szSid)))
|
|
g_fSidInit = TRUE;
|
|
|
|
return g_fSidInit;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsVisibleWindowInDesktop()
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL CALLBACK EnumVisibleWindowProc(HWND hwnd, LPARAM lParam)
|
|
{
|
|
DWORD dwProcessId;
|
|
|
|
if (!GetWindowThreadProcessId(hwnd, &dwProcessId))
|
|
dwProcessId = 0;
|
|
|
|
//
|
|
// we're not interested in ctfmon's process window.
|
|
//
|
|
if (g_pTipbarWnd && !g_pTipbarWnd->IsInDeskBand())
|
|
if (dwProcessId == GetCurrentProcessId())
|
|
return TRUE;
|
|
|
|
if (IsWindowVisible(hwnd))
|
|
{
|
|
if (g_fSidInit)
|
|
{
|
|
//
|
|
// if the process is owned by different user, we skip it.
|
|
//
|
|
char szSid[UNLEN + 1];
|
|
GetUserSIDString(dwProcessId, szSid, ARRAYSIZE(szSid));
|
|
if (lstrcmp(szSid, g_szSid))
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL *pfFound = (BOOL *)lParam;
|
|
*pfFound = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL IsVisibleWindowInDesktop()
|
|
{
|
|
BOOL fFound = FALSE;
|
|
|
|
InitCurrentProcessSid();
|
|
EnumWindows(EnumVisibleWindowProc, (LPARAM)&fFound);
|
|
return fFound;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarGripper
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarGripper::ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarGripper::CTipbarGripper(CTipbarWnd *pTipbarWnd, RECT *prc, DWORD dwStyle) : CUIFGripper( pTipbarWnd, prc, dwStyle)
|
|
{
|
|
_pTipbarWnd = pTipbarWnd;
|
|
_fInMenu = FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarGripper::OnSetCursor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarGripper::OnSetCursor(UINT uMsg, POINT pt)
|
|
{
|
|
if (!_fInMenu)
|
|
return CUIFGripper::OnSetCursor(uMsg, pt);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarGripper::OnRButtonUp
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarGripper::OnRButtonUp(POINT pt)
|
|
{
|
|
if (!g_bShowDebugMenu)
|
|
return;
|
|
|
|
HMENU hMenu = CreatePopupMenu();
|
|
if (!hMenu)
|
|
return;
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
ClientToScreen(_pTipbarWnd->GetWnd(), &pt);
|
|
|
|
|
|
InsertMenu(hMenu, -1, MF_BYPOSITION | MF_STRING, IDM_CLOSECICLOAD, "Close cicload");
|
|
|
|
#ifdef DEBUG
|
|
InsertMenu(hMenu, -1, MF_BYPOSITION | MF_STRING, IDM_BREAK, CRStr(IDS_BREAK));
|
|
#endif
|
|
InsertMenu(hMenu, -1, MF_BYPOSITION | MF_STRING, IDCANCEL, CRStr(IDS_CANCEL));
|
|
|
|
_fInMenu = TRUE;
|
|
int nRet = TrackPopupMenuEx(hMenu,
|
|
TPM_LEFTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD,
|
|
pt.x, pt.y, _pTipbarWnd->GetWnd(), NULL);
|
|
_fInMenu = FALSE;
|
|
|
|
DestroyMenu(hMenu);
|
|
|
|
switch (nRet)
|
|
{
|
|
case IDM_CLOSECICLOAD:
|
|
{
|
|
_pTipbarWnd->UnInit();
|
|
if (IsWindow(g_hwndParent))
|
|
DestroyWindow(g_hwndParent);
|
|
MSG msg;
|
|
while(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE | PM_NOYIELD));
|
|
PostQuitMessage(0);
|
|
}
|
|
break;
|
|
|
|
#ifdef DEBUG
|
|
case IDM_BREAK:
|
|
DebugBreak();
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarGripper::OnLButtonUp
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarGripper::OnLButtonUp(POINT pt)
|
|
{
|
|
_pTipbarWnd->RestoreFromStub();
|
|
|
|
//
|
|
// Mouse Drag/Drop from floating language bar to deskband.
|
|
//
|
|
if (IsOnNT51())
|
|
{
|
|
APPBARDATA abd;
|
|
RECT rcTrayWnd;
|
|
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
|
|
abd.hWnd = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
|
|
|
|
if (SHAppBarMessage(ABM_GETTASKBARPOS, &abd))
|
|
{
|
|
POINT ptCursor;
|
|
|
|
rcTrayWnd = abd.rc;
|
|
|
|
GetCursorPos(&ptCursor);
|
|
|
|
if ((ptCursor.x >= rcTrayWnd.left && ptCursor.x <= rcTrayWnd.right) &&
|
|
(ptCursor.y >= rcTrayWnd.top && ptCursor.y <= rcTrayWnd.bottom))
|
|
{
|
|
if (g_pTipbarWnd)
|
|
g_pTipbarWnd->GetLangBarMgr()->ShowFloating(TF_SFT_DESKBAND |
|
|
TF_SFT_EXTRAICONSONMINIMIZED);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
CUIFGripper::OnLButtonUp(pt);
|
|
|
|
//
|
|
// CUIFGripper::OnLButonUp() calls MoveWindow.
|
|
// Now we update pos flags of TipbarWnd.
|
|
//
|
|
_pTipbarWnd->UpdatePosFlags();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarWnd
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IUnknown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarWnd::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfLangBarEventSink))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarEventSink *);
|
|
}
|
|
else if (IsEqualIID(riid, IID_ITfLangBarEventSink_P))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarEventSink_P *);
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarWnd::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarWnd::Release()
|
|
{
|
|
_cRef--;
|
|
Assert(_cRef >= 0);
|
|
|
|
if (_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return _cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarWnd::CTipbarWnd(DWORD dwStyle) : CUIFWindow(g_hInst, dwStyle)
|
|
{
|
|
Dbg_MemSetThisName(TEXT("CTipbarWnd"));
|
|
POINT pt;
|
|
RECT rc;
|
|
|
|
pt.x = g_nLeft;
|
|
pt.y = g_nTop;
|
|
CUIGetScreenRect(pt, &rc);
|
|
if (!PtInRect(&rc, pt))
|
|
{
|
|
if (IsOnFE())
|
|
{
|
|
RECT rcWork;
|
|
SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
|
|
g_nLeft = rcWork.right;
|
|
g_nTop = rcWork.bottom;
|
|
}
|
|
else if (g_fRTL)
|
|
{
|
|
g_nLeft = GetSystemMetrics(SM_CXSIZE) * 3;
|
|
g_nTop = 0;
|
|
}
|
|
else
|
|
{
|
|
g_nLeft = GetSystemMetrics(SM_CXSCREEN) - (GetSystemMetrics(SM_CXSIZE) * 3);
|
|
g_nTop = 0;
|
|
}
|
|
}
|
|
|
|
Move(g_nLeft, g_nTop, STATUSWND_WIDTH, STATUSWND_HEIGHT);
|
|
|
|
//
|
|
// initialize Pos flags after calling Move().
|
|
//
|
|
UpdatePosFlags();
|
|
|
|
_fShowText = FALSE;
|
|
_fInStub = FALSE;
|
|
|
|
_hfontMarlett = CreateFont(8, 8, 0, 0, 400, FALSE, FALSE, FALSE, SYMBOL_CHARSET, 0, 0, 0, 0, "Marlett");
|
|
|
|
ITfLangBarMgr *putb;
|
|
if (SUCCEEDED(TF_CreateLangBarMgr(&putb)) && putb)
|
|
{
|
|
putb->QueryInterface(IID_ITfLangBarMgr_P, (void **)&_putb);
|
|
|
|
putb->Release();
|
|
}
|
|
|
|
|
|
if (dwStyle & UIWINDOW_WHISTLERLOOK)
|
|
{
|
|
if (g_fTaskbarTheme)
|
|
SetActiveTheme(L"TASKBAR", TBP_BACKGROUNDBOTTOM, TS_NORMAL );
|
|
else
|
|
SetActiveTheme(L"REBAR", 0, TS_NORMAL );
|
|
}
|
|
|
|
SetVertical(g_fVertical);
|
|
|
|
_cRef = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarWnd::~CTipbarWnd()
|
|
{
|
|
Assert(!_pModalMenu);
|
|
|
|
UnInit();
|
|
|
|
DeleteObject(_hfontMarlett);
|
|
if (_hfontVert)
|
|
DeleteObject(_hfontVert);
|
|
|
|
TFUninitLib_Thread(&g_libTLS);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnInit
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::UnInit()
|
|
{
|
|
SetFocusThread(NULL);
|
|
|
|
int i;
|
|
for (i = 0; i < _rgThread.Count(); i++)
|
|
{
|
|
CTipbarThread *pThread = _rgThread.Get(i);
|
|
if (!pThread)
|
|
continue;
|
|
|
|
pThread->_UninitItemList(TRUE);
|
|
pThread->Disconnect();
|
|
pThread->_Release();
|
|
}
|
|
_rgThread.Clear();
|
|
|
|
if (_putb)
|
|
_putb->UnadviseEventSink(_dwlbimCookie);
|
|
|
|
SafeReleaseClear(_putb);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::OnSetFocus(DWORD dwThreadId)
|
|
{
|
|
BOOL fNewThread = FALSE;
|
|
CTipbarThread *pThread;
|
|
CTipbarThread *pPrevFocusThread;
|
|
BOOL fWasInFullScreen = _fInFullScreen;
|
|
HWND hwndFore = GetForegroundWindow();
|
|
DWORD dwThreadIdFore = GetWindowThreadProcessId(hwndFore, NULL);
|
|
HRESULT hr;
|
|
CTipbarThread *pThreadPrev = NULL;
|
|
BOOL fSkipRedrawOnNoItem = FALSE;
|
|
|
|
TraceMsg(TF_FUNC, "focusnfy OnSetFocus %x ", dwThreadId);
|
|
|
|
//
|
|
// if the toolbar is being terminated, do nothing.
|
|
//
|
|
if (_fTerminating)
|
|
return S_OK;
|
|
|
|
if (_dwThreadIdWaitNotify && (_dwThreadIdWaitNotify != dwThreadId))
|
|
return S_OK;
|
|
//
|
|
// If this MSUTB is in ctfmon.exe and the langbar status is in Deskband,
|
|
// this meutb should stop wroking.
|
|
//
|
|
if (!_fInDeskBand && IsSFDeskband())
|
|
return S_OK;
|
|
|
|
if (!IsWindow(GetWnd()))
|
|
return E_FAIL;
|
|
|
|
StartPendingUpdateUI();
|
|
AddRef();
|
|
|
|
if (!_fInDeskBand && dwThreadIdFore)
|
|
{
|
|
BOOL fScreenSaverRunning = FALSE;
|
|
|
|
if (IsOnNT5() || IsOn98())
|
|
{
|
|
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0,
|
|
&fScreenSaverRunning, FALSE);
|
|
}
|
|
|
|
if (IsFullScreenWindow(hwndFore) || fScreenSaverRunning)
|
|
{
|
|
if (GetWindowLongPtr(GetWnd(), GWL_STYLE) & WS_VISIBLE)
|
|
{
|
|
Show(FALSE);
|
|
_fInFullScreen = TRUE;
|
|
_dwPrevTBStatus = _dwSFTFlags;
|
|
}
|
|
}
|
|
else if (fWasInFullScreen)
|
|
{
|
|
Show(TRUE);
|
|
_fInFullScreen = FALSE;
|
|
|
|
//
|
|
// Bug#500507 - Need to recover language bar show status value.
|
|
//
|
|
if (!(_dwPrevTBStatus & TF_SFT_DESKBAND))
|
|
GetLangBarMgr()->ShowFloating(_dwPrevTBStatus);
|
|
}
|
|
}
|
|
|
|
KillTimer(TIPWND_TIMER_SETWINDOWPOS);
|
|
SetTimer(TIPWND_TIMER_SETWINDOWPOS, g_uTimerElapseSETWINDOWPOS);
|
|
|
|
pThread = _FindThread(dwThreadId);
|
|
if (_pFocusThread && (pThread == _pFocusThread))
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// keep the current focus thread.
|
|
//
|
|
pPrevFocusThread = _pFocusThread;
|
|
|
|
CancelMenu();
|
|
|
|
if (!pThread)
|
|
{
|
|
pThread = _CreateThread(dwThreadId);
|
|
if (!pThread)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
fNewThread = TRUE;
|
|
}
|
|
|
|
//
|
|
// focus has been change during creating pThread.
|
|
// we don't have to do anything now.
|
|
//
|
|
if (_pFocusThread && (pPrevFocusThread != _pFocusThread))
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
_pFocusThread->RemoveUIObjs();
|
|
}
|
|
|
|
SetFocusThread(pThread);
|
|
|
|
if (pThread)
|
|
{
|
|
Assert(pThread == _pFocusThread);
|
|
BOOL fItemChanged = pThread->_fItemChanged;
|
|
|
|
//
|
|
// addref to increment the refcount.
|
|
//
|
|
pThread->_AddRef();
|
|
|
|
hr = S_OK;
|
|
if (fItemChanged)
|
|
hr = pThread->_UninitItemList(TRUE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pThread->RemoveUIObjs();
|
|
|
|
if (fItemChanged)
|
|
pThread->InitItemList();
|
|
}
|
|
|
|
//
|
|
// UninitItemList and InitItemList make marshaling calls.
|
|
// we need to check _pFocusThread again.
|
|
//
|
|
if (pThread == _pFocusThread)
|
|
{
|
|
pThread->LocateItems();
|
|
pThread->AddUIObjs();
|
|
|
|
if (fNewThread || fItemChanged)
|
|
{
|
|
if (!pThread->UpdateItems())
|
|
{
|
|
pThread->RemoveUIObjs();
|
|
SetFocusThread(NULL);
|
|
}
|
|
}
|
|
else if (pThread->IsDirtyItem())
|
|
{
|
|
//
|
|
// this thread has a update dirty item. Need to update now.
|
|
// We got OnUpdate call while it was background thread.
|
|
//
|
|
KillTimer(TIPWND_TIMER_ONUPDATECALLED);
|
|
SetTimer(TIPWND_TIMER_ONUPDATECALLED, g_uTimerElapseONUPDATECALLED);
|
|
}
|
|
}
|
|
|
|
fSkipRedrawOnNoItem = pThread->_fSkipRedrawOnNoItem;
|
|
//
|
|
// release to decrement the refcount.
|
|
//
|
|
pThread->_Release();
|
|
}
|
|
|
|
_ctrlbtnHolder.EnableBtns();
|
|
|
|
if (_fShowTrayIcon)
|
|
{
|
|
KillTimer(TIPWND_TIMER_MOVETOTRAY);
|
|
SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
}
|
|
|
|
//
|
|
// Cic#4712
|
|
//
|
|
if (_dwThreadItemChangedForTimer != dwThreadId)
|
|
{
|
|
KillOnTheadItemChangeTimer();
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
if (fSkipRedrawOnNoItem)
|
|
KillTimer(TIPWND_TIMER_UPDATEUI);
|
|
|
|
EndPendingUpdateUI();
|
|
Release();
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsFullScreenWindow
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::IsFullScreenWindow(HWND hwnd)
|
|
{
|
|
ULONG_PTR dwStyle;
|
|
ULONG_PTR dwExStyle;
|
|
|
|
dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
|
|
if (!(dwStyle & WS_VISIBLE))
|
|
return FALSE;
|
|
|
|
if (dwStyle & WS_CAPTION)
|
|
return FALSE;
|
|
|
|
dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
|
|
|
|
#ifdef OLD_FULLSCREENDETECTION
|
|
if (dwExStyle & WS_EX_TOOLWINDOW)
|
|
return FALSE;
|
|
|
|
if (!IsZoomed(hwnd) && !(dwExStyle & WS_EX_LAYERED))
|
|
{
|
|
if (IsFullScreenSize(hwnd))
|
|
return TRUE;
|
|
}
|
|
#else
|
|
if (dwExStyle & WS_EX_LAYERED)
|
|
return FALSE;
|
|
|
|
//
|
|
// #376691
|
|
//
|
|
// the full screen mode of Windows Media Player uses WS_EX_TOOLWINDOW style.
|
|
// we need to check if it is fullscreen window or not.
|
|
//
|
|
if (dwExStyle & WS_EX_TOOLWINDOW)
|
|
{
|
|
if (hwnd == shellwnd.GetWndProgman())
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// And some shell fullscreen window (such as slide show)
|
|
// has "mazimized" status. So we don't want to check IsZoomed().
|
|
//
|
|
// Thus any application without caption covers the screen won't have a
|
|
// floating toolbar.
|
|
//
|
|
if (IsFullScreenSize(hwnd))
|
|
return TRUE;
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetFocusThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::SetFocusThread(CTipbarThread *pThread)
|
|
{
|
|
if (pThread == _pFocusThread)
|
|
return S_OK;
|
|
|
|
DWORD dwThreadId = GetCurrentThreadId();
|
|
|
|
DestroyOverScreenSizeBalloon();
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
_pFocusThread->SetFocus(FALSE);
|
|
AttachThreadInput(dwThreadId, _pFocusThread->_dwThreadId, FALSE);
|
|
}
|
|
|
|
_pFocusThread = pThread;
|
|
|
|
//
|
|
// we will attach the focus thread input into this thread when
|
|
// when we need (mouse message comes and any other case?).
|
|
//
|
|
_fFocusAttached = FALSE;
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
_pFocusThread->SetFocus(TRUE);
|
|
}
|
|
|
|
if (!_pFocusThread)
|
|
{
|
|
if (!IsVisibleWindowInDesktop())
|
|
{
|
|
// this is a hack to shut down ctfmon.exe when we're in a terminal server session
|
|
// and the main app has shutdown and no shell is running -- terminal server won't
|
|
// end the session as long as ctfmon is running which effectively locks the machine.
|
|
// See cicero bug 4235.
|
|
//
|
|
// Issue: got some more info from the terminal server team, another cleaner fix:
|
|
//
|
|
// Anyway if you need to put something in "not wait for" list, just add a value to
|
|
// "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\SysProcs" key.
|
|
// Name of the value should be equal to a name of executable, type is REG_DWORD, value is 0.
|
|
if (!_fInDeskBand)
|
|
PostQuitMessage(0);
|
|
else if (_pDeskBand)
|
|
_pDeskBand->DeleteBand();
|
|
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AttachFocusThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::AttachFocusThread()
|
|
{
|
|
if (_fFocusAttached)
|
|
return TRUE;
|
|
|
|
//
|
|
// Attach the focus thread when mouse message is coming. Since this
|
|
// toolbar window is disabled window, using different input focus
|
|
// causes unexpected focus change.
|
|
//
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
DWORD dwThreadId = GetCurrentThreadId();
|
|
AttachThreadInput(dwThreadId, _pFocusThread->_dwThreadId, TRUE);
|
|
_fFocusAttached = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ThreadTerminate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::OnThreadTerminate(DWORD dwThreadId)
|
|
{
|
|
HRESULT hr;
|
|
|
|
StartPendingUpdateUI();
|
|
AddRef();
|
|
|
|
hr = OnThreadTerminateInternal(dwThreadId);
|
|
if (!_pFocusThread)
|
|
EnsureFocusThread();
|
|
|
|
EndPendingUpdateUI();
|
|
Release();
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnThreadTerminateInternal
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::OnThreadTerminateInternal(DWORD dwThreadId)
|
|
{
|
|
TraceMsg(TF_FUNC, "focusnfy OnThreadTerminate %x ", dwThreadId);
|
|
|
|
int i;
|
|
for (i = 0; i < _rgThread.Count(); i++)
|
|
{
|
|
CTipbarThread *pThread = _rgThread.Get(i);
|
|
if (!pThread)
|
|
continue;
|
|
|
|
if (pThread->_dwThreadId == dwThreadId)
|
|
{
|
|
_rgThread.Remove(i, 1);
|
|
|
|
pThread->RemoveUIObjs();
|
|
|
|
CleanUpThreadPointer(pThread, FALSE);
|
|
|
|
pThread->_UninitItemList(TRUE);
|
|
pThread->Disconnect();
|
|
pThread->_Release();
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CleanUpThreadPointer
|
|
//
|
|
// This function make sure CTipbarWnd does not have pThread pointer any more.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::CleanUpThreadPointer(CTipbarThread *pThread, BOOL fCheckThreadArray)
|
|
{
|
|
Assert(pThread);
|
|
|
|
if (fCheckThreadArray)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgThread.Count(); i++)
|
|
{
|
|
if (pThread == _rgThread.Get(i))
|
|
{
|
|
_rgThread.Remove(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pThread == _pFocusThread)
|
|
SetFocusThread(NULL);
|
|
|
|
if (pThread == _pttModal)
|
|
_pttModal = NULL;
|
|
|
|
if (pThread == _pThreadShowWindowAtTimer)
|
|
_pThreadShowWindowAtTimer = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnsureFocusThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::EnsureFocusThread()
|
|
{
|
|
if (_pFocusThread)
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
if (_fTerminating)
|
|
return;
|
|
|
|
if (_fInEnsureFocusThread)
|
|
return;
|
|
|
|
_fInEnsureFocusThread = TRUE;
|
|
|
|
HWND hwndFore = GetForegroundWindow();
|
|
if (hwndFore)
|
|
{
|
|
DWORD dwThreadId = GetWindowThreadProcessId(hwndFore, NULL);
|
|
if (dwThreadId)
|
|
OnSetFocus(dwThreadId);
|
|
}
|
|
|
|
_fInEnsureFocusThread = FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnThreadItemChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::OnThreadItemChange(DWORD dwThreadId)
|
|
{
|
|
CTipbarThread *pThread;
|
|
TraceMsg(TF_FUNC, "focusnfy OnThreadItemChange %x ", dwThreadId);
|
|
|
|
//
|
|
// if the toolbar is being terminated, do nothing.
|
|
//
|
|
if (_fTerminating)
|
|
return S_OK;
|
|
|
|
//
|
|
// If this MSUTB is in ctfmon.exe and the langbar status is in Deskband,
|
|
// this meutb should stop wroking.
|
|
//
|
|
if (!_fInDeskBand && IsSFDeskband())
|
|
return S_OK;
|
|
|
|
pThread = _FindThread(dwThreadId);
|
|
if (!pThread)
|
|
{
|
|
#if 0
|
|
//
|
|
// Issue: #365434 - In the running of Deskband after just restart
|
|
// machine, this hit will disable the showing deskband.
|
|
//
|
|
if (!_pFocusThread)
|
|
Show(FALSE);
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
if ((_dwThreadIdWaitNotify && (_dwThreadIdWaitNotify != dwThreadId)) ||
|
|
(pThread != _pFocusThread))
|
|
{
|
|
pThread->_fItemChanged = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
KillOnTheadItemChangeTimer();
|
|
|
|
_dwThreadItemChangedForTimer = dwThreadId;
|
|
KillTimer(TIPWND_TIMER_ONUPDATECALLED);
|
|
SetTimer(TIPWND_TIMER_ONTHREADITEMCHANGE, g_uTimerElapseONTHREADITEMCHANGE);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnThreadItemChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarWnd::OnThreadItemChangeInternal(DWORD dwThreadId)
|
|
{
|
|
CTipbarThread *pThread;
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceMsg(TF_FUNC, "focusnfy OnThreadItemChangeInternal %x ", dwThreadId);
|
|
|
|
if (_dwThreadIdWaitNotify && (_dwThreadIdWaitNotify != dwThreadId))
|
|
return S_OK;
|
|
|
|
//
|
|
// If this MSUTB is in ctfmon.exe and the langbar status is in Deskband,
|
|
// this meutb should stop wroking.
|
|
//
|
|
if (!_fInDeskBand && IsSFDeskband())
|
|
return S_OK;
|
|
|
|
pThread = _FindThread(dwThreadId);
|
|
|
|
if (!pThread)
|
|
return S_OK;
|
|
|
|
if (pThread != _pFocusThread)
|
|
{
|
|
pThread->_fItemChanged = TRUE;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Ok, dwThreadId has a focus now, we need immediate action to update
|
|
// langbar.
|
|
//
|
|
Assert(dwThreadId == pThread->_dwThreadId);
|
|
|
|
StartPendingUpdateUI();
|
|
|
|
//
|
|
// addref to increment the refcount.
|
|
//
|
|
pThread->_AddRef();
|
|
|
|
hr = pThread->_UninitItemList(TRUE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pThread->RemoveUIObjs();
|
|
hr = pThread->InitItemList();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// UninitItemList and InitItemList make marshaling calls.
|
|
// we need to check _pFocusThread again.
|
|
//
|
|
if (pThread == _pFocusThread)
|
|
{
|
|
pThread->LocateItems();
|
|
pThread->AddUIObjs();
|
|
pThread->UpdateItems();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// release to decrement the refcount.
|
|
//
|
|
pThread->_Release();
|
|
|
|
//
|
|
// #366835
|
|
//
|
|
// We got an error for the focus thread. Marshalling stubs might been gone!
|
|
// Let's restart marshaling.
|
|
//
|
|
if (hr == RPC_E_CONNECTION_TERMINATED)
|
|
{
|
|
//
|
|
// Throw away lost marshalled interfaces.
|
|
//
|
|
OnThreadTerminateInternal(dwThreadId);
|
|
|
|
//
|
|
// OnSetFocus() will reacate CTipbarThread.
|
|
//
|
|
OnSetFocus(dwThreadId);
|
|
}
|
|
|
|
_ctrlbtnHolder.EnableBtns();
|
|
|
|
// InvalidateRect(GetWnd(), NULL, TRUE);
|
|
if (_fShowTrayIcon)
|
|
{
|
|
KillTimer(TIPWND_TIMER_MOVETOTRAY);
|
|
SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
}
|
|
|
|
EndPendingUpdateUI();
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MoveToTray
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::MoveToTray()
|
|
{
|
|
//
|
|
// we don't use NotyfTrayIcon on WinXP.
|
|
//
|
|
if (IsOnNT51())
|
|
return;
|
|
|
|
if (!g_pTrayIconWnd)
|
|
return;
|
|
|
|
//
|
|
// Even if the floating toolbar setting is "minimized", we need to show
|
|
// it when explorer.exe is not running.
|
|
//
|
|
if (!g_pTrayIconWnd->GetNotifyWnd())
|
|
{
|
|
Show(TRUE);
|
|
return;
|
|
}
|
|
|
|
if (_fShowTrayIcon)
|
|
{
|
|
if (_pFocusThread)
|
|
{
|
|
if (TF_IsInMarshaling(_pFocusThread->_dwThreadId))
|
|
{
|
|
SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
// we move to TrayIcon. Make sure the toolbar is hidden.
|
|
//
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
Show(FALSE);
|
|
|
|
DestroyOverScreenSizeBalloon();
|
|
CTipbarItem *pItem = NULL;
|
|
BOOL fIsKeyboardItemVisible = FALSE;
|
|
CTipbarItem *pKeyboardItem = NULL;
|
|
if (_pFocusThread)
|
|
{
|
|
if (_pFocusThread->IsConsole())
|
|
pItem = _pFocusThread->GetItem(GUID_LBI_INATITEM);
|
|
else
|
|
pItem = _pFocusThread->GetItem(GUID_LBI_CTRL);
|
|
|
|
if (pItem && !pItem->IsVisibleInToolbar())
|
|
pItem = NULL;
|
|
|
|
pKeyboardItem = _pFocusThread->GetItem(GUID_TFCAT_TIP_KEYBOARD);
|
|
if (pKeyboardItem && !pKeyboardItem->IsInHiddenStatus())
|
|
fIsKeyboardItemVisible = TRUE;
|
|
}
|
|
|
|
//
|
|
// we don't have to show UTB's Main Icon when
|
|
// - there is LBI_INATITEM or LBI_CTRL item.
|
|
// - there is a visible keyboard item.
|
|
//
|
|
g_pTrayIconWnd->SetMainIcon(pItem ? NULL : fIsKeyboardItemVisible ? NULL : GetFocusKeyboardLayout());
|
|
|
|
if (!g_pTrayIconWnd->_fShowExtraIcons)
|
|
{
|
|
DWORD dwRAIFlags = 0;
|
|
if (pItem)
|
|
dwRAIFlags |= TIW_RAI_LEAVELANGICON;
|
|
|
|
if (fIsKeyboardItemVisible)
|
|
dwRAIFlags |= TIW_RAI_LEAVEKEYBOARDICON;
|
|
|
|
g_pTrayIconWnd->RemoveAllIcon(dwRAIFlags);
|
|
|
|
if (pItem)
|
|
{
|
|
pItem->MoveToTray();
|
|
}
|
|
else if (fIsKeyboardItemVisible)
|
|
{
|
|
Assert(!!pKeyboardItem)
|
|
pKeyboardItem->MoveToTray();
|
|
}
|
|
}
|
|
else if (_pFocusThread)
|
|
{
|
|
int i;
|
|
|
|
g_pTrayIconWnd->RemoveUnusedIcons(&_pFocusThread->_rgItem);
|
|
|
|
for (i = 0; i < _pFocusThread->_rgItem.Count(); i++)
|
|
{
|
|
if (TF_IsInMarshaling(_pFocusThread->_dwThreadId))
|
|
{
|
|
SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
return;
|
|
}
|
|
|
|
pItem = _pFocusThread->_rgItem.Get(i);
|
|
if (pItem)
|
|
pItem->MoveToTray();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnModalInput
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarWnd::OnModalInput(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_KEYDOWN:
|
|
case WM_KEYUP:
|
|
if (_pttModal)
|
|
{
|
|
Assert(_pModalMenu);
|
|
Assert(_pttModal->_dwThreadId == dwThreadId);
|
|
_pModalMenu->PostKey((uMsg == WM_KEYUP), wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_NCLBUTTONDOWN:
|
|
case WM_NCRBUTTONDOWN:
|
|
case WM_NCMBUTTONDOWN:
|
|
break;
|
|
|
|
case WM_NCLBUTTONUP:
|
|
case WM_NCRBUTTONUP:
|
|
case WM_NCMBUTTONUP:
|
|
//
|
|
// Multi Monitor
|
|
//
|
|
// if the disable window is in the negative location of
|
|
// screen coordinate, wm_ncxx message is generated.
|
|
// (maybe this is not mm specific, since siable window does not
|
|
// get WM_NCHITTEST.)
|
|
//
|
|
// we just forward this message to modal menu window as a normal
|
|
// mouse message to simulate the mouse action.
|
|
//
|
|
if (_pttModal)
|
|
{
|
|
Assert(_pModalMenu);
|
|
Assert(_pttModal->_dwThreadId == dwThreadId);
|
|
HWND hwnd = _pModalMenu->GetWnd();
|
|
if (hwnd)
|
|
{
|
|
POINT pt;
|
|
POINTSTOPOINT( pt, MAKEPOINTS( lParam ) );
|
|
ScreenToClient(hwnd, &pt);
|
|
PostMessage(hwnd,
|
|
uMsg + (WM_MOUSEMOVE - WM_NCMOUSEMOVE),
|
|
wParam,
|
|
MAKELPARAM(pt.x, pt.y));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
case WM_MBUTTONUP:
|
|
break;
|
|
|
|
default:
|
|
CancelMenu();
|
|
break;
|
|
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ShowFloating
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarWnd::ShowFloating(DWORD dwFlags)
|
|
{
|
|
if (_fInDeskBand)
|
|
{
|
|
_dwSFTFlags = dwFlags;
|
|
|
|
if (dwFlags & TF_SFT_DESKBAND)
|
|
{
|
|
//
|
|
// If we don't have _pFocusThread, the empty langbar is shown.
|
|
// Try to get the thread of the foreground window. This may not
|
|
// work correctly because the actual focus could be different
|
|
// from the thread of the foreground window.
|
|
//
|
|
if (!_pFocusThread)
|
|
{
|
|
KillTimer(TIPWND_TIMER_ENSUREFOCUS);
|
|
SetTimer(TIPWND_TIMER_ENSUREFOCUS, g_uTimerElapseENSUREFOCUS);
|
|
}
|
|
|
|
//
|
|
// Update Extra icons changing options
|
|
//
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
SetTimer(TIPWND_TIMER_SYSCOLORCHANGED, g_uTimerElapseSYSCOLORCHANGED);
|
|
}
|
|
|
|
if (dwFlags & TF_SFT_EXTRAICONSONMINIMIZED)
|
|
{
|
|
_fAddExtraIcon = TRUE;
|
|
ClearDeskbandSizeAdjusted();
|
|
}
|
|
else if (dwFlags & TF_SFT_NOEXTRAICONSONMINIMIZED)
|
|
{
|
|
_fAddExtraIcon = FALSE;
|
|
ClearDeskbandSizeAdjusted();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
if (dwFlags & TF_SFT_SHOWNORMAL)
|
|
{
|
|
//
|
|
// we update the itemlist from registry now.
|
|
// something might be change during deskbanding.
|
|
//
|
|
_itemList.Load();
|
|
|
|
SetShowTrayIcon(FALSE);
|
|
|
|
//
|
|
// Call SetLangBar() before updating _dwSFTFlags.
|
|
//
|
|
SetLangBand(FALSE);
|
|
|
|
//
|
|
// Set SHOWNOARMAL flag before calling OnSetFocus().
|
|
//
|
|
_dwSFTFlags = TF_SFT_SHOWNORMAL;
|
|
|
|
//
|
|
// If we don't have _pFocusThread, the empty langbar is shown.
|
|
// Try to get the thread of the foreground window. This may not
|
|
// work correctly because the actual focus could be different
|
|
// from the thread of the foreground window.
|
|
//
|
|
if (!_pFocusThread)
|
|
EnsureFocusThread();
|
|
|
|
Show(TRUE);
|
|
|
|
}
|
|
else if (dwFlags & TF_SFT_DOCK)
|
|
{
|
|
//
|
|
// Call SetLangBar() before updating _dwSFTFlags.
|
|
//
|
|
SetLangBand(FALSE);
|
|
_dwSFTFlags = TF_SFT_DOCK;
|
|
}
|
|
else if (dwFlags & TF_SFT_MINIMIZED)
|
|
{
|
|
SetShowTrayIcon(TRUE);
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
Show(FALSE);
|
|
|
|
//
|
|
// Call SetLangBar() before updating _dwSFTFlags.
|
|
//
|
|
SetLangBand(FALSE);
|
|
|
|
_dwSFTFlags = TF_SFT_MINIMIZED;
|
|
}
|
|
else if (dwFlags & TF_SFT_HIDDEN)
|
|
{
|
|
SetShowTrayIcon(FALSE);
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
Show(FALSE);
|
|
|
|
//
|
|
// Call SetLangBar() before updating _dwSFTFlags.
|
|
//
|
|
SetLangBand(FALSE);
|
|
_dwSFTFlags = TF_SFT_HIDDEN;
|
|
|
|
TurnOffSpeechIfItsOn();
|
|
}
|
|
else if (dwFlags & TF_SFT_DESKBAND)
|
|
{
|
|
SetShowTrayIcon(FALSE);
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
KillTimer(TIPWND_TIMER_SHOWDESKBAND);
|
|
Show(FALSE);
|
|
|
|
//
|
|
// if the process of explorer belongs to different user, we don't
|
|
// set langband.
|
|
//
|
|
if (InitCurrentProcessSid())
|
|
{
|
|
DWORD dwProcessIdTray;
|
|
HWND hwndTray = shellwnd.GetWndTray();
|
|
GetWindowThreadProcessId(hwndTray, &dwProcessIdTray);
|
|
if (dwProcessIdTray)
|
|
{
|
|
char szSid[UNLEN + 1];
|
|
GetUserSIDString(dwProcessIdTray, szSid, ARRAYSIZE(szSid));
|
|
if (lstrcmp(szSid, g_szSid))
|
|
return S_OK;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Need to make sure adding the language bar menu on taskbar
|
|
//
|
|
SetRegisterLangBand(TRUE);
|
|
|
|
//
|
|
// BugBug#377897 - Always show the extra additional icons in case of
|
|
// single keyboard layout.
|
|
//
|
|
if (IsSFNoExtraIcon())
|
|
{
|
|
if (IsSingleKeyboardLayout())
|
|
{
|
|
GetLangBarMgr()->ShowFloating(TF_SFT_EXTRAICONSONMINIMIZED);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call SetLangBar() before updating _dwSFTFlags.
|
|
//
|
|
if (SetLangBand(TRUE))
|
|
_dwSFTFlags = TF_SFT_DESKBAND;
|
|
else
|
|
SetTimer(TIPWND_TIMER_SHOWDESKBAND, g_uTimerElapseSHOWDESKBAND);
|
|
}
|
|
|
|
if (dwFlags & TF_SFT_NOTRANSPARENCY)
|
|
{
|
|
SetAlpha(255, FALSE);
|
|
}
|
|
else if (dwFlags & TF_SFT_LOWTRANSPARENCY)
|
|
{
|
|
SetAlpha(128, FALSE);
|
|
}
|
|
else if (dwFlags & TF_SFT_HIGHTRANSPARENCY)
|
|
{
|
|
SetAlpha(62, FALSE);
|
|
}
|
|
|
|
if (dwFlags & TF_SFT_LABELS)
|
|
{
|
|
SetShowText(TRUE);
|
|
}
|
|
else if (dwFlags & TF_SFT_NOLABELS)
|
|
{
|
|
SetShowText(FALSE);
|
|
}
|
|
|
|
if (dwFlags & TF_SFT_EXTRAICONSONMINIMIZED)
|
|
{
|
|
_fAddExtraIcon = TRUE;
|
|
|
|
if (g_pTrayIconWnd)
|
|
{
|
|
g_pTrayIconWnd->_fShowExtraIcons = TRUE;
|
|
if (_fShowTrayIcon)
|
|
SetShowTrayIcon(TRUE);
|
|
}
|
|
}
|
|
else if (dwFlags & TF_SFT_NOEXTRAICONSONMINIMIZED)
|
|
{
|
|
_fAddExtraIcon = FALSE;
|
|
|
|
if (g_pTrayIconWnd)
|
|
{
|
|
g_pTrayIconWnd->_fShowExtraIcons = FALSE;
|
|
if (_fShowTrayIcon)
|
|
SetShowTrayIcon(TRUE);
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetItemFloatingRect
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarWnd::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (IsShowTrayIcon())
|
|
return E_UNEXPECTED;
|
|
|
|
if (!_pFocusThread)
|
|
return E_FAIL;
|
|
|
|
if (_pFocusThread->_dwThreadId != dwThreadId)
|
|
return E_FAIL;
|
|
|
|
hr = E_FAIL;
|
|
|
|
int i;
|
|
for (i = 0; i < _pFocusThread->_rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _pFocusThread->_rgItem.Get(i);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
if (pItem->IsVisibleInToolbar() && IsEqualGUID(*pItem->GetGUID(), rguid))
|
|
{
|
|
pItem->GetScreenRect(prc);
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnLangBarUpdate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarWnd::OnLangBarUpdate(UINT uUpdate, LPARAM lParam)
|
|
{
|
|
switch (uUpdate)
|
|
{
|
|
case TF_LBU_CAPSKANAKEY:
|
|
_ctrlbtnHolder.UpdateCapsKanaState(lParam);
|
|
break;
|
|
|
|
case TF_LBU_NTCONSOLELANGCHANGE:
|
|
if (_pFocusThread && _pFocusThread->IsConsole())
|
|
{
|
|
CTipbarItem *pItem = _pFocusThread->GetItem(GUID_LBI_INATITEM);
|
|
if (pItem)
|
|
{
|
|
CLBarInatItem *plbi = (CLBarInatItem *)pItem->GetNotifyUI();
|
|
|
|
HKL hkl = (HKL)lParam;
|
|
if (!hkl)
|
|
{
|
|
//
|
|
// #403714
|
|
//
|
|
// Don't know when GetKeyboardLayout() starts returning
|
|
// the correct value for the Console thread id.
|
|
// Want to use another timer to have an interval but
|
|
// having lots of code and path is not good idea at
|
|
// this time (just before releasing WinXP).
|
|
// Calling Sleep() with small interval looks the
|
|
// safest way to solve this problem.
|
|
//
|
|
Sleep(50);
|
|
hkl = GetKeyboardLayout(_pFocusThread->_dwThreadId);
|
|
}
|
|
|
|
plbi->SetHKL(hkl);
|
|
if (g_pTrayIconWnd)
|
|
{
|
|
g_pTrayIconWnd->SetMainIcon(NULL);
|
|
}
|
|
}
|
|
_pFocusThread->UpdateItems();
|
|
}
|
|
break;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// FindAndCreateThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarThread *CTipbarWnd::_FindThread(DWORD dwThreadId)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgThread.Count(); i++)
|
|
{
|
|
CTipbarThread *pThread = _rgThread.Get(i);
|
|
if (!pThread)
|
|
continue;
|
|
|
|
if (pThread->_dwThreadId == dwThreadId)
|
|
{
|
|
DWORD dwProcessId;
|
|
DWORD dwThreadFlags;
|
|
DWORD dwTickTime;
|
|
|
|
//
|
|
// TF_GetThreadFlag() does not work corrently on
|
|
// winlogon desktop..
|
|
//
|
|
if (g_bWinLogon)
|
|
break;
|
|
|
|
TF_GetThreadFlags(dwThreadId, &dwThreadFlags, &dwProcessId, &dwTickTime);
|
|
|
|
if (!dwProcessId ||
|
|
(dwProcessId != pThread->_dwProcessId) ||
|
|
(dwTickTime != pThread->_dwTickTime))
|
|
{
|
|
OnThreadTerminateInternal(dwThreadId);
|
|
pThread = NULL;
|
|
}
|
|
|
|
return pThread;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// FindAndCreateThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarThread *CTipbarWnd::_CreateThread(DWORD dwThreadId)
|
|
{
|
|
HRESULT hr;
|
|
CTipbarThread *pThread = _FindThread(dwThreadId);
|
|
|
|
if (pThread)
|
|
return pThread;
|
|
|
|
CTipbarThread **ppThread;
|
|
|
|
MyWaitForInputIdle(dwThreadId, UTB_INPUTIDLETIMEOUT);
|
|
|
|
pThread = new CTipbarThread(this);
|
|
if (!pThread)
|
|
goto Exit;
|
|
|
|
hr = pThread->Init(dwThreadId);
|
|
if (FAILED(hr))
|
|
{
|
|
goto FreeThread;
|
|
}
|
|
|
|
if (SUCCEEDED(pThread->InitItemList()))
|
|
{
|
|
TraceMsg(TF_GENERAL, "OnSetFocus Create New CTipbarThreadm");
|
|
|
|
ppThread = _rgThread.Append(1);
|
|
if (!ppThread)
|
|
{
|
|
goto FreeThread;
|
|
}
|
|
|
|
*ppThread = pThread;
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(TF_GENERAL, "focusnfy OnSetFocus fail to create CTipbarThreadm");
|
|
FreeThread:
|
|
pThread->_UninitItemList(TRUE);
|
|
pThread->Disconnect();
|
|
pThread->_Release();
|
|
pThread = NULL;
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return pThread;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::Init(BOOL fInDeskBand, CDeskBand *pDeskBand)
|
|
{
|
|
RECT rc;
|
|
|
|
|
|
if (_fInDeskBand = fInDeskBand)
|
|
_fShowText = FALSE;
|
|
|
|
_pDeskBand = pDeskBand;
|
|
|
|
::SetRect(&rc, 0, 0, 0, 0);
|
|
|
|
if (g_bNewLook &&
|
|
!_pWndFrame &&
|
|
(GetStyle() & UIWINDOW_OFC10TOOLBAR))
|
|
{
|
|
UINT uWndFrameStyle;
|
|
|
|
uWndFrameStyle = UIWNDFRAME_THIN | UIWNDFRAME_NORESIZE;
|
|
|
|
_pWndFrame = new CUIFWndFrame(this, &rc, uWndFrameStyle);
|
|
|
|
if (_pWndFrame)
|
|
{
|
|
_pWndFrame->Initialize();
|
|
|
|
AddUIObj(_pWndFrame);
|
|
}
|
|
}
|
|
|
|
if (!_pGripper && !_fInDeskBand)
|
|
{
|
|
_pGripper = new CTipbarGripper(this, &rc, IsVertical() ? UIGRIPPER_VERTICAL : 0);
|
|
|
|
if (_pGripper)
|
|
{
|
|
_pGripper->Initialize();
|
|
|
|
AddUIObj(_pGripper);
|
|
}
|
|
}
|
|
|
|
|
|
_ctrlbtnHolder.Init(this);
|
|
|
|
if (!IsVertical())
|
|
Move(_xWnd, _yWnd, 0, GetTipbarHeight());
|
|
else
|
|
Move(_xWnd, _yWnd, GetTipbarHeight(), 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetVertical
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::SetVertical(BOOL fVertical)
|
|
{
|
|
int iPartID;
|
|
_fVertical = fVertical;
|
|
|
|
if (_fVertical)
|
|
iPartID = TBP_BACKGROUNDLEFT;
|
|
else
|
|
iPartID = TBP_BACKGROUNDBOTTOM;
|
|
|
|
if (_pGripper)
|
|
{
|
|
DWORD dwStyle = _pGripper->GetStyle();
|
|
if (fVertical)
|
|
dwStyle |= UIGRIPPER_VERTICAL;
|
|
else
|
|
dwStyle &= ~UIGRIPPER_VERTICAL;
|
|
_pGripper->SetStyle(dwStyle);
|
|
}
|
|
|
|
if (g_fTaskbarTheme)
|
|
SetActiveTheme(L"TASKBAR", iPartID, TS_NORMAL );
|
|
|
|
if (!_fInDeskBand)
|
|
{
|
|
if (!IsVertical())
|
|
Move(_xWnd, _yWnd, 0, GetTipbarHeight());
|
|
else
|
|
Move(_xWnd, _yWnd, GetTipbarHeight(), 0);
|
|
}
|
|
|
|
if (GetWnd())
|
|
{
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
SetTimer(TIPWND_TIMER_SYSCOLORCHANGED, g_uTimerElapseSYSCOLORCHANGED);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitThemeMargins
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::InitThemeMargins()
|
|
{
|
|
CUIFTheme themeBtn;
|
|
memset(&_marginsItem, 0, sizeof(_marginsItem));
|
|
_cxItemMargin = CX_ITEMMARGIN;
|
|
_nItemDistance = ITEMDISTANCE;
|
|
_nCtrlItemHeightMargin = CTRLITEMHEIGHTMARGIN;
|
|
_cxCapBtn = GetSystemMetrics( SM_CXSIZE );
|
|
|
|
themeBtn.SetActiveTheme(L"TOOLBAR", TP_BUTTON, 0);
|
|
if (SUCCEEDED(themeBtn.OpenThemeData(GetWnd())))
|
|
{
|
|
themeBtn.GetThemeMargins(NULL, TS_NORMAL,
|
|
TMT_CONTENTMARGINS,
|
|
NULL, &_marginsItem);
|
|
_cxItemMargin = CX_ITEMMARGIN_THEME;
|
|
_nItemDistance = ITEMDISTANCE_THEME;
|
|
_nCtrlItemHeightMargin = CTRLITEMHEIGHTMARGIN_THEME;
|
|
}
|
|
|
|
themeBtn.CloseThemeData();
|
|
themeBtn.SetActiveTheme(L"WINDOW", WP_CLOSEBUTTON, 0);
|
|
if (SUCCEEDED(themeBtn.OpenThemeData(GetWnd())))
|
|
{
|
|
SIZE size;
|
|
themeBtn.GetThemePartSize(NULL, TS_NORMAL,
|
|
NULL,
|
|
TS_TRUE,
|
|
&size);
|
|
|
|
int cy = themeBtn.GetThemeSysSize(SM_CYSIZE);
|
|
_cxCapBtn = MulDiv(cy, size.cx, size.cy);
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateVerticalFont
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::UpdateVerticalFont()
|
|
{
|
|
if (_fVertical)
|
|
{
|
|
if (_hfontVert)
|
|
{
|
|
DeleteObject(_hfontVert);
|
|
SetFontToThis(NULL);
|
|
_hfontVert = NULL;
|
|
}
|
|
|
|
_hfontVert = CreateVerticalFont();
|
|
SetFontToThis(_hfontVert);
|
|
}
|
|
else
|
|
{
|
|
SetFontToThis(NULL);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CheckEAFonts
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int CALLBACK FindEAEnumFontProc(const LOGFONT *plf, const TEXTMETRIC *ptm, WORD wType, LPARAM lParam)
|
|
{
|
|
BOOL *pf = (BOOL *)lParam;
|
|
|
|
if (wType != TRUETYPE_FONTTYPE)
|
|
return 1;
|
|
|
|
if (plf->lfFaceName[0] == '@')
|
|
{
|
|
*pf = TRUE;
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
BOOL CheckEAFonts()
|
|
{
|
|
HDC hdc = GetDC(NULL);
|
|
BOOL fFound = FALSE;
|
|
|
|
EnumFonts(hdc, NULL, (FONTENUMPROC)FindEAEnumFontProc, (LPARAM)&fFound);
|
|
|
|
ReleaseDC(NULL, hdc);
|
|
return fFound;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CreateVerticalFont
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HFONT CTipbarWnd::CreateVerticalFont()
|
|
{
|
|
HFONT hfontVert = NULL;
|
|
CUIFTheme themeBtn;
|
|
themeBtn.SetActiveTheme(L"TOOLBAR", TP_BUTTON, 0);
|
|
|
|
if (!GetWnd())
|
|
return NULL;
|
|
|
|
BOOL fIsEAFonts = CheckEAFonts();
|
|
|
|
if (SUCCEEDED(themeBtn.OpenThemeData(GetWnd())))
|
|
{
|
|
LOGFONTW lfw;
|
|
Assert(IsOnNT51());
|
|
|
|
if (SUCCEEDED(themeBtn.GetThemeFont(NULL, 0 , TMT_FONT, &lfw)))
|
|
{
|
|
lfw.lfEscapement = 2700;
|
|
lfw.lfOrientation = 2700;
|
|
lfw.lfOutPrecision = OUT_TT_ONLY_PRECIS;
|
|
|
|
if (fIsEAFonts)
|
|
{
|
|
//
|
|
// Use @font for vertical langbar.
|
|
//
|
|
WCHAR szFaceName[LF_FACESIZE];
|
|
szFaceName[0] = L'@';
|
|
StringCchCopyW(&szFaceName[1], ARRAYSIZE(szFaceName) -1, lfw.lfFaceName);
|
|
StringCchCopyW(lfw.lfFaceName, ARRAYSIZE(lfw.lfFaceName), szFaceName);
|
|
|
|
}
|
|
hfontVert = CreateFontIndirectW(&lfw);
|
|
goto CheckFont;
|
|
}
|
|
}
|
|
|
|
LOGFONT lf;
|
|
HFONT hDefFont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
|
|
GetObject(hDefFont, sizeof(LOGFONT), &lf);
|
|
lf.lfEscapement = 2700;
|
|
lf.lfOrientation = 2700;
|
|
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
|
|
|
|
if (fIsEAFonts)
|
|
{
|
|
//
|
|
// Use @font for vertical langbar.
|
|
//
|
|
char szFaceName[LF_FACESIZE];
|
|
szFaceName[0] = '@';
|
|
StringCchCopy(&szFaceName[1], ARRAYSIZE(szFaceName) -1, lf.lfFaceName);
|
|
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), szFaceName);
|
|
}
|
|
|
|
hfontVert = CreateFontIndirect(&lf);
|
|
|
|
CheckFont:
|
|
return hfontVert;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetLangBand
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::SetLangBand(BOOL fLangBand, BOOL fNotify)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
if (fLangBand == (IsSFDeskband() ? TRUE : FALSE))
|
|
return fRet;
|
|
|
|
//
|
|
// Set/Remove language band object
|
|
//
|
|
HWND hwndTray = shellwnd.GetWndTray();
|
|
|
|
if (fNotify && hwndTray)
|
|
{
|
|
#ifndef CUAS_ENABLE
|
|
DWORD_PTR dwResult;
|
|
LRESULT lResult = (LRESULT)0;
|
|
|
|
lResult = SendMessageTimeout(hwndTray,
|
|
TM_LANGUAGEBAND,
|
|
0,
|
|
fLangBand,
|
|
SMTO_ABORTIFHUNG | SMTO_BLOCK,
|
|
5000,
|
|
&dwResult);
|
|
|
|
//
|
|
// Checking the language band setting fail case
|
|
//
|
|
if (!lResult || dwResult != fLangBand)
|
|
{
|
|
Assert(0);
|
|
}
|
|
#else
|
|
DWORD_PTR dwResult;
|
|
LRESULT lResult = (LRESULT)0;
|
|
|
|
//
|
|
// Workaround fixes of Cicero 5181
|
|
// Explorer process doesn't initialize _ptbs yet when receive TM_LANGUAGEBAND.
|
|
//
|
|
HWND hwndIME = NULL;
|
|
|
|
//
|
|
// we should not load IMM32 here. If there is no IMM32.DLL loaded,
|
|
// there is no hwndIME.
|
|
//
|
|
if (GetSystemModuleHandle("imm32.dll"))
|
|
hwndIME = ImmGetDefaultIMEWnd(hwndTray);
|
|
|
|
if (hwndIME)
|
|
{
|
|
lResult = SendMessageTimeout(hwndIME,
|
|
WM_IME_SYSTEM,
|
|
fLangBand ? IMS_SETLANGBAND : IMS_RESETLANGBAND,
|
|
(LPARAM)hwndTray,
|
|
SMTO_ABORTIFHUNG | SMTO_BLOCK,
|
|
5000,
|
|
&dwResult);
|
|
}
|
|
else
|
|
{
|
|
lResult = SendMessageTimeout(hwndTray,
|
|
TM_LANGUAGEBAND,
|
|
0,
|
|
fLangBand,
|
|
SMTO_ABORTIFHUNG | SMTO_BLOCK,
|
|
5000,
|
|
&dwResult);
|
|
}
|
|
|
|
//
|
|
// Checking the language band setting fail case
|
|
//
|
|
if (!lResult || dwResult != fLangBand)
|
|
{
|
|
Assert(0);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// If this MSUTB is in ctfmon.exe and the langbar status is in Deskband,
|
|
// this meutb should stop wroking.
|
|
//
|
|
if (!_fInDeskBand && fLangBand)
|
|
{
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
SetTimer(TIPWND_TIMER_SYSCOLORCHANGED, g_uTimerElapseSYSCOLORCHANGED);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetMoveRect
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::SetMoveRect( int x, int y, int nWidth, int nHeight)
|
|
{
|
|
if (_fInDeskBand)
|
|
{
|
|
//
|
|
// In case of DeskBand case, only update width and height.
|
|
//
|
|
_nWidth = nWidth;
|
|
_nHeight = nHeight;
|
|
|
|
return;
|
|
}
|
|
|
|
_rcNew.left = x;
|
|
_rcNew.top = y;
|
|
_rcNew.right = nWidth;
|
|
_rcNew.bottom = nHeight;
|
|
_fNeedMoveWindow = TRUE;
|
|
|
|
StartPendingUpdateUI();
|
|
|
|
RECT rc;
|
|
SIZE sizeWndFrame;
|
|
sizeWndFrame.cx = 0;
|
|
sizeWndFrame.cy = 0;
|
|
if (_pWndFrame)
|
|
{
|
|
::SetRect(&rc, 0, 0,
|
|
nWidth - GetCxDlgFrame(),
|
|
nHeight - GetCyDlgFrame());
|
|
_pWndFrame->SetRect(&rc);
|
|
_pWndFrame->GetFrameSize( &sizeWndFrame );
|
|
}
|
|
|
|
if (_pGripper)
|
|
{
|
|
if (!IsVertical())
|
|
{
|
|
::SetRect(&rc,
|
|
sizeWndFrame.cx,
|
|
sizeWndFrame.cy,
|
|
sizeWndFrame.cx + GetGripperWidth(),
|
|
nHeight - GetCyDlgFrame() - sizeWndFrame.cy);
|
|
}
|
|
else
|
|
{
|
|
::SetRect(&rc,
|
|
sizeWndFrame.cx,
|
|
sizeWndFrame.cy,
|
|
nWidth - GetCxDlgFrame() - sizeWndFrame.cx,
|
|
sizeWndFrame.cy + GetGripperWidth());
|
|
}
|
|
_pGripper->SetRect(&rc);
|
|
}
|
|
EndPendingUpdateUI();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetGripperWidth
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int CTipbarWnd::GetGripperWidth()
|
|
{
|
|
if (_fInDeskBand)
|
|
return 0;
|
|
|
|
if (_pGripper)
|
|
{
|
|
if (SUCCEEDED(_pGripper->EnsureThemeData(GetWnd())))
|
|
{
|
|
int nRet = -1;
|
|
|
|
SIZE size;
|
|
HDC hdc = GetDC(GetWnd());
|
|
if (SUCCEEDED(_pGripper->GetThemePartSize(hdc,
|
|
TS_NORMAL,
|
|
NULL,
|
|
TS_TRUE,
|
|
&size)))
|
|
{
|
|
if (!IsVertical())
|
|
nRet = size.cx + CUI_GRIPPER_THEME_MARGIN * 2;
|
|
else
|
|
nRet = size.cy + CUI_GRIPPER_THEME_MARGIN * 2;
|
|
}
|
|
|
|
ReleaseDC(GetWnd(), hdc);
|
|
|
|
if (nRet >= 0)
|
|
return nRet;
|
|
}
|
|
}
|
|
|
|
return 5;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Move
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::Move( int x, int y, int nWidth, int nHeight)
|
|
{
|
|
CUIFWindow::Move(x, y, nWidth, nHeight);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// LocateCtrlButtons
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::LocateCtrlButtons()
|
|
{
|
|
DWORD dwFlags = 0;
|
|
|
|
if (IsSFDeskband() && IsSFNoExtraIcon())
|
|
dwFlags |= TCBH_NOCOLUMN;
|
|
|
|
if (!IsCapKanaShown())
|
|
dwFlags |= TCBH_NOCOLUMN0;
|
|
|
|
SIZE sizeWndFrame;
|
|
sizeWndFrame.cx = 0;
|
|
sizeWndFrame.cy = 0;
|
|
if (_pWndFrame != NULL)
|
|
_pWndFrame->GetFrameSize( &sizeWndFrame );
|
|
|
|
int nTipbarHeight = GetTipbarHeight();
|
|
RECT rc;
|
|
GetRect(&rc);
|
|
int nHeightPadding = 0;
|
|
|
|
if (!IsVertical())
|
|
{
|
|
if (rc.bottom - rc.top > nTipbarHeight)
|
|
nHeightPadding = (rc.bottom - rc.top - nTipbarHeight) / 2;
|
|
|
|
int xNew;
|
|
if (_fNeedMoveWindow)
|
|
xNew = _rcNew.right - GetCtrlButtonWidth() - sizeWndFrame.cx;
|
|
else
|
|
xNew = _nWidth - GetCtrlButtonWidth() - sizeWndFrame.cx;
|
|
|
|
_ctrlbtnHolder.Locate(this,
|
|
xNew,
|
|
sizeWndFrame.cy + nHeightPadding,
|
|
nTipbarHeight - (sizeWndFrame.cy * 2),
|
|
dwFlags, FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (rc.right - rc.left > nTipbarHeight)
|
|
nHeightPadding = (rc.right - rc.left - nTipbarHeight) / 2;
|
|
|
|
int yNew;
|
|
if (_fNeedMoveWindow)
|
|
yNew = _rcNew.bottom - GetCtrlButtonWidth() - sizeWndFrame.cy;
|
|
else
|
|
yNew = _nHeight - GetCtrlButtonWidth() - sizeWndFrame.cy;
|
|
|
|
_ctrlbtnHolder.Locate(this,
|
|
sizeWndFrame.cx + nHeightPadding,
|
|
yNew,
|
|
nTipbarHeight - (sizeWndFrame.cx * 2),
|
|
dwFlags, TRUE);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetFocusKeyboardLayout
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HKL CTipbarWnd::GetFocusKeyboardLayout()
|
|
{
|
|
return GetKeyboardLayout(_pFocusThread ? _pFocusThread->_dwThreadId : 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// HandleMouseMsg
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::HandleMouseMsg( UINT uMsg, POINT pt )
|
|
{
|
|
if (_fInHandleMouseMsg)
|
|
return;
|
|
|
|
//
|
|
// Bug#477031: Add the reference count to finish the current task before
|
|
// destructing this object.
|
|
//
|
|
//
|
|
AddRef();
|
|
|
|
_fInHandleMouseMsg = TRUE;
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
AttachFocusThread();
|
|
|
|
if ((uMsg == WM_LBUTTONDOWN) || (uMsg == WM_RBUTTONDOWN))
|
|
if (!MyWaitForInputIdle(_pFocusThread->_dwThreadId,
|
|
UTB_INPUTIDLETIMEOUT))
|
|
_pFocusThread->_ptw->_putb->RestoreLastFocus(NULL, FALSE);
|
|
}
|
|
|
|
POINT ptScrn = pt;
|
|
ClientToScreen(GetWnd(), &ptScrn);
|
|
if (WindowFromPoint(ptScrn) == GetWnd())
|
|
{
|
|
SetAlpha(255, TRUE);
|
|
|
|
if (_fInStub)
|
|
{
|
|
KillTimer(TIPWND_TIMER_STUBEND);
|
|
|
|
if (!_fInStubShow)
|
|
SetTimer(TIPWND_TIMER_STUBSTART, g_uTimerElapseSTUBSTART);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetAlpha(_bAlpha, TRUE);
|
|
|
|
if (_fInStub && _fInStubShow)
|
|
SetTimer(TIPWND_TIMER_STUBEND, g_uTimerElapseSTUBEND);
|
|
}
|
|
CUIFWindow::HandleMouseMsg(uMsg, pt);
|
|
|
|
if (uMsg == WM_RBUTTONUP)
|
|
{
|
|
CUIFObject *pUIObj = ObjectFromPoint( pt );
|
|
if (pUIObj && pUIObj->GetID() != (-1))
|
|
{
|
|
PostMessage(GetWnd(), WM_LBWND_SHOWCONTEXTMENU, 0, MAKELPARAM(pt.x, pt.y));
|
|
}
|
|
}
|
|
|
|
_fInHandleMouseMsg = FALSE;
|
|
Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnMouseOutFromWindow
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnMouseOutFromWindow( POINT pt )
|
|
{
|
|
StartBackToAlphaTimer();
|
|
|
|
if (_fInStub && _fInStubShow)
|
|
SetTimer(TIPWND_TIMER_STUBEND, g_uTimerElapseSTUBEND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CheckO10Flag
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifdef USE_OFC10LOOKONWINXP
|
|
|
|
void CTipbarWnd::CheckO10Flag()
|
|
{
|
|
if (!g_bNewLook)
|
|
return;
|
|
|
|
EnsureThemeData(GetWnd());
|
|
if (IsThemeActive() || _fInDeskBand)
|
|
{
|
|
g_dwWndStyle &= ~UIWINDOW_OFC10TOOLBAR;
|
|
}
|
|
else
|
|
{
|
|
g_dwWndStyle |= UIWINDOW_OFC10TOOLBAR;
|
|
}
|
|
|
|
SetStyle(g_dwWndStyle);
|
|
CreateScheme();
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnCreate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnCreate(HWND hWnd)
|
|
{
|
|
|
|
if (g_fTaskbarTheme)
|
|
SetWindowTheme(hWnd, L"TASKBAR", NULL);
|
|
|
|
#ifdef USE_OFC10LOOKONWINXP
|
|
CheckO10Flag();
|
|
#endif
|
|
|
|
if (_fVertical)
|
|
{
|
|
if (!_hfontVert)
|
|
{
|
|
_hfontVert = CreateVerticalFont();
|
|
}
|
|
SetFontToThis(_hfontVert);
|
|
}
|
|
|
|
_ctrlbtnHolder.UpdateBitmap(this);
|
|
|
|
_itemList.Load();
|
|
|
|
if (_putb)
|
|
_putb->AdviseEventSink(this, hWnd, TF_LBESF_GLOBAL, &_dwlbimCookie);
|
|
|
|
if (_pFocusThread)
|
|
_pFocusThread->InitItemList();
|
|
|
|
InitHighContrast();
|
|
SetAlpha(128, FALSE);
|
|
|
|
InitMetrics();
|
|
|
|
|
|
//
|
|
// MSAA support
|
|
//
|
|
Assert(!_pTipbarAcc);
|
|
_pTipbarAcc = new CTipbarAccessible(this);
|
|
if (_pTipbarAcc)
|
|
{
|
|
_pTipbarAcc->SetWindow(hWnd);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetAlpha
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
typedef BOOL (WINAPI * SETLAYERWINDOWATTRIBUTE)(HWND, COLORREF, BYTE, DWORD);
|
|
void CTipbarWnd::SetAlpha(BYTE bAlpha, BOOL fTemp)
|
|
{
|
|
if (!_fInDeskBand && IsOnNT5())
|
|
{
|
|
|
|
//
|
|
// we don't do alpha blending.
|
|
//
|
|
// when high contrast is on
|
|
// when Modal Menu is shown.
|
|
//
|
|
//
|
|
if (IsHighContrastOn() ||
|
|
_pModalMenu)
|
|
{
|
|
fTemp = TRUE;
|
|
bAlpha = 255;
|
|
}
|
|
|
|
if (!fTemp)
|
|
_bAlpha = bAlpha;
|
|
|
|
if (_bCurAlpha == bAlpha)
|
|
return;
|
|
|
|
CUIFShadow *pShadowWnd = GetShadowWnd();
|
|
if (pShadowWnd)
|
|
{
|
|
EnableShadow(bAlpha == 255);
|
|
pShadowWnd->Show((bAlpha == 255) && IsVisible());
|
|
}
|
|
|
|
DWORD dwExStyle = GetWindowLong(GetWnd(), GWL_EXSTYLE);
|
|
SetWindowLong(GetWnd(), GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED);
|
|
|
|
static SETLAYERWINDOWATTRIBUTE pfnSetLayeredWindowAttributes = NULL;
|
|
if (!pfnSetLayeredWindowAttributes)
|
|
{
|
|
HINSTANCE hUser32;
|
|
hUser32 = GetSystemModuleHandle(TEXT("user32.dll"));
|
|
if (hUser32)
|
|
pfnSetLayeredWindowAttributes = (SETLAYERWINDOWATTRIBUTE)GetProcAddress(hUser32, TEXT("SetLayeredWindowAttributes"));
|
|
}
|
|
|
|
if (pfnSetLayeredWindowAttributes)
|
|
pfnSetLayeredWindowAttributes(GetWnd(), 0, (BYTE)bAlpha, LWA_ALPHA);
|
|
|
|
|
|
_bCurAlpha = bAlpha;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnDestroy
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnDestroy(HWND hWnd)
|
|
{
|
|
CancelMenu();
|
|
|
|
//
|
|
// MSAA support
|
|
//
|
|
if (_pTipbarAcc)
|
|
_pTipbarAcc->NotifyWinEvent( EVENT_OBJECT_DESTROY, this);
|
|
|
|
OnTerminateToolbar();
|
|
|
|
if (_pTipbarAcc)
|
|
{
|
|
_pTipbarAcc->ClearAccItems();
|
|
_pTipbarAcc->Release();
|
|
_pTipbarAcc = NULL;
|
|
}
|
|
|
|
CoUninit();
|
|
|
|
if (_putb)
|
|
_putb->UnadviseEventSink(_dwlbimCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnShowWindow
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnShowWindow( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
//
|
|
// MSAA support
|
|
//
|
|
if (_pTipbarAcc)
|
|
{
|
|
if (wParam)
|
|
{
|
|
_pTipbarAcc->NotifyWinEvent( EVENT_OBJECT_SHOW ,this);
|
|
|
|
//
|
|
// MSCANDUI does this.
|
|
//
|
|
// REVIEW: KOJIW: Unless we send notify EVENT_OBJECT_FOCUS,
|
|
// we never receive WM_GETOBJECT message. Why???
|
|
//
|
|
|
|
_pTipbarAcc->NotifyWinEvent( EVENT_OBJECT_FOCUS ,this);
|
|
}
|
|
else
|
|
{
|
|
_pTipbarAcc->NotifyWinEvent( EVENT_OBJECT_HIDE ,this);
|
|
}
|
|
}
|
|
|
|
return CUIFWindow::OnShowWindow( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnEndSession
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (!g_bWinLogon)
|
|
OnTerminateToolbar();
|
|
|
|
if (wParam)
|
|
{
|
|
if (lParam & ENDSESSION_LOGOFF)
|
|
{
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
Show(FALSE);
|
|
}
|
|
else
|
|
{
|
|
OnTerminateToolbar();
|
|
|
|
AddRef();
|
|
DestroyWindow(hwnd);
|
|
Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnTerminateToolbar
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnTerminateToolbar()
|
|
{
|
|
_fTerminating = TRUE;
|
|
|
|
DestroyOverScreenSizeBalloon();
|
|
|
|
TerminateAllThreads(TRUE);
|
|
|
|
if (!_fInDeskBand)
|
|
SavePosition();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SavePosition
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::SavePosition()
|
|
{
|
|
CMyRegKey keyUTB;
|
|
|
|
if (keyUTB.Create(HKEY_CURRENT_USER, c_szUTBKey) == S_OK)
|
|
{
|
|
POINT pt;
|
|
pt.x = 0;
|
|
pt.y = 0;
|
|
MyClientToScreen(&pt, NULL);
|
|
keyUTB.SetValue((DWORD)pt.x, c_szLeft);
|
|
keyUTB.SetValue((DWORD)pt.y, c_szTop);
|
|
keyUTB.SetValue((DWORD)_fVertical ? 1 : 0, c_szVertical);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// TerminateAllThreads
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::TerminateAllThreads(BOOL fTerminatFocusThread)
|
|
{
|
|
int nCnt = _rgThread.Count();
|
|
int i;
|
|
DWORD *pdwThread;
|
|
|
|
pdwThread = new DWORD[nCnt + 1];
|
|
if (!pdwThread)
|
|
return;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
pdwThread[i] = 0;
|
|
|
|
CTipbarThread *pThread = _rgThread.Get(i);
|
|
if (!pThread)
|
|
continue;
|
|
|
|
if (!fTerminatFocusThread && (pThread == _pFocusThread))
|
|
continue;
|
|
|
|
pdwThread[i] = pThread->_dwThreadId;
|
|
}
|
|
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
if (pdwThread[i])
|
|
OnThreadTerminateInternal(pdwThread[i]);
|
|
}
|
|
|
|
delete[] pdwThread;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetShowText()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::SetShowText(BOOL fShowText)
|
|
{
|
|
_fShowText = fShowText;
|
|
|
|
if (_pFocusThread)
|
|
{
|
|
OnThreadItemChange(_pFocusThread->_dwThreadId);
|
|
}
|
|
|
|
TerminateAllThreads(FALSE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnWindowPosChanged
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (_pFocusThread)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _pFocusThread->_rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _pFocusThread->_rgItem.Get(i);
|
|
if (pItem)
|
|
pItem->OnPosChanged();
|
|
}
|
|
}
|
|
|
|
return CUIFWindow::OnWindowPosChanged(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnWindowPosChanging
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnWindowPosChanging(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WINDOWPOS *pwp = (WINDOWPOS *)lParam;
|
|
|
|
if (!(pwp->flags & SWP_NOZORDER))
|
|
{
|
|
CUIFToolTip *ptip = GetToolTipWnd();
|
|
|
|
//
|
|
// we don't patch hwndInsertAfter, when
|
|
// - Tooltip is being shown.
|
|
// - Modal Popup menu is shown.
|
|
//
|
|
if ((!ptip || !(ptip->IsBeingShown())) &&
|
|
!_pttModal)
|
|
pwp->hwndInsertAfter = HWND_TOP;
|
|
}
|
|
|
|
return CUIFWindow::OnWindowPosChanged(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnEraseBkGnd()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnEraseBkGnd( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// PaintObject()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::PaintObject( HDC hDC, const RECT *prcUpdate )
|
|
{
|
|
// KillTimer(TIPWND_TIMER_ONUPDATECALLED);
|
|
|
|
if (_fNeedMoveWindow)
|
|
{
|
|
Move(_rcNew.left, _rcNew.top, _rcNew.right, _rcNew.bottom);
|
|
_fNeedMoveWindow = FALSE;
|
|
}
|
|
|
|
if (_pFocusThread && _pFocusThread->IsDirtyItem())
|
|
{
|
|
_pFocusThread->CallOnUpdateHandler();
|
|
|
|
//
|
|
// #432697: Stress fault
|
|
//
|
|
// ClosePopupTipbar() could be called while CallOnUpdateHandler()
|
|
// is calling marshaling. We should check if g_pTIpbarWnd is
|
|
// available.
|
|
//
|
|
if (!g_pTipbarWnd)
|
|
return;
|
|
}
|
|
|
|
CUIFWindow::PaintObject(hDC, prcUpdate);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateUI()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::UpdateUI( const RECT *prcUpdate )
|
|
{
|
|
// TraceMsg(TF_FUNC, "UpdateUI");
|
|
|
|
KillTimer(TIPWND_TIMER_UPDATEUI);
|
|
|
|
if (_dwThreadItemChangedForTimer ||
|
|
_dwPendingUpdateUI ||
|
|
(_pFocusThread && _pFocusThread->IsDirtyItem()))
|
|
{
|
|
SetTimer(TIPWND_TIMER_UPDATEUI, g_uTimerElapseUPDATEUI);
|
|
return;
|
|
}
|
|
|
|
if (_fNeedMoveWindow)
|
|
{
|
|
// TraceMsg(TF_FUNC, "UpdateUI need move window");
|
|
StartPendingUpdateUI();
|
|
Move(_rcNew.left, _rcNew.top, _rcNew.right, _rcNew.bottom);
|
|
_fNeedMoveWindow = FALSE;
|
|
EndPendingUpdateUI();
|
|
}
|
|
|
|
TraceMsg(TF_FUNC, "UpdateUI update now ");
|
|
CUIFWindow::UpdateUI(NULL);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetShowTrayIcon()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::SetShowTrayIcon(BOOL fShowTrayIcon)
|
|
{
|
|
_fShowTrayIcon = fShowTrayIcon;
|
|
|
|
if (_fShowTrayIcon && _pFocusThread)
|
|
{
|
|
KillTimer(TIPWND_TIMER_MOVETOTRAY);
|
|
SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
}
|
|
else if (g_pTrayIconWnd)
|
|
{
|
|
g_pTrayIconWnd->SetMainIcon(NULL);
|
|
g_pTrayIconWnd->RemoveAllIcon(0);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ShowOverScreenSizeBalloon
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::ShowOverScreenSizeBalloon()
|
|
{
|
|
RECT rc;
|
|
POINT pt;
|
|
CTipbarCtrlButton *pcuiCtrlbtn = _ctrlbtnHolder.GetCtrlBtn(ID_CBTN_EXTMENU);
|
|
if (!pcuiCtrlbtn)
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
DestroyOverScreenSizeBalloon();
|
|
|
|
_pblnOverScreenSize = new CUIFBalloonWindow(g_hInst, UIBALLOON_OK);
|
|
if (!_pblnOverScreenSize)
|
|
return;
|
|
|
|
_pblnOverScreenSize->Initialize();
|
|
|
|
pcuiCtrlbtn->GetRect(&rc);
|
|
pt.x = (rc.left + rc.right) / 2;
|
|
pt.y = rc.top;
|
|
MyClientToScreen(&pt, &rc);
|
|
|
|
_pblnOverScreenSize->SetTargetPos(pt);
|
|
_pblnOverScreenSize->SetExcludeRect(&rc);
|
|
|
|
_pblnOverScreenSize->SetText(CRStr(IDS_OVERSCREENSIZE));
|
|
_pblnOverScreenSize->CreateWnd(GetWnd());
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DestroyMinimizeBalloon
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::DestroyOverScreenSizeBalloon()
|
|
{
|
|
if (_pblnOverScreenSize)
|
|
{
|
|
if (IsWindow(_pblnOverScreenSize->GetWnd()))
|
|
DestroyWindow(_pblnOverScreenSize->GetWnd());
|
|
delete _pblnOverScreenSize;
|
|
_pblnOverScreenSize = NULL;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CancelMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::CancelMenu()
|
|
{
|
|
if (_pttModal)
|
|
{
|
|
if (_pttModal->_ptw && _pttModal->_ptw->_putb)
|
|
_pttModal->_ptw->StartModalInput(NULL, _pttModal->_dwThreadId);
|
|
Assert(_pModalMenu);
|
|
_pModalMenu->CancelMenu();
|
|
|
|
StartBackToAlphaTimer();
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MoveToStub
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::MoveToStub(BOOL fHide)
|
|
{
|
|
RECT rc;
|
|
_fInStub = TRUE;
|
|
|
|
SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
|
|
|
|
if (fHide)
|
|
{
|
|
_xWnd = rc.right - (24 + 14);
|
|
_fInStubShow = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RECT rcWnd;
|
|
GetWindowRect(GetWnd(), &rcWnd);
|
|
_xWnd = rc.right - (rcWnd.right - rcWnd.left);
|
|
_fInStubShow = TRUE;
|
|
}
|
|
_yWnd = rc.bottom - GetTipbarHeight() - _cyDlgFrame;
|
|
|
|
if (_pFocusThread)
|
|
_pFocusThread->MyMoveWnd(0, 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RestoreFromStub
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::RestoreFromStub()
|
|
{
|
|
_fInStub = FALSE;
|
|
_fInStubShow = FALSE;
|
|
KillTimer(TIPWND_TIMER_STUBSTART);
|
|
KillTimer(TIPWND_TIMER_STUBEND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarWnd::KillOnThreadItemChangeTimer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::KillOnTheadItemChangeTimer()
|
|
{
|
|
DWORD dwThreadId = _dwThreadItemChangedForTimer;
|
|
_dwThreadItemChangedForTimer = 0;
|
|
|
|
KillTimer(TIPWND_TIMER_ONTHREADITEMCHANGE);
|
|
|
|
if (dwThreadId)
|
|
{
|
|
CTipbarThread *pThread = _FindThread(dwThreadId);
|
|
if (pThread)
|
|
pThread->_fItemChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarWnd::OnTimer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnTimer(UINT uId)
|
|
{
|
|
DWORD dwFocusThreadId;
|
|
DWORD dwRet;
|
|
|
|
AddRef();
|
|
|
|
switch (uId)
|
|
{
|
|
case TIPWND_TIMER_STUBSTART:
|
|
KillTimer(TIPWND_TIMER_STUBSTART);
|
|
MoveToStub(FALSE);
|
|
break;
|
|
|
|
case TIPWND_TIMER_STUBEND:
|
|
KillTimer(TIPWND_TIMER_STUBEND);
|
|
MoveToStub(TRUE);
|
|
break;
|
|
|
|
case TIPWND_TIMER_BACKTOALPHA:
|
|
KillTimer(TIPWND_TIMER_BACKTOALPHA);
|
|
SetAlpha(_bAlpha, TRUE);
|
|
break;
|
|
|
|
case TIPWND_TIMER_ONTHREADITEMCHANGE:
|
|
//
|
|
// OnThreadItemChangeInternat will disconnect the marshaling for
|
|
// all items. It is better todo this later.
|
|
//
|
|
dwRet = MyWaitForInputIdle(_dwThreadItemChangedForTimer,
|
|
UTB_INPUTIDLETIMEOUT);
|
|
if (dwRet)
|
|
{
|
|
if (dwRet != WAIT_TIMEOUT)
|
|
{
|
|
KillTimer(TIPWND_TIMER_ONTHREADITEMCHANGE);
|
|
_dwThreadItemChangedForTimer = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!_pttModal)
|
|
{
|
|
KillTimer(TIPWND_TIMER_ONTHREADITEMCHANGE);
|
|
|
|
//
|
|
// #509156
|
|
//
|
|
// Set _dwThreadItemChagnedForTimer before calling
|
|
// OnThreadItemChangeInternal(). During the marshaling call
|
|
// in the function, someone else may set
|
|
// _dwThreadItemChangedForTimer.
|
|
//
|
|
DWORD dwThreadIdTemp = _dwThreadItemChangedForTimer;
|
|
_dwThreadItemChangedForTimer = 0;
|
|
OnThreadItemChangeInternal(dwThreadIdTemp);
|
|
}
|
|
break;
|
|
|
|
case TIPWND_TIMER_SETWINDOWPOS:
|
|
KillTimer(TIPWND_TIMER_SETWINDOWPOS);
|
|
SetWindowPos(GetWnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
break;
|
|
|
|
case TIPWND_TIMER_ONUPDATECALLED:
|
|
KillTimer(TIPWND_TIMER_ONUPDATECALLED);
|
|
//
|
|
// if _dwThreadItemChangedForTimer is not 0, we will
|
|
// update all items later.
|
|
//
|
|
if (_pFocusThread &&
|
|
(_pFocusThread->_dwThreadId != _dwThreadItemChangedForTimer))
|
|
{
|
|
if (!_pFocusThread->CallOnUpdateHandler())
|
|
{
|
|
if (_pFocusThread)
|
|
OnThreadItemChange(_pFocusThread->_dwThreadId);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TIPWND_TIMER_SYSCOLORCHANGED:
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
|
|
//
|
|
// the sys colors were changed, we recreate all thread info
|
|
// again.
|
|
//
|
|
|
|
if (_pFocusThread)
|
|
dwFocusThreadId = _pFocusThread->_dwThreadId;
|
|
else
|
|
dwFocusThreadId = 0;
|
|
|
|
TerminateAllThreads(TRUE);
|
|
|
|
UpdateVerticalFont();
|
|
|
|
if (dwFocusThreadId)
|
|
OnSetFocus(dwFocusThreadId);
|
|
|
|
InitMetrics();
|
|
_ctrlbtnHolder.UpdateBitmap(this);
|
|
InitHighContrast();
|
|
SetAlpha(255, TRUE);
|
|
|
|
::RedrawWindow(GetWnd(),
|
|
NULL,
|
|
NULL,
|
|
RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
|
|
break;
|
|
|
|
case TIPWND_TIMER_DISPLAYCHANGE:
|
|
KillTimer(TIPWND_TIMER_DISPLAYCHANGE);
|
|
|
|
AdjustPosOnDisplayChange();
|
|
break;
|
|
|
|
|
|
case TIPWND_TIMER_UPDATEUI:
|
|
KillTimer(TIPWND_TIMER_UPDATEUI);
|
|
UpdateUI(NULL);
|
|
break;
|
|
|
|
case TIPWND_TIMER_SHOWWINDOW:
|
|
KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
|
|
if (_pThreadShowWindowAtTimer == _pFocusThread)
|
|
Show(_fShowWindowAtTimer);
|
|
|
|
_pThreadShowWindowAtTimer = NULL;
|
|
|
|
//
|
|
// If the window was over the screen and hide some items,
|
|
// we show balloon tips.
|
|
//
|
|
if (_fShowOverItemBalloonAtTimer)
|
|
ShowOverScreenSizeBalloon();
|
|
|
|
break;
|
|
|
|
case TIPWND_TIMER_SHOWDESKBAND:
|
|
if (SetLangBand(TRUE))
|
|
{
|
|
_dwSFTFlags = TF_SFT_DESKBAND;
|
|
KillTimer(TIPWND_TIMER_SHOWDESKBAND);
|
|
}
|
|
|
|
break;
|
|
|
|
case TIPWND_TIMER_MOVETOTRAY:
|
|
KillTimer(TIPWND_TIMER_MOVETOTRAY);
|
|
MoveToTray();
|
|
break;
|
|
|
|
case TIPWND_TIMER_ENSUREFOCUS:
|
|
if (_pDeskBand && _pDeskBand->IsInTipbarCreating())
|
|
break;
|
|
|
|
KillTimer(TIPWND_TIMER_ENSUREFOCUS);
|
|
if (!_pFocusThread)
|
|
EnsureFocusThread();
|
|
break;
|
|
|
|
case TIPWND_TIMER_DOACCDEFAULTACTION:
|
|
//
|
|
// MSAA support
|
|
//
|
|
KillTimer(TIPWND_TIMER_DOACCDEFAULTACTION);
|
|
if (_pTipbarAcc && _nDoAccDefaultActionItemId)
|
|
{
|
|
_pTipbarAcc->DoDefaultActionReal(_nDoAccDefaultActionItemId);
|
|
_nDoAccDefaultActionItemId = 0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if ((uId >= TIPWND_TIMER_DEMOTEITEMFIRST) &&
|
|
(uId < TIPWND_TIMER_DEMOTEITEMLAST))
|
|
{
|
|
LANGBARITEMSTATE *pItemState;
|
|
if (pItemState = _itemList.GetItemStateFromTimerId(uId))
|
|
{
|
|
CTipbarItem *pItem;
|
|
_itemList.SetDemoteLevel(pItemState->guid, DL_HIDDENLEVEL1);
|
|
if (_pFocusThread &&
|
|
(pItem = _pFocusThread->GetItem(pItemState->guid)))
|
|
{
|
|
Assert(!pItem->IsHiddenStatusControl())
|
|
pItem->AddRemoveMeToUI(FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Release();
|
|
return;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CTipbarWnd::OnSysColoeChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnSysColorChange()
|
|
{
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
SetTimer(TIPWND_TIMER_SYSCOLORCHANGED, g_uTimerElapseSYSCOLORCHANGED);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnUser
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnUser(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
POINT pt;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_LBWND_SHOWCONTEXTMENU:
|
|
pt.x = LOWORD(lParam);
|
|
pt.y = HIWORD(lParam);
|
|
MyClientToScreen(&pt, NULL);
|
|
ShowContextMenu(pt, NULL, TRUE);
|
|
break;
|
|
|
|
default:
|
|
if (uMsg == g_wmTaskbarCreated)
|
|
{
|
|
shellwnd.Clear();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnSettingChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case 0:
|
|
case SPI_SETHIGHCONTRAST:
|
|
case SPI_SETNONCLIENTMETRICS:
|
|
KillTimer(TIPWND_TIMER_SYSCOLORCHANGED);
|
|
SetTimer(TIPWND_TIMER_SYSCOLORCHANGED, g_uTimerElapseSYSCOLORCHANGED);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnDisplayChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnDisplayChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
if (!_fInDeskBand)
|
|
{
|
|
KillTimer(TIPWND_TIMER_DISPLAYCHANGE);
|
|
SetTimer(TIPWND_TIMER_DISPLAYCHANGE, g_uTimerElapseDISPLAYCHANGE);
|
|
}
|
|
return CUIFWindow::OnDisplayChange(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AdjustPosOnDisplayChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::AdjustPosOnDisplayChange()
|
|
{
|
|
RECT rc;
|
|
RECT rcWnd;
|
|
int xWnd = _xWnd;
|
|
int yWnd = _yWnd;
|
|
|
|
Assert(!_fInDeskBand);
|
|
|
|
rcWnd.left = _xWnd;
|
|
rcWnd.top = _yWnd;
|
|
rcWnd.right = _xWnd + _nWidth;
|
|
rcWnd.bottom = _yWnd + _nHeight;
|
|
if (!GetWorkArea(&rcWnd, &rc))
|
|
return;
|
|
|
|
if (_fPosLeft)
|
|
xWnd = rc.left;
|
|
|
|
if (_fPosTop)
|
|
yWnd = rc.top;
|
|
|
|
if (_fPosRight)
|
|
xWnd = rc.right - _nWidth;
|
|
|
|
if (_fPosBottom)
|
|
yWnd = rc.bottom - _nHeight;
|
|
|
|
if ((xWnd != _xWnd) || (yWnd != _yWnd))
|
|
Move(xWnd, yWnd, _nWidth, _nHeight);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdatePosFlags
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#define POSFLAG_MARGIN 2
|
|
|
|
void CTipbarWnd::UpdatePosFlags()
|
|
{
|
|
RECT rc;
|
|
RECT rcWnd;
|
|
|
|
if (_fInDeskBand)
|
|
return;
|
|
|
|
|
|
rcWnd.left = _xWnd;
|
|
rcWnd.top = _yWnd;
|
|
rcWnd.right = _xWnd + _nWidth;
|
|
rcWnd.bottom = _yWnd + _nHeight;
|
|
if (!GetWorkArea(&rcWnd, &rc))
|
|
return;
|
|
|
|
if (_xWnd <= rc.left + POSFLAG_MARGIN)
|
|
_fPosLeft = TRUE;
|
|
else
|
|
_fPosLeft = FALSE;
|
|
|
|
if (_yWnd <= rc.top + POSFLAG_MARGIN)
|
|
_fPosTop = TRUE;
|
|
else
|
|
_fPosTop = FALSE;
|
|
|
|
if (_xWnd + _nWidth >= rc.right - POSFLAG_MARGIN)
|
|
_fPosRight = TRUE;
|
|
else
|
|
_fPosRight = FALSE;
|
|
|
|
if (_yWnd + _nHeight >= rc.bottom - POSFLAG_MARGIN)
|
|
_fPosBottom = TRUE;
|
|
else
|
|
_fPosBottom = FALSE;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AutoAdjustDeskBandSize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::AutoAdjustDeskBandSize()
|
|
{
|
|
if (_fDeskbandSizeAdjusted)
|
|
return FALSE;
|
|
|
|
if (!_pFocusThread)
|
|
return FALSE;
|
|
|
|
if (_pFocusThread->IsCtfmonProcess())
|
|
return FALSE;
|
|
|
|
//
|
|
// if _fAdjustDeskbandIfNoRoom is on, don't put fFit so we don't
|
|
// do anything if there is a room.
|
|
//
|
|
BOOL fFit = TRUE;
|
|
if (_fAdjustDeskbandIfNoRoom)
|
|
fFit = FALSE;
|
|
|
|
_fAdjustDeskbandIfNoRoom = FALSE;
|
|
|
|
if (AdjustDeskBandSize(fFit))
|
|
{
|
|
SetDeskbandSizeAdjusted();
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AdjustDeskBandSize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::AdjustDeskBandSize(BOOL fFit)
|
|
{
|
|
if (!_fInDeskBand)
|
|
return FALSE;
|
|
|
|
if (!_pDeskBand)
|
|
return FALSE;
|
|
|
|
return _pDeskBand->ResizeRebar(GetWnd(),
|
|
IsVertical() ? _nHeight : _nWidth,
|
|
fFit);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetThread
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarThread *CTipbarWnd::GetThread(DWORD dwThreadId)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgThread.Count(); i++)
|
|
{
|
|
CTipbarThread *pThread = _rgThread.Get(i);
|
|
if (!pThread)
|
|
continue;
|
|
|
|
if (pThread->_dwThreadId == dwThreadId)
|
|
{
|
|
if (TF_GetThreadFlags(dwThreadId, NULL, NULL, NULL))
|
|
{
|
|
return pThread;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RestoreLastFocs
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::RestoreLastFocus(DWORD *pdwThreadId, BOOL fPrev)
|
|
{
|
|
if (_putb)
|
|
_putb->RestoreLastFocus(pdwThreadId, fPrev);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// StartModalInput
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::StartModalInput(ITfLangBarEventSink *pSink, DWORD dwThreadId)
|
|
{
|
|
if (!_putb)
|
|
return;
|
|
|
|
_putb->SetModalInput(pSink, dwThreadId, 0);
|
|
|
|
//
|
|
// we want this to track a mouse event of Tray window.
|
|
//
|
|
if (g_pTrayIconWnd)
|
|
_putb->SetModalInput(pSink, g_pTrayIconWnd->GetThreadIdTray(), 0);
|
|
|
|
//
|
|
// we want this to track a mouse event of CMD prompt window.
|
|
//
|
|
_putb->SetModalInput(pSink, GetCurrentThreadId(), TF_LBSMI_FILTERCURRENTTHREAD );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// StopModalInput
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::StopModalInput(DWORD dwThreadId)
|
|
{
|
|
if (!_putb)
|
|
return;
|
|
|
|
_putb->SetModalInput(NULL, dwThreadId, 0);
|
|
|
|
if (g_pTrayIconWnd)
|
|
_putb->SetModalInput(NULL, g_pTrayIconWnd->GetThreadIdTray(), 0);
|
|
|
|
_putb->SetModalInput(NULL, GetCurrentThreadId(), 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ClearLBItemList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::ClearLBItemList()
|
|
{
|
|
_itemList.Clear();
|
|
if (_pFocusThread)
|
|
{
|
|
OnThreadItemChange(_pFocusThread->_dwThreadId);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ShowMenuExtendMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::ShowContextMenu(POINT pt, RECT *prc, BOOL fExtendMenuItems)
|
|
{
|
|
CUTBContextMenu *pMenu = NULL;
|
|
RECT rc;
|
|
CTipbarThread *ptt = GetFocusThread();
|
|
DWORD dwThreadId;
|
|
UINT uId = CUI_MENU_UNSELECTED;
|
|
|
|
//
|
|
// CTipbarWnd could be destroyed during ShowPopup().
|
|
//
|
|
AddRef();
|
|
|
|
if (!prc)
|
|
{
|
|
rc.left = pt.x;
|
|
rc.top = pt.y;
|
|
rc.right = pt.x;
|
|
rc.bottom = pt.y;
|
|
prc = &rc;
|
|
}
|
|
|
|
if (!ptt)
|
|
goto Exit;
|
|
|
|
pMenu = new CUTBContextMenu(this);
|
|
if (!pMenu)
|
|
goto Exit;
|
|
|
|
if (!pMenu->Init())
|
|
goto Exit;
|
|
|
|
_pttModal = ptt;
|
|
StartModalInput(this, ptt->_dwThreadId);
|
|
|
|
dwThreadId = GetCurrentThreadId();
|
|
_pModalMenu = pMenu;
|
|
|
|
uId = pMenu->ShowPopup(this, pt, prc, fExtendMenuItems);
|
|
|
|
_pModalMenu = NULL;
|
|
|
|
if (_pttModal)
|
|
StopModalInput(_pttModal->_dwThreadId);
|
|
_pttModal = NULL;
|
|
|
|
if (uId != CUI_MENU_UNSELECTED)
|
|
{
|
|
pMenu->SelectMenuItem(uId);
|
|
}
|
|
|
|
Exit:
|
|
if (pMenu)
|
|
delete pMenu;
|
|
|
|
Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsInItemChangOrDirty
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::IsInItemChangeOrDirty(CTipbarThread *pThread)
|
|
{
|
|
if (pThread->_dwThreadId == _dwThreadItemChangedForTimer)
|
|
return TRUE;
|
|
|
|
return pThread->IsDirtyItem();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnGetObject
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LRESULT CTipbarWnd::OnGetObject( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LRESULT lResult = (LRESULT)0;
|
|
|
|
switch (lParam)
|
|
{
|
|
//
|
|
// We process the OBJID_CLIENT object identifier;
|
|
// this is the client area of our application
|
|
// window.
|
|
//
|
|
|
|
case OBJID_CLIENT:
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (_pTipbarAcc == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if (!_pTipbarAcc->IsInitialized())
|
|
{
|
|
//
|
|
//
|
|
//
|
|
hr = EnsureCoInit();
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize our Accessible object. If the
|
|
// initialization fails, delete the Accessible
|
|
// object and return the failure code.
|
|
//
|
|
|
|
hr = _pTipbarAcc->Initialize();
|
|
if (FAILED(hr))
|
|
{
|
|
_pTipbarAcc->Release();
|
|
_pTipbarAcc = NULL;
|
|
|
|
lResult = (LRESULT)hr;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Send an EVENT_OBJECT_CREATE WinEvent for the
|
|
// creation of the Accessible object for the
|
|
// client area.
|
|
//
|
|
|
|
_pTipbarAcc->NotifyWinEvent( EVENT_OBJECT_CREATE , this);
|
|
}
|
|
|
|
//
|
|
// Call LresultFromObject() to create reference to
|
|
// our Accessible object that MSAA will marshal to
|
|
// the client.
|
|
//
|
|
|
|
lResult = _pTipbarAcc->CreateRefToAccObj( wParam );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return lResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnThemeChanged
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarWnd::OnThemeChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#ifdef USE_OFC10LOOKONWINXP
|
|
CheckO10Flag();
|
|
#endif
|
|
CUIFWindow::OnThemeChanged(hwnd, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// StartDoDefaultActionTimer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::StartDoAccDefaultActionTimer(CTipbarItem *pItem)
|
|
{
|
|
if (!_pTipbarAcc)
|
|
return FALSE;
|
|
|
|
_nDoAccDefaultActionItemId = _pTipbarAcc->GetIDOfItem(pItem);
|
|
if ((_nDoAccDefaultActionItemId == 0) || (_nDoAccDefaultActionItemId == -1))
|
|
return FALSE;
|
|
|
|
KillTimer(TIPWND_TIMER_DOACCDEFAULTACTION);
|
|
SetTimer(TIPWND_TIMER_DOACCDEFAULTACTION, g_uTimerElapseDOACCDEFAULTACTION);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarThread
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarThread::CTipbarThread(CTipbarWnd *ptw)
|
|
{
|
|
|
|
Dbg_MemSetThisName(TEXT("CTipbarThread"));
|
|
|
|
_ptw = ptw;
|
|
_dwThreadId = 0;
|
|
_plbim = NULL;
|
|
_ref = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarThread::Init(DWORD dwThreadId)
|
|
{
|
|
DWORD dwThreadIdTmp;
|
|
HRESULT hr = S_OK;
|
|
|
|
_dwThreadId = dwThreadId;
|
|
|
|
if (!TF_GetThreadFlags(_dwThreadId, &_dwThreadFlags, &_dwProcessId, &_dwTickTime))
|
|
return E_FAIL;
|
|
|
|
if (IsConsole())
|
|
return S_OK;
|
|
|
|
// What's happening: we eventually reach InternalGetThreadUIManager
|
|
// which, if _dwThreadId is NULL, will substitute
|
|
// g_ShareMem.dwActiveThreadId.
|
|
// This is dangerous, because if the active thread does not match
|
|
// this one we'll do rpc and _plbim will be on the wrong thread.
|
|
// Passing in _dwThreadId seems like the right thing to do....
|
|
|
|
hr = _ptw->GetLangBarMgr()->GetThreadLangBarItemMgr(_dwThreadId, &_plbim, &dwThreadIdTmp);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
Assert(dwThreadIdTmp == _dwThreadId);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarThread::~CTipbarThread()
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(!_fInCallOnUpdateHandler);
|
|
#endif
|
|
|
|
if (_ptw)
|
|
{
|
|
Assert(this != _ptw->GetFocusThread());
|
|
RemoveUIObjs();
|
|
|
|
_ptw->CleanUpThreadPointer(this, TRUE);
|
|
}
|
|
|
|
_UninitItemList(TRUE);
|
|
SafeReleaseClear(_plbim);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG CTipbarThread::_AddRef( )
|
|
{
|
|
_ref++;
|
|
|
|
return _ref;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Release
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG CTipbarThread::_Release( )
|
|
{
|
|
ULONG cr;
|
|
|
|
_ref--;
|
|
|
|
cr = _ref;
|
|
|
|
if (cr == 0) {
|
|
delete this;
|
|
}
|
|
|
|
return cr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarThread::SetFocus(BOOL fFocus)
|
|
{
|
|
|
|
if (!fFocus)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
CTipbarBalloonItem *pballoon;
|
|
if (pItem &&
|
|
SUCCEEDED(pItem->QueryInterface(IID_PRIV_BALLOONITEM, (void **)&pballoon)))
|
|
{
|
|
pballoon->DestroyBalloonTip();
|
|
pballoon->Release();
|
|
}
|
|
}
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitItemList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#define NUM_GETITEMATONCE 30
|
|
|
|
HRESULT CTipbarThread::InitItemList()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IEnumTfLangBarItems *pEnum = NULL;
|
|
RECT rc;
|
|
CEnumCatCache *penumcache = NULL;
|
|
CGuidDwordCache *pgdcache = NULL;
|
|
|
|
if (!_ptw)
|
|
return hr;
|
|
|
|
SIZE sizeWndFrame;
|
|
sizeWndFrame.cx = 0;
|
|
sizeWndFrame.cy = 0;
|
|
if (_ptw->GetWndFrame() != NULL)
|
|
_ptw->GetWndFrame()->GetFrameSize( &sizeWndFrame );
|
|
|
|
_ptw->InitThemeMargins();
|
|
|
|
if (!IsVertical())
|
|
{
|
|
rc.left = _ptw->GetGripperWidth() + 1 + sizeWndFrame.cx;
|
|
rc.top = 0 + sizeWndFrame.cy;
|
|
rc.right = 0;
|
|
rc.bottom = _ptw->GetTipbarHeight() - sizeWndFrame.cy;
|
|
}
|
|
else
|
|
{
|
|
rc.left = 0 + sizeWndFrame.cx;
|
|
rc.top = _ptw->GetGripperWidth() + 1 + sizeWndFrame.cy;
|
|
rc.right = _ptw->GetTipbarHeight() - sizeWndFrame.cx;
|
|
rc.bottom = 0;
|
|
}
|
|
|
|
|
|
_nNumItem = 0;
|
|
|
|
penumcache = new CEnumCatCache;
|
|
if (!penumcache)
|
|
{
|
|
TraceMsg(TF_FUNC, "could not create CEnumCatCache");
|
|
goto Exit;
|
|
}
|
|
|
|
pgdcache = new CGuidDwordCache;
|
|
if (!pgdcache)
|
|
{
|
|
TraceMsg(TF_FUNC, "could not create CGuidDwordCache");
|
|
goto Exit;
|
|
}
|
|
|
|
if (_plbim)
|
|
{
|
|
ULONG ulFetched = 0;
|
|
ITfLangBarItem *plbi[NUM_GETITEMATONCE] = {NULL};
|
|
TF_LANGBARITEMINFO lbiInfo[NUM_GETITEMATONCE];
|
|
DWORD dwStatus[NUM_GETITEMATONCE];
|
|
ULONG ul;
|
|
if (SUCCEEDED(hr = _plbim->GetItems(NUM_GETITEMATONCE,
|
|
plbi,
|
|
lbiInfo,
|
|
dwStatus,
|
|
&ulFetched)) && ulFetched)
|
|
{
|
|
for (ul = 0; ul < ulFetched; ul++)
|
|
{
|
|
if (plbi[ul])
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!InsertItem(plbi[ul],
|
|
penumcache,
|
|
pgdcache,
|
|
&rc,
|
|
_ptw->GetThemeMargins(),
|
|
&lbiInfo[ul],
|
|
&dwStatus[ul]))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
plbi[ul]->Release();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
_AdviseItemsSink();
|
|
}
|
|
else if (IsConsole())
|
|
{
|
|
CLBarInatItem *pInatItem = new CLBarInatItem(_dwThreadId);
|
|
if (pInatItem)
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(!_fIsInatItem);
|
|
_fIsInatItem = TRUE;
|
|
#endif
|
|
|
|
TF_LANGBARITEMINFO lbiInfo;
|
|
DWORD dwStatus;
|
|
pInatItem->GetInfo(&lbiInfo);
|
|
pInatItem->GetStatus(&dwStatus);
|
|
InsertItem(pInatItem, penumcache, pgdcache, &rc, _ptw->GetThemeMargins(), &lbiInfo, &dwStatus);
|
|
|
|
pInatItem->Release();
|
|
|
|
_AdviseItemsSink();
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
LocateItems();
|
|
|
|
Exit:
|
|
|
|
if (penumcache)
|
|
delete penumcache;
|
|
|
|
if (pgdcache)
|
|
delete pgdcache;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetTextSize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::GetTextSize(BSTR bstr, SIZE *psize)
|
|
{
|
|
HFONT hfontOld = NULL;
|
|
HDC hdc = GetDC(_ptw->GetWnd());
|
|
|
|
if (SUCCEEDED(_ptw->EnsureThemeData(_ptw->GetWnd())))
|
|
{
|
|
RECT rcText;
|
|
LOGFONTW lf;
|
|
HFONT hfont = NULL;
|
|
CUIFTheme themeBtn;
|
|
|
|
Assert(IsOnNT51());
|
|
|
|
themeBtn.SetActiveTheme(L"TOOLBAR", TP_BUTTON, 0);
|
|
|
|
if (SUCCEEDED(themeBtn.OpenThemeData(_ptw->GetWnd())))
|
|
{
|
|
if (SUCCEEDED(themeBtn.GetThemeFont(NULL, 0 , TMT_FONT, &lf)))
|
|
if (hfont = CreateFontIndirectW(&lf))
|
|
hfontOld = (HFONT)SelectObject(hdc, hfont);
|
|
|
|
themeBtn.GetThemeTextExtent(hdc, 0 , bstr, SysStringLen(bstr),0, NULL, &rcText);
|
|
}
|
|
psize->cx = rcText.right;
|
|
psize->cy = rcText.bottom;
|
|
|
|
|
|
if (hfontOld)
|
|
SelectObject(hdc, hfontOld);
|
|
|
|
if (hfont)
|
|
DeleteObject(hfont);
|
|
}
|
|
else
|
|
{
|
|
if (_ptw->GetFont())
|
|
hfontOld = (HFONT)SelectObject(hdc, _ptw->GetFont());
|
|
|
|
FLGetTextExtentPoint32( hdc, bstr, SysStringLen(bstr), psize);
|
|
|
|
if (hfontOld)
|
|
SelectObject(hdc, hfontOld);
|
|
}
|
|
|
|
|
|
ReleaseDC(_ptw->GetWnd(), hdc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InsertItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarThread::InsertItem(ITfLangBarItem *plbi, CEnumCatCache *penumcache, CGuidDwordCache *pgdcache, RECT *prc, MARGINS *pmargins, TF_LANGBARITEMINFO *plbiInfo, DWORD *pdwStatus)
|
|
{
|
|
ITfLangBarItemButton *plbiButton = NULL;
|
|
ITfLangBarItemBitmapButton *plbiBitmapButton = NULL;
|
|
ITfLangBarItemBitmap *plbiBitmap = NULL;
|
|
ITfLangBarItemBalloon *plbiBalloon = NULL;
|
|
CTipbarItem *ptbItem = NULL;
|
|
RECT rc = {0, 0, 0, 0};
|
|
BOOL bRet = FALSE;
|
|
BSTR bstrText = NULL;
|
|
|
|
Assert(plbi);
|
|
|
|
if ((SUCCEEDED(plbi->QueryInterface(IID_ITfLangBarItemButton,
|
|
(void **)&plbiButton))) ||
|
|
(SUCCEEDED(plbi->QueryInterface(IID_ITfLangBarItemBitmapButton,
|
|
(void **)&plbiBitmapButton))))
|
|
{
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
SIZE sizeText = {0,0};
|
|
DWORD dwNuiBtnStyle = 0;
|
|
DWORD dwSBtnShowType = 0;
|
|
int nWidth = _ptw->GetSmIconWidth() + _ptw->GetItemMargin();
|
|
|
|
if (_ptw->IsShowText())
|
|
{
|
|
dwSBtnShowType |= UITBBUTTON_TEXT;
|
|
HRESULT hr;
|
|
|
|
if (plbiButton)
|
|
hr = plbiButton->GetText(&bstrText);
|
|
else if (plbiBitmapButton)
|
|
hr = plbiBitmapButton->GetText(&bstrText);
|
|
else
|
|
goto Next;
|
|
|
|
//
|
|
// check if it is disconnected.
|
|
//
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
if (SUCCEEDED(hr) && bstrText)
|
|
{
|
|
|
|
GetTextSize(bstrText, &sizeText);
|
|
//
|
|
// use height for text margin.
|
|
//
|
|
nWidth += (sizeText.cx + (sizeText.cy / 2));
|
|
}
|
|
}
|
|
|
|
nWidth += pmargins->cxLeftWidth;
|
|
nWidth += pmargins->cxRightWidth;
|
|
|
|
dwNuiBtnStyle = plbiInfo->dwStyle &
|
|
(TF_LBI_STYLE_BTN_BUTTON |
|
|
TF_LBI_STYLE_BTN_MENU |
|
|
TF_LBI_STYLE_BTN_TOGGLE);
|
|
|
|
if ((dwNuiBtnStyle & (TF_LBI_STYLE_BTN_BUTTON | TF_LBI_STYLE_BTN_MENU))
|
|
== (TF_LBI_STYLE_BTN_BUTTON | TF_LBI_STYLE_BTN_MENU))
|
|
nWidth += 14;
|
|
|
|
if (!IsVertical())
|
|
{
|
|
prc->right = prc->left + nWidth;
|
|
}
|
|
else
|
|
{
|
|
prc->bottom = prc->top + nWidth;
|
|
dwNuiBtnStyle |= UITBBUTTON_VERTICAL;
|
|
}
|
|
|
|
if (plbiButton)
|
|
{
|
|
ptbItem = new CTipbarButtonItem(this,
|
|
plbiButton,
|
|
plbiButton,
|
|
0,
|
|
prc,
|
|
0,
|
|
dwNuiBtnStyle,
|
|
dwSBtnShowType,
|
|
plbiInfo,
|
|
*pdwStatus);
|
|
}
|
|
else if (plbiBitmapButton)
|
|
{
|
|
ptbItem = new CTipbarBitmapButtonItem(this,
|
|
plbiBitmapButton,
|
|
plbiBitmapButton,
|
|
0,
|
|
prc,
|
|
0,
|
|
dwNuiBtnStyle,
|
|
dwSBtnShowType,
|
|
plbiInfo,
|
|
*pdwStatus);
|
|
}
|
|
else
|
|
{
|
|
Assert(0);
|
|
goto Next;
|
|
}
|
|
|
|
if (!ptbItem)
|
|
goto Next;
|
|
|
|
ptbItem->Init();
|
|
|
|
if (IsVertical())
|
|
ptbItem->SetFont(_ptw->GetVerticalFont());
|
|
|
|
ptbItem->SetText((bstrText && SysStringLen(bstrText)) ? bstrText : NULL);
|
|
ptbItem->SetTextSize(&sizeText);
|
|
|
|
GetSortScore(ptbItem->GetItemSortScore(), plbiInfo, penumcache, pgdcache);
|
|
ptbItem->SetWidth(nWidth);
|
|
|
|
}
|
|
else if (SUCCEEDED(plbi->QueryInterface(IID_ITfLangBarItemBitmap,
|
|
(void **)&plbiBitmap)))
|
|
{
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
if (!plbiBitmap)
|
|
goto Next;
|
|
|
|
SIZE sizeDefault = {_ptw->GetSmIconWidth() * 2,
|
|
_ptw->GetSmIconHeight()};
|
|
SIZE size;
|
|
plbiBitmap->GetPreferredSize(&sizeDefault, &size);
|
|
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
if (!IsVertical())
|
|
prc->right = prc->left + size.cx;
|
|
else
|
|
prc->bottom = prc->top + size.cx;
|
|
|
|
ptbItem = new CTipbarBitmapItem(this,
|
|
plbiBitmap,
|
|
plbiBitmap,
|
|
0,
|
|
prc,
|
|
0,
|
|
plbiInfo,
|
|
*pdwStatus);
|
|
|
|
if (!ptbItem)
|
|
goto Next;
|
|
|
|
ptbItem->Init();
|
|
GetSortScore(ptbItem->GetItemSortScore(), plbiInfo, penumcache, pgdcache);
|
|
ptbItem->SetWidth(size.cx);
|
|
}
|
|
else if (SUCCEEDED(plbi->QueryInterface(IID_ITfLangBarItemBalloon,
|
|
(void **)&plbiBalloon)))
|
|
{
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
if (!plbiBalloon)
|
|
goto Next;
|
|
|
|
SIZE sizeDefault = {32,16};
|
|
SIZE size;
|
|
plbiBalloon->GetPreferredSize(&sizeDefault, &size);
|
|
|
|
if (!_ptw)
|
|
goto Next;
|
|
|
|
if (!IsVertical())
|
|
prc->right = prc->left + size.cx;
|
|
else
|
|
prc->bottom = prc->top + size.cx;
|
|
|
|
ptbItem = new CTipbarBalloonItem(this,
|
|
plbiBalloon,
|
|
plbiBalloon,
|
|
0,
|
|
prc,
|
|
0,
|
|
plbiInfo,
|
|
*pdwStatus);
|
|
|
|
if (!ptbItem)
|
|
goto Next;
|
|
|
|
ptbItem->Init();
|
|
|
|
if (IsVertical())
|
|
ptbItem->SetFont(_ptw->GetVerticalFont());
|
|
|
|
GetSortScore(ptbItem->GetItemSortScore(), plbiInfo, penumcache, pgdcache);
|
|
ptbItem->SetWidth(size.cx);
|
|
|
|
}
|
|
|
|
Next:
|
|
SafeReleaseClear(plbiButton);
|
|
SafeReleaseClear(plbiBitmapButton);
|
|
SafeReleaseClear(plbiBitmap);
|
|
SafeReleaseClear(plbiBalloon);
|
|
|
|
if (!_ptw && ptbItem)
|
|
{
|
|
delete ptbItem;
|
|
ptbItem = NULL;
|
|
}
|
|
|
|
if (ptbItem)
|
|
{
|
|
CTipbarItem **pptbItem = _rgItem.Append(1);
|
|
if (pptbItem)
|
|
{
|
|
*pptbItem = ptbItem;
|
|
|
|
if (!IsVertical())
|
|
prc->left = prc->right;
|
|
else
|
|
prc->top = prc->bottom;
|
|
|
|
_nNumItem++;
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
delete ptbItem;
|
|
ptbItem = NULL;
|
|
}
|
|
}
|
|
|
|
if (bstrText)
|
|
SysFreeString(bstrText);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UninitItemList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarThread::_UninitItemList(BOOL fUnAdvise)
|
|
{
|
|
int i = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
pItem->Disconnect();
|
|
}
|
|
|
|
if (fUnAdvise)
|
|
{
|
|
if ((_dwThreadId == GetCurrentThreadId()) ||
|
|
!MyWaitForInputIdle(_dwThreadId, UTB_INPUTIDLETIMEOUT))
|
|
hr = _UnadviseItemsSink();
|
|
}
|
|
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
if (_ptw)
|
|
pItem->RemoveMeToUI(_ptw);
|
|
|
|
pItem->ClearConnections();
|
|
|
|
if (!_ptw)
|
|
pItem->ClearWnd();
|
|
else
|
|
pItem->DetachWnd();
|
|
pItem->UninitUIResource();
|
|
pItem->Release();
|
|
}
|
|
|
|
_rgItem.Clear();
|
|
|
|
RemoveAllSeparators();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _AdviseItemsSink
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::_AdviseItemsSink()
|
|
{
|
|
HRESULT hr;
|
|
int nCnt = _rgItem.Count();
|
|
int i = 0;
|
|
ITfLangBarItemSink **pplbis = NULL;
|
|
GUID *pguid = NULL;
|
|
DWORD *pdwCookie = NULL;
|
|
|
|
if (!_plbim || !nCnt)
|
|
goto Exit;
|
|
|
|
pplbis = new ITfLangBarItemSink*[nCnt];
|
|
if (!pplbis)
|
|
goto Exit;
|
|
|
|
pguid = new GUID[nCnt];
|
|
if (!pguid)
|
|
goto Exit;
|
|
|
|
pdwCookie = new DWORD[nCnt];
|
|
if (!pdwCookie)
|
|
goto Exit;
|
|
|
|
for (i = 0; (i < nCnt) && (i < _rgItem.Count()); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (!pItem)
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
pguid[i] = *pItem->GetGUID();
|
|
|
|
hr = pItem->QueryInterface(IID_ITfLangBarItemSink, (void **)&pplbis[i]);
|
|
if (FAILED(hr))
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (FAILED(_plbim->AdviseItemsSink(nCnt, pplbis, pguid, pdwCookie)))
|
|
goto Exit;
|
|
|
|
for (i = 0; (i < nCnt) && (i < _rgItem.Count()); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (pItem)
|
|
pItem->_dwlbiSinkCookie = pdwCookie[i];
|
|
|
|
pplbis[i]->Release();
|
|
}
|
|
|
|
Exit:
|
|
if (pplbis)
|
|
delete[] pplbis;
|
|
if (pguid)
|
|
delete[] pguid;
|
|
if (pdwCookie)
|
|
delete[] pdwCookie;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UnadviseItemsSink
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarThread::_UnadviseItemsSink()
|
|
{
|
|
int nCnt = _rgItem.Count();
|
|
int i = 0;
|
|
DWORD *pdwCookie = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!nCnt)
|
|
goto Exit;
|
|
|
|
if (!_plbim)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
pdwCookie = new DWORD[nCnt];
|
|
if (!pdwCookie)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (pItem)
|
|
pdwCookie[i] = pItem->_dwlbiSinkCookie;
|
|
}
|
|
|
|
if (FAILED(hr = _plbim->UnadviseItemsSink(nCnt, pdwCookie)))
|
|
goto Exit;
|
|
Exit:
|
|
if (pdwCookie)
|
|
delete[] pdwCookie;
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsHKLToSkipRedrawOnNoItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarWnd::IsHKLToSkipRedrawOnNoItem()
|
|
{
|
|
return IsSkipRedrawHKL(GetFocusKeyboardLayout());
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// LocateItems
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::LocateItems()
|
|
{
|
|
int i = 0;
|
|
SIZE sizeWndFrame;
|
|
POINT pt;
|
|
RECT rcWork;
|
|
RECT rc;
|
|
BOOL fOverScreen = FALSE;
|
|
int nTipbarHeight;
|
|
|
|
_fSkipRedrawOnNoItem = FALSE;
|
|
|
|
if (!_ptw)
|
|
return;
|
|
|
|
_ptw->GetRect(&rc);
|
|
|
|
pt.x = rc.left;
|
|
pt.y = rc.top;
|
|
CUIGetWorkAreaRect(pt, &rcWork);
|
|
|
|
sizeWndFrame.cx = 0;
|
|
sizeWndFrame.cy = 0;
|
|
if (_ptw->GetWndFrame() != NULL)
|
|
_ptw->GetWndFrame()->GetFrameSize( &sizeWndFrame );
|
|
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
CTipbarItem *ptbMin = NULL;
|
|
if (!ptbItem)
|
|
continue;
|
|
|
|
|
|
int j;
|
|
CItemSortScore issMin(-1, -1, -1);
|
|
int nMin;
|
|
|
|
for (j = i; j < _rgItem.Count(); j++)
|
|
{
|
|
CTipbarItem *ptb = _rgItem.Get(j);
|
|
CItemSortScore *piss = ptb->GetItemSortScore();
|
|
if (issMin > *piss)
|
|
{
|
|
ptbMin = ptb;
|
|
issMin = *piss;
|
|
nMin = j;
|
|
}
|
|
}
|
|
if (ptbMin)
|
|
{
|
|
CTipbarItem **pptbItem = _rgItem.GetPtr(i);
|
|
CTipbarItem **pptbMin = _rgItem.GetPtr(nMin);
|
|
|
|
*pptbItem = ptbMin;
|
|
*pptbMin = ptbItem;
|
|
}
|
|
|
|
}
|
|
|
|
LocateItemsAgain:
|
|
RemoveAllSeparators();
|
|
|
|
nTipbarHeight = _ptw->GetTipbarHeight();
|
|
if (!IsVertical())
|
|
{
|
|
rc.left = 1 + _ptw->GetGripperWidth() + sizeWndFrame.cx;
|
|
|
|
if (rc.bottom - rc.top > nTipbarHeight)
|
|
{
|
|
int nHeightPadding = (rc.bottom - rc.top - nTipbarHeight) / 2;
|
|
|
|
if (nHeightPadding > CY_ITEMMARGIN_THEME)
|
|
nHeightPadding -= CY_ITEMMARGIN_THEME;
|
|
else
|
|
nHeightPadding = 0;
|
|
|
|
rc.top += (0 + sizeWndFrame.cy + nHeightPadding);
|
|
rc.bottom -= (sizeWndFrame.cy + nHeightPadding);
|
|
}
|
|
else
|
|
{
|
|
rc.top = 0 + sizeWndFrame.cy;
|
|
rc.bottom = nTipbarHeight - sizeWndFrame.cy;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
rc.top = 1 + _ptw->GetGripperWidth() + sizeWndFrame.cx;
|
|
|
|
if (rc.right - rc.left > nTipbarHeight)
|
|
{
|
|
int nHeightPadding = (rc.right - rc.left - nTipbarHeight) / 2;
|
|
|
|
if (nHeightPadding > CY_ITEMMARGIN_THEME)
|
|
nHeightPadding -= CY_ITEMMARGIN_THEME;
|
|
else
|
|
nHeightPadding = 0;
|
|
|
|
rc.left += (0 + sizeWndFrame.cy + nHeightPadding);
|
|
rc.right -= (sizeWndFrame.cy + nHeightPadding);
|
|
}
|
|
else
|
|
{
|
|
rc.left = 0 + sizeWndFrame.cy;
|
|
rc.right = nTipbarHeight - sizeWndFrame.cy;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
DWORD dwCatScore = 0;
|
|
ULONG ulShownItemInPrevCat = 0;
|
|
BOOL bShowToolbar = FALSE;
|
|
LANGID langid = LANGID(LOWORD(HandleToLong(_ptw->GetFocusKeyboardLayout())));
|
|
|
|
CTipbarItem *ptbLastHiddenableItem = NULL;
|
|
|
|
while (i < _rgItem.Count())
|
|
{
|
|
LANGBARITEMSTATE *pItemState;
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
DWORD dwWidth = ptbItem->GetWidth();
|
|
|
|
if (ptbItem->IsHiddenStatusControl())
|
|
{
|
|
if (ptbItem->IsInHiddenStatus())
|
|
goto HideThis;
|
|
}
|
|
else
|
|
{
|
|
pItemState = _ptw->_itemList.FindItem(*ptbItem->GetGUID());
|
|
if (pItemState)
|
|
{
|
|
if (!pItemState->IsShown())
|
|
goto HideThis;
|
|
}
|
|
else
|
|
{
|
|
if (ptbItem->IsHiddenByDefault())
|
|
goto HideThis;
|
|
}
|
|
ptbLastHiddenableItem = ptbItem;
|
|
}
|
|
|
|
if (_ptw->IsSFDeskband() && _ptw->IsSFNoExtraIcon())
|
|
{
|
|
REFGUID rguidItem = *ptbItem->GetGUID();
|
|
|
|
if (!IsEqualGUID(rguidItem, GUID_TFCAT_TIP_KEYBOARD) &&
|
|
!IsEqualGUID(rguidItem, GUID_LBI_INATITEM) &&
|
|
!IsEqualGUID(rguidItem, GUID_LBI_CTRL) &&
|
|
(!IsFELangId(langid) || (IsFELangId(langid) && !ptbItem->IsShownInTray())))
|
|
goto HideThis;
|
|
}
|
|
|
|
if (ptbItem->IsShownInTrayOnly())
|
|
{
|
|
HideThis:
|
|
RECT rcEmp = {0, 0, 0, 0};
|
|
ptbItem->SetRect(&rcEmp);
|
|
ptbItem->VisibleInToolbar(FALSE);
|
|
goto Next;
|
|
}
|
|
|
|
if (!ptbItem->IsHiddenStatusControl())
|
|
_ptw->_itemList.StartDemotingTimer(*ptbItem->GetGUID(), FALSE);
|
|
|
|
//
|
|
// If we find an Item to be shown, we show toolbar.
|
|
// If we have only "HideOnNoOterItems" to be shown, we hide toolbar.
|
|
//
|
|
if (!ptbItem->IsHideOnNoOtherItems())
|
|
{
|
|
bShowToolbar = TRUE;
|
|
}
|
|
|
|
if (ulShownItemInPrevCat && (dwCatScore != ptbItem->GetCatScore()))
|
|
{
|
|
DWORD dwSepStyle = 0;
|
|
if (!IsVertical())
|
|
rc.right = rc.left + _ptw->GetItemDistance();
|
|
else
|
|
{
|
|
rc.bottom = rc.top + _ptw->GetItemDistance();
|
|
dwSepStyle |= UITBSEPARATOR_VERTICAL;
|
|
}
|
|
|
|
CUIFSeparator *pSep = new CUIFSeparator(_ptw, -1, &rc, dwSepStyle);
|
|
if (pSep)
|
|
{
|
|
int nCntSep = _rgSep.Count();
|
|
pSep->Initialize();
|
|
|
|
if (_rgSep.Insert(nCntSep, 1))
|
|
{
|
|
_rgSep.Set(nCntSep, pSep);
|
|
}
|
|
else
|
|
{
|
|
delete pSep;
|
|
pSep = NULL;
|
|
}
|
|
}
|
|
|
|
if (!IsVertical())
|
|
rc.left = rc.right;
|
|
else
|
|
rc.top = rc.bottom;
|
|
|
|
ulShownItemInPrevCat = 0;
|
|
}
|
|
|
|
dwCatScore = ptbItem->GetCatScore();
|
|
|
|
if (!IsVertical())
|
|
rc.right = rc.left + dwWidth;
|
|
else
|
|
rc.bottom = rc.top + dwWidth;
|
|
|
|
ptbItem->SetRect(&rc);
|
|
ptbItem->VisibleInToolbar(TRUE);
|
|
|
|
if (!IsVertical())
|
|
rc.left = rc.right;
|
|
else
|
|
rc.top = rc.bottom;
|
|
|
|
ulShownItemInPrevCat++;
|
|
Next:
|
|
i++;
|
|
}
|
|
|
|
// Add the last sepcarator
|
|
if (!IsVertical())
|
|
rc.right = rc.left + 4;
|
|
else
|
|
rc.bottom = rc.top + 4;
|
|
|
|
DWORD dwSepStyle = 0;
|
|
if (IsVertical())
|
|
dwSepStyle |= UITBSEPARATOR_VERTICAL;
|
|
|
|
CUIFSeparator *pSep = new CUIFSeparator(_ptw, -1, &rc, dwSepStyle);
|
|
|
|
if (pSep)
|
|
{
|
|
int nCntSep = _rgSep.Count();
|
|
pSep->Initialize();
|
|
if (_rgSep.Insert(nCntSep, 1))
|
|
{
|
|
_rgSep.Set(nCntSep, pSep);
|
|
}
|
|
else
|
|
{
|
|
delete pSep;
|
|
pSep = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
if (!IsVertical())
|
|
{
|
|
rc.left = rc.right;
|
|
// allocate the space for ctrl buttons.
|
|
rc.right = rc.left + _ptw->GetCtrlButtonWidth();
|
|
}
|
|
else
|
|
{
|
|
rc.top = rc.bottom;
|
|
// allocate the space for ctrl buttons.
|
|
rc.bottom = rc.top + _ptw->GetCtrlButtonWidth();
|
|
}
|
|
|
|
_sizeWnd.cx = rc.right + sizeWndFrame.cx;
|
|
_sizeWnd.cy = rc.bottom + sizeWndFrame.cy;
|
|
|
|
if (_ptw->GetWndFrame() != NULL)
|
|
{
|
|
RECT rcWnd;
|
|
rcWnd.left = 0;
|
|
rcWnd.top = 0;
|
|
rcWnd.right = _sizeWnd.cx;
|
|
rcWnd.bottom = _sizeWnd.cy;
|
|
_ptw->GetWndFrame()->SetRect(&rcWnd);
|
|
}
|
|
|
|
//
|
|
// If the window is wider than WorkArea, we hide one item and locate items
|
|
// again.
|
|
//
|
|
if (_sizeWnd.cx > (rcWork.right - rcWork.left))
|
|
{
|
|
fOverScreen = TRUE;
|
|
if (ptbLastHiddenableItem)
|
|
{
|
|
_ptw->_itemList.SetDemoteLevel(*ptbLastHiddenableItem->GetGUID(),
|
|
DL_HIDDENLEVEL1);
|
|
goto LocateItemsAgain;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Exclude caption buttons.
|
|
//
|
|
int dxOffset = 0;
|
|
int dyOffset = 0;
|
|
if (!IsVertical() && g_bExcludeCaptionButtons)
|
|
{
|
|
RECT rcWnd;
|
|
_ptw->GetRect(&rcWnd);
|
|
_ptw->MyClientToScreen(NULL, &rcWnd);
|
|
if (_ptw->CheckExcludeCaptionButtonMode(&rcWnd, &rcWork))
|
|
{
|
|
if ((rcWnd.left + _sizeWnd.cx + _ptw->GetCxDlgFrame()) >
|
|
(rcWork.right - (_ptw->GetCaptionButtonWidth() * 3)))
|
|
{
|
|
dyOffset = 0 - rcWnd.top;
|
|
dxOffset = (rcWork.right - (_ptw->GetCaptionButtonWidth() * 3)) -
|
|
(rcWnd.left + _sizeWnd.cx + _ptw->GetCxDlgFrame());
|
|
_ptw->SetRect(&rcWnd);
|
|
_ptw->SetExcludeCaptionButtonMode(TRUE);
|
|
}
|
|
}
|
|
else
|
|
_ptw->SetExcludeCaptionButtonMode(FALSE);
|
|
}
|
|
|
|
MyMoveWnd(dxOffset, dyOffset);
|
|
|
|
if (!_ptw)
|
|
goto Exit;
|
|
|
|
_ptw->_fIsItemShownInFloatingToolbar = bShowToolbar;
|
|
//
|
|
// We show or hide only when toolbar is floating arround.
|
|
//
|
|
if (IsFocusThread() && _ptw->IsSFShowNormal() && !_ptw->IsInFullScreen())
|
|
{
|
|
//
|
|
// Satori Hack.
|
|
//
|
|
// If the focus thread is running with Satori we don't hide
|
|
// the toolbar.
|
|
//
|
|
if (!bShowToolbar && _ptw->IsHKLToSkipRedrawOnNoItem())
|
|
{
|
|
_fSkipRedrawOnNoItem = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
_ptw->_fShowWindowAtTimer = bShowToolbar;
|
|
_ptw->_pThreadShowWindowAtTimer = this;
|
|
_ptw->_fShowOverItemBalloonAtTimer = fOverScreen;
|
|
|
|
_ptw->KillTimer(TIPWND_TIMER_SHOWWINDOW);
|
|
_ptw->SetTimer(TIPWND_TIMER_SHOWWINDOW, g_uTimerElapseSHOWWINDOW);
|
|
|
|
#if 0
|
|
_ptw->Show(bShowToolbar);
|
|
|
|
//
|
|
// If the window was over the screen and hide some items,
|
|
// we show balloon tips.
|
|
//
|
|
if (fOverScreen)
|
|
_ptw->ShowOverScreenSizeBalloon();
|
|
#endif
|
|
}
|
|
Exit:
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetSortScore
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::GetSortScore(CItemSortScore *pScore, TF_LANGBARITEMINFO *plbiInfo, CEnumCatCache *penumcache, CGuidDwordCache *pgdcache)
|
|
{
|
|
DWORD dwSub = 0;
|
|
DWORD dwCat = 0;
|
|
DWORD dwCatIndex = 256;
|
|
IEnumGUID *pEnum;
|
|
BOOL bFound = FALSE;
|
|
GUID guid;
|
|
|
|
//
|
|
// check system device type button.
|
|
//
|
|
if (pEnum = penumcache->GetEnumItemsInCategory(GUID_TFCAT_CATEGORY_OF_TIP))
|
|
{
|
|
while (!bFound && (pEnum->Next(1, &guid, NULL) == S_OK))
|
|
{
|
|
dwCatIndex++;
|
|
|
|
if (!(dwCat = pgdcache->GetGuidDWORD(guid)))
|
|
dwCat = dwCatIndex;
|
|
|
|
if (IsEqualGUID(guid, plbiInfo->guidItem))
|
|
bFound = TRUE;
|
|
else
|
|
{
|
|
IEnumGUID *pEnumTip;
|
|
if (pEnumTip = penumcache->GetEnumItemsInCategory(guid))
|
|
{
|
|
CLSID clsid;
|
|
while (!bFound && (pEnumTip->Next(1, &clsid, NULL) == S_OK))
|
|
{
|
|
|
|
dwSub++;
|
|
|
|
if (IsEqualGUID(clsid, plbiInfo->clsidService))
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bFound)
|
|
{
|
|
pScore->Set(dwCat, plbiInfo->ulSort, dwSub);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// check system toolbar button.
|
|
//
|
|
if (IsEqualGUID(GUID_NULL, plbiInfo->clsidService))
|
|
{
|
|
pScore->Set(0, plbiInfo->ulSort, 0);
|
|
return;
|
|
}
|
|
else if (IsEqualGUID(CLSID_SYSTEMLANGBARITEM, plbiInfo->clsidService))
|
|
{
|
|
pScore->Set(0, plbiInfo->ulSort, 0);
|
|
return;
|
|
}
|
|
else if (IsEqualGUID(CLSID_SYSTEMLANGBARITEM2, plbiInfo->clsidService))
|
|
{
|
|
pScore->Set((-1), plbiInfo->ulSort, 0);
|
|
return;
|
|
}
|
|
else if (IsEqualGUID(CLSID_SYSTEMLANGBARITEM_KEYBOARD, plbiInfo->clsidService))
|
|
{
|
|
dwCat = pgdcache->GetGuidDWORD(GUID_TFCAT_TIP_KEYBOARD);
|
|
pScore->Set(dwCat, plbiInfo->ulSort, (DWORD)-1);
|
|
return;
|
|
}
|
|
else if (IsEqualGUID(CLSID_SYSTEMLANGBARITEM_SPEECH, plbiInfo->clsidService))
|
|
{
|
|
dwCat = pgdcache->GetGuidDWORD(GUID_TFCAT_TIP_SPEECH);
|
|
pScore->Set(dwCat, plbiInfo->ulSort, (DWORD)-1);
|
|
return;
|
|
}
|
|
else if (IsEqualGUID(CLSID_SYSTEMLANGBARITEM_HANDWRITING, plbiInfo->clsidService))
|
|
{
|
|
dwCat = pgdcache->GetGuidDWORD(GUID_TFCAT_TIP_HANDWRITING);
|
|
pScore->Set(dwCat, plbiInfo->ulSort, (DWORD)-1);
|
|
return;
|
|
}
|
|
|
|
pScore->Set((DWORD)-1, (DWORD)-1, (DWORD)-1);
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateItems
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarThread::UpdateItems()
|
|
{
|
|
int i;
|
|
|
|
_fItemChanged = FALSE;
|
|
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
|
|
if (ptbItem)
|
|
ptbItem->OnUpdate(TF_LBI_STATUS | TF_LBI_BTNALL | TF_LBI_BMPALL | TF_LBI_BALLOON);
|
|
|
|
}
|
|
|
|
for (i = 0; i < _rgSep.Count(); i++)
|
|
{
|
|
CUIFSeparator *pSep = _rgSep.Get(i);
|
|
if (pSep)
|
|
pSep->CallOnPaint();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MyMoveWnd
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::MyMoveWnd(int dxOffset, int dyOffset)
|
|
{
|
|
if (!_ptw)
|
|
return;
|
|
|
|
if (_ptw->GetFocusThread() != this)
|
|
return;
|
|
|
|
POINT pt;
|
|
RECT rc;
|
|
RECT rcWork;
|
|
|
|
_ptw->GetRect(&rc);
|
|
pt.x = rc.left;
|
|
pt.y = rc.top;
|
|
CUIGetWorkAreaRect(pt, &rcWork);
|
|
|
|
GetWindowRect(_ptw->GetWnd(), &rc);
|
|
int x = rc.left + dxOffset;
|
|
int y = rc.top + dyOffset;
|
|
|
|
if (_ptw->IsInExcludeCaptionButtonMode())
|
|
{
|
|
//
|
|
// now we're in exclude caption button mode.
|
|
// adjust position to the next of caption buttons.
|
|
//
|
|
if (_ptw->CheckExcludeCaptionButtonMode(&rc, &rcWork))
|
|
{
|
|
x = (rcWork.right - (_ptw->GetCaptionButtonWidth() * 3)) -
|
|
(_sizeWnd.cx + _ptw->GetCxDlgFrame());
|
|
y = 0;
|
|
}
|
|
else
|
|
{
|
|
_ptw->SetExcludeCaptionButtonMode(FALSE);
|
|
}
|
|
}
|
|
|
|
if (!IsVertical())
|
|
{
|
|
_ptw->SetMoveRect(x, y,
|
|
_sizeWnd.cx + _ptw->GetCxDlgFrame(),
|
|
_ptw->GetTipbarHeight() + _ptw->GetCyDlgFrame());
|
|
}
|
|
else
|
|
{
|
|
_ptw->SetMoveRect(x, y,
|
|
_ptw->GetTipbarHeight() + _ptw->GetCxDlgFrame(),
|
|
_sizeWnd.cy + _ptw->GetCyDlgFrame());
|
|
}
|
|
|
|
SIZE sizeWndFrame;
|
|
sizeWndFrame.cx = 0;
|
|
sizeWndFrame.cy = 0;
|
|
if (_ptw->GetWndFrame() != NULL)
|
|
_ptw->GetWndFrame()->GetFrameSize( &sizeWndFrame );
|
|
|
|
_ptw->LocateCtrlButtons();
|
|
|
|
//
|
|
// call AutoAdjustDeskBandSize() now.
|
|
// this function adjust the deskband size at first call only.
|
|
//
|
|
_ptw->AutoAdjustDeskBandSize();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddUIObjs
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::AddUIObjs()
|
|
{
|
|
|
|
_AddRef();
|
|
|
|
int i;
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
if (ptbItem && ptbItem->IsVisibleInToolbar())
|
|
ptbItem->AddMeToUI(_ptw);
|
|
|
|
}
|
|
|
|
AddAllSeparators();
|
|
MyMoveWnd(0, 0);
|
|
|
|
_Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddAllSeparators
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::AddAllSeparators()
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgSep.Count(); i++)
|
|
{
|
|
CUIFSeparator *pSep = _rgSep.Get(i);
|
|
if (pSep)
|
|
_ptw->AddUIObj(pSep);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemoveUIObjs
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::RemoveUIObjs()
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
if (ptbItem)
|
|
ptbItem->RemoveMeToUI(_ptw);
|
|
}
|
|
RemoveAllSeparators();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemoveAllSeparators
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarThread::RemoveAllSeparators()
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgSep.Count(); i++)
|
|
{
|
|
CUIFSeparator *pSep = _rgSep.Get(i);
|
|
if (pSep)
|
|
{
|
|
if (_ptw)
|
|
_ptw->RemoveUIObj(pSep);
|
|
|
|
delete pSep;
|
|
}
|
|
}
|
|
_rgSep.Clear();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarItem *CTipbarThread::GetItem(REFGUID guid)
|
|
{
|
|
int i;
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *ptbItem = _rgItem.Get(i);
|
|
if (ptbItem)
|
|
{
|
|
GUID *pguid= ptbItem->GetGUID();
|
|
if (IsEqualGUID(*pguid, guid))
|
|
return ptbItem;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsDirtyItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD CTipbarThread::IsDirtyItem()
|
|
{
|
|
DWORD dwFlags = 0;
|
|
|
|
int i;
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (pItem)
|
|
dwFlags |= pItem->GetDirtyUpdateFlags();
|
|
}
|
|
|
|
return dwFlags;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CallOnUpdateHandler
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarThread::CallOnUpdateHandler()
|
|
{
|
|
int i;
|
|
int nCnt;
|
|
DWORD dwFlags;
|
|
CTipbarItemGuidArray rgGuid;
|
|
DWORD *pdw = NULL;
|
|
BOOL bRet = TRUE;
|
|
|
|
//
|
|
// Windows Bug #367869.
|
|
//
|
|
// AddRef now because there is a change for this thread to be removed.
|
|
//
|
|
_AddRef();
|
|
|
|
#ifdef DEBUG
|
|
_fInCallOnUpdateHandler = TRUE;
|
|
#endif
|
|
|
|
//
|
|
// we want to use g_pTipbarWnd instead of _ptw.
|
|
// _ptw could be disconnected during this function. If it is disconnected,
|
|
// we can not decrement the pending counter.
|
|
//
|
|
if (g_pTipbarWnd)
|
|
g_pTipbarWnd->StartPendingUpdateUI();
|
|
|
|
//
|
|
// if there is no items, do nothing
|
|
//
|
|
nCnt = _rgItem.Count();
|
|
if (!nCnt)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (!_plbim)
|
|
{
|
|
if (IsConsole())
|
|
{
|
|
for (i = 0; i < _rgItem.Count(); i++)
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
|
|
if (pItem && pItem->GetNotifyUI())
|
|
{
|
|
dwFlags = pItem->GetDirtyUpdateFlags();
|
|
if (dwFlags & TF_LBI_STATUS)
|
|
pItem->GetNotifyUI()->GetStatus(&dwStatus);
|
|
else
|
|
dwStatus = 0;
|
|
|
|
pItem->ClearDirtyUpdateFlags();
|
|
pItem->OnUpdateHandler(dwFlags, dwStatus);
|
|
}
|
|
}
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
rgGuid.Init(&_rgItem);
|
|
|
|
//
|
|
// if there is no dirty flag, do nothig.
|
|
//
|
|
dwFlags = IsDirtyItem();
|
|
if (!dwFlags)
|
|
goto Exit;
|
|
|
|
pdw = new DWORD[nCnt];
|
|
if (!pdw)
|
|
goto Exit;
|
|
|
|
//
|
|
// Clear the each item OnUpdate() request
|
|
//
|
|
for (i = 0; (i < nCnt) && (i < _rgItem.Count()); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
pItem->ClearOnUpdateRequest();
|
|
}
|
|
|
|
//
|
|
// get items flag at once.
|
|
//
|
|
if (FAILED(_plbim->GetItemsStatus(nCnt, rgGuid.GetPtr(), pdw)))
|
|
{
|
|
TraceMsg(TF_FUNC, "GetItemStatus failed");
|
|
bRet = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
for (i = 0; (i < nCnt) && (i < _rgItem.Count()); i++)
|
|
{
|
|
CTipbarItem *pItem = _rgItem.Get(i);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
//
|
|
// Skip the current item update request if the item has another OnUpdate() Request
|
|
//
|
|
if (pItem->IsNewOnUpdateRequest())
|
|
continue;
|
|
|
|
dwFlags = pItem->GetDirtyUpdateFlags();
|
|
if (dwFlags)
|
|
{
|
|
pItem->ClearDirtyUpdateFlags();
|
|
pItem->OnUpdateHandler(dwFlags, pdw[i]);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (pdw)
|
|
delete[] pdw;
|
|
|
|
//
|
|
// we want to use g_pTipbarWnd instead of _ptw.
|
|
// _ptw could be disconnected during this function. If it is disconnected,
|
|
// we can not decrement the pending counter.
|
|
//
|
|
if (g_pTipbarWnd)
|
|
g_pTipbarWnd->EndPendingUpdateUI();
|
|
|
|
#ifdef DEBUG
|
|
_fInCallOnUpdateHandler = FALSE;
|
|
#endif
|
|
|
|
_Release();
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarItem::CTipbarItem(CTipbarThread *ptt,
|
|
ITfLangBarItem *plbi,
|
|
TF_LANGBARITEMINFO *plbiInfo,
|
|
DWORD dwStatus)
|
|
{
|
|
_ptt = ptt;
|
|
_lbiInfo = *plbiInfo;
|
|
_plbi = plbi;
|
|
_plbi->AddRef();
|
|
_fToolTipInit = FALSE;
|
|
_fAddedToUI = FALSE;
|
|
_fDisconnected = FALSE;
|
|
|
|
_dwDirtyUpdateFlags = (TF_LBI_STATUS | TF_LBI_BTNALL | TF_LBI_BMPALL | TF_LBI_BALLOON);
|
|
|
|
_dwStatus = dwStatus;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarItem::~CTipbarItem()
|
|
{
|
|
if (g_pTipbarWnd && g_pTipbarWnd->GetAccessible())
|
|
{
|
|
g_pTipbarWnd->GetAccessible()->RemoveAccItem(this);
|
|
}
|
|
|
|
SafeRelease(_plbi);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnSetCursor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarItem::OnSetCursor(UINT uMsg, POINT pt)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetToolTip
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPCWSTR CTipbarItem::GetToolTip()
|
|
{
|
|
AddRef();
|
|
|
|
if (!_fToolTipInit)
|
|
{
|
|
BSTR bstrTooltip;
|
|
HRESULT hr;
|
|
|
|
_fToolTipInit = TRUE;
|
|
if (FAILED(hr =_plbi->GetTooltipString(&bstrTooltip)))
|
|
return NULL;
|
|
|
|
if (bstrTooltip)
|
|
{
|
|
SetToolTip(bstrTooltip);
|
|
SysFreeString(bstrTooltip);
|
|
}
|
|
}
|
|
|
|
LPCWSTR psz;
|
|
psz = GetToolTipFromUIOBJ();
|
|
|
|
Release();
|
|
return psz;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddedToUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarItem::_AddedToUI()
|
|
{
|
|
if (!IsConnected())
|
|
return;
|
|
|
|
AddRef();
|
|
|
|
_fAddedToUI = TRUE;
|
|
if (_dwDirtyUpdateFlags)
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
if (_dwDirtyUpdateFlags & TF_LBI_STATUS)
|
|
_plbi->GetStatus(&dwStatus);
|
|
else
|
|
dwStatus = 0;
|
|
|
|
OnUpdateHandler(_dwDirtyUpdateFlags, dwStatus);
|
|
_dwDirtyUpdateFlags = 0;
|
|
}
|
|
|
|
if (_ptt && _ptt->_ptw && _ptt->_ptw->GetAccessible())
|
|
{
|
|
_ptt->_ptw->GetAccessible()->AddAccItem(this);
|
|
}
|
|
|
|
Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemovedToUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarItem::_RemovedToUI()
|
|
{
|
|
_fAddedToUI = FALSE;
|
|
|
|
if (g_pTipbarWnd && g_pTipbarWnd->GetAccessible())
|
|
{
|
|
g_pTipbarWnd->GetAccessible()->RemoveAccItem(this);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Update
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarItem::OnUpdate(DWORD dwFlags)
|
|
{
|
|
DWORD dwPrevDirtyUpdateFlags = _dwDirtyUpdateFlags;
|
|
if (!IsConnected())
|
|
return S_OK;
|
|
|
|
_dwDirtyUpdateFlags |= dwFlags;
|
|
_fNewOnUpdateRequest = TRUE;
|
|
|
|
//
|
|
// if this item is not aded to UI or TrayIcon,
|
|
// we don't have to update anything yet.
|
|
// OnUpdate() will be called again
|
|
// when this item is added to UI or TrayIcon.
|
|
//
|
|
if ((!(dwFlags & TF_LBI_STATUS)) && !_fAddedToUI && !_fAddedToIconTray)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (_ptt && _ptt->_ptw && _ptt->_ptw->GetWnd())
|
|
{
|
|
_ptt->_ptw->KillTimer(TIPWND_TIMER_ONUPDATECALLED);
|
|
_ptt->_ptw->SetTimer(TIPWND_TIMER_ONUPDATECALLED, g_uTimerElapseONUPDATECALLED);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnUpdateHandler
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarItem::OnUpdateHandler(DWORD dwFlags, DWORD dwStatus)
|
|
{
|
|
if (!IsConnected())
|
|
return S_OK;
|
|
|
|
BOOL fPrevHidden = TRUE;
|
|
|
|
if (IsHiddenStatusControl())
|
|
fPrevHidden = IsInHiddenStatus();
|
|
|
|
if (dwFlags & TF_LBI_TOOLTIP)
|
|
{
|
|
_fToolTipInit = FALSE;
|
|
}
|
|
|
|
if (dwFlags & TF_LBI_STATUS)
|
|
{
|
|
BOOL fEnabled = (_dwStatus & TF_LBI_STATUS_DISABLED) ? FALSE : TRUE;
|
|
|
|
if (!IsHiddenStatusControl())
|
|
{
|
|
// Assert(dwStatus & TF_LBI_STATUS_HIDDEN);
|
|
dwStatus &= ~TF_LBI_STATUS_HIDDEN;
|
|
}
|
|
|
|
//
|
|
// MSAA support
|
|
//
|
|
if (_dwStatus != dwStatus)
|
|
{
|
|
if (_ptt && _ptt->_ptw && _ptt->_ptw->GetAccessible())
|
|
_ptt->_ptw->GetAccessible()->NotifyWinEvent( EVENT_OBJECT_STATECHANGE , this);
|
|
}
|
|
|
|
_dwStatus = dwStatus;
|
|
|
|
if (fEnabled && (_dwStatus & TF_LBI_STATUS_DISABLED))
|
|
Enable(FALSE);
|
|
else if (!fEnabled && !(_dwStatus & TF_LBI_STATUS_DISABLED))
|
|
Enable(TRUE);
|
|
}
|
|
|
|
if (IsHiddenStatusControl())
|
|
{
|
|
if (fPrevHidden != IsInHiddenStatus())
|
|
AddRemoveMeToUI(!IsInHiddenStatus() && !IsShownInTrayOnly());
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddRemoveMeToUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarItem::AddRemoveMeToUI(BOOL fAdd)
|
|
{
|
|
if (!IsConnected())
|
|
return;
|
|
|
|
_ptt->LocateItems();
|
|
_ptt->AddAllSeparators();
|
|
if (fAdd)
|
|
{
|
|
Assert(IsVisibleInToolbar());
|
|
AddMeToUI(_ptt->_ptw);
|
|
}
|
|
else
|
|
{
|
|
Assert(!IsVisibleInToolbar());
|
|
RemoveMeToUI(_ptt->_ptw);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarButtonItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IUnknown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarButtonItem::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfLangBarItemSink))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarItemSink *);
|
|
}
|
|
else if (IsEqualIID(riid, IID_PRIV_BUTTONITEM))
|
|
{
|
|
*ppvObj = this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarButtonItem::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarButtonItem::Release()
|
|
{
|
|
_cRef--;
|
|
Assert(_cRef >= 0);
|
|
|
|
if (_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return _cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarButtonItem::CTipbarButtonItem(CTipbarThread *ptt,
|
|
ITfLangBarItem *plbi,
|
|
ITfLangBarItemButton *plbiButton,
|
|
DWORD dwId,
|
|
RECT *prc,
|
|
DWORD dwStyle,
|
|
DWORD dwNuiBtnStyle,
|
|
DWORD dwSBtnShowType,
|
|
TF_LANGBARITEMINFO *plbiInfo,
|
|
DWORD dwStatus)
|
|
: CUIFToolbarButton(ptt->_ptw,
|
|
dwId,
|
|
prc,
|
|
dwStyle,
|
|
dwNuiBtnStyle,
|
|
dwSBtnShowType) ,
|
|
CTipbarItem(ptt, plbi, plbiInfo, dwStatus)
|
|
{
|
|
Dbg_MemSetThisName(TEXT("CTipbarButtonItem"));
|
|
|
|
_plbiButton = plbiButton;
|
|
_plbiButton->AddRef();
|
|
|
|
|
|
if (_dwStatus & TF_LBI_STATUS_DISABLED)
|
|
Enable(FALSE);
|
|
|
|
_cRef = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarButtonItem::~CTipbarButtonItem()
|
|
{
|
|
UninitUIResource();
|
|
SafeRelease(_plbiButton);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnUpdateHandler
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarButtonItem::OnUpdateHandler(DWORD dwFlags, DWORD dwStatus)
|
|
{
|
|
BOOL fPrevHidden = TRUE;
|
|
|
|
if (!IsConnected())
|
|
return S_OK;
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fCallPaint = FALSE;
|
|
BOOL fUpdateToggleStatus = FALSE;
|
|
|
|
//
|
|
// add ref count to be safe for releasing during marshaling.
|
|
//
|
|
AddRef();
|
|
|
|
if (dwFlags & TF_LBI_ICON)
|
|
{
|
|
HICON hIconOld;
|
|
HICON hIcon = GetIcon();
|
|
|
|
if (!_ptt || !_ptt->_ptw)
|
|
goto Exit;
|
|
|
|
if (hIconOld = GetIconFromUIObj())
|
|
DestroyIcon(hIconOld);
|
|
|
|
|
|
if (hIcon)
|
|
{
|
|
HICON hSmIcon = NULL;
|
|
int cxSmIcon;
|
|
int cySmIcon;
|
|
|
|
#ifdef SCALE_ICON
|
|
cxSmIcon = GetSystemMetrics( SM_CXSMICON );
|
|
cySmIcon = GetSystemMetrics( SM_CYSMICON );
|
|
#else
|
|
cxSmIcon = 16;
|
|
cySmIcon = 16;
|
|
#endif
|
|
|
|
if (IsTextColorIcon())
|
|
{
|
|
COLORREF rgbText = GetSysColor(COLOR_BTNTEXT);
|
|
if (_ptt &&
|
|
_ptt->_ptw &&
|
|
SUCCEEDED(_pBtn->EnsureThemeData(_ptt->_ptw->GetWnd())))
|
|
{
|
|
COLORREF col;
|
|
if (SUCCEEDED(_pBtn->GetThemeColor(TS_NORMAL, TMT_TEXTCOLOR, &col)))
|
|
rgbText = col;
|
|
}
|
|
|
|
CMaskBitmap maskbmp;
|
|
maskbmp.Init(hIcon, 16,16, rgbText);
|
|
|
|
ICONINFO ii;
|
|
ii.fIcon = TRUE;
|
|
ii.xHotspot = 0;
|
|
ii.yHotspot = 0;
|
|
ii.hbmMask = maskbmp.GetBmpMask();
|
|
ii.hbmColor = maskbmp.GetBmp();
|
|
hSmIcon = CreateIconIndirect(&ii);
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef SCALE_ICON
|
|
hSmIcon = StretchIcon(hIcon, cxSmIcon, cySmIcon);
|
|
#else
|
|
hSmIcon = (HICON)CopyImage(hIcon,
|
|
IMAGE_ICON,
|
|
cxSmIcon, cySmIcon,
|
|
LR_COPYFROMRESOURCE);
|
|
#endif
|
|
}
|
|
|
|
SetIcon(hSmIcon ? hSmIcon : hIcon);
|
|
|
|
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
|
|
StartDemotingTimer(FALSE);
|
|
|
|
if (hSmIcon)
|
|
DestroyIcon(hIcon);
|
|
}
|
|
else
|
|
SetIcon((HICON)NULL);
|
|
|
|
fCallPaint = TRUE;
|
|
}
|
|
|
|
if ((dwFlags & TF_LBI_TEXT) &&
|
|
_ptt &&
|
|
_ptt->_ptw &&
|
|
_ptt->_ptw->IsShowText())
|
|
{
|
|
BSTR bstr;
|
|
hr = _plbiButton->GetText(&bstr);
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
if (_ptt && bstr && (!GetText() || wcscmp(GetText(), bstr)))
|
|
{
|
|
SIZE size;
|
|
_ptt->GetTextSize(bstr, &size);
|
|
|
|
SetText(SysStringLen(bstr) ? bstr : NULL);
|
|
|
|
|
|
if (_sizeText.cx != size.cx)
|
|
{
|
|
_dwWidth += (size.cx - _sizeText.cx);
|
|
_ptt->LocateItems();
|
|
}
|
|
|
|
_sizeText = size;
|
|
fCallPaint = TRUE;
|
|
}
|
|
|
|
if (bstr)
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
if (IsHiddenStatusControl())
|
|
fPrevHidden = IsInHiddenStatus();
|
|
|
|
CTipbarItem::OnUpdateHandler(dwFlags, dwStatus);
|
|
|
|
if (_pBtn->GetToggleState() != IsToggled())
|
|
{
|
|
_pBtn->SetToggleState(IsToggled());
|
|
fUpdateToggleStatus = TRUE;
|
|
}
|
|
|
|
if ((dwFlags & (TF_LBI_ICON | TF_LBI_TOOLTIP)) ||
|
|
fUpdateToggleStatus ||
|
|
(fPrevHidden != IsInHiddenStatus()))
|
|
{
|
|
// we need to call Thread's MoveToTray too keep the order of Icons.
|
|
// _ptt->_ptw->MoveToTray();
|
|
if (_ptt && _ptt->_ptw && _ptt->_ptw->IsShowTrayIcon())
|
|
{
|
|
_ptt->_ptw->KillTimer(TIPWND_TIMER_MOVETOTRAY);
|
|
_ptt->_ptw->SetTimer(TIPWND_TIMER_MOVETOTRAY, g_uTimerElapseMOVETOTRAY);
|
|
}
|
|
}
|
|
|
|
if (fCallPaint)
|
|
CallOnPaint();
|
|
|
|
Exit:
|
|
Release();
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnRightClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarButtonItem::OnRightClick()
|
|
{
|
|
if (_plbiButton)
|
|
{
|
|
HRESULT hr;
|
|
POINT pt;
|
|
RECT rc;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiButton);
|
|
|
|
if (pac)
|
|
{
|
|
hr = pac->OnClick(TF_LBI_CLK_RIGHT, pt, &rc);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnLeftClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarButtonItem::OnLeftClick()
|
|
{
|
|
if (_plbiButton)
|
|
{
|
|
HRESULT hr;
|
|
POINT pt;
|
|
RECT rc;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiButton);
|
|
|
|
if (pac)
|
|
{
|
|
hr = pac->OnClick(TF_LBI_CLK_LEFT, pt, &rc);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
return;
|
|
}
|
|
|
|
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
|
|
StartDemotingTimer(TRUE);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnShowMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarButtonItem::OnShowMenu()
|
|
{
|
|
if (!_ptt)
|
|
return;
|
|
|
|
if (!_ptt->_ptw)
|
|
return;
|
|
|
|
if (_plbiButton)
|
|
{
|
|
POINT pt;
|
|
RECT rc;
|
|
GetRect(&rc);
|
|
pt.x = rc.left;
|
|
pt.y = rc.bottom;
|
|
MyClientToScreen(&pt, &rc);
|
|
|
|
DoModalMenu(&pt, &rc);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DoModalMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarButtonItem::DoModalMenu(POINT *ppt, RECT *prc)
|
|
{
|
|
HRESULT hr;
|
|
UINT uId;
|
|
DWORD dwThreadId;
|
|
CTipbarWnd *ptw;
|
|
|
|
if (!_ptt)
|
|
return;
|
|
|
|
if (!_ptt->_ptw)
|
|
return;
|
|
|
|
CUTBLBarMenu *pMenu = new CUTBLBarMenu(g_hInst);
|
|
if (!pMenu)
|
|
return;
|
|
|
|
AddRef();
|
|
|
|
hr = _plbiButton->InitMenu(pMenu);
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
goto Exit;
|
|
}
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
ptw = _ptt->_ptw;
|
|
dwThreadId = _ptt->_dwThreadId;
|
|
Assert(!_ptt->_ptw->_pttModal);
|
|
ptw->_pttModal = _ptt;
|
|
ptw->StartModalInput(ptw, dwThreadId);
|
|
|
|
Assert(!ptw->_pModalMenu);
|
|
ptw->_pModalMenu = pMenu;
|
|
uId = pMenu->ShowPopup(ptw, *ppt, prc);
|
|
|
|
ptw->_pModalMenu = NULL;
|
|
|
|
ptw->StopModalInput(dwThreadId);
|
|
ptw->_pttModal = NULL;
|
|
|
|
if (IsConnected() && (uId != CUI_MENU_UNSELECTED))
|
|
{
|
|
CAsyncCall *pac = new CAsyncCall(_plbiButton);
|
|
if (pac)
|
|
{
|
|
hr = pac->OnMenuSelect(uId);
|
|
pac->_Release();
|
|
}
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
goto Exit;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
pMenu->Release();
|
|
Release();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MoveToTray
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarButtonItem::MoveToTray()
|
|
{
|
|
if (!g_pTrayIconWnd)
|
|
return;
|
|
|
|
if (IsVisibleInToolbar() && (IsShownInTray() || IsShownInTrayOnly()))
|
|
{
|
|
HICON hIcon = GetIcon();
|
|
if (hIcon)
|
|
{
|
|
SIZE size;
|
|
if (IsToggled() && CUIGetIconSize(hIcon, &size))
|
|
{
|
|
COLORREF cr;
|
|
RECT rc;
|
|
CBitmapDC hdcSrc(TRUE);
|
|
CBitmapDC hdcMask(TRUE);
|
|
|
|
#if 0
|
|
CUIFScheme *pscheme = _ptt->_ptw->GetUIFScheme();
|
|
if (!pscheme)
|
|
cr = GetSysColor(COLOR_HIGHLIGHT);
|
|
else
|
|
cr = pscheme->GetColor(UIFCOLOR_MOUSEDOWNBKGND);
|
|
#else
|
|
cr = GetSysColor(COLOR_HIGHLIGHT);
|
|
#endif
|
|
|
|
CSolidBrush hbrBk(cr);
|
|
hdcSrc.SetDIB(size.cx, size.cy);
|
|
hdcMask.SetBitmap(size.cx, size.cy, 1, 1);
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = size.cx;
|
|
rc.bottom = size.cy;
|
|
FillRect(hdcSrc, &rc, (HBRUSH)hbrBk);
|
|
DrawIconEx(hdcSrc, 0, 0, hIcon, size.cx, size.cy, 0, NULL, DI_NORMAL);
|
|
FillRect(hdcMask, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
|
ICONINFO ii;
|
|
ii.fIcon = TRUE;
|
|
ii.xHotspot = 0;
|
|
ii.yHotspot = 0;
|
|
ii.hbmMask = hdcMask.GetBitmap();
|
|
ii.hbmColor = hdcSrc.GetBitmap();
|
|
DestroyIcon(hIcon);
|
|
hIcon = CreateIconIndirect(&ii);
|
|
}
|
|
|
|
if (hIcon)
|
|
{
|
|
g_pTrayIconWnd->SetIcon(*GetGUID(), IsMenuBtn(), hIcon, GetToolTip());
|
|
DestroyIcon(hIcon);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
g_pTrayIconWnd->SetIcon(*GetGUID(), IsMenuBtn(), NULL, NULL);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarBitmapButtonItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IUnknown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarBitmapButtonItem::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfLangBarItemSink))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarItemSink *);
|
|
}
|
|
else if (IsEqualIID(riid, IID_PRIV_BITMAPBUTTONITEM))
|
|
{
|
|
*ppvObj = this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarBitmapButtonItem::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarBitmapButtonItem::Release()
|
|
{
|
|
_cRef--;
|
|
Assert(_cRef >= 0);
|
|
|
|
if (_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return _cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarBitmapButtonItem::CTipbarBitmapButtonItem(CTipbarThread *ptt,
|
|
ITfLangBarItem *plbi,
|
|
ITfLangBarItemBitmapButton *plbiBitmapButton,
|
|
DWORD dwId,
|
|
RECT *prc,
|
|
DWORD dwStyle,
|
|
DWORD dwNuiBtnStyle,
|
|
DWORD dwSBtnShowType,
|
|
TF_LANGBARITEMINFO *plbiInfo,
|
|
DWORD dwStatus)
|
|
: CUIFToolbarButton(ptt->_ptw,
|
|
dwId,
|
|
prc,
|
|
dwStyle,
|
|
dwNuiBtnStyle,
|
|
dwSBtnShowType) ,
|
|
CTipbarItem(ptt, plbi, plbiInfo, dwStatus)
|
|
{
|
|
Dbg_MemSetThisName(TEXT("CTipbarBitmapButtonItem"));
|
|
|
|
_plbiBitmapButton = plbiBitmapButton;
|
|
_plbiBitmapButton->AddRef();
|
|
|
|
if (_dwStatus & TF_LBI_STATUS_DISABLED)
|
|
Enable(FALSE);
|
|
|
|
_cRef = 1;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarBitmapButtonItem::~CTipbarBitmapButtonItem()
|
|
{
|
|
HBITMAP hbmpOld;
|
|
HBITMAP hbmpMaskOld;
|
|
|
|
hbmpOld = GetBitmap();
|
|
hbmpMaskOld = GetBitmapMask();
|
|
if (hbmpOld)
|
|
DeleteObject(hbmpOld);
|
|
if (hbmpMaskOld)
|
|
DeleteObject(hbmpMaskOld);
|
|
SetBitmap((HBITMAP)NULL);
|
|
SetBitmapMask((HBITMAP)NULL);
|
|
|
|
SafeRelease(_plbiBitmapButton);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Update
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarBitmapButtonItem::OnUpdateHandler(DWORD dwFlags, DWORD dwStatus)
|
|
{
|
|
if (!IsConnected())
|
|
return S_OK;
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fCallPaint = FALSE;
|
|
|
|
//
|
|
// add ref count to be safe for releasing during marshaling.
|
|
//
|
|
AddRef();
|
|
|
|
if (dwFlags & TF_LBI_BITMAP)
|
|
{
|
|
if (!_GetBitmapFromNUI())
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
|
|
StartDemotingTimer(FALSE);
|
|
|
|
fCallPaint = TRUE;
|
|
}
|
|
|
|
if ((dwFlags & TF_LBI_TEXT) &&
|
|
_ptt &&
|
|
_ptt->_ptw &&
|
|
_ptt->_ptw->IsShowText())
|
|
{
|
|
BSTR bstr;
|
|
hr = _plbiBitmapButton->GetText(&bstr);
|
|
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
if (bstr && (!GetText() || wcscmp(GetText(), bstr)))
|
|
{
|
|
SIZE size;
|
|
_ptt->GetTextSize(bstr, &size);
|
|
|
|
SetText(SysStringLen(bstr) ? bstr : NULL);
|
|
|
|
|
|
if (_sizeText.cx != size.cx)
|
|
{
|
|
_dwWidth += (size.cx - _sizeText.cx);
|
|
_ptt->LocateItems();
|
|
}
|
|
|
|
_sizeText = size;
|
|
fCallPaint = TRUE;
|
|
}
|
|
|
|
if (bstr)
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
CTipbarItem::OnUpdateHandler(dwFlags, dwStatus);
|
|
|
|
if (_pBtn->GetToggleState() != IsToggled())
|
|
{
|
|
_pBtn->SetToggleState(IsToggled());
|
|
}
|
|
|
|
if (fCallPaint)
|
|
CallOnPaint();
|
|
|
|
Exit:
|
|
Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetBitmapFromNUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarBitmapButtonItem::_GetBitmapFromNUI()
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HBITMAP hbmp;
|
|
HBITMAP hbmpMask;
|
|
HBITMAP hbmpOld;
|
|
HBITMAP hbmpMaskOld;
|
|
int x, y;
|
|
|
|
hbmpOld = GetBitmap();
|
|
if (hbmpOld)
|
|
DeleteObject(hbmpOld);
|
|
hbmpMaskOld = GetBitmapMask();
|
|
if (hbmpMaskOld)
|
|
DeleteObject(hbmpMaskOld);
|
|
SetBitmap((HBITMAP)NULL);
|
|
SetBitmapMask((HBITMAP)NULL);
|
|
|
|
x = GetRectRef().right - GetRectRef().left;
|
|
y = GetRectRef().bottom - GetRectRef().top;
|
|
if (_ptt->_ptw->IsShowText())
|
|
y -= 12;
|
|
|
|
HRESULT hr = _plbiBitmapButton->DrawBitmap(x, y, 0, &hbmp, &hbmpMask);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SetBitmap(hbmp);
|
|
SetBitmapMask(hbmpMask);
|
|
bRet = TRUE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnRightClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapButtonItem::OnRightClick()
|
|
{
|
|
if (_plbiBitmapButton)
|
|
{
|
|
HRESULT hr;
|
|
POINT pt;
|
|
RECT rc;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiBitmapButton);
|
|
|
|
if (pac)
|
|
{
|
|
hr = pac->OnClick(TF_LBI_CLK_RIGHT, pt, &rc);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnLeftClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapButtonItem::OnLeftClick()
|
|
{
|
|
if (_plbiBitmapButton)
|
|
{
|
|
HRESULT hr;
|
|
POINT pt;
|
|
RECT rc;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiBitmapButton);
|
|
|
|
if (pac)
|
|
{
|
|
hr = pac->OnClick(TF_LBI_CLK_LEFT, pt, &rc);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
return;
|
|
}
|
|
|
|
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
|
|
StartDemotingTimer(TRUE);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnShowMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapButtonItem::OnShowMenu()
|
|
{
|
|
if (!_ptt)
|
|
return;
|
|
|
|
if (!_ptt->_ptw)
|
|
return;
|
|
|
|
if (_plbiBitmapButton)
|
|
{
|
|
POINT pt;
|
|
RECT rc;
|
|
GetRect(&rc);
|
|
pt.x = rc.left;
|
|
pt.y = rc.bottom;
|
|
MyClientToScreen(&pt, &rc);
|
|
HRESULT hr;
|
|
UINT uId;
|
|
DWORD dwThreadId;
|
|
CTipbarWnd *ptw;
|
|
|
|
CUTBLBarMenu *pMenu = new CUTBLBarMenu(g_hInst);
|
|
if (!pMenu)
|
|
return;
|
|
|
|
hr = _plbiBitmapButton->InitMenu(pMenu);
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
goto Exit;
|
|
}
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
ptw = _ptt->_ptw;
|
|
dwThreadId = _ptt->_dwThreadId;
|
|
|
|
Assert(!ptw->_pttModal);
|
|
ptw->_pttModal = _ptt;
|
|
ptw->StartModalInput(ptw, dwThreadId);
|
|
|
|
Assert(!ptw->_pModalMenu);
|
|
ptw->_pModalMenu = pMenu;
|
|
uId = pMenu->ShowPopup(ptw, pt, &rc);
|
|
ptw->_pModalMenu = NULL;
|
|
|
|
ptw->StopModalInput(dwThreadId);
|
|
ptw->_pttModal = NULL;
|
|
|
|
if (IsConnected() && (uId != CUI_MENU_UNSELECTED))
|
|
{
|
|
Assert(_ptt);
|
|
CAsyncCall *pac = new CAsyncCall(_plbiBitmapButton);
|
|
if (pac)
|
|
{
|
|
hr = pac->OnMenuSelect(uId);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
ptw->OnThreadTerminate(dwThreadId);
|
|
goto Exit;
|
|
}
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
pMenu->Release();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarBitmapItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IUnknown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CTipbarBitmapItem::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfLangBarItemSink))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfLangBarItemSink *);
|
|
}
|
|
else if (IsEqualIID(riid, IID_PRIV_BITMAPITEM))
|
|
{
|
|
*ppvObj = this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarBitmapItem::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
STDAPI_(ULONG) CTipbarBitmapItem::Release()
|
|
{
|
|
_cRef--;
|
|
Assert(_cRef >= 0);
|
|
|
|
if (_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return _cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarBitmapItem::CTipbarBitmapItem(CTipbarThread *ptt,
|
|
ITfLangBarItem *plbi,
|
|
ITfLangBarItemBitmap *plbiBitmap,
|
|
DWORD dwId,
|
|
RECT *prc,
|
|
DWORD dwStyle,
|
|
TF_LANGBARITEMINFO *plbiInfo,
|
|
DWORD dwStatus)
|
|
: CUIFObject(ptt->_ptw,
|
|
dwId,
|
|
prc,
|
|
dwStyle) ,
|
|
CTipbarItem(ptt, plbi, plbiInfo, dwStatus)
|
|
{
|
|
Dbg_MemSetThisName(TEXT("CTipbarBitmapItem"));
|
|
|
|
_plbiBitmap = plbiBitmap;
|
|
_plbiBitmap->AddRef();
|
|
|
|
if (_dwStatus & TF_LBI_STATUS_DISABLED)
|
|
Enable(FALSE);
|
|
|
|
_cRef = 1;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarBitmapItem::~CTipbarBitmapItem()
|
|
{
|
|
if (_hbmp)
|
|
DeleteObject(_hbmp);
|
|
SafeRelease(_plbiBitmap);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Update
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CTipbarBitmapItem::OnUpdateHandler(DWORD dwFlags, DWORD dwStatus)
|
|
{
|
|
if (!IsConnected())
|
|
return S_OK;
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fCallPaint = FALSE;
|
|
|
|
//
|
|
// add ref count to be safe for releasing during marshaling.
|
|
//
|
|
AddRef();
|
|
|
|
|
|
if (dwFlags & TF_LBI_BITMAP)
|
|
{
|
|
if (!_GetBitmapFromNUI())
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
fCallPaint = TRUE;
|
|
}
|
|
|
|
CTipbarItem::OnUpdateHandler(dwFlags, dwStatus);
|
|
|
|
if (fCallPaint)
|
|
CallOnPaint();
|
|
|
|
Exit:
|
|
Release();
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetBitmapFromNUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CTipbarBitmapItem::_GetBitmapFromNUI()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
HBITMAP hbmp = NULL;
|
|
HBITMAP hbmpMask = NULL;
|
|
int x = GetRectRef().right - GetRectRef().left;
|
|
int y = GetRectRef().bottom - GetRectRef().top;
|
|
|
|
HRESULT hr = _plbiBitmap->DrawBitmap(x, y, 0, &hbmp, &hbmpMask);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (_hbmp)
|
|
DeleteObject(_hbmp);
|
|
_hbmp = NULL;
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (!hbmpMask)
|
|
{
|
|
if (_hbmp)
|
|
DeleteObject(_hbmp);
|
|
_hbmp = hbmp;
|
|
}
|
|
else
|
|
{
|
|
CUIFScheme *pScheme = GetUIFScheme();
|
|
|
|
if (_hbmp)
|
|
DeleteObject(_hbmp);
|
|
|
|
_hbmp = CreateMaskBmp(&GetRectRef(), hbmp, hbmpMask,
|
|
pScheme->GetBrush(UIFCOLOR_CTRLBKGND), 0, 0);
|
|
}
|
|
|
|
if (hbmp)
|
|
DeleteObject(hbmp);
|
|
if (hbmpMask)
|
|
DeleteObject(hbmpMask);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnPaint
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapItem::OnPaint( HDC hdc )
|
|
{
|
|
CBitmapDC hdcMem(TRUE);
|
|
hdcMem.SetBitmap(_hbmp);
|
|
|
|
BitBlt(hdc,
|
|
GetRectRef().left,
|
|
GetRectRef().top,
|
|
GetRectRef().right - GetRectRef().left,
|
|
GetRectRef().bottom - GetRectRef().top,
|
|
hdcMem,
|
|
0,
|
|
0,
|
|
SRCCOPY);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetRect
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapItem::SetRect( const RECT *prc )
|
|
{
|
|
|
|
if (((GetRectRef().bottom - GetRectRef().top) != (prc->bottom - prc->top)) ||
|
|
((GetRectRef().right - GetRectRef().left) != (prc->right - prc->left)))
|
|
{
|
|
if (_hbmp)
|
|
DeleteObject(_hbmp);
|
|
_hbmp = NULL;
|
|
}
|
|
|
|
CUIFObject::SetRect(prc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnRightClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapItem::OnRightClick()
|
|
{
|
|
if (_plbiBitmap)
|
|
{
|
|
POINT pt;
|
|
RECT rc;
|
|
HRESULT hr;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiBitmap);
|
|
if (!pac)
|
|
return;
|
|
|
|
hr = pac->OnClick(TF_LBI_CLK_RIGHT, pt, &rc);
|
|
pac->_Release();
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnLeftClick
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarBitmapItem::OnLeftClick()
|
|
{
|
|
if (_plbiBitmap)
|
|
{
|
|
HRESULT hr;
|
|
POINT pt;
|
|
RECT rc;
|
|
GetCursorPos(&pt);
|
|
GetRect(&rc);
|
|
MyClientToScreen(&rc);
|
|
|
|
CAsyncCall *pac = new CAsyncCall(_plbiBitmap);
|
|
|
|
if (pac)
|
|
{
|
|
hr = pac->OnClick(TF_LBI_CLK_LEFT, pt, &rc);
|
|
pac->_Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if (RPC_S_SERVER_UNAVAILABLE == HRESULT_CODE(hr))
|
|
{
|
|
if (_ptt && _ptt->_ptw)
|
|
_ptt->_ptw->OnThreadTerminate(_ptt->_dwThreadId);
|
|
return;
|
|
}
|
|
|
|
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
|
|
StartDemotingTimer(TRUE);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarCtrlButtonHolder
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarCtrlButtonHolder::CTipbarCtrlButtonHolder()
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButtonHolder::Init(CTipbarWnd *ptw)
|
|
{
|
|
int i;
|
|
RECT rc;
|
|
::SetRect(&rc, 0, 0, 0, 0);
|
|
|
|
if (ptw->IsInDeskBand())
|
|
_pcbCtrlBtn = g_cbCtrlBtnDeskBand;
|
|
else
|
|
_pcbCtrlBtn = g_cbCtrlBtn;
|
|
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
Assert(!_rgpCtrlBtn[i]);
|
|
|
|
_rgpCtrlBtn[i] = new CTipbarCtrlButton(ptw,
|
|
_pcbCtrlBtn[i].dwId,
|
|
&rc,
|
|
_pcbCtrlBtn[i].dwStyle);
|
|
_rgpCtrlBtn[i]->Initialize();
|
|
|
|
ptw->AddUIObj(_rgpCtrlBtn[i]);
|
|
|
|
if (_pcbCtrlBtn[i].dwFlags & CTRL_USEMARLETT)
|
|
_rgpCtrlBtn[i]->SetFont(ptw->GetMarlett());
|
|
|
|
if (_pcbCtrlBtn[i].dwFlags & CTRL_ICONFROMRES)
|
|
{
|
|
if (_pcbCtrlBtn[i].dwId == ID_CBTN_CAPSKEY)
|
|
{
|
|
_rgpCtrlBtn[i]->SetVKey(VK_CAPITAL);
|
|
}
|
|
else
|
|
{
|
|
_rgpCtrlBtn[i]->SetVKey(VK_KANA);
|
|
}
|
|
_rgpCtrlBtn[i]->SetToggleStateByVKey();
|
|
}
|
|
else
|
|
_rgpCtrlBtn[i]->SetText(_pcbCtrlBtn[i].wsz);
|
|
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnableBtns
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButtonHolder::EnableBtns()
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
if (_pcbCtrlBtn[i].dwFlags & CTRL_DISABLEONWINLOGON)
|
|
{
|
|
if (g_bWinLogon || (g_pTipbarWnd && g_pTipbarWnd->IsSFMinmized()))
|
|
_rgpCtrlBtn[i]->Enable(FALSE);
|
|
else
|
|
_rgpCtrlBtn[i]->Enable(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateBitmap
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButtonHolder::UpdateBitmap(CTipbarWnd *ptw)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
if (_pcbCtrlBtn[i].dwFlags & CTRL_ICONFROMRES)
|
|
{
|
|
HBITMAP hbmp;
|
|
HBITMAP hbmpMask;
|
|
COLORREF rgbText = GetSysColor(COLOR_BTNTEXT);
|
|
if (SUCCEEDED(_rgpCtrlBtn[i]->EnsureThemeData(ptw->GetWnd())))
|
|
{
|
|
COLORREF col;
|
|
if (SUCCEEDED(_rgpCtrlBtn[i]->GetThemeColor(TS_NORMAL, TMT_TEXTCOLOR, &col)))
|
|
rgbText = col;
|
|
}
|
|
|
|
if (_pcbCtrlBtn[i].dwId == ID_CBTN_CAPSKEY)
|
|
{
|
|
if (!ptw->IsVertical())
|
|
_maskbmpCap.Init(ID_BITMAP_CAPS ,
|
|
KANACAPSBMP_WIDTH,
|
|
KANACAPSBMP_HEIGHT,
|
|
rgbText);
|
|
else
|
|
_maskbmpCap.Init(ID_BITMAP_CAPSV,
|
|
KANACAPSBMP_HEIGHT,
|
|
KANACAPSBMP_WIDTH,
|
|
rgbText);
|
|
|
|
hbmp = _maskbmpCap.GetBmp();
|
|
hbmpMask = _maskbmpCap.GetBmpMask();
|
|
}
|
|
else
|
|
{
|
|
if (!ptw->IsVertical())
|
|
_maskbmpKana.Init(ID_BITMAP_KANA ,
|
|
KANACAPSBMP_WIDTH,
|
|
KANACAPSBMP_HEIGHT,
|
|
rgbText);
|
|
else
|
|
_maskbmpKana.Init(ID_BITMAP_KANAV,
|
|
KANACAPSBMP_HEIGHT,
|
|
KANACAPSBMP_WIDTH,
|
|
rgbText);
|
|
|
|
hbmp = _maskbmpKana.GetBmp();
|
|
hbmpMask = _maskbmpKana.GetBmpMask();
|
|
}
|
|
|
|
_rgpCtrlBtn[i]->SetBitmap(hbmp);
|
|
_rgpCtrlBtn[i]->SetBitmapMask(hbmpMask);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Locate
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButtonHolder::Locate(CTipbarWnd *ptw, int x, int y, int nHeight, DWORD dwFlags, BOOL fVertical)
|
|
{
|
|
int i;
|
|
int nCtrlItemHeight = (nHeight - ptw->GetCtrlItemHeightMargin() * 2) / 2;
|
|
c_nColumnStart[0] = 0;
|
|
c_nColumnStart[1] = CX_COLUMN0 +
|
|
ptw->GetThemeMargins()->cxLeftWidth +
|
|
ptw->GetThemeMargins()->cxRightWidth;
|
|
c_nColumnStart[2] = CX_COLUMN1 +
|
|
ptw->GetThemeMargins()->cxLeftWidth +
|
|
ptw->GetThemeMargins()->cxRightWidth;
|
|
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
RECT rc;
|
|
int nColumn = _pcbCtrlBtn[i].nColumn;
|
|
int nRow = _pcbCtrlBtn[i].nRow;
|
|
|
|
if (dwFlags & TCBH_NOCOLUMN)
|
|
{
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = 0;
|
|
rc.bottom = 0;
|
|
_rgpCtrlBtn[i]->SetRect(&rc);
|
|
continue;
|
|
}
|
|
|
|
if (dwFlags & TCBH_NOCOLUMN0)
|
|
{
|
|
if (!_pcbCtrlBtn[i].nColumn)
|
|
{
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = 0;
|
|
rc.bottom = 0;
|
|
_rgpCtrlBtn[i]->SetRect(&rc);
|
|
continue;
|
|
}
|
|
|
|
nColumn--;
|
|
}
|
|
|
|
if (!fVertical)
|
|
{
|
|
rc.left = x + c_nColumnStart[nColumn];
|
|
rc.top = ptw->GetCtrlItemHeightMargin() + y + nRow * nCtrlItemHeight;
|
|
rc.right = rc.left + c_nColumnStart[_pcbCtrlBtn[i].nColumn + 1];
|
|
rc.bottom = rc.top + nCtrlItemHeight;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// swap Row when this is the vertical langbar.
|
|
//
|
|
rc.left = ptw->GetCtrlItemHeightMargin() + x + (1 - nRow) * nCtrlItemHeight;
|
|
rc.top = y + c_nColumnStart[nColumn];
|
|
rc.right = rc.left + nCtrlItemHeight;
|
|
rc.bottom = rc.top + c_nColumnStart[_pcbCtrlBtn[i].nColumn + 1];
|
|
}
|
|
|
|
_rgpCtrlBtn[i]->SetRect(&rc);
|
|
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetWidth
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
int CTipbarCtrlButtonHolder::GetWidth(DWORD dwFlags)
|
|
{
|
|
if (dwFlags & TCBH_NOCOLUMN)
|
|
return 0;
|
|
|
|
int nWidth = 0;
|
|
|
|
if (!(dwFlags & TCBH_NOCOLUMN0))
|
|
nWidth += c_nColumnStart[1];
|
|
|
|
nWidth += c_nColumnStart[2];
|
|
return nWidth;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateCapsKanaState
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButtonHolder::UpdateCapsKanaState(LPARAM lParam)
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
if (_rgpCtrlBtn[i]->GetVKey())
|
|
{
|
|
if (_rgpCtrlBtn[i]->GetVKey() == VK_CAPITAL)
|
|
_rgpCtrlBtn[i]->SetToggleState((lParam & TF_LBUF_CAPS) ? TRUE: FALSE);
|
|
else if (_rgpCtrlBtn[i]->GetVKey() == VK_KANA)
|
|
_rgpCtrlBtn[i]->SetToggleState((lParam & TF_LBUF_KANA) ? TRUE: FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCtrlBtn
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
CTipbarCtrlButton *CTipbarCtrlButtonHolder::GetCtrlBtn(DWORD dwId)
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_CTRLBUTTONS; i++)
|
|
{
|
|
if (_rgpCtrlBtn[i]->GetID() == dwId)
|
|
return _rgpCtrlBtn[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTipbarCtrlButton
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CTipbarCtrlButton::CTipbarCtrlButton(CTipbarWnd *ptw,
|
|
DWORD dwId,
|
|
const RECT *prc,
|
|
DWORD dwStyle)
|
|
: CUIFButton2(ptw,
|
|
dwId,
|
|
prc,
|
|
dwStyle)
|
|
{
|
|
_ptw = ptw;
|
|
_fInMenu = FALSE;
|
|
SetToolTip(CRStr(IDS_CONTROLBUTTONTOOLTIP + dwId));
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnLButtonUp
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButton::OnLButtonUp(POINT pt)
|
|
{
|
|
CUIFButton2::OnLButtonUp(pt);
|
|
CUTBMinimizeLangBarDlg *pMinimizeDlg;
|
|
|
|
switch (GetID())
|
|
{
|
|
case ID_CBTN_MINIMIZE:
|
|
//
|
|
// Use Deskband object instead of system tray icon on NT51
|
|
//
|
|
if (IsOnNT51())
|
|
{
|
|
if (!_ptw->IsSFDeskband())
|
|
{
|
|
_ptw->GetLangBarMgr()->ShowFloating(TF_SFT_DESKBAND);
|
|
|
|
if (pMinimizeDlg = new CUTBMinimizeLangBarDlg)
|
|
{
|
|
pMinimizeDlg->DoModal(_ptw->GetWnd());
|
|
pMinimizeDlg->_Release();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
_ptw->GetLangBarMgr()->ShowFloating(TF_SFT_MINIMIZED);
|
|
|
|
if (pMinimizeDlg = new CUTBMinimizeLangBarDlg)
|
|
{
|
|
pMinimizeDlg->DoModal(_ptw->GetWnd());
|
|
pMinimizeDlg->_Release();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ID_CBTN_RESTORE:
|
|
//
|
|
// Use Deskband object instead of system tray icon on NT51
|
|
//
|
|
Assert(IsOnNT51());
|
|
if (_ptw->IsSFDeskband())
|
|
{
|
|
_ptw->GetLangBarMgr()->ShowFloating(TF_SFT_SHOWNORMAL);
|
|
}
|
|
break;
|
|
|
|
case ID_CBTN_EXTMENU:
|
|
ShowExtendMenu(pt);
|
|
break;
|
|
|
|
case ID_CBTN_KANAKEY:
|
|
keybd_event(VK_KANA, 0, 0, 0);
|
|
keybd_event(VK_KANA, 0, KEYEVENTF_KEYUP, 0);
|
|
break;
|
|
|
|
case ID_CBTN_CAPSKEY:
|
|
keybd_event(VK_CAPITAL, 0, 0, 0);
|
|
keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ShowExtendMenu
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTipbarCtrlButton::ShowExtendMenu(POINT pt)
|
|
{
|
|
CUTBIntelliMenu *pMenu;
|
|
RECT rc;
|
|
GetRect(&rc);
|
|
MyClientToScreen(&pt, &rc);
|
|
DWORD dwThreadId;
|
|
UINT uId = CUI_MENU_UNSELECTED;
|
|
|
|
if (!_ptw)
|
|
return;
|
|
|
|
if (!_ptw->GetFocusThread())
|
|
return;
|
|
|
|
dwThreadId = _ptw->GetFocusThread()->_dwThreadId;
|
|
|
|
pMenu = new CUTBIntelliMenu(_ptw);
|
|
if (!pMenu)
|
|
return;
|
|
|
|
if (!pMenu->Init())
|
|
goto Exit;
|
|
|
|
_ptw->_pttModal = _ptw->GetFocusThread();
|
|
|
|
_ptw->StartModalInput(_ptw, dwThreadId);
|
|
|
|
_ptw->_pModalMenu = pMenu;
|
|
|
|
uId = pMenu->ShowPopup(_ptw, pt, &rc);
|
|
|
|
_ptw->_pModalMenu = NULL;
|
|
|
|
_ptw->StopModalInput(dwThreadId);
|
|
_ptw->_pttModal = NULL;
|
|
|
|
if (uId != CUI_MENU_UNSELECTED)
|
|
{
|
|
pMenu->SelectMenuItem(uId);
|
|
}
|
|
|
|
Exit:
|
|
delete pMenu;
|
|
}
|