Solved

Background button flashing ...

Posted on 1998-04-25
1
437 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying 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

Title # Comments Views Activity
Turn a spreadsheet into a vba executable. 2 92
Expand to include initial dialog with two choices. 9 80
centeredAverage challenge 8 179
wait notify demo infinite loop 3 122
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
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.
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

856 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