445 lines
12 KiB
C++
445 lines
12 KiB
C++
#include "stdafx.h"
|
|
#include "Ctrl.h"
|
|
#include "SmCheckBox.h"
|
|
|
|
#if ENABLE_MSGTABLE_API
|
|
|
|
/***************************************************************************\
|
|
*****************************************************************************
|
|
*
|
|
* class SmCheckBox
|
|
*
|
|
*****************************************************************************
|
|
\***************************************************************************/
|
|
|
|
const SIZE SIZE_Box = {13, 13};
|
|
|
|
HFONT SmCheckBox::s_hfntCheck = NULL;
|
|
HFONT SmCheckBox::s_hfntText = NULL;
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiOnEvent(EventMsg * pmsg)
|
|
{
|
|
switch (GET_EVENT_DEST(pmsg))
|
|
{
|
|
case GMF_DIRECT:
|
|
case GMF_EVENT:
|
|
switch (pmsg->nMsg)
|
|
{
|
|
case GM_PAINT:
|
|
{
|
|
GMSG_PAINT * pmsgPaint = (GMSG_PAINT *) pmsg;
|
|
if (pmsgPaint->nCmd == GPAINT_RENDER) {
|
|
switch (pmsgPaint->nSurfaceType)
|
|
{
|
|
case GSURFACE_HDC:
|
|
{
|
|
GMSG_PAINTRENDERI * pmsgR = (GMSG_PAINTRENDERI *) pmsgPaint;
|
|
OnDraw(pmsgR->hdc, pmsgR);
|
|
}
|
|
break;
|
|
|
|
case GSURFACE_GPGRAPHICS:
|
|
{
|
|
GMSG_PAINTRENDERF * pmsgR = (GMSG_PAINTRENDERF *) pmsgPaint;
|
|
OnDraw(pmsgR->pgpgr, pmsgR);
|
|
}
|
|
break;
|
|
default:
|
|
Trace("WARNING: Unknown surface type\n");
|
|
}
|
|
|
|
return DU_S_PARTIAL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GM_CHANGERECT:
|
|
{
|
|
GMSG_CHANGERECT * pmsgR = (GMSG_CHANGERECT *) pmsg;
|
|
if (TestFlag(pmsgR->nFlags, SGR_SIZE)) {
|
|
ComputeLayout();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GM_INPUT:
|
|
{
|
|
MouseDown:
|
|
GMSG_INPUT * pmsgI = (GMSG_INPUT *) pmsg;
|
|
if (pmsgI->nDevice == GINPUT_MOUSE) {
|
|
GMSG_MOUSE * pmsgM = (GMSG_MOUSE *) pmsgI;
|
|
if (pmsgM->nCode == GMOUSE_DOWN) {
|
|
return OnMouseDown(pmsgM);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GM_CHANGESTATE:
|
|
{
|
|
ChangeState:
|
|
GMSG_CHANGESTATE * pmsgS = (GMSG_CHANGESTATE *) pmsg;
|
|
switch (pmsgS->nCode)
|
|
{
|
|
case GSTATE_KEYBOARDFOCUS:
|
|
SetKeyboardFocus(pmsgS->nCmd == GSC_SET);
|
|
return DU_S_PARTIAL;
|
|
|
|
#if TEST_MOUSEFOCUS
|
|
case GSTATE_MOUSEFOCUS:
|
|
SetMouseFocus(pmsgS->nCmd == GSC_SET);
|
|
return DU_S_PARTIAL;
|
|
#endif // TEST_MOUSEFOCUS
|
|
}
|
|
}
|
|
break;
|
|
case GM_QUERY:
|
|
{
|
|
GMSG_QUERY * pmsgQ = (GMSG_QUERY *) pmsg;
|
|
switch (pmsgQ->nCode)
|
|
{
|
|
case GQUERY_DESCRIPTION:
|
|
{
|
|
GMSG_QUERYDESC * pmsgQD = (GMSG_QUERYDESC *) pmsg;
|
|
CopyString(pmsgQD->szType, L"SmCheckBox", _countof(pmsgQD->szType));
|
|
return DU_S_COMPLETE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case GMF_ROUTED:
|
|
//
|
|
// Routed message before handled by control.
|
|
//
|
|
|
|
switch (pmsg->nMsg)
|
|
{
|
|
case GM_CHANGESTATE:
|
|
//
|
|
// When focus changes for the checkbox or one of its children,
|
|
// the checkbox wants to know.
|
|
//
|
|
goto ChangeState;
|
|
}
|
|
break;
|
|
|
|
case GMF_BUBBLED:
|
|
//
|
|
// Bubbled message not handled by control
|
|
//
|
|
|
|
switch (pmsg->nMsg)
|
|
{
|
|
case GM_INPUT:
|
|
goto MouseDown;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return SVisual::ApiOnEvent(pmsg);
|
|
}
|
|
|
|
|
|
inline bool
|
|
PtInBox(int cx, int cy, POINT & pt)
|
|
{
|
|
return (pt.x <= cx) && (pt.y <= cy) && (pt.x >= 0) && (pt.y >= 0);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
UINT
|
|
SmCheckBox::OnMouseDown(GMSG_MOUSE * pmsg)
|
|
{
|
|
if (pmsg->bButton == GBUTTON_LEFT) {
|
|
if (((GET_EVENT_DEST(pmsg) == GMF_DIRECT) && PtInRect(&m_rcCheckPxl, pmsg->ptClientPxl)) ||
|
|
PtInBox(m_rcItemPxl.right, m_rcItemPxl.bottom, pmsg->ptClientPxl)) {
|
|
|
|
m_bChecked++;
|
|
if (m_bChecked > GetMaxCheck()) {
|
|
m_bChecked = 0;
|
|
}
|
|
GetStub()->Invalidate();
|
|
|
|
return DU_S_COMPLETE;
|
|
}
|
|
}
|
|
|
|
return DU_S_NOTHANDLED;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
SmCheckBox::OnDraw(HDC hdc, GMSG_PAINTRENDERI * pmsgR)
|
|
{
|
|
UNREFERENCED_PARAMETER(pmsgR);
|
|
|
|
HFONT hfntOld = (HFONT) SelectObject(hdc, s_hfntCheck);
|
|
COLORREF crOld = SetTextColor(hdc, m_crCheckBox);
|
|
int nOldMode = 0;
|
|
|
|
RECT rcDraw = m_rcCheckPxl;
|
|
OffsetRect(&rcDraw, pmsgR->prcGadgetPxl->left, pmsgR->prcGadgetPxl->top);
|
|
|
|
WCHAR * pszCheck;
|
|
switch (m_bChecked)
|
|
{
|
|
default:
|
|
case CheckBoxGadget::csUnchecked:
|
|
pszCheck = NULL;
|
|
break;
|
|
|
|
case CheckBoxGadget::csChecked:
|
|
pszCheck = L"a";
|
|
nOldMode = SetBkMode(hdc, TRANSPARENT);
|
|
break;
|
|
|
|
case CheckBoxGadget::csUnknown:
|
|
pszCheck = L"a";
|
|
nOldMode = SetBkMode(hdc, OPAQUE);
|
|
SetBkColor(hdc, RGB(223, 223, 223));
|
|
break;
|
|
}
|
|
|
|
if (pszCheck != NULL) {
|
|
OS()->TextOut(hdc, rcDraw.left - 1, rcDraw.top, pszCheck, 1);
|
|
}
|
|
|
|
DrawEdge(hdc, &rcDraw, EDGE_SUNKEN, BF_RECT);
|
|
|
|
switch (m_bChecked)
|
|
{
|
|
case CheckBoxGadget::csChecked:
|
|
case CheckBoxGadget::csUnknown:
|
|
SetBkMode(hdc, nOldMode);
|
|
break;
|
|
}
|
|
|
|
SetTextColor(hdc, crOld);
|
|
SelectObject(hdc, hfntOld);
|
|
|
|
if (m_fKeyboardFocus) {
|
|
RECT rcItem = m_rcItemPxl;
|
|
OffsetRect(&rcItem, pmsgR->prcGadgetPxl->left, pmsgR->prcGadgetPxl->top);
|
|
InflateRect(&rcItem, 2, 1);
|
|
DrawFocusRect(hdc, &rcItem);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
SmCheckBox::OnDraw(Gdiplus::Graphics * pgpgr, GMSG_PAINTRENDERF * pmsgR)
|
|
{
|
|
UNREFERENCED_PARAMETER(pmsgR);
|
|
|
|
Gdiplus::Color cr(GetRValue(m_crCheckBox), GetGValue(m_crCheckBox), GetBValue(m_crCheckBox));
|
|
Gdiplus::SolidBrush br(cr);
|
|
Gdiplus::Font fnt(L"Marlett", 8.0f, Gdiplus::FontStyleRegular, Gdiplus::UnitPoint);
|
|
Gdiplus::RectF rc(
|
|
(float) m_rcCheckPxl.left,
|
|
(float) m_rcCheckPxl.top,
|
|
(float) (m_rcCheckPxl.right - m_rcCheckPxl.left),
|
|
(float) (m_rcCheckPxl.bottom - m_rcCheckPxl.top));
|
|
rc.Offset((float) pmsgR->prcGadgetPxl->X, (float) pmsgR->prcGadgetPxl->Y);
|
|
|
|
WCHAR * pszCheck;
|
|
switch (m_bChecked)
|
|
{
|
|
default:
|
|
case CheckBoxGadget::csUnchecked:
|
|
pszCheck = NULL;
|
|
break;
|
|
|
|
case CheckBoxGadget::csChecked:
|
|
pszCheck = L"\xf061";
|
|
break;
|
|
|
|
case CheckBoxGadget::csUnknown:
|
|
pszCheck = L"\xf061";
|
|
break;
|
|
}
|
|
|
|
if (pszCheck != NULL) {
|
|
pgpgr->DrawString(pszCheck, 1, &fnt, rc, 0, &br);
|
|
}
|
|
|
|
if (m_fKeyboardFocus) {
|
|
Gdiplus::RectF rcItem(
|
|
(float) m_rcItemPxl.left,
|
|
(float) m_rcItemPxl.top,
|
|
(float) (m_rcItemPxl.right - m_rcItemPxl.left),
|
|
(float) (m_rcItemPxl.bottom - m_rcItemPxl.top));
|
|
rcItem.Offset(pmsgR->prcGadgetPxl->X, pmsgR->prcGadgetPxl->Y);
|
|
rcItem.Inflate(2.0f, 1.0f);
|
|
|
|
Gdiplus::Pen pen(cr);
|
|
pgpgr->DrawRectangle(&pen, rcItem);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiGetColor(CheckBoxGadget::GetColorMsg * pmsg)
|
|
{
|
|
pmsg->crCheckBox = m_crCheckBox;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiSetColor(CheckBoxGadget::SetColorMsg * pmsg)
|
|
{
|
|
m_crCheckBox = pmsg->crCheckBox;
|
|
GetStub()->Invalidate();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiGetCheck(CheckBoxGadget::GetCheckMsg * pmsg)
|
|
{
|
|
pmsg->nCheck = m_bChecked;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiSetCheck(CheckBoxGadget::SetCheckMsg * pmsg)
|
|
{
|
|
if (pmsg->nCheck <= GetMaxCheck()) {
|
|
m_bChecked = (BYTE) pmsg->nCheck;
|
|
GetStub()->Invalidate();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiGetType(CheckBoxGadget::GetTypeMsg * pmsg)
|
|
{
|
|
pmsg->nType = m_bType;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiSetType(CheckBoxGadget::SetTypeMsg * pmsg)
|
|
{
|
|
if (pmsg->nType <= CheckBoxGadget::ctMax) {
|
|
m_bType = (BYTE) pmsg->nType;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiGetItem(CheckBoxGadget::GetItemMsg * pmsg)
|
|
{
|
|
pmsg->pgvItem = m_pgvItem;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiSetItem(CheckBoxGadget::SetItemMsg * pmsg)
|
|
{
|
|
AssertMsg(m_pgvItem == NULL, "TODO: Destroy existing item");
|
|
|
|
m_pgvItem = pmsg->pgvItem;
|
|
|
|
if (m_pgvItem != NULL) {
|
|
ComputeLayout();
|
|
}
|
|
|
|
m_fText = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
SmCheckBox::ApiSetText(CheckBoxGadget::SetTextMsg * pmsg)
|
|
{
|
|
TextGadget * pgvText = NULL;
|
|
if (!m_fText) {
|
|
AssertMsg(m_pgvItem == NULL, "TODO: Destroy existing item");
|
|
|
|
pgvText = BuildVisual<TextGadget>((Visual *) m_pgad);
|
|
m_pgvItem = pgvText;
|
|
if (m_pgvItem == NULL) {
|
|
return S_OK;
|
|
}
|
|
|
|
m_fText = TRUE;
|
|
} else {
|
|
pgvText = (TextGadget *) m_pgvItem;
|
|
}
|
|
|
|
AssertMsg(m_pgvItem != NULL, "Must have valid TextGadget by now");
|
|
|
|
if (s_hfntText == NULL) {
|
|
s_hfntText = UtilBuildFont(L"Tahoma", 85, FS_NORMAL);
|
|
}
|
|
|
|
pgvText->SetAutoSize(TRUE);
|
|
pgvText->SetFont(s_hfntText);
|
|
pgvText->SetText(pmsg->pszText);
|
|
pgvText->SetColor(RGB(0, 0, 128));
|
|
|
|
ComputeLayout();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void
|
|
SmCheckBox::ComputeLayout()
|
|
{
|
|
SIZE sizePxl;
|
|
GetStub()->GetSize(&sizePxl);
|
|
int nHeight = sizePxl.cy;
|
|
|
|
if (m_pgvItem != NULL) {
|
|
SIZE sizeBound, sizeBorderPxl;
|
|
sizeBound.cx = sizePxl.cx - (SIZE_Box.cx + 4 + 4);
|
|
sizeBound.cy = sizePxl.cy - 2;
|
|
sizeBorderPxl.cx = SIZE_Box.cx + 4;
|
|
sizeBorderPxl.cy = (sizePxl.cy - sizeBound.cy) / 2;
|
|
|
|
m_pgvItem->SetRect(SGR_MOVE | SGR_SIZE | SGR_PARENT | SGR_NOINVALIDATE,
|
|
sizeBorderPxl.cx, sizeBorderPxl.cy, sizeBound.cx, sizeBound.cy);
|
|
|
|
m_rcItemPxl.left = sizeBorderPxl.cx;
|
|
m_rcItemPxl.top = sizeBorderPxl.cy;
|
|
m_rcItemPxl.right = m_rcItemPxl.left + sizeBound.cx;
|
|
m_rcItemPxl.bottom = m_rcItemPxl.top + sizeBound.cy;
|
|
}
|
|
|
|
m_rcCheckPxl.left = 0;
|
|
m_rcCheckPxl.top = (nHeight - SIZE_Box.cy) / 2;
|
|
m_rcCheckPxl.right = m_rcCheckPxl.left + SIZE_Box.cx;
|
|
m_rcCheckPxl.bottom = m_rcCheckPxl.top + SIZE_Box.cy;
|
|
}
|
|
|
|
#endif // ENABLE_MSGTABLE_API
|