Introduction
The CInputEvent
class manages mouse events. It updates a data structure which is available DrawItem or OnPaint methods to allow you to draw control at with the correct visual state.
Using the code
This class avoids the use of all the methods usually used to get the button state. The Button class doesn't need all the OnLButtonDown
, OnMouseMove
, etc. methods anymore Also, all the usual m_OverTracking
, m_ButtonDown
, TrackMouseEvent
etc. are not necessary in the derived CWnd
class (button, static, etc...).
The data structure is updated for each of these received messages. When the button needs to be drawn, say in the DrawItem() method, you just need to get the button status and then draw the corresponding bitmap or text or what ever you want.
To Use
Declare a pointer to a CInputEvent
data :
CInputEvent* m_pInputEvent;
Init this data once the CWnd button is created, in the
PreSubclassWindow
.
void CMyButton::PreSubclassWindow()
{
m_pInputEvent = new CInputEvent(this);
CButton::PreSubclassWindow();
}
Filter the Windows Message in PreTranslateMessage(MSG* pMsg)
. This will fill a data structure which updates the button state.
The CInputEvent
class will filter the messages:
WM_MOUSEMOVE
WM_MOUSELEAVE
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
BOOL CMyButton::PreTranslateMessage(MSG* pMsg)
{
m_pInputEvent->RelayMsg(pMsg);
return CButton::PreTranslateMessage(pMsg);
}
In the DrawItem
method, get the InputStatus
sructure. This structure contains the button state, the client rect (CRect
), the mouse coords, the status of the ctrl and shift keys and other mouse buttons.
Here is the code used in the demo :
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CInputEvent::INPUTSTATUS ips;
m_pInputEvent->GetStatus(&ips);
CString str;
CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
if (lpDrawItemStruct->itemState & ODS_DISABLED)
{
str="Disabled";
}
else
{
switch (ips.drawPosition)
{
case 1:
str="Normal";
break;
case 2:
str="Over";
break;
case 3:
str="Pushed";
break;
}
}
pDC->FillSolidRect(&ips.rect, RGB(100,200,255));
pDC->DrawText(str, &ips.rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
Note that the disabled state is not managed since the button is disabled before receiving the
WM_ENABLE
message. So I use the
DrawItem
Structure to get this info. I could use
WindowProc
method but it receives messages from other controls.
Delete the CInputEvent
data in the button destructor.
CMyButton::~CMyButton()
{
delete m_pInputEvent;
}
Points of Interest
Using this class avoids to overload an Ownerdraw button class or a graphical static responding to mouse.
The other point is the windows message filtering. The class can manage any of the received messages. It becomes easy to add Wheel mouse, right click, keyboard input etc.. to manage the drawing of any control.