Windows NT 4.0 source code leak
 
 
 
 
 
 

519 lines
11 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1995 **/
/**********************************************************************/
/*
FILE HISTORY:
*/
//
// CSpinControl -- a spin control edit box
//
#define OEMRESOURCE
#include "stdafx.h"
#include "COMMON.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
CSpinBox::CSpinBox(
int nMin,
int nMax,
int nButtonId,
EDITTYPE nType,
BOOL fLeadingZero
)
: m_nMin(nMin), m_nMax(nMax), m_nButtonId(nButtonId),
m_etType(nType), m_fLeadingZero(fLeadingZero)
{
}
BOOL
CSpinBox::SubclassDlgItem(
UINT nID,
CWnd *pParent
)
{
m_button_Spin.SubclassDlgItem(m_nButtonId, pParent);
m_button_Spin.Associate(this);
BOOL f = CEdit::SubclassDlgItem(nID, pParent);
//
// Set maximum character width allowed in listbox.
//
int nMaxDigits = 1;
int n = m_nMax;
while ( n > 9 )
{
++nMaxDigits;
n /= 10;
}
LimitText(nMaxDigits);
return f;
}
BOOL
CSpinBox::EnableWindow(
BOOL bEnable
)
{
m_button_Spin.EnableWindow(bEnable);
return CEdit::EnableWindow(bEnable);
}
void
CSpinBox::OnBadInput()
{
::MessageBeep(MB_ICONEXCLAMATION);
}
BEGIN_MESSAGE_MAP(CSpinBox, CEdit)
ON_WM_CHAR()
END_MESSAGE_MAP()
void
CSpinBox::SetValue(
int nValue
)
{
CHAR sz[256];
//
// If this is a time control, only show the remaindered
// portion of the value
//
switch(m_etType)
{
case enumNormal:
break;
case enumSeconds:
nValue %= 60;
break;
case enumMinutes:
nValue = (nValue / 60) % 60;
break;
case enumMinutesHigh:
nValue /= 60;
break;
case enumHours:
nValue = (nValue / (60 * 60)) % 24;
break;
case enumHoursHigh:
nValue /= (60 * 60);
break;
case enumDays:
nValue = (nValue / (24 * 60 * 60)) % 30;
break;
case enumDaysHigh:
nValue /= (24 * 60 * 60);
break;
}
::wsprintf ( sz, m_fLeadingZero ? "%02d" : "%d", nValue);
SetWindowText(sz);
}
BOOL
CSpinBox::GetValue(
int &nValue
)
{
CHAR sz[256];
GetWindowText(sz, sizeof sz);
nValue = ::atoi(sz);
if (nValue < m_nMin || nValue > m_nMax)
{
//
// Highlight bad value
//
SetSel(0,-1);
SetFocus();
return(FALSE);
}
//
// If this is a time control, convert the value
// to seconds.
//
switch(m_etType)
{
case enumNormal:
break;
case enumSeconds:
break;
case enumMinutes:
case enumMinutesHigh:
nValue *= 60;
break;
case enumHours:
case enumHoursHigh:
nValue *= (60 * 60);
break;
case enumDays:
case enumDaysHigh:
nValue *= (24 * 60 * 60);
break;
}
return(TRUE);
}
void
CSpinBox::IncreaseContent(
int nDelta
)
{
int n;
CHAR sz[256];
GetWindowText(sz, sizeof sz);
n = ::atoi(sz);
//
// Adjust values that have gotten out
// of range.
//
if (n < m_nMin)
{
n = m_nMin;
}
else if (n > m_nMax)
{
n = m_nMax;
}
n += nDelta;
if (n >= m_nMin && n <= m_nMax)
{
::wsprintf ( sz, m_fLeadingZero ? "%02d" : "%d", n);
SetWindowText(sz);
}
else
{
OnBadInput();
}
}
// Validate char
void
CSpinBox::OnChar(
UINT nChar,
UINT nRepCnt,
UINT nFlags
)
{
//
// Filter out undesirable characters
//
if (nChar < 0x20 || (nChar >= '0' && nChar <= '9'))
{
CEdit::OnChar(nChar, nRepCnt, nFlags); // permitted
//
// Now make sure min/max have not been exceeded
//
int n;
CHAR sz[256];
GetWindowText(sz, sizeof sz);
n = ::atoi(sz);
if (n < m_nMin)
{
::wsprintf ( sz, m_fLeadingZero ? "%02d" : "%d", m_nMin);
SetWindowText(sz);
OnBadInput();
}
else if (n > m_nMax)
{
::wsprintf ( sz, m_fLeadingZero ? "%02d" : "%d", m_nMax);
SetWindowText(sz);
OnBadInput();
}
}
else
{
OnBadInput();
}
}
void
CSpinBox::OnScrollDown()
{
IncreaseContent(-1);
}
void
CSpinBox::OnScrollUp()
{
IncreaseContent(+1);
}
// SpinButton class
CSpinButton::CSpinButton()
: m_pParent(NULL),
m_fButton(FALSE),
m_fRealButton(FALSE)
{
}
BEGIN_MESSAGE_MAP(CSpinButton, CButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_TIMER()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
BOOL
CSpinButton::OnEraseBkgnd(
CDC* pDC
)
{
CBrush brBack(::GetSysColor(COLOR_BTNFACE));
CBrush* pbrOld = pDC->SelectObject(&brBack);
CRect rect;
GetClientRect(&rect);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pbrOld);
return TRUE;
}
void
CSpinButton::DrawItem(
LPDRAWITEMSTRUCT lpDIS
)
{
Paint(lpDIS);
}
void
CSpinButton::Paint(
LPDRAWITEMSTRUCT lpDIS
)
{
if (IsWindowVisible())
{
CRect rcHalf;
UINT uMiddle;
CBrush * hbrOld;
int iLoop;
BOOL fCurrentButtonDown;
CPen * hpenOld;
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CBrush brBlack;
brBlack.CreateStockObject(BLACK_BRUSH);
pDC->FrameRect(&lpDIS->rcItem, &brBlack);
::InflateRect(&lpDIS->rcItem, -1, -1);
//
// Create the barrier between the two buttons...;
//
uMiddle = lpDIS->rcItem.top + (lpDIS->rcItem.bottom - lpDIS->rcItem.top) / 2 + 1;
CBrush brFrame(::GetSysColor(COLOR_WINDOWFRAME));
hbrOld = pDC->SelectObject(&brFrame);
pDC->PatBlt(0, lpDIS->rcItem.bottom / 2 - 1, lpDIS->rcItem.right, 2, PATCOPY);
::DeleteObject(pDC->SelectObject((HGDIOBJ)hbrOld));
//
// Draw the shadows and the face of the button...;
//
for (iLoop = enumArrowUp; iLoop <= enumArrowDown; iLoop++)
{
POINT ptArrow[3];
DWORD dwColor;
fCurrentButtonDown = (m_fButton && (iLoop == m_ArrowType));
//
// get the rectangle for the button half we're dealing with;
//
rcHalf.top = (iLoop == enumArrowDown) ? uMiddle : lpDIS->rcItem.top;
rcHalf.bottom = (iLoop == enumArrowDown) ? lpDIS->rcItem.bottom : uMiddle - 2;
rcHalf.right = lpDIS->rcItem.right;
rcHalf.left = lpDIS->rcItem.left;
//
// draw the highlight lines;
//
if (fCurrentButtonDown)
{
dwColor = ::GetSysColor(COLOR_BTNSHADOW);
}
else
{
dwColor = RGB(255, 255, 255);
}
CPen penSolid(PS_SOLID, 1, dwColor);
hpenOld = pDC->SelectObject(&penSolid);
::MoveToEx(pDC->m_hDC, rcHalf.right - 1, rcHalf.top, NULL);
pDC->LineTo(rcHalf.left, rcHalf.top);
pDC->LineTo(rcHalf.left, rcHalf.bottom - 1 + fCurrentButtonDown);
::DeleteObject(pDC->SelectObject(hpenOld));
if (!fCurrentButtonDown)
{
//
// draw the shadow lines;
//
CPen penShadow(PS_SOLID, 1, ::GetSysColor(COLOR_BTNSHADOW));
hpenOld = pDC->SelectObject(&penShadow);
::MoveToEx(pDC->m_hDC, rcHalf.right - 1, rcHalf.top, NULL);
pDC->LineTo(rcHalf.right - 1, rcHalf.bottom - 1);
pDC->LineTo(rcHalf.left - 1, rcHalf.bottom - 1);
::MoveToEx(pDC->m_hDC, rcHalf.right - 2, rcHalf.top + 1, NULL);
pDC->LineTo(rcHalf.right - 2, rcHalf.bottom - 2);
pDC->LineTo(rcHalf.left, rcHalf.bottom - 2);
::DeleteObject(pDC->SelectObject(hpenOld));
}
//
// calculate the arrow triangle coordinates;
//
ptArrow[0].x = rcHalf.left + (rcHalf.right - rcHalf.left) / 2 + fCurrentButtonDown;
ptArrow[0].y = rcHalf.top + 2 + fCurrentButtonDown;
ptArrow[1].y = ptArrow[2].y = rcHalf.bottom - 4 + fCurrentButtonDown;
if (ptArrow[0].y > ptArrow[1].y)
{
ptArrow[1].y = ptArrow[2].y = ptArrow[0].y;
}
ptArrow[1].x = ptArrow[0].x - (ptArrow[1].y - ptArrow[0].y);
ptArrow[2].x = ptArrow[0].x + (ptArrow[1].y - ptArrow[0].y);
//
// flip over if we're drawing bottom button;
//
if (iLoop == enumArrowDown)
{
ptArrow[2].y = ptArrow[0].y;
ptArrow[0].y = ptArrow[1].y;
ptArrow[1].y = ptArrow[2].y;
}
if (IsWindowEnabled())
{
dwColor = ::GetSysColor(COLOR_BTNTEXT);
}
else
{
dwColor = ::GetSysColor(COLOR_GRAYTEXT);
}
//
// draw the triangle;
//
CBrush brTriangle(dwColor);
CPen penTriangle(PS_SOLID, 1, dwColor);
hbrOld = pDC->SelectObject(&brTriangle);
hpenOld = pDC->SelectObject(&penTriangle);
pDC->Polygon(ptArrow, 3);
::DeleteObject(pDC->SelectObject(hbrOld));
::DeleteObject(pDC->SelectObject(hpenOld));
}
}
}
void
CSpinButton::NotifyParent()
{
if (m_uScroll == SB_LINEDOWN)
{
m_pParent->OnScrollDown();
}
else
{
m_pParent->OnScrollUp();
}
}
void
CSpinButton::OnLButtonDown(
UINT nFlags,
CPoint point
)
{
if (!m_fRealButton)
{
m_fButton = TRUE; // Button not yet down
m_fRealButton = TRUE;
SetCapture();
GetClientRect(&m_rcUp);
m_rcDown.CopyRect(&m_rcUp);
m_rcUp.bottom = (m_rcUp.top + m_rcUp.bottom) / 2 - 1;
m_rcDown.top = m_rcUp.bottom + 1;
m_uScroll = (point.y >= m_rcDown.top) ? SB_LINEDOWN : SB_LINEUP;
m_ArrowType = (m_uScroll == SB_LINEDOWN) ? enumArrowDown : enumArrowUp;
//
// Tell parent edit control about in/de-crease in value
//
NotifyParent();
m_uTimer = SetTimer(1, 150, NULL);
if (m_ArrowType == enumArrowDown)
{
InvalidateRect(&m_rcDown, TRUE);
}
else
{
InvalidateRect(&m_rcUp, TRUE);
}
}
}
void
CSpinButton::OnLButtonUp(
UINT nFlags,
CPoint point
)
{
if (m_fButton)
{
ReleaseCapture();
m_fButton = FALSE;
if (m_ArrowType == enumArrowDown)
{
InvalidateRect(&m_rcDown, TRUE);
}
else
{
InvalidateRect(&m_rcUp, TRUE);
}
}
m_fRealButton = FALSE;
if (m_uTimer)
{
KillTimer(m_uTimer);
m_uTimer = 0;
}
}
void
CSpinButton::OnTimer(
UINT nIDEvent
)
{
NotifyParent(); // Still holding down the button
}