CScrollerButton Class Reference

This OIL class extends standard Windows bitmapped buttons so that they respond to clicks with the right mouse-button, and send notification messages as long as they are held down. More...

#include <scrlbutn.h>

List of all members.

Public Types

enum  Orientation { UP, DOWN, LEFT, RIGHT }

Public Member Functions

 CScrollerButton (Orientation ort, UINT32 msg)
 Constructs a CScrollerButton with the appropriate face.
virtual BOOL Create (LPCTSTR, DWORD style, const RECT &rect, CWnd *parent, UINT32 id)

Protected Member Functions

afx_msg void OnLButtonDown (UINT32 nFlags, CPoint point)
 We must override the default handling for push-buttons because scroll-bar buttons generate a sequence of messages until they are released, whilst normal buttons generate only one message when pressed. This member function passes the message on to HandleButtonDown() with a FALSE parameter.
afx_msg void OnLButtonUp (UINT32 nFlags, CPoint point)
 Passes message on to HandleButtonUp().
afx_msg void OnRButtonDown (UINT32 nFlags, CPoint point)
 We must override the default handling for push-buttons because Windows buttons do not respond to clicks with the right mouse-button. This member function passes the message on to HandleButtonDown() with a TRUE parameter, after calling CButton::SetState(TRUE) to "simulate" the button being clicked.
afx_msg void OnRButtonUp (UINT32 nFlags, CPoint point)
 Passes message on to HandleButtonUp(), after calling CButton::SetState(FALSE) to draw the button "undepressed".
afx_msg void OnTimer (UINT32 nIDEvent)
 Responds to the elapsed timer, set in HandleButtonDown(), by repeating the last "button-clicked" message sent to the parent CScroller. This allows the button to send a stream of messages until it is released - normally, Windows buttons send only one message per click.
afx_msg void OnCancelMode ()
 Sent by windows if the user hits ESCAPE or the dialog of another app. pops up in the middle of some mouse capturing. Gives this window a chance to release the captured mouse and kill any running timer.
afx_msg void OnLButtonDblClk (UINT32 nFlags, CPoint point)
 Calls CScrollerButton::OnLButtonDown(), to convert a double-click into a single click (MFC buttons don't normally respond to double-clicks).
afx_msg void OnRButtonDblClk (UINT32 nFlags, CPoint point)
 Calls CScrollerButton::OnRButtonDown(), to convert a double-click into a single click (MFC buttons don't normally respond to double-clicks).

Private Member Functions

virtual BOOL LoadOEMBitmaps (UINT32 upID, UINT32 downID, UINT32 disableID)
 Some display drivers, such as the ET4000, do not contain a "disabled" bitmap for scroll bars buttons. In this case the function substitutes the "up" bitmap for the "disabled" bitmap.
void HandleButtonDown (BOOL reverse)
 Captures the mouse, to guarantee receiving a button-up message some time in the future. Sets a timer in case that the button is held down and further messages must be processed (Windows buttons only send one notification message, no matter how long they are held down for). Sends a private "button clicked" message to the parent CScroller object.
void HandleButtonUp ()
 Releases the captured mouse and kills the timer set by HandleButtonDown().
void DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct)
BOOL PlotMaskedBitmap (CDC *destDC, CBitmap *srcBitmap, INT32 SrcOffset, INT32 xPlotOffset, INT32 yPlotOffset, INT32 width, INT32 height)

Private Attributes

Orientation Orient
BOOL Reversed
BOOL TimerOn
UINT32 Message

Static Private Attributes

static UINT32 BitmapNames [4][3]


Detailed Description

This OIL class extends standard Windows bitmapped buttons so that they respond to clicks with the right mouse-button, and send notification messages as long as they are held down.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago

Definition at line 135 of file scrlbutn.h.


Member Enumeration Documentation

enum CScrollerButton::Orientation
 

Enumerator:
UP 
DOWN 
LEFT 
RIGHT 

Definition at line 142 of file scrlbutn.h.

00143     {
00144         UP, DOWN, LEFT, RIGHT
00145     };


Constructor & Destructor Documentation

CScrollerButton::CScrollerButton CScrollerButton::Orientation  ort,
UINT32  msg
 

Constructs a CScrollerButton with the appropriate face.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
The orientation of the bitmap on the button's face, the message the button [INPUTS] button should send the CScroller parent when it is clicked.
- [OUTPUTS]
Returns:
-

Errors: ENSURE failure if, for any stupid reason, the orientation is invalid. Scope: Public

See also:
CScrollerButton::Create(); CScroller::OnCreate()

Definition at line 166 of file scrlbutn.cpp.

00167   : CBitmapButton(), Orient(ort), Message(msg)
00168 {
00169     // So far, very little to do here.
00170     ENSURE(ort >= CScrollerButton::UP && ort <= CScrollerButton::RIGHT,
00171            "Unknown orientation code passed to scroller button constructor!\n");
00172 }


Member Function Documentation

BOOL CScrollerButton::Create LPCTSTR  ,
DWORD  style,
const RECT rect,
CWnd *  parent,
UINT32  id
[virtual]
 

Definition at line 195 of file scrlbutn.cpp.

00197 {
00198     return CBitmapButton::Create("",
00199                                  style | WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD
00200                                  | BS_OWNERDRAW | BS_PUSHBUTTON,
00201                                  rect,
00202                                  parent,
00203                                  id)
00204         && LoadOEMBitmaps(BitmapNames[Orient][0],           // button up
00205                           BitmapNames[Orient][1],           // button down
00206                           BitmapNames[Orient][2]);          // disabled
00207 }

void CScrollerButton::DrawItem LPDRAWITEMSTRUCT  lpDrawItemStruct  )  [private]
 

Definition at line 657 of file scrlbutn.cpp.

00658 {
00659 
00660 
00661     ASSERT(lpDIS != NULL);
00662     // must have at least the first bitmap loaded before calling DrawItem
00663     ASSERT(m_bitmap.m_hObject != NULL);     // required
00664 
00665     // use the main bitmap for up, the selected bitmap for down
00666     CBitmap* pBitmap = &m_bitmap;
00667     UINT32 state = lpDIS->itemState;
00668     if ((state & ODS_SELECTED) && m_bitmapSel.m_hObject != NULL)
00669         pBitmap = &m_bitmapSel;
00670 
00671 #ifndef _MAC
00672     else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL)
00673 #else
00674     else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL &&
00675             (GetParent()->GetStyle() & DS_WINDOWSUI))
00676 #endif
00677         pBitmap = &m_bitmapFocus;   // third image for focused
00678     else if ((state & ODS_DISABLED) && m_bitmapDisabled.m_hObject != NULL)
00679         pBitmap = &m_bitmapDisabled;   // last image for disabled
00680 
00681     
00682 
00683     CDC* pDC = CDC::FromHandle(lpDIS->hDC);
00684     
00685     // New masked version
00686     //------------------------------------------------------------------------------
00687     CRect rect;
00688     rect.CopyRect(&lpDIS->rcItem);
00689     if(!IS_CHICAGO)  // UIC
00690     {
00691         // draw the whole button
00692         PlotMaskedBitmap(pDC,pBitmap,0,rect.left, rect.top, rect.Width(), rect.Height());
00693     }
00694     else
00695     { 
00696         UINT32 Flags =0;
00697         switch(Orient)
00698         {
00699         case UP:
00700             Flags = DFCS_SCROLLUP;
00701             break;
00702         case DOWN:
00703             Flags = DFCS_SCROLLDOWN;
00704             break;
00705         case LEFT:
00706             Flags = DFCS_SCROLLLEFT;
00707             break;
00708         case RIGHT:
00709             Flags = DFCS_SCROLLRIGHT;
00710             break;
00711         }
00712         if (state & ODS_SELECTED)
00713             Flags |= DFCS_PUSHED;
00714 
00715         pDC->DrawFrameControl(&rect,DFC_SCROLL, Flags);
00716     }
00717 
00718 
00719     //-------------------------------------------------------------------------------
00720     
00721     // Old "scrcopy" version
00722     //-------------------------------------------------------------------------------
00723     /*
00724     CDC memDC;
00725     memDC.CreateCompatibleDC(pDC);
00726     CBitmap* pOld = memDC.SelectObject(pBitmap);
00727     if (pOld == NULL)
00728         return;     // destructors will clean up
00729 
00730     CRect rect;
00731     rect.CopyRect(&lpDIS->rcItem);
00732     pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
00733         &memDC, 0, 0, SRCCOPY);
00734 
00735     memDC.SelectObject(pOld);
00736     */
00737     //-------------------------------------------------------------------------------
00738 }

void CScrollerButton::HandleButtonDown BOOL  reverse  )  [private]
 

Captures the mouse, to guarantee receiving a button-up message some time in the future. Sets a timer in case that the button is held down and further messages must be processed (Windows buttons only send one notification message, no matter how long they are held down for). Sends a private "button clicked" message to the parent CScroller object.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
A boolean which if TRUE indicates that the button is responding to a click [INPUTS] with the right mouse button, so the scroll is in the opposite direction.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Private

See also:
CScrollerButton::HandleButtonUp(); CScrollerButton::OnLButtonDown(); CScrollerButton::OnRButtonDown(); CScrollerButton::OnTimer() CScroller::OnDecBtnClicked(); CScroller::OnIncBtnClicked()

Definition at line 276 of file scrlbutn.cpp.

00277 {
00278     // On the initial click, we set up an auto-repeat timer to start after the configured
00279     // keyboard auto-repeat delay
00280     UINT32 CallbackTime = 1000;
00281     UINT32 RepsPerSec;
00282 
00283     ::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &RepsPerSec, 0);
00284     RepsPerSec = 4 - RepsPerSec;
00285     if (RepsPerSec > 1)
00286         CallbackTime = (UINT32) 1000 / RepsPerSec;
00287 
00288     TimerOn = ::FixSetTimer(m_hWnd, 3, CallbackTime, 0);
00289 
00290     #ifdef  _DEBUG
00291         if (!TimerOn)
00292             TRACE( _T("Unable to allocate a timer in CScrollerButton::HandleButtonDown()!\n"));
00293     #endif  // _DEBUG
00294 
00295     SetCapture();
00296     GetParent()->SendMessage(Message, WPARAM(Reversed = reverse));
00297     SetState(TRUE);
00298 }

void CScrollerButton::HandleButtonUp  )  [private]
 

Releases the captured mouse and kills the timer set by HandleButtonDown().

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: - Scope: Private

See also:
CScrollerButton::HandleButtonDown(); CScrollerButton::OnLButtonUp(); CScrollerButton::OnRButtonUp(); CScrollerButton::OnTimer()

Definition at line 317 of file scrlbutn.cpp.

00318 {
00319     ReleaseCapture();
00320     if (TimerOn)
00321     {
00322         ::FixKillTimer(m_hWnd, 3);
00323         TimerOn = FALSE;
00324     }
00325     SetState(FALSE);
00326 
00327     // tell people things have changed on screen
00328     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
00329 }

BOOL CScrollerButton::LoadOEMBitmaps UINT32  upID,
UINT32  downID,
UINT32  disableID
[private, virtual]
 

Some display drivers, such as the ET4000, do not contain a "disabled" bitmap for scroll bars buttons. In this case the function substitutes the "up" bitmap for the "disabled" bitmap.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
The resource identifier of the bitmap displayed on the button when it is [INPUTS] "up", ie. not clicked; the ID of the "down" bitmap; the ID of the "disabled" bitmap.
- [OUTPUTS]
Returns:
TRUE if the bitmaps are successfully extracted from the display driver, FALSE if some essential bitmaps cannot be extracted.

Errors: - Scope: Private

See also:
CScrollerButton::Create()

Definition at line 230 of file scrlbutn.cpp.

00231 {
00232     m_bitmap.DeleteObject();
00233     m_bitmapSel.DeleteObject();
00234     m_bitmapDisabled.DeleteObject();
00235 
00236 #ifndef _MAC
00237     // The up/down bitmaps are essential and must be present.
00238     if (!m_bitmap.LoadOEMBitmap(upID) || !m_bitmapSel.LoadOEMBitmap(downID))
00239         return FALSE;
00240     
00241     // The disabled bitmap is not essential, and if not present, the up
00242     // bitmap can be substituted for it.
00243     if (!m_bitmapDisabled.LoadOEMBitmap(disableID))
00244         m_bitmapDisabled.LoadOEMBitmap(upID);
00245 #endif
00246     return TRUE;
00247 }

void CScrollerButton::OnCancelMode  )  [protected]
 

Sent by windows if the user hits ESCAPE or the dialog of another app. pops up in the middle of some mouse capturing. Gives this window a chance to release the captured mouse and kill any running timer.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonDown(); CScrollerButton::OnTimer(); CScrollerButton::HandleButtonUp()

Definition at line 535 of file scrlbutn.cpp.

00536 {
00537     CBitmapButton::OnCancelMode();
00538     if (TimerOn) HandleButtonUp();
00539 }

void CScrollerButton::OnLButtonDblClk UINT32  nFlags,
CPoint  point
[protected]
 

Calls CScrollerButton::OnLButtonDown(), to convert a double-click into a single click (MFC buttons don't normally respond to double-clicks).

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::OnLButtonDown(); CScrollerButton::OnRButtonDblClk()

Definition at line 452 of file scrlbutn.cpp.

00453 {
00454     OnLButtonDown(nFlags, point);
00455 }

void CScrollerButton::OnLButtonDown UINT32  nFlags,
CPoint  point
[protected]
 

We must override the default handling for push-buttons because scroll-bar buttons generate a sequence of messages until they are released, whilst normal buttons generate only one message when pressed. This member function passes the message on to HandleButtonDown() with a FALSE parameter.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonDown(); CScrollerButton::OnLButtonUp()

Definition at line 354 of file scrlbutn.cpp.

00355 {
00356     CBitmapButton::OnLButtonDown(nFlags, point);
00357     HandleButtonDown(FALSE);
00358 }

void CScrollerButton::OnLButtonUp UINT32  nFlags,
CPoint  point
[protected]
 

Passes message on to HandleButtonUp().

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonUp(); CScrollerButton::OnLButtonDown()

Definition at line 377 of file scrlbutn.cpp.

00378 {
00379     CBitmapButton::OnLButtonUp(nFlags, point);
00380     SetState(FALSE);
00381     HandleButtonUp();
00382 }

void CScrollerButton::OnRButtonDblClk UINT32  nFlags,
CPoint  point
[protected]
 

Calls CScrollerButton::OnRButtonDown(), to convert a double-click into a single click (MFC buttons don't normally respond to double-clicks).

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::OnRButtonDown(); CScrollerButton::OnLButtonDblClk()

Definition at line 475 of file scrlbutn.cpp.

00476 {
00477     OnRButtonDown(nFlags, point);
00478 }

void CScrollerButton::OnRButtonDown UINT32  nFlags,
CPoint  point
[protected]
 

We must override the default handling for push-buttons because Windows buttons do not respond to clicks with the right mouse-button. This member function passes the message on to HandleButtonDown() with a TRUE parameter, after calling CButton::SetState(TRUE) to "simulate" the button being clicked.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonDown(); CScrollerButton::OnRButtonUp()

Definition at line 404 of file scrlbutn.cpp.

00405 {
00406     SetState(TRUE);
00407     HandleButtonDown(TRUE);
00408 }

void CScrollerButton::OnRButtonUp UINT32  nFlags,
CPoint  point
[protected]
 

Passes message on to HandleButtonUp(), after calling CButton::SetState(FALSE) to draw the button "undepressed".

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
Some flags detailing which buttons and keys were down when the mouse message [INPUTS] was generated; the coordinates of the mouse cursor.
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonUp(); CScrollerButton::OnRButtonDown()

Definition at line 428 of file scrlbutn.cpp.

00429 {
00430     SetState(FALSE);
00431     HandleButtonUp();
00432 }

void CScrollerButton::OnTimer UINT32  nIDEvent  )  [protected]
 

Responds to the elapsed timer, set in HandleButtonDown(), by repeating the last "button-clicked" message sent to the parent CScroller. This allows the button to send a stream of messages until it is released - normally, Windows buttons send only one message per click.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
ages ago
Parameters:
The timer's numeric identifier (not used). [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: - Scope: Protected

See also:
CScrollerButton::HandleButtonDown(); CScrollerButton::HandleButtonUp()

Definition at line 499 of file scrlbutn.cpp.

00500 {
00501     // This checks for auto-repeat on the scroll button at the keyboard auto-repeat rate
00502     UINT32 CallbackTime = 1000;
00503     UINT32 RepsPerSec;
00504 
00505     ::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &RepsPerSec, 0);
00506     CallbackTime = (UINT32) 1000 / (RepsPerSec + 1);
00507     TimerOn = ::FixSetTimer(m_hWnd, 3, CallbackTime, 0);
00508 
00509 #ifdef  _DEBUG
00510     if (!TimerOn) TRACE( _T("Unable to allocate a timer in CScrollerButton::OnTimer()!\n"));
00511 #endif  // _DEBUG
00512 
00513     GetParent()->SendMessage(Message, WPARAM(Reversed));
00514 }

BOOL CScrollerButton::PlotMaskedBitmap CDC destDC,
CBitmap *  srcBitmap,
INT32  SrcOffset,
INT32  xPlotOffset,
INT32  yPlotOffset,
INT32  width,
INT32  height
[private]
 

Definition at line 594 of file scrlbutn.cpp.

00596 {
00597     
00598     ERROR2IF(srcBitmap == NULL,FALSE,"NULL Bitmap in PlotMaskedBitmap()");
00599     ERROR2IF(destDC == NULL,FALSE,"NULL DC in PlotMaskedBitmap()");
00600 
00601     // always fill the entire background with BTNFACE to make sure we don't
00602     // miss any pixels 
00603 
00604     PatB(destDC, 0, 0, width, height, GetSysColor(COLOR_BTNFACE));
00605     
00606     // create a screen dc
00607     CDC scrDC ;
00608     scrDC.CreateCompatibleDC(destDC);
00609     
00610     // and select the bitmap into it
00611     CBitmap* OldSrcBitmap = (CBitmap *) scrDC.SelectObject(srcBitmap);
00612 
00613     // create a mask for the button glyph... First a DC
00614     CDC hDCMono ;
00615     hDCMono.CreateCompatibleDC(NULL);
00616 
00617     // create a mono bitmap for the mask
00618     CBitmap hbmMono ; 
00619     hbmMono.CreateBitmap(width, height, 1, 1, NULL);
00620     
00621     CBitmap * oldmonobitmap = (CBitmap *)hDCMono.SelectObject(&hbmMono);
00622 
00623     // initalize the bitmapto white (all 1's)
00624     hDCMono.PatBlt(0, 0, width, height, WHITENESS);
00625 
00626     // plot all non-lightgrey  pixels in the glyph as black in our mask
00627     scrDC.SetBkColor( RGB(192,192,192));
00628     hDCMono.BitBlt(xPlotOffset,yPlotOffset, width, height, &scrDC,
00629             SrcOffset, 0, SRCCOPY);
00630 
00631     destDC->SetTextColor(0L);                  // 0's in mono -> 0 (for ROP)
00632     destDC->SetBkColor((COLORREF)0x00FFFFFFL); // 1's in mono -> 1
00633 
00634     // plot the glyph 
00635     destDC->BitBlt( xPlotOffset, yPlotOffset, width, height,
00636                     &scrDC, SrcOffset, 0, SRCCOPY);
00637         
00638     // fill with the normal BTNFACE colour
00639     CBrush HighlightBrush ; 
00640     HighlightBrush.CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
00641 
00642     CBrush* hbrOld = (CBrush *) destDC->SelectObject(&HighlightBrush);
00643     if (hbrOld != NULL)
00644     {
00645         // draw highlight color where we have 0's in the mask
00646         destDC->BitBlt( xPlotOffset,yPlotOffset, width, height,  &hDCMono, 0, 0, ROP_DSPDxax);
00647         destDC->SelectObject(hbrOld);
00648     }
00649     
00650     // clean up DC's
00651     hDCMono.SelectObject(oldmonobitmap);
00652     scrDC.SelectObject(OldSrcBitmap);
00653     return TRUE;
00654 }


Member Data Documentation

UINT32 CScrollerButton::BitmapNames [static, private]
 

Initial value:

 
{
      { OBM_UPARROW,    OBM_UPARROWD,   OBM_UPARROWI },
      { OBM_DNARROW,    OBM_DNARROWD,   OBM_DNARROWI },
      { OBM_LFARROW,    OBM_LFARROWD,   OBM_LFARROWI },
      { OBM_RGARROW,    OBM_RGARROWD,   OBM_RGARROWI }
}

Definition at line 149 of file scrlbutn.h.

UINT32 CScrollerButton::Message [private]
 

Definition at line 154 of file scrlbutn.h.

Orientation CScrollerButton::Orient [private]
 

Definition at line 151 of file scrlbutn.h.

BOOL CScrollerButton::Reversed [private]
 

Definition at line 152 of file scrlbutn.h.

BOOL CScrollerButton::TimerOn [private]
 

Definition at line 153 of file scrlbutn.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:53:16 2007 for Camelot by  doxygen 1.4.4