Solved

Background button flashing ...

Posted on 1998-04-25
1
438 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
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.
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

730 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