// // 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 ); } }