Solved

Background button flashing ...

Posted on 1998-04-25
1
430 Views
Last Modified: 2013-11-19
I have created a class named CAlarmButton. This class permit to falsh
background when I call member function StartFlashing and stop it when
calling member function StopFlashing.
The StartFlashing function starts a timer which Invalidate the control.
The StopFlashing function stop the timer.

My problem is when I use more then one button and when I call StartFlashing
for each button, all button are not flashing in rhythm. I wan't that all button
flash in rhythm.

I have tried to start the timer when I construct the control, but the result
is the same !

How can I do this ?

You can find the code below.

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------

class CAlarmButton : public CButton
 {
  COLORREF  m_BackgroundColor1, m_BackgroundColor2, m_BackgroundColor, m_TextColor;
  BOOL      m_IsBackgroundFlashing;
  CBitmap  *m_pImage, *m_pMask;
  int       m_ImageW, m_ImageH;
  UINT      m_TextAlignment, m_ImageAlignment;
  BOOL      m_HoldState;
 
  // Construction
  public :
           CAlarmButton();

           void SetBackgroundColor(COLORREF BackgroundColor, BOOL First = TRUE);
           void SetTextColor(COLORREF TextColor);
           void StartFlashing(UINT Time = 1000);
           void StopFlashing();
           void SetBitmap(UINT ImageID, UINT MaskID = NULL);
           void SetTextAlignment(UINT Alignment = HCENTER | VCENTER);
           void SetImageAlignment(UINT Alignment = HCENTER | VCENTER);
           void HoldState(BOOL HoldState = FALSE);

  // Attributes
  public :

  // Operations
  public :
           BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);

  // Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CAlarmButton)
      protected:
      virtual void PreSubclassWindow();
    virtual void DrawItem(LPDRAWITEMSTRUCT);
      //}}AFX_VIRTUAL

  // Implementation
  public :
           virtual ~CAlarmButton();

  // Generated message map functions
  protected :
      //{{AFX_MSG(CAlarmButton)
      afx_msg void OnTimer(UINT nIDEvent);
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
      //}}AFX_MSG

  DECLARE_MESSAGE_MAP()
 };

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------

CAlarmButton::CAlarmButton()
 {
  m_BackgroundColor  = m_BackgroundColor1 = RGB(198,198,198);
  m_BackgroundColor2 = RGB(255,0,0);
  m_TextColor        = RGB(0,0,0);

  m_IsBackgroundFlashing = FALSE;
  m_pImage               = NULL;
  m_pMask                = NULL;
  m_TextAlignment        = HCENTER | VCENTER;
  m_ImageAlignment       = HCENTER | VCENTER;
  m_HoldState            = FALSE;
 }

// --------------------------------------------------------------------------

CAlarmButton::~CAlarmButton()
 {
  if (m_pImage) delete m_pImage;
  if (m_pMask ) delete m_pMask;
 }

// --------------------------------------------------------------------------

void CAlarmButton::SetBackgroundColor(COLORREF BackgroundColor, BOOL First)
 {
  if (First) m_BackgroundColor1 = BackgroundColor;
  else m_BackgroundColor2 = BackgroundColor;
 }

// --------------------------------------------------------------------------

void CAlarmButton::StartFlashing(UINT Time)
 {
  SetTimer(TIMER_FLASHING, Time, NULL);
 }

// --------------------------------------------------------------------------

void CAlarmButton::StopFlashing()
 {
  KillTimer(TIMER_FLASHING);
  m_BackgroundColor = m_BackgroundColor1;
  Invalidate();
 }

// --------------------------------------------------------------------------

void CAlarmButton::SetBitmap(UINT ImageID, UINT MaskID)
 {
  if (m_pImage) delete m_pImage;
  if (m_pMask) delete m_pMask;

  m_pImage = m_pMask = NULL;

  if (ImageID)
   {
    m_pImage = new CBitmap;
    m_pImage->LoadBitmap(ImageID);

    BITMAP Bitmap;
    m_pImage->GetBitmap(&Bitmap);
    m_ImageW = Bitmap.bmWidth;
    m_ImageH = Bitmap.bmHeight;
   }
 
  if (MaskID)
   {
    m_pMask = new CBitmap;
    m_pMask->LoadBitmap(MaskID);
   }

  Invalidate();
 }

// --------------------------------------------------------------------------

void CAlarmButton::SetTextAlignment(UINT Alignment)
 {
  m_TextAlignment = Alignment;
  Invalidate();
 }

// --------------------------------------------------------------------------

void CAlarmButton::SetImageAlignment(UINT Alignment)
 {
  m_ImageAlignment = Alignment;
  Invalidate();
 }

// --------------------------------------------------------------------------

void CAlarmButton::HoldState(BOOL HoldState)
 {
  m_HoldState = HoldState;
 }

// --------------------------------------------------------------------------

BOOL CAlarmButton::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
 {
  BOOL rcCode = CButton::ModifyStyle(dwRemove,dwAdd,nFlags);

  Invalidate();

  return rcCode;
 }

// --------------------------------------------------------------------------

BEGIN_MESSAGE_MAP(CAlarmButton, CButton)
      //{{AFX_MSG_MAP(CAlarmButton)
      ON_WM_TIMER()
      ON_WM_LBUTTONDOWN()
      ON_WM_LBUTTONUP()
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAlarmButton message handlers

void CAlarmButton::OnTimer(UINT nIDEvent)
 {
  if (m_IsBackgroundFlashing)
   {
    m_IsBackgroundFlashing = FALSE;
    m_BackgroundColor = m_BackgroundColor2;
   }
  else {
        m_IsBackgroundFlashing = TRUE;
        m_BackgroundColor = m_BackgroundColor1;
       }

  Invalidate();
             
  CButton::OnTimer(nIDEvent);
 }

// --------------------------------------------------------------------------

void CAlarmButton::PreSubclassWindow()
 {
  CButton::PreSubclassWindow();
  ModifyStyle(0, BS_OWNERDRAW);
 }

// --------------------------------------------------------------------------

void CAlarmButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
 {
  ASSERT(lpDrawItemStruct != NULL);

  CDC   *pMemDC;
  int    Offset,
         X,
         Y;
  CDC   *pDC    = CDC::FromHandle(lpDrawItemStruct->hDC);
  CRect  Rect   = lpDrawItemStruct->rcItem;
  UINT   State  = lpDrawItemStruct->itemState;
  UINT   nStyle = GetStyle();

  pDC->SelectStockObject(NULL_BRUSH);
  pDC->FillSolidRect(Rect, m_BackgroundColor);

  // Draw the focus rectangle around the button
  if ((State & ODS_FOCUS))
   {
    CRect FocusRect(Rect.left + 4, Rect.top + 4, Rect.right - 4, Rect.bottom - 4);
    pDC->DrawFocusRect(FocusRect);
   }

  // Draw Bitmap if one
  if (m_pImage != NULL)
   {
    pMemDC = new CDC;
    pMemDC->CreateCompatibleDC(pDC);

    Offset = 0;
    if (State & ODS_SELECTED) Offset++;

    if ((m_ImageAlignment & HLEFT) == HLEFT) X = 4;
    else if ((m_ImageAlignment & HCENTER) == HCENTER) X = (Rect.Width()  - m_ImageW) / 2;
         else if ((m_ImageAlignment & HRIGHT) == HRIGHT) X = Rect.Width() - m_ImageW - 4;

    if ((m_ImageAlignment & VTOP) == VTOP) Y = 4;
    else if ((m_ImageAlignment & VCENTER) == VCENTER) Y = (Rect.Height() - m_ImageH) / 2;
         else if ((m_ImageAlignment & VBOTTOM) == VBOTTOM) Y = Rect.Height() - m_ImageH - 4;

    if (X < 0) X=0;
    if (Y < 0) Y=0;

    X += Offset;
    Y += Offset;

    if (m_pMask != NULL)
     {
      pMemDC->SelectObject(m_pMask);
      pDC->BitBlt(X,Y,m_ImageW,m_ImageH,pMemDC,0,0,SRCAND);
     }

    pMemDC->SelectObject(m_pImage);
    if (m_pMask != NULL) pDC->BitBlt(X,Y,m_ImageW,m_ImageH,pMemDC,0,0,SRCINVERT);
    else pDC->BitBlt(X,Y,m_ImageW,m_ImageH,pMemDC,0,0,SRCCOPY);

    delete pMemDC;
   }

  // Draw the raised/sunken edges of the button
  if (nStyle & BS_FLAT)
   {
    pDC->DrawEdge(Rect,EDGE_ETCHED, BF_RECT);
   }
  else {
        if ((State & ODS_SELECTED))
         {
          pDC->Draw3dRect(Rect,RGB(0,0,0),RGB(255,255,255));
         }
        else {
              pDC->Draw3dRect(Rect,RGB(255,255,255),RGB(0,0,0));
             }
       }

  // Draw the text if there is any
  CString strText;
  GetWindowText(strText);

  if (!strText.IsEmpty())
   {
    CSize  Extent = pDC->GetTextExtent(strText);
    CPoint Pt;
   
    if ((m_TextAlignment & HLEFT) == HLEFT) Pt.x = 4;
    else if ((m_TextAlignment & HCENTER) == HCENTER) Pt.x = (Rect.Width() - Extent.cx) / 2;
         else if ((m_TextAlignment & HRIGHT) == HRIGHT) Pt.x = Rect.Width() - Extent.cx - 4;

    if ((m_TextAlignment & VTOP) == VTOP) Pt.y = 4;
    else if ((m_TextAlignment & VCENTER) == VCENTER) Pt.y = (Rect.Height() - Extent.cy) / 2;
         else if ((m_TextAlignment & VBOTTOM) == VBOTTOM) Pt.y = Rect.Height() - Extent.cy - 4;

    if (State & ODS_SELECTED) Pt.Offset(1,1);

    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(m_TextColor);

    if (State & ODS_DISABLED)
     pDC->DrawState(Pt, Extent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
    else
     pDC->TextOut(Pt.x, Pt.y, strText);
   }
 }
0
Comment
Question by:mike_marquet
1 Comment
 
LVL 10

Accepted Solution

by:
RONSLOW earned 20 total points
ID: 1302264
Get the system time and calculate the time for the first interval to make it in sync with the system time (eg. flash every second).

So, when you turn the alarm on.  If the system time is 0.4s after the second, then set the inital timer for 0.6s.  When the timer goes off, change the color and repeat the process (work out the time required until the next whole second and set the timer again).



0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now