WindowsXP-SP1/windows/advcore/ctf/cuilib/cuibln.cpp
2020-09-30 16:53:49 +02:00

1608 lines
43 KiB
C++

//
// cuibln.cpp - ui frame object for balloon message window
//
#include "private.h"
#include "cuiobj.h"
#include "cuiwnd.h"
#include "cuibln.h"
#include "cuiutil.h"
#include "cresstr.h"
#include "cuires.h"
//
// constants
//
#define cxyTailWidth 10
#define cxyTailHeight 16
#define cxRoundSize 16
#define cyRoundSize 16
#define WM_HOOKEDKEY (WM_USER + 0x0001)
//
/* C U I F B A L L O O N B U T T O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
CUIFBalloonButton::CUIFBalloonButton( CUIFObject *pParent, DWORD dwID, const RECT *prc, DWORD dwStyle ) : CUIFButton( pParent, dwID, prc, dwStyle )
{
m_iButtonID = 0;
}
/* ~ C U I F B A L L O O N B U T T O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
CUIFBalloonButton::~CUIFBalloonButton( void )
{
}
/* O N P A I N T */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonButton::OnPaint( HDC hDC )
{
HDC hDCMem = NULL;
HBITMAP hBmMem = NULL;
HBITMAP hBmMemOld = NULL;
BOOL fDownFace = FALSE;
COLORREF colLTFrame;
COLORREF colRBFrame;
HBRUSH hBrush;
HBRUSH hBrushOld;
HPEN hPen;
HPEN hPenOld;
RECT rcItem;
rcItem = GetRectRef();
OffsetRect( &rcItem, -rcItem.left, -rcItem.top );
// create memory DC
hDCMem = CreateCompatibleDC( hDC );
hBmMem = CreateCompatibleBitmap( hDC, rcItem.right, rcItem.bottom );
hBmMemOld = (HBITMAP)SelectObject( hDCMem, hBmMem );
// determine button image
switch (m_dwStatus) {
default: {
colLTFrame = GetSysColor( COLOR_INFOBK );
colRBFrame = GetSysColor( COLOR_INFOBK );
fDownFace = FALSE;
break;
}
case UIBUTTON_DOWN: {
colLTFrame = GetSysColor( COLOR_3DSHADOW );
colRBFrame = GetSysColor( COLOR_3DHILIGHT );
fDownFace = TRUE;
break;
}
case UIBUTTON_HOVER: {
colLTFrame = GetSysColor( COLOR_3DHILIGHT );
colRBFrame = GetSysColor( COLOR_3DSHADOW );
fDownFace = FALSE;
break;
}
case UIBUTTON_DOWNOUT: {
colLTFrame = GetSysColor( COLOR_3DHILIGHT );
colRBFrame = GetSysColor( COLOR_3DSHADOW );
fDownFace = FALSE;
break;
}
}
// paint button face
hBrush = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
FillRect( hDCMem, &rcItem, hBrush );
DeleteObject( hBrush );
// paint image on button
DrawTextProc( hDCMem, &rcItem, fDownFace );
// paint button frame (hilight/shadow)
hBrushOld = (HBRUSH)SelectObject( hDCMem, GetStockObject( NULL_BRUSH ) );
hPen = CreatePen( PS_SOLID, 0, colLTFrame );
hPenOld = (HPEN)SelectObject( hDCMem, hPen );
RoundRect( hDCMem, rcItem.left, rcItem.top, rcItem.right - 1, rcItem.bottom - 1, 6, 6 );
SelectObject( hDCMem, hPenOld );
DeleteObject( hPen );
hPen = CreatePen( PS_SOLID, 0, colRBFrame );
hPenOld = (HPEN)SelectObject( hDCMem, hPen );
RoundRect( hDCMem, rcItem.left + 1, rcItem.top + 1, rcItem.right, rcItem.bottom, 6, 6 );
SelectObject( hDCMem, hPenOld );
DeleteObject( hPen );
// paint button frame (fixed)
hPen = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_3DFACE ) );
hPenOld = (HPEN)SelectObject( hDCMem, hPen );
RoundRect( hDCMem, rcItem.left + 1, rcItem.top + 1, rcItem.right - 1, rcItem.bottom - 1, 6, 6 );
SelectObject( hDCMem, hPenOld );
DeleteObject( hPen );
SelectObject( hDCMem, hBrushOld );
//
BitBlt( hDC,
GetRectRef().left,
GetRectRef().top,
GetRectRef().right - GetRectRef().left,
GetRectRef().bottom - GetRectRef().top,
hDCMem,
rcItem.left,
rcItem.top,
SRCCOPY );
//
SelectObject( hDCMem, hBmMemOld );
DeleteObject( hBmMem );
DeleteDC( hDCMem );
}
/* G E T B U T T O N I D */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
int CUIFBalloonButton::GetButtonID( void )
{
return m_iButtonID;
}
/* S E T B U T T O N I D */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonButton::SetButtonID( int iButtonID )
{
m_iButtonID = iButtonID;
}
/* D R A W T E X T P R O C */
/*------------------------------------------------------------------------------
Draw text on button face
------------------------------------------------------------------------------*/
void CUIFBalloonButton::DrawTextProc( HDC hDC, const RECT *prc, BOOL fDown )
{
HFONT hFontOld;
COLORREF colTextOld;
int iBkModeOld;
DWORD dwAlign = 0;
RECT rc;
//
if (m_pwchText == NULL) {
return;
}
//
hFontOld = (HFONT)SelectObject( hDC, GetFont() );
// calc text width
switch (m_dwStyle & UIBUTTON_HALIGNMASK) {
case UIBUTTON_LEFT:
default: {
dwAlign |= DT_LEFT;
break;
}
case UIBUTTON_CENTER: {
dwAlign |= DT_CENTER;
break;
}
case UIBUTTON_RIGHT: {
dwAlign |= DT_RIGHT;
break;
}
}
switch (m_dwStyle & UIBUTTON_VALIGNMASK) {
case UIBUTTON_TOP:
default: {
dwAlign |= DT_TOP;
break;
}
case UIBUTTON_VCENTER: {
dwAlign |= DT_VCENTER;
break;
}
case UIBUTTON_BOTTOM: {
dwAlign |= DT_BOTTOM;
break;
}
}
//
colTextOld = SetTextColor( hDC, GetSysColor( COLOR_BTNTEXT ) );
iBkModeOld = SetBkMode( hDC, TRANSPARENT );
rc = *prc;
if (fDown) {
OffsetRect( &rc, +1, +1 );
}
CUIDrawText( hDC, m_pwchText, -1, &rc, dwAlign | DT_SINGLELINE );
SetBkMode( hDC, iBkModeOld );
SetTextColor( hDC, colTextOld );
SelectObject( hDC, hFontOld );
}
/*=============================================================================*/
/* */
/* C U I F B A L L O O N W I N D O W */
/* */
/*=============================================================================*/
/* C U I F B A L L O O N W I N D O W */
/*------------------------------------------------------------------------------
Constructor of CUIFBalloonWindow
------------------------------------------------------------------------------*/
CUIFBalloonWindow::CUIFBalloonWindow( HINSTANCE hInst, DWORD dwStyle ) : CUIFWindow( hInst, dwStyle )
{
m_hWindowRgn = NULL;
m_pwszText = NULL;
m_rcMargin.left = 8;
m_rcMargin.top = 8;
m_rcMargin.right = 8;
m_rcMargin.bottom = 8;
m_iMaxTxtWidth = -1;
m_fColBack = FALSE;
m_fColText = FALSE;
m_colBack = RGB( 0, 0, 0 );
m_colText = RGB( 0, 0, 0 );
m_ptTarget.x = 0;
m_ptTarget.y = 0;
m_rcExclude.left = 0;
m_rcExclude.right = 0;
m_rcExclude.top = 0;
m_rcExclude.bottom = 0;
m_posDef = BALLOONPOS_ABOVE;
m_pos = BALLOONPOS_ABOVE;
m_dir = BALLOONDIR_LEFT;
m_align = BALLOONALIGN_CENTER;
m_ptTail.x = 0;
m_ptTail.y = 0;
m_nButton = 0;
m_iCmd = -1;
m_hWndNotify = 0;
m_uiMsgNotify = WM_NULL;
}
/* ~ C U I F B A L L O O N W I N D O W */
/*------------------------------------------------------------------------------
Destructor of CUIFBalloonWindow
------------------------------------------------------------------------------*/
CUIFBalloonWindow::~CUIFBalloonWindow( void )
{
if (m_pwszText != NULL) {
delete m_pwszText;
}
}
/* G E T C L A S S N A M E */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LPCTSTR CUIFBalloonWindow::GetClassName( void )
{
return TEXT(WNDCLASS_BALLOONWND);
}
/* G E T W N D T I T L E */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LPCTSTR CUIFBalloonWindow::GetWndTitle( void )
{
return TEXT(WNDTITLE_BALLOONWND);
}
/* I N I T I A L I Z E */
/*------------------------------------------------------------------------------
Initialize UI window object
(UIFObject method)
------------------------------------------------------------------------------*/
CUIFObject *CUIFBalloonWindow::Initialize( void )
{
CUIFObject *pUIObj = CUIFWindow::Initialize();
// create buttons
switch (GetStyleBits( UIBALLOON_BUTTONS )) {
case UIBALLOON_OK: {
AddButton( IDOK );
break;
}
case UIBALLOON_YESNO: {
AddButton( IDYES );
AddButton( IDNO );
break;
}
}
return pUIObj;
}
/* O N C R E A T E */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::OnCreate( HWND hWnd )
{
UNREFERENCED_PARAMETER( hWnd );
m_iCmd = -1;
AdjustPos();
}
/* O N D E S T R O Y */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::OnDestroy( HWND hWnd )
{
UNREFERENCED_PARAMETER( hWnd );
SendNotification( m_iCmd );
DoneWindowRegion();
}
/* O N P A I N T */
/*------------------------------------------------------------------------------
Paint window object
(UIFObject method)
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::OnPaint( HDC hDC )
{
RECT rcClient;
RECT rcMargin;
// paint balloon frame
GetRect( &rcClient );
PaintFrameProc( hDC, &rcClient );
// paint message
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
rcClient.bottom -= cxyTailHeight;
break;
}
case BALLOONPOS_BELLOW: {
rcClient.top += cxyTailHeight;
break;
}
case BALLOONPOS_LEFT: {
rcClient.right -= cxyTailHeight;
break;
}
case BALLOONPOS_RIGHT: {
rcClient.left += cxyTailHeight;
break;
}
}
GetMargin( &rcMargin );
rcClient.left = rcClient.left + rcMargin.left;
rcClient.top = rcClient.top + rcMargin.top;
rcClient.right = rcClient.right - rcMargin.right;
rcClient.bottom = rcClient.bottom - rcMargin.bottom;
PaintMessageProc( hDC, &rcClient, m_pwszText );
}
/* O N K E Y D O W N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::OnKeyDown( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER( hWnd );
UNREFERENCED_PARAMETER( lParam );
BOOL fEnd = FALSE;
switch (wParam) {
case VK_RETURN: {
CUIFBalloonButton *pUIBtn = (CUIFBalloonButton *)FindUIObject( 0 ); /* first button */
if (pUIBtn != NULL) {
m_iCmd = pUIBtn->GetButtonID();
fEnd = TRUE;
}
break;
}
case VK_ESCAPE: {
m_iCmd = -1;
fEnd = TRUE;
break;
}
case 'Y': {
CUIFBalloonButton *pUIBtn = FindButton( IDYES );
if (pUIBtn != NULL) {
m_iCmd = pUIBtn->GetButtonID();
fEnd = TRUE;
}
break;
}
case 'N': {
CUIFBalloonButton *pUIBtn = FindButton( IDNO );
if (pUIBtn != NULL) {
m_iCmd = pUIBtn->GetButtonID();
fEnd = TRUE;
}
break;
}
}
if (fEnd) {
DestroyWindow( GetWnd() );
}
}
/* O N O B J E C T N O T I F Y */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::OnObjectNotify( CUIFObject *pUIObj, DWORD dwCommand, LPARAM lParam )
{
UNREFERENCED_PARAMETER( dwCommand );
UNREFERENCED_PARAMETER( lParam );
m_iCmd = ((CUIFBalloonButton*)pUIObj)->GetButtonID();
DestroyWindow( GetWnd() );
return 0;
}
/* S E T T E X T */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetText( LPCWSTR pwchMessage )
{
if (m_pwszText != NULL) {
delete m_pwszText;
m_pwszText = NULL;
}
if (pwchMessage != NULL) {
int l = lstrlenW( pwchMessage );
m_pwszText = new WCHAR[ l+1 ];
if (m_pwszText)
StrCpyW( m_pwszText, pwchMessage );
}
else {
m_pwszText = new WCHAR[1];
if (m_pwszText)
*m_pwszText = L'\0';
}
AdjustPos();
return 0;
}
/* S E T N O T I F Y W I N D O W */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetNotifyWindow( HWND hWndNotify, UINT uiMsgNotify )
{
m_hWndNotify = hWndNotify;
m_uiMsgNotify = uiMsgNotify;
return 0;
}
/* S E T B A L L O O N P O S */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetBalloonPos( BALLOONWNDPOS pos )
{
m_posDef = pos;
AdjustPos();
return 0;
}
/* S E T B A L L O O N A L I G N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetBalloonAlign( BALLOONWNDALIGN align )
{
m_align = align;
AdjustPos();
return 0;
}
/* G E T B K C O L O R */
/*------------------------------------------------------------------------------
Retrieves the background color in a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::GetBalloonBkColor( void )
{
if (m_fColBack) {
return (LRESULT)m_colBack;
}
else {
return (LRESULT)GetSysColor( COLOR_INFOBK );
}
}
/* G E T T E X T C O L O R */
/*------------------------------------------------------------------------------
Retrieves the text color in a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::GetBalloonTextColor( void )
{
if (m_fColText) {
return (LRESULT)m_colText;
}
else {
return (LRESULT)GetSysColor( COLOR_INFOTEXT );
}
}
/* G E T M A R G I N */
/*------------------------------------------------------------------------------
Retrieves the top, left, bottom, and right margins set for a tooltip window.
A margin is the distance, in pixels, between the tooltip window border and
the text contained within the tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::GetMargin( RECT *prc )
{
if (prc == NULL) {
return 0;
}
*prc = m_rcMargin;
return 0;
}
/* G E T M A X T I P W I D T H */
/*------------------------------------------------------------------------------
Retrieves the maximum width for a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::GetMaxBalloonWidth( void )
{
return m_iMaxTxtWidth;
}
/* S E T B K C O L O R */
/*------------------------------------------------------------------------------
Sets the background color in a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetBalloonBkColor( COLORREF col )
{
m_fColBack = TRUE;
m_colBack = col;
return 0;
}
/* S E T T E X T C O L O R */
/*------------------------------------------------------------------------------
Sets the text color in a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetBalloonTextColor( COLORREF col )
{
m_fColText = TRUE;
m_colText = col;
return 0;
}
/* S E T M A R G I N */
/*------------------------------------------------------------------------------
Sets the top, left, bottom, and right margins for a tooltip window. A margin
is the distance, in pixels, between the tooltip window border and the text
contained within the tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetMargin( RECT *prc )
{
if (prc == NULL) {
return 0;
}
m_rcMargin = *prc;
return 0;
}
/* S E T M A X T I P W I D T H */
/*------------------------------------------------------------------------------
Sets the maximum width for a tooltip window.
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetMaxBalloonWidth( INT iWidth )
{
m_iMaxTxtWidth = iWidth;
return 0;
}
/* S E T B U T T O N T E X T */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetButtonText( int idCmd, LPCWSTR pwszText )
{
CUIFBalloonButton *pUIBtn = FindButton( idCmd );
if (pUIBtn != NULL) {
pUIBtn->SetText( pwszText );
}
return 0;
}
/* S E T T A R G E T P O S */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetTargetPos( POINT pt )
{
m_ptTarget = pt;
AdjustPos();
return 0;
}
/* S E T E X C L U D E R E C T */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
LRESULT CUIFBalloonWindow::SetExcludeRect( const RECT *prcExclude )
{
m_rcExclude = *prcExclude;
AdjustPos();
return 0;
}
/* C R E A T E R E G I O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
HRGN CUIFBalloonWindow::CreateRegion( RECT *prc )
{
POINT rgPt[4];
HRGN hRgn;
HRGN hRgnTail;
// create message body window
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
#ifndef UNDER_CE // CE does not support RoundRectRgn
hRgn = CreateRoundRectRgn(
prc->left,
prc->top,
prc->right,
prc->bottom - cxyTailHeight,
cxRoundSize,
cyRoundSize );
#else // UNDER_CE
hRgn = CreateRectRgn(
prc->left,
prc->top,
prc->right,
prc->bottom - cxyTailHeight );
#endif // UNDER_CE
rgPt[0].x = m_ptTail.x;
rgPt[0].y = prc->bottom - 1 - cxyTailHeight;
rgPt[1].x = m_ptTail.x;
rgPt[1].y = m_ptTail.y;
rgPt[2].x = m_ptTail.x + cxyTailWidth * (m_dir == BALLOONDIR_LEFT ? +1 : -1 );
rgPt[2].y = prc->bottom - 1 - cxyTailHeight;
rgPt[3] = rgPt[0];
break;
}
case BALLOONPOS_BELLOW: {
#ifndef UNDER_CE // CE does not support RoundRectRgn
hRgn = CreateRoundRectRgn(
prc->left,
prc->top + cxyTailHeight,
prc->right,
prc->bottom,
cxRoundSize,
cyRoundSize );
#else // UNDER_CE
hRgn = CreateRectRgn(
prc->left,
prc->top + cxyTailHeight,
prc->right,
prc->bottom );
#endif // UNDER_CE
rgPt[0].x = m_ptTail.x;
rgPt[0].y = prc->top + cxyTailHeight;
rgPt[1].x = m_ptTail.x;
rgPt[1].y = m_ptTail.y;
rgPt[2].x = m_ptTail.x + cxyTailWidth * (m_dir == BALLOONDIR_LEFT ? +1 : -1 );
rgPt[2].y = prc->top + cxyTailHeight;
rgPt[3] = rgPt[0];
break;
}
case BALLOONPOS_LEFT: {
#ifndef UNDER_CE // CE does not support RoundRectRgn
hRgn = CreateRoundRectRgn(
prc->left,
prc->top,
prc->right - cxyTailHeight,
prc->bottom,
cxRoundSize,
cyRoundSize );
#else // UNDER_CE
hRgn = CreateRectRgn(
prc->left,
prc->top,
prc->right - cxyTailHeight,
prc->bottom );
#endif // UNDER_CE
rgPt[0].x = prc->right - 1 - cxyTailHeight;
rgPt[0].y = m_ptTail.y;
rgPt[1].x = m_ptTail.x;
rgPt[1].y = m_ptTail.y;
rgPt[2].x = prc->right - 1 - cxyTailHeight;
rgPt[2].y = m_ptTail.y + cxyTailWidth * (m_dir == BALLOONDIR_UP ? +1 : -1 );
rgPt[3] = rgPt[0];
break;
}
case BALLOONPOS_RIGHT: {
#ifndef UNDER_CE // CE does not support RoundRectRgn
hRgn = CreateRoundRectRgn(
prc->left + cxyTailHeight,
prc->top,
prc->right,
prc->bottom,
cxRoundSize,
cyRoundSize );
#else // UNDER_CE
hRgn = CreateRectRgn(
prc->left + cxyTailHeight,
prc->top,
prc->right,
prc->bottom );
#endif // UNDER_CE
rgPt[0].x = prc->left + cxyTailHeight;
rgPt[0].y = m_ptTail.y;
rgPt[1].x = m_ptTail.x;
rgPt[1].y = m_ptTail.y;
rgPt[2].x = prc->left + cxyTailHeight;
rgPt[2].y = m_ptTail.y + cxyTailWidth * (m_dir == BALLOONDIR_UP ? +1 : -1 );
rgPt[3] = rgPt[0];
break;
}
}
// add balloon tail region
#ifndef UNDER_CE // tmptmp CE does not support. check later !!
hRgnTail = CreatePolygonRgn( rgPt, 4, WINDING );
#endif // UNDER_CE
CombineRgn( hRgn, hRgn, hRgnTail, RGN_OR );
DeleteRgn( hRgnTail );
return hRgn;
}
/* P A I N T F R A M E P R O C */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::PaintFrameProc( HDC hDC, RECT *prc )
{
HRGN hRgn;
HBRUSH hBrushFrm;
HBRUSH hBrushWnd;
Assert( hDC != NULL );
hRgn = CreateRegion( prc );
hBrushWnd = CreateSolidBrush( (COLORREF)GetBalloonBkColor() );
hBrushFrm = CreateSolidBrush( GetSysColor( COLOR_WINDOWFRAME ) );
FillRgn( hDC, hRgn, hBrushWnd );
#ifndef UNDER_CE // tmptmp CE does not support. check later !!
FrameRgn( hDC, hRgn, hBrushFrm, 1, 1 );
#endif // UNDER_CE
DeleteObject( hBrushWnd );
DeleteObject( hBrushFrm );
DeleteObject( hRgn );
}
/* P A I N T M E S S A G E P R O C */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::PaintMessageProc( HDC hDC, RECT *prc, WCHAR *pwszText )
{
HFONT hFontOld;
COLORREF colTextOld;
int iBkModeOld;
Assert( hDC != NULL );
hFontOld = (HFONT)SelectObject( hDC, m_hFont );
colTextOld = SetTextColor( hDC, (COLORREF)GetBalloonTextColor() );
iBkModeOld = SetBkMode( hDC, TRANSPARENT );
CUIDrawText( hDC, pwszText, -1, prc, DT_LEFT | DT_WORDBREAK );
SelectObject( hDC, hFontOld );
SetTextColor( hDC, colTextOld );
SetBkMode( hDC, iBkModeOld );
}
/* I N I T W I N D O W R E G I O N */
/*------------------------------------------------------------------------------
Set window region
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::InitWindowRegion( void )
{
RECT rcClient;
GetRect( &rcClient );
m_hWindowRgn = CreateRegion( &rcClient );
if (m_hWindowRgn != NULL) {
SetWindowRgn( GetWnd(), m_hWindowRgn, TRUE );
}
}
/* D O N E W I N D O W R E G I O N */
/*------------------------------------------------------------------------------
Reset window region
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::DoneWindowRegion( void )
{
if (m_hWindowRgn != NULL) {
SetWindowRgn( GetWnd(), NULL, TRUE );
DeleteObject( m_hWindowRgn );
m_hWindowRgn = NULL;
}
}
/* G E T B U T T O N S I Z E */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::GetButtonSize( SIZE *pSize )
{
HDC hDC;
HFONT hFontOld;
TEXTMETRIC TM;
// get text metrics
#ifndef UNDER_CE // DCA => DCW
hDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
#else // UNDER_CE
hDC = CreateDCW( L"DISPLAY", NULL, NULL, NULL );
#endif // UNDER_CE
hFontOld = (HFONT)SelectObject( hDC, GetFont() );
GetTextMetrics( hDC, &TM );
SelectObject( hDC, hFontOld );
DeleteDC( hDC );
// calc button size
pSize->cx = TM.tmAveCharWidth * 16;
pSize->cy = TM.tmHeight + 10;
}
/* A D J U S T P O S */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::AdjustPos( void )
{
HDC hDC;
HFONT hFontOld;
TEXTMETRIC TM;
RECT rcWork;
RECT rcWindow = {0};
SIZE WndSize;
RECT rcText;
SIZE BtnSize;
if (!IsWindow( GetWnd() )) {
return;
}
if (m_pwszText == NULL) {
return;
}
//
GetButtonSize( &BtnSize );
// get text size
#ifndef UNDER_CE // DCA => DCW
hDC = GetDC( GetWnd() ); //CreateDC( "DISPLAY", NULL, NULL, NULL );
#else // UNDER_CE
hDC = GetDCW( GetWnd() ); //CreateDCW( L"DISPLAY", NULL, NULL, NULL );
#endif // UNDER_CE
hFontOld = (HFONT)SelectObject( hDC, GetFont() );
GetTextMetrics( hDC, &TM );
rcText.left = 0;
rcText.right = TM.tmAveCharWidth * 40;
rcText.top = 0;
rcText.bottom = 0;
if (0 < m_nButton) {
rcText.right = max( rcText.right, BtnSize.cx*m_nButton + BtnSize.cx/2*(m_nButton-1) );
}
CUIDrawText( hDC, m_pwszText, -1, &rcText, DT_LEFT | DT_WORDBREAK | DT_CALCRECT );
SelectObject( hDC, hFontOld );
ReleaseDC( GetWnd(), hDC );
//
// determine window size
//
// max width
if (0 < m_nButton) {
rcText.right = max( rcText.right, BtnSize.cx*m_nButton + BtnSize.cx/2*(m_nButton-1) );
}
// client width
WndSize.cx = (rcText.right - rcText.left)
+ m_rcMargin.left
+ m_rcMargin.right;
WndSize.cy = (rcText.bottom - rcText.top)
+ m_rcMargin.top
+ m_rcMargin.bottom;
// tail width
switch (m_pos) {
default:
case BALLOONPOS_ABOVE:
case BALLOONPOS_BELLOW: {
WndSize.cy += cxyTailHeight; /* balloon tail height */
break;
}
case BALLOONPOS_LEFT:
case BALLOONPOS_RIGHT: {
WndSize.cx += cxyTailHeight; /* balloon tail height */
break;
}
}
// buton height
if (0 < m_nButton) {
WndSize.cy += m_rcMargin.bottom + BtnSize.cy; /* margin and button height */
}
//
// determine tip window place
//
SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
if (CUIIsMonitorAPIAvail()) {
HMONITOR hMonitor;
MONITORINFO MonitorInfo;
hMonitor = CUIMonitorFromPoint( m_ptTarget, MONITOR_DEFAULTTONEAREST );
if (hMonitor != NULL) {
MonitorInfo.cbSize = sizeof(MonitorInfo);
if (CUIGetMonitorInfo( hMonitor, &MonitorInfo )) {
rcWork = MonitorInfo.rcMonitor;
}
}
}
m_pos = m_posDef;
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
if (m_rcExclude.top - WndSize.cy < rcWork.top) {
// cannot locate the tip window at above. can put it at bellow?
if (m_rcExclude.bottom + WndSize.cy < rcWork.bottom) {
m_pos = BALLOONPOS_BELLOW;
}
}
break;
}
case BALLOONPOS_BELLOW: {
if (rcWork.bottom <= m_rcExclude.bottom + WndSize.cy) {
// cannot locate the tip window at bellow. can put it at above?
if (rcWork.top < m_rcExclude.top - WndSize.cy) {
m_pos = BALLOONPOS_ABOVE;
}
}
break;
}
case BALLOONPOS_LEFT: {
if (m_rcExclude.left - WndSize.cx < rcWork.left) {
// cannot locate the tip window at left. can put it at right?
if (m_rcExclude.right + WndSize.cx < rcWork.right) {
m_pos = BALLOONPOS_RIGHT;
}
}
break;
}
case BALLOONPOS_RIGHT: {
if (rcWork.right <= m_rcExclude.right + WndSize.cx) {
// cannot locate the tip window at right. can put it at left?
if (rcWork.left < m_rcExclude.left - WndSize.cx) {
m_pos = BALLOONPOS_LEFT;
}
}
break;
}
}
//
// calc window position
//
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
switch (m_align) {
default:
case BALLOONALIGN_CENTER: {
rcWindow.left = m_ptTarget.x - WndSize.cx / 2;
break;
}
case BALLOONALIGN_LEFT: {
rcWindow.left = m_rcExclude.left;
break;
}
case BALLOONALIGN_RIGHT: {
rcWindow.left = m_rcExclude.right - WndSize.cx;
break;
}
}
rcWindow.top = m_rcExclude.top - WndSize.cy;
break;
}
case BALLOONPOS_BELLOW: {
switch (m_align) {
default:
case BALLOONALIGN_CENTER: {
rcWindow.left = m_ptTarget.x - WndSize.cx / 2;
break;
}
case BALLOONALIGN_LEFT: {
rcWindow.left = m_rcExclude.left;
break;
}
case BALLOONALIGN_RIGHT: {
rcWindow.left = m_rcExclude.right - WndSize.cx;
break;
}
}
rcWindow.top = m_rcExclude.bottom;
break;
}
case BALLOONPOS_LEFT: {
rcWindow.left = m_rcExclude.left - WndSize.cx;
switch (m_align) {
default:
case BALLOONALIGN_CENTER: {
rcWindow.top = m_ptTarget.y - WndSize.cy / 2;
break;
}
case BALLOONALIGN_TOP: {
rcWindow.top = m_rcExclude.top;
break;
}
case BALLOONALIGN_BOTTOM: {
rcWindow.top = m_rcExclude.bottom - WndSize.cy;
break;
}
}
break;
}
case BALLOONPOS_RIGHT: {
rcWindow.left = m_rcExclude.right;
switch (m_align) {
default:
case BALLOONALIGN_CENTER: {
rcWindow.top = m_ptTarget.y - WndSize.cy / 2;
break;
}
case BALLOONALIGN_TOP: {
rcWindow.top = m_rcExclude.top;
break;
}
case BALLOONALIGN_BOTTOM: {
rcWindow.top = m_rcExclude.bottom - WndSize.cy;
break;
}
}
break;
}
}
rcWindow.right = rcWindow.left + WndSize.cx;
rcWindow.bottom = rcWindow.top + WndSize.cy;
if (rcWindow.left < rcWork.left) {
OffsetRect( &rcWindow, rcWork.left - rcWindow.left, 0 );
}
else if (rcWork.right < rcWindow.right) {
OffsetRect( &rcWindow, rcWork.right - rcWindow.right, 0 );
}
if (rcWindow.top < rcWork.top) {
OffsetRect( &rcWindow, 0, rcWork.top - rcWindow.top );
}
else if (rcWork.bottom < rcWindow.bottom) {
OffsetRect( &rcWindow, 0, rcWork.bottom - rcWindow.bottom );
}
//
// calc target (end of balloon tail) point and direction
//
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
m_ptTail.x = m_ptTarget.x;
m_ptTail.x = max( m_ptTail.x, rcWindow.left + cxRoundSize/2 );
m_ptTail.x = min( m_ptTail.x, rcWindow.right - cxRoundSize/2 - 1 );
m_ptTail.y = rcWindow.bottom - 1;
m_dir = ((m_ptTail.x < (rcWindow.left + rcWindow.right)/2) ? BALLOONDIR_LEFT : BALLOONDIR_RIGHT);
break;
}
case BALLOONPOS_BELLOW: {
m_ptTail.x = m_ptTarget.x;
m_ptTail.x = max( m_ptTail.x, rcWindow.left + cxRoundSize/2 );
m_ptTail.x = min( m_ptTail.x, rcWindow.right - cxRoundSize/2 - 1 );
m_ptTail.y = rcWindow.top;
m_dir = ((m_ptTail.x < (rcWindow.left + rcWindow.right)/2) ? BALLOONDIR_LEFT : BALLOONDIR_RIGHT);
break;
}
case BALLOONPOS_LEFT: {
m_ptTail.x = rcWindow.right - 1;
m_ptTail.y = m_ptTarget.y;
m_ptTail.y = max( m_ptTail.y, rcWindow.top + cyRoundSize/2 );
m_ptTail.y = min( m_ptTail.y, rcWindow.bottom - cyRoundSize/2 - 1 );
m_dir = ((m_ptTail.y < (rcWindow.top + rcWindow.bottom)/2) ? BALLOONDIR_UP : BALLOONDIR_DOWN);
break;
}
case BALLOONPOS_RIGHT: {
m_ptTail.x = rcWindow.left;
m_ptTail.y = m_ptTarget.y;
m_ptTail.y = max( m_ptTail.y, rcWindow.top + cyRoundSize/2 );
m_ptTail.y = min( m_ptTail.y, rcWindow.bottom - cyRoundSize/2 - 1 );
m_dir = ((m_ptTail.y < (rcWindow.top + rcWindow.bottom)/2) ? BALLOONDIR_UP : BALLOONDIR_DOWN);
break;
}
}
m_ptTail.x -= rcWindow.left; // client pos
m_ptTail.y -= rcWindow.top; // client pos
//
Show( FALSE );
DoneWindowRegion();
Move( rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top );
LayoutObject();
InitWindowRegion();
Show( TRUE );
}
/* L A Y O U T O B J E C T */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::LayoutObject( void )
{
RECT rcClient;
RECT rcMargin;
SIZE BtnSize;
int i;
//
GetButtonSize( &BtnSize );
// layout buttons
GetRect( &rcClient );
switch (m_pos) {
default:
case BALLOONPOS_ABOVE: {
rcClient.bottom -= cxyTailHeight;
break;
}
case BALLOONPOS_BELLOW: {
rcClient.top += cxyTailHeight;
break;
}
case BALLOONPOS_LEFT: {
rcClient.right -= cxyTailHeight;
break;
}
case BALLOONPOS_RIGHT: {
rcClient.left += cxyTailHeight;
break;
}
}
GetMargin( &rcMargin );
rcClient.left = rcClient.left + rcMargin.left;
rcClient.top = rcClient.top + rcMargin.top;
rcClient.right = rcClient.right - rcMargin.right;
rcClient.bottom = rcClient.bottom - rcMargin.bottom;
//
for (i = 0; i < m_nButton; i++) {
CUIFObject *pUIBtn = FindUIObject( i );
if (pUIBtn != NULL) {
RECT rcButton;
rcButton.left = ((rcClient.left + rcClient.right) - (BtnSize.cx*m_nButton + BtnSize.cx/2*(m_nButton-1))) / 2 + BtnSize.cx*i + BtnSize.cx/2*i;
rcButton.top = rcClient.bottom - BtnSize.cy;
rcButton.right = rcButton.left + BtnSize.cx;
rcButton.bottom = rcButton.top + BtnSize.cy;
pUIBtn->SetRect( &rcButton );
pUIBtn->Show( TRUE );
}
}
}
/* A D D B U T T O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::AddButton( int idCmd )
{
CUIFBalloonButton *pUIBtn = NULL;
RECT rcNull = { 0, 0, 0, 0 };
switch (idCmd) {
case IDOK:
case IDCANCEL:
case IDABORT:
case IDRETRY:
case IDIGNORE:
case IDYES:
case IDNO: {
pUIBtn = new CUIFBalloonButton( this, (DWORD)m_nButton, &rcNull, UIBUTTON_PUSH | UIBUTTON_CENTER | UIBUTTON_VCENTER );
break;
}
}
if (pUIBtn != NULL) {
//
WCHAR *pwsz;
pUIBtn->Initialize();
pUIBtn->SetButtonID( idCmd );
switch (idCmd) {
case IDOK: {
pwsz = CRStr(CUI_IDS_OK);
pUIBtn->SetText( *pwsz ? pwsz : L"OK" );
break;
}
case IDCANCEL: {
pwsz = CRStr(CUI_IDS_CANCEL);
pUIBtn->SetText( *pwsz ? pwsz : L"Cancel" );
break;
}
case IDABORT: {
pwsz = CRStr(CUI_IDS_ABORT);
pUIBtn->SetText( *pwsz ? pwsz : L"&Abort" );
break;
}
case IDRETRY: {
pwsz = CRStr(CUI_IDS_RETRY);
pUIBtn->SetText( *pwsz ? pwsz : L"&Retry" );
break;
}
case IDIGNORE: {
pwsz = CRStr(CUI_IDS_IGNORE);
pUIBtn->SetText( *pwsz ? pwsz : L"&Ignore" );
break;
}
case IDYES: {
pwsz = CRStr(CUI_IDS_YES);
pUIBtn->SetText( *pwsz ? pwsz : L"&Yes" );
break;
}
case IDNO: {
pwsz = CRStr(CUI_IDS_NO);
pUIBtn->SetText( *pwsz ? pwsz : L"&No" );
break;
}
}
AddUIObj( pUIBtn );
m_nButton++;
}
}
/* F I N D U I O B J E C T */
/*------------------------------------------------------------------------------
Find UI object which has an ID
When no UI object found, returns NULL.
------------------------------------------------------------------------------*/
CUIFObject *CUIFBalloonWindow::FindUIObject( DWORD dwID )
{
int nChild;
int i;
nChild = m_ChildList.GetCount();
for (i = 0; i < nChild; i++) {
CUIFObject *pUIObj = m_ChildList.Get( i );
Assert(PtrToInt( pUIObj ));
if (pUIObj->GetID() == dwID) {
return pUIObj;
}
}
return NULL;
}
/* F I N D B U T T O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
CUIFBalloonButton *CUIFBalloonWindow::FindButton( int idCmd )
{
int i;
for (i = 0; i < m_nButton; i++) {
CUIFBalloonButton *pUIBtn = (CUIFBalloonButton*)FindUIObject( i );
if ((pUIBtn != NULL) && (pUIBtn->GetButtonID() == idCmd)) {
return pUIBtn;
}
}
return NULL;
}
/* S E N D N O T I F I C A T I O N */
/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void CUIFBalloonWindow::SendNotification( int iCmd )
{
if (m_hWndNotify != NULL) {
PostMessage( m_hWndNotify, m_uiMsgNotify, (WPARAM)iCmd, 0 );
}
}