Leaked source code of windows server 2003
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.
 
 
 
 
 
 

731 lines
19 KiB

//
// balloon.cpp
//
#include "private.h"
#include "globals.h"
#include "tipbar.h"
#include "helpers.h"
#include "xstring.h"
#include "immxutil.h"
#include "balloon.h"
#include "fontlink.h"
#include "asynccal.h"
extern CTipbarWnd *g_pTipbarWnd;
#define SHOWTOOLTIP_ONUPDATE
__inline void PrectSet(RECT *prc, int left, int top, int right, int bottom)
{
prc->left = left;
prc->top = top;
prc->right = right;
prc->bottom = bottom;
}
//////////////////////////////////////////////////////////////////////////////
//
// CTipbarBalloonItem
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// IUnknown
//
//----------------------------------------------------------------------------
STDAPI CTipbarBalloonItem::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_BALLOONITEM))
{
*ppvObj = this;
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDAPI_(ULONG) CTipbarBalloonItem::AddRef()
{
return ++_cRef;
}
STDAPI_(ULONG) CTipbarBalloonItem::Release()
{
_cRef--;
Assert(_cRef >= 0);
if (_cRef == 0)
{
delete this;
return 0;
}
return _cRef;
}
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CTipbarBalloonItem::CTipbarBalloonItem(CTipbarThread *ptt,
ITfLangBarItem *plbi,
ITfLangBarItemBalloon *plbiBalloon,
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("CTipbarBalloonItem"));
_plbiBalloon = plbiBalloon;
_plbiBalloon->AddRef();
if (_dwStatus & TF_LBI_STATUS_DISABLED)
Enable(FALSE);
_cRef = 1;
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CTipbarBalloonItem::~CTipbarBalloonItem()
{
if (_bstrText)
SysFreeString(_bstrText);
SafeRelease(_plbiBalloon);
}
//+---------------------------------------------------------------------------
//
// Update
//
//----------------------------------------------------------------------------
HRESULT CTipbarBalloonItem::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_BALLOON)
{
TF_LBBALLOONINFO info;
if (_bstrText)
{
SysFreeString(_bstrText);
_bstrText = NULL;
}
if (SUCCEEDED(_plbiBalloon->GetBalloonInfo(&info)))
{
_bstrText = info.bstrText;
_style = info.style;
}
if (!IsHiddenStatusControl() && IsVisibleInToolbar())
StartDemotingTimer(FALSE);
EndTimer();
DestroyBalloonTip();
#ifdef SHOWTOOLTIP_ONUPDATE
if (IsTextEllipsis(_bstrText, &GetRectRef()))
{
StartTimer(2000);
}
#endif
fCallPaint = TRUE;
}
CTipbarItem::OnUpdateHandler(dwFlags, dwStatus);
if ((_dwStatus & TF_LBI_STATUS_DISABLED) ||
(_dwStatus & TF_LBI_STATUS_HIDDEN))
{
DestroyBalloonTip();
}
if (fCallPaint)
CallOnPaint();
Release();
return hr;
}
//+---------------------------------------------------------------------------
//
// OnTimer
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::OnTimer()
{
if (!_pblnTip)
{
EndTimer();
StartTimer(20000);
ShowBalloonTip();
}
else
{
EndTimer();
DestroyBalloonTip();
}
}
//----------------------------------------------------------------------------
//
// OnPosChanged
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::OnPosChanged()
{
EndTimer();
DestroyBalloonTip();
}
//+---------------------------------------------------------------------------
//
// ShowBalloonTip
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::ShowBalloonTip()
{
RECT rc;
POINT pt;
DestroyBalloonTip();
if (!_ptt)
return;
if (!_ptt->_ptw)
return;
if (!IsVisibleInToolbar() || !_ptt->IsFocusThread())
return;
_pblnTip = new CUIFBalloonWindow(g_hInst, 0);
if (!_pblnTip)
return;
_pblnTip->Initialize();
GetRect(&rc);
pt.x = (rc.left + rc.right) / 2;
pt.y = rc.top;
MyClientToScreen(&pt, &rc);
_pblnTip->SetTargetPos(pt);
_pblnTip->SetExcludeRect(&rc);
_pblnTip->SetText(_bstrText);
_pblnTip->CreateWnd(_ptt->_ptw->GetWnd());
}
//+---------------------------------------------------------------------------
//
// DestroyBalloonTip
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::DestroyBalloonTip()
{
if (_pblnTip)
{
if (IsWindow(_pblnTip->GetWnd()))
DestroyWindow(_pblnTip->GetWnd());
delete _pblnTip;
_pblnTip = NULL;
}
}
//+---------------------------------------------------------------------------
//
// OnPaint
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::OnPaint( HDC hdc )
{
switch (_style)
{
case TF_LB_BALLOON_RECO:
DrawRecoBalloon(hdc, _bstrText, &GetRectRef());
break;
case TF_LB_BALLOON_SHOW:
DrawShowBalloon(hdc, _bstrText, &GetRectRef());
break;
case TF_LB_BALLOON_MISS:
DrawUnrecognizedBalloon(hdc, _bstrText, &GetRectRef());
break;
default:
Assert(0);
}
}
//+---------------------------------------------------------------------------
//
// OnRightClick
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::OnRightClick()
{
if (_plbiBalloon)
{
HRESULT hr;
POINT pt;
RECT rc;
GetCursorPos(&pt);
GetRect(&rc);
MyClientToScreen(&rc);
CAsyncCall *pac = new CAsyncCall(_plbiBalloon);
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 CTipbarBalloonItem::OnLeftClick()
{
if (_plbiBalloon)
{
HRESULT hr;
POINT pt;
RECT rc;
GetCursorPos(&pt);
GetRect(&rc);
MyClientToScreen(&rc);
CAsyncCall *pac = new CAsyncCall(_plbiBalloon);
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);
}
}
//+---------------------------------------------------------------------------
//
// SetRect
//
//----------------------------------------------------------------------------
void CTipbarBalloonItem::SetRect( const RECT *prc )
{
CUIFObject::SetRect(prc);
}
/*---------------------------------------------------------------------------
DrawTransparentText
Draws the text string wtz in the font ft with text color crText.
------------------------------------------------------------------- TCOON -*/
void CTipbarBalloonItem::DrawTransparentText(HDC hdc, COLORREF crText, WCHAR *psz, const RECT *prc)
{
HFONT hFontOld;
SIZE size;
int cch;
RECT rc;
WORD rgfJustify = DT_END_ELLIPSIS | DT_WORDBREAK | DT_EDITCONTROL | DT_CENTER | DT_VCENTER;
if (!psz || !_ptt || !_ptt->_ptw)
return;
cch = wcslen(psz);
// prepare objects
hFontOld= (HFONT)SelectObject(hdc, GetFont() );
// calc alignment
FLGetTextExtentPoint32( hdc, psz, cch, &size );
COLORREF crSave = SetTextColor(hdc, crText);
SetBkMode(hdc, TRANSPARENT);
if (!_ptt->IsVertical())
{
int yAlign = (prc->bottom - prc->top - size.cy) / 2;
rc = *prc;
rc.left += 1;
rc.right -= 1;
rc.top += yAlign;
FLDrawTextW(hdc, psz, cch, &rc, rgfJustify);
}
else
{
int xAlign = (prc->right - prc->left - size.cy) / 2;
rc = *prc;
rc.top += 1;
rc.bottom -= 1;
rc.right -= xAlign;
FLDrawTextWVert(hdc, psz, cch, &rc, rgfJustify);
}
SetTextColor(hdc, crSave);
SelectObject(hdc, hFontOld);
}
/*---------------------------------------------------------------------------
DrawRect
Draws the text string wtz in the font ft with text color crText.
------------------------------------------------------------------- TCOON -*/
void CTipbarBalloonItem::DrawRect(HDC hdc, const RECT *prc, COLORREF crBorder, COLORREF crFill)
{
HPEN hpen = NULL;
HPEN hpenOld;
HBRUSH hbr = NULL;
HBRUSH hbrOld;
hpen = CreatePen(PS_SOLID, 0, crBorder);
if (!hpen)
goto Exit;
hbr = CreateSolidBrush(crFill);
if (!hbr)
goto Exit;
hpenOld = (HPEN)SelectObject(hdc, hpen);
hbrOld = (HBRUSH)SelectObject(hdc, hbr);
Rectangle(hdc, prc->left, prc->top, prc->right, prc->bottom);
SelectObject(hdc, hpenOld);
SelectObject(hdc, hbrOld);
Exit:
if (hpen)
DeleteObject(hpen);
if (hbr)
DeleteObject(hbr);
}
/*---------------------------------------------------------------------------
DrawUnrecognizedBalloon
Draws the Unrecognized balloon to show the user that the command was
misunderstood.
------------------------------------------------------------------- TCOON -*/
void CTipbarBalloonItem::DrawUnrecognizedBalloon(HDC hdc, WCHAR *wtz, const RECT *prc)
{
RECT rc = *prc;
COLORREF crBtnText;
HPEN hpen = NULL;
HPEN hpenOld;
HBRUSH hbrOld;
crBtnText = GetSysColor(COLOR_BTNTEXT);
hpen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWFRAME));
if (!hpen)
goto Exit;
hbrOld = (HBRUSH)SelectObject(hdc, GetSysColorBrush(COLOR_HIGHLIGHT));
InflateRect(&rc, -2, -2);
hpenOld = (HPEN)SelectObject(hdc, hpen);
RoundRect(hdc, rc.left,rc.top, rc.right, rc.bottom, 12, 12);
DrawTransparentText(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT), wtz, &rc);
// Restore DC contents
SelectObject(hdc, hpenOld);
SelectObject(hdc, hbrOld);
Exit:
if (hpen)
DeleteObject(hpen);
}
/*---------------------------------------------------------------------------
DrawShowBalloon
Draws the Show balloon to suggest the user say a given command.
------------------------------------------------------------------- TCOON -*/
void CTipbarBalloonItem::DrawShowBalloon(HDC hdc, WCHAR *wtz, const RECT *prc)
{
COLORREF crBtnFace;
COLORREF crBtnShad;
COLORREF crBalloonText;
COLORREF crBalloon;
RECT rc = *prc;
crBtnFace = GetSysColor(COLOR_BTNFACE);
crBtnShad = GetSysColor(COLOR_BTNSHADOW);
// crBalloonText = GetSysColor(COLOR_INFOTEXT);
// crBalloon = GetSysColor(COLOR_INFOBK) & 0x0000ff00;
// crBalloon = col(30, RGB(0, 0xFF, 0), 70, GetSysColor(COLOR_INFOBK));
crBalloon = GetSysColor(COLOR_BTNFACE);
crBalloonText = GetSysColor(COLOR_BTNTEXT);
// Draw Black outline
InflateRect(&rc, -2, -2);
// rc.bottom -= 5;
DrawRect(hdc, &rc, GetSysColor(COLOR_WINDOWFRAME), crBalloon);
InflateRect(&rc, -1, -1);
// Knock off the corner
RECT rcDraw;
int bkSav = SetBkColor(hdc, crBalloon);
for (int iPixel = 0; iPixel < 7; iPixel++)
{
PrectSet(&rcDraw, rc.right-(7-iPixel), rc.bottom-iPixel-1,
rc.right-(7-iPixel)+1, rc.bottom-iPixel);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
PrectSet(&rcDraw, rc.right-3, rc.bottom-2, rc.right-2, rc.bottom);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
PrectSet(&rcDraw, rc.right-2, rc.bottom-3, rc.right, rc.bottom-2);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// Shadows
SetBkColor(hdc, crBtnShad);
// Lower Shadow
PrectSet(&rcDraw, rc.left+2, rc.bottom+1, rc.right+1, rc.bottom+2);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
for (iPixel = 0; iPixel < 8; iPixel++)
{
PrectSet(&rcDraw, rc.right-(7-iPixel), rc.bottom-iPixel,
rc.right-(7-iPixel)+1, rc.bottom-iPixel+2);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
// Button Face portions
SetBkColor(hdc, crBtnFace);
for (iPixel = 0; iPixel < 3; iPixel++)
{
PrectSet(&rcDraw, rc.right-6+iPixel, rc.bottom+1-iPixel,
rc.right-3, rc.bottom-iPixel+2);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
for (iPixel = 0; iPixel < 2; iPixel++)
{
PrectSet(&rcDraw, rc.right+iPixel-1, rc.bottom-4-iPixel,
rc.right+iPixel, rc.bottom+iPixel-3);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
PrectSet(&rcDraw, rc.right-3, rc.bottom, rc.right-2, rc.bottom+2);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// Clean up and draw text
SetBkColor(hdc, bkSav);
DrawTransparentText(hdc, crBalloonText, wtz, &rc);
}
/*---------------------------------------------------------------------------
DrawRecoBalloon
Draws the Recognition Balloon.
------------------------------------------------------------------- TCOON -*/
void CTipbarBalloonItem::DrawRecoBalloon(HDC hdc, WCHAR *wtz, const RECT *prc)
{
COLORREF crBtnFace;
COLORREF crBtnShad;
COLORREF crBalloonText;
COLORREF crBalloon;
RECT rc = *prc;
crBtnFace = GetSysColor(COLOR_BTNFACE);
crBtnShad = GetSysColor(COLOR_BTNSHADOW);
crBalloonText = GetSysColor(COLOR_INFOTEXT);
crBalloon = GetSysColor(COLOR_INFOBK);
// Draw Black outline
InflateRect(&rc, -2, -2);
// rc.bottom -= 5;
rc.bottom -= 1;
DrawRect(hdc, &rc, GetSysColor(COLOR_WINDOWFRAME), crBalloon);
InflateRect(&rc, -1, -1);
// Knock off the corners
int bkSav = SetBkColor(hdc, crBtnFace);
InflateRect(&rc, +1, +1);
RECT rcDraw;
// UpperLeft
PrectSet(&rcDraw, rc.left, rc.top, rc.left+1, rc.top+1);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// UpperRight
PrectSet(&rcDraw, rc.right-1, rc.top, rc.right, rc.top+1);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// LowerLeft
PrectSet(&rcDraw, rc.left, rc.bottom-1, rc.left+1, rc.bottom);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
SetBkColor(hdc, crBtnShad);
// LowerRight (done in shadow color)
PrectSet(&rcDraw, rc.right-1, rc.bottom-1, rc.right, rc.bottom);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// Lower Shadow
PrectSet(&rcDraw, rc.left+2, rc.bottom, rc.right-1, rc.bottom+1);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// RightSide Shadow
PrectSet(&rcDraw, rc.right, rc.top+2, rc.right+1, rc.bottom-1);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// Arrow Shadow
PrectSet(&rcDraw, rc.right-4, rc.bottom+1, rc.right-3, rc.bottom+5);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
// Arrow
SetBkColor(hdc, crBalloonText);
PrectSet(&rcDraw, rc.right-5, rc.bottom, rc.right-4, rc.bottom+4);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
int iPixel;
for (iPixel = 0; iPixel < 3; iPixel++)
{
PrectSet(&rcDraw, rc.right-(6+iPixel), rc.bottom+(2-iPixel),
rc.right-(5+iPixel), rc.bottom+(3-iPixel));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
// Fill in Arrow
SetBkColor(hdc, crBalloon);
for (iPixel = 0; iPixel < 3; iPixel++)
{
PrectSet(&rcDraw, rc.right-(8-iPixel), rc.bottom-(1-iPixel),
rc.right-5, rc.bottom+iPixel);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, 0);
}
SetBkColor(hdc, bkSav);
DrawTransparentText(hdc, crBalloonText, wtz, &rc);
}
/*---------------------------------------------------------------------------
IsTextEllipsis
Draws the text string wtz in the font ft with text color crText.
------------------------------------------------------------------- TCOON -*/
BOOL CTipbarBalloonItem::IsTextEllipsis(WCHAR *psz, const RECT *prc)
{
HDC hdc;
HFONT hFontOld;
SIZE size;
int cch;
RECT rc;
BOOL bRet = FALSE;
// detect if the item is hidden and return immediately here
if (IsInHiddenStatus())
return bRet;
if (g_pTipbarWnd && g_pTipbarWnd->IsSFHidden( ))
return bRet;
if (!psz)
return bRet;
hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
if (!hdc)
return bRet;
cch = wcslen(psz);
// prepare objects
hFontOld= (HFONT)SelectObject(hdc, GetFont() );
// calc alignment
FLGetTextExtentPoint32( hdc, psz, cch, &size );
rc = *prc;
rc.left += 3;
rc.right -= 3;
SelectObject(hdc, hFontOld);
DeleteDC(hdc);
return (size.cx > (rc.right - rc.left)) ? TRUE : FALSE;
}