/***********************************************************************/ /* Copyright (C) 2002 Definitive Solutions, Inc. All Rights Reserved. */ /* THIS COMPUTER PROGRAM IS PROPRIETARY AND CONFIDENTIAL TO DEFINITIVE */ /* SOLUTIONS, INC. AND ITS LICENSORS AND CONTAINS TRADE SECRETS OF */ /* DEFINITIVE SOLUTIONS, INC. THAT ARE PROVIDED PURSUANT TO A WRITTEN */ /* AGREEMENT CONTAINING RESTRICTIONS ON USE AND DISCLOSURE. ANY USE, */ /* REPRODUCTION, OR TRANSFER EXCEPT AS PROVIDED IN SUCH AGREEMENT */ /* IS STRICTLY PROHIBITED. */ /***********************************************************************/ #include "stdafx.h" #include "MyStatic.h" #include "Generic.h" #include "MyLog.h" #include "MyApp.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // MyStatic // Constructor. MyStatic::MyStatic() : m_crText(::GetSysColor(COLOR_WINDOWTEXT)) , m_hBrush(::CreateSolidBrush(GetSysColor(COLOR_3DFACE))) , m_hBrushWnd((HBRUSH) ::GetStockObject(NULL_BRUSH)) , m_bFlashState(false) , m_bTimer(false) , m_FlashType(MyStatic::NoFlash) , m_nFlashReqMS(-1) , m_nFlashDurMS(0) , m_nFlashMS(0) { // Load the default font into the logfont structure, and create a CFont. HRESULT hr(S_OK); ::ZeroMemory(&m_lf, sizeof m_lf); EC_B(::GetObject(static_cast (::GetStockObject(DEFAULT_GUI_FONT)), sizeof(m_lf), &m_lf)); EC_B(m_font.CreateFontIndirect(&m_lf)); } // Destructor. /* virtual */ MyStatic::~MyStatic() { HRESULT hr(S_OK); EC_B_(m_font.DeleteObject()); EC_B_(::DeleteObject(m_hBrush)); EC_V_(m_hBrush = NULL); } // User has requested new text. We just assign it because we don't want it to // appear while it is flashed on. MyStatic& MyStatic::SetText(const CString& sText) { VALIDATE; if (MyStatic::NoFlash == m_FlashType) { m_sText = sText; m_sTextNew.Empty(); SetWindowText(m_sText); } else { m_sTextNew = sText; } return *this; } // MyStatic& MyStatic::SetTextColor(COLORREF crText) { VALIDATE; HRESULT hr(S_OK); m_crText = crText; EC_B(RedrawWindow()); return *this; } // Is the font currently italic? bool MyStatic::GetFontItalic() const { VALIDATE; return m_lf.lfItalic; } // MyStatic& MyStatic::SetFontBold(bool bBold /* = true */ ) { VALIDATE; HRESULT hr(S_OK); m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; ReconstructFont(); EC_B(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetFontUnderline(bool bSet /* = true */ ) { VALIDATE; HRESULT hr(S_OK); m_lf.lfUnderline = bSet; ReconstructFont(); EC_B(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetFontItalic(bool bSet /* = true */ ) { VALIDATE; _ASSERTE(! (bSet && 13 < GetFontSize()) && "Don't italicize large fonts - looks very jaggy on some systems"); HRESULT hr(S_OK); m_lf.lfItalic = bSet; ReconstructFont(); EC_B(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetSunken(bool bSet /* = true */ ) { VALIDATE; HRESULT hr(S_OK); if (bSet) { EC_B(ModifyStyleEx(0, WS_EX_STATICEDGE, SWP_DRAWFRAME)); } else { EC_B(ModifyStyleEx(WS_EX_STATICEDGE, 0, SWP_DRAWFRAME)); } EC_B(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetBorder(bool bSet /* = true */ ) { VALIDATE; HRESULT hr(S_OK); if (bSet) { EC_B(ModifyStyle(0, WS_BORDER, SWP_DRAWFRAME)); } else { EC_B(ModifyStyle(WS_BORDER, 0, SWP_DRAWFRAME)); } EC_B(RedrawWindow()); return *this; } // What is the current point size for this control's font? int MyStatic::GetFontSize() { VALIDATE; int nPointSize(0); CDC* pDC = GetDC(); ASSERT_VALID(pDC); if (pDC) { nPointSize = -MulDiv(m_lf.lfHeight, 72, pDC->GetDeviceCaps(LOGPIXELSY)); } return nPointSize; } // MyStatic& MyStatic::SetFontSize(int nSize) { VALIDATE; _ASSERTE(! (GetFontItalic() && 13 < nSize) && "Don't italicize large fonts - looks very jaggy on some systems"); HRESULT hr(S_OK); m_lf.lfHeight = -nSize; EC_V(ReconstructFont()); EC_B(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetBkColor(COLORREF crBkgnd) { VALIDATE; HRESULT hr(S_OK); if (m_hBrush) { EC_B(::DeleteObject(m_hBrush)); EC_V_(m_hBrush = NULL); } EC_B_(NULL != (m_hBrush = ::CreateSolidBrush(crBkgnd))); EC_B_(RedrawWindow()); return *this; } // MyStatic& MyStatic::SetFontName(const CString& sFont) { VALIDATE; HRESULT hr(S_OK); lstrcpy(m_lf.lfFaceName, sFont); _ASSERTE(lstrlen(m_lf.lfFaceName) < sizeof m_lf.lfFaceName && "Buffer overrun"); EC_V(ReconstructFont()); EC_B(RedrawWindow()); return *this; } IMPLEMENT_DYNAMIC(MyStatic, CStatic) BEGIN_MESSAGE_MAP(MyStatic, CStatic) //{{AFX_MSG_MAP(MyStatic) ON_WM_CTLCOLOR_REFLECT() ON_WM_TIMER() ON_CONTROL_REFLECT(BN_CLICKED, OnClicked) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // MyStatic message handlers // Handle WM_CTLCOLOR. HBRUSH MyStatic::CtlColor(CDC* pDC, UINT nCtlColor) { VALIDATE; if (CTLCOLOR_STATIC == nCtlColor) { pDC->SelectObject(&m_font); pDC->SetTextColor(m_crText); pDC->SetBkMode(TRANSPARENT); // Make sure it's been populated. if (m_sText.IsEmpty()) { GetWindowText(m_sText); } } if (MyStatic::BackgroundFlash == m_FlashType) { if (! m_bFlashState) { return m_hBrushWnd; } } // Return a non-NULL brush if the parent's handler should not be called. return m_hBrush; } // Rebuild the font based on the current logfont structure. HRESULT MyStatic::ReconstructFont() { VALIDATE; HRESULT hr(S_OK); EC_B(m_font.DeleteObject()); EC_B(m_font.CreateFontIndirect(&m_lf)); return hr; } // Turn on/ off text flash. Default is: turn on flashing every half-second, // forever. MyStatic& MyStatic::FlashText(bool bActivate /* = true */ , int nRequestedMS /* = -1 */ , int nFlashMS /* = 500 */ ) { VALIDATE; HRESULT hr(S_OK); if (m_bTimer) { EC_B(KillTimer(1)); m_bTimer = false; SetWindowText(m_sText); m_FlashType = MyStatic::NoFlash; } if (bActivate) { GetWindowText(m_sText); m_bFlashState = false; m_bTimer = true; m_nFlashDurMS = 0; m_nFlashReqMS = nRequestedMS; m_nFlashMS = nFlashMS; EC_B_(1 == SetTimer(1, m_nFlashMS, NULL)); m_FlashType = MyStatic::TextFlash; } else { m_FlashType = MyStatic::NoFlash; } return *this; } // Turn on or off background flashing. MyStatic& MyStatic::FlashBackground(bool bActivate /* = true */ , int nRequestedMS /* = -1 */ , int nFlashMS /* = 500 */ ) { VALIDATE; HRESULT hr(S_OK); if (m_bTimer) { EC_B(KillTimer(1)); m_bTimer = false; } if (bActivate) { m_bFlashState = false; m_bTimer = true; m_nFlashDurMS = 0; m_nFlashReqMS = nRequestedMS; m_nFlashMS = nFlashMS; EC_B_(1 == SetTimer(1, m_nFlashMS, NULL)); m_FlashType = MyStatic::BackgroundFlash; } return *this; } // Handle WM_TIMER. void MyStatic::OnTimer(UINT nIDEvent) { VALIDATE; _ASSERTE(0 < m_nFlashMS && "m_nFlashMS never set"); HRESULT hr(S_OK); // Toggle the flash state, and check to see if the flash has expired. m_bFlashState = ! m_bFlashState; m_nFlashDurMS += m_nFlashMS; if (-1 != m_nFlashReqMS && m_nFlashDurMS > m_nFlashReqMS && ! m_bFlashState) { EC_B(KillTimer(nIDEvent)); m_bTimer = false; m_nFlashDurMS = 0; } // See if we have new text, and if we can apply it. if (! m_sTextNew.IsEmpty() && MyStatic::TextFlash == m_FlashType && m_bFlashState) { m_sText = m_sTextNew; m_sTextNew.Empty(); } // Do the flash. switch (m_FlashType) { case MyStatic::TextFlash: SetWindowText(m_bFlashState ? "" : m_sText); break; case MyStatic::BackgroundFlash: InvalidateRect(NULL, /* bErase */ false); UpdateWindow(); break; default: DOMYLOGE ("Bad default case: %d\n", m_FlashType); break; } CStatic::OnTimer(nIDEvent); } // User has clicked it, so stop flashing. (Must have "Notify" style.) void MyStatic::OnClicked() { VALIDATE; HRESULT hr(S_OK); if (m_bTimer) { EC_B(KillTimer(1)); m_bTimer = false; SetWindowText(m_sText); } } // WM_DESTROY. void MyStatic::OnDestroy() { VALIDATE; HRESULT hr(S_OK); // We have to kill the timer when we exit, in case someone left it flashing. // Yes, the timer is suppossed to be killed when the CWnd goes our of scope, // but that's not what I'm seeing. EC_V_(KillTimer(1)); m_bTimer = false; CStatic::OnDestroy(); } // Simple way to load a DDB into a DIB. bool MyStatic::LoadBitmap(const CString& sPath) { VALIDATE; _ASSERTE(! sPath.IsEmpty()); _ASSERTE(Generic::IsFile(sPath)); bool bReturn(false); HBITMAP hBitmap((HBITMAP) ::LoadImage( NULL, // hInstance - NULL since not a resource. sPath, // File full pathname. IMAGE_BITMAP, // Or IMAGE_CURSOR, or IMAGE_ICON. 0, // Width - not used for bitmap. 0, // Height - not used for bitmap. LR_LOADFROMFILE | // Not a resource. LR_CREATEDIBSECTION | // Return a DibSection. LR_DEFAULTSIZE)); // Use actual size. if (hBitmap) { SetBitmap(hBitmap); bReturn = true; } else { _ASSERTE(! "Error"); DOMYLOGST(API_FAILURE), "::LoadImage", ::GetLastError, sPath); } return bReturn; }