mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
805 lines
17 KiB
C++
805 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "widgetry.h"
|
|
|
|
class CProgressMeterClass
|
|
{
|
|
protected:
|
|
HWND m_hWnd;
|
|
int cubeHeight;
|
|
int cubeWidth;
|
|
int cubeCount;
|
|
int percent;
|
|
int lastUpdate;
|
|
|
|
HBRUSH m_hbrushBlue;
|
|
|
|
void PaintCube(HDC hdc, int position);
|
|
|
|
public:
|
|
static void RegisterClass();
|
|
|
|
CProgressMeterClass(HWND hwnd);
|
|
~CProgressMeterClass();
|
|
|
|
void OnPaint();
|
|
void OnStep();
|
|
void OnStepTo(int newPercent);
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CProgressMeter
|
|
// The progress meter draws a 3D progress status inside the static
|
|
// control
|
|
|
|
#define EDGE_WIDTH 2 // default bevel edge width
|
|
|
|
CProgressMeterClass::CProgressMeterClass(HWND hwnd)
|
|
{
|
|
m_hWnd = hwnd;
|
|
lastUpdate = percent = cubeWidth = cubeHeight = 0;
|
|
cubeCount = 1;
|
|
m_hbrushBlue = ::CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
|
}
|
|
|
|
CProgressMeterClass::~CProgressMeterClass()
|
|
{
|
|
VERIFY(::DeleteObject(m_hbrushBlue));
|
|
}
|
|
|
|
|
|
void CProgressMeterClass::OnPaint()
|
|
{
|
|
PAINTSTRUCT paint;
|
|
BeginPaint(m_hWnd, &paint);
|
|
HDC hdc = paint.hdc;
|
|
RECT rect; // get the entire area of the static region
|
|
::GetClientRect(m_hWnd, &rect);
|
|
|
|
int nCubes, oldmod = 21;
|
|
|
|
// try 20 to 30 cubes and select the best fit (least modulo)
|
|
for ( nCubes = 30; nCubes <= 50; nCubes++ )
|
|
{
|
|
int extra = ( rect.right - 4 ) / nCubes;
|
|
int val = ( ( rect.right - 4 ) + ( extra / 2 ) ) % nCubes;
|
|
|
|
// is this a better fit than the last try?
|
|
if ( val < oldmod )
|
|
{
|
|
oldmod = val; // yes, save count
|
|
cubeCount = nCubes;
|
|
|
|
// compute the cube width and height for the control
|
|
cubeWidth = ( ( ( rect.right - 4 ) + ( extra / 2 ) ) ) / nCubes;
|
|
cubeHeight = rect.bottom - 4;
|
|
|
|
// if this is a perfect fit, look no further
|
|
if ( !val )
|
|
break;
|
|
}
|
|
}
|
|
|
|
WFE_DrawLoweredRect(hdc, &rect);
|
|
|
|
// draw the center of the control in the button face color
|
|
::InflateRect(&rect, -EDGE_WIDTH, -EDGE_WIDTH);
|
|
::FillRect( hdc, &rect, sysInfo.m_hbrBtnFace );
|
|
|
|
// paint all the cubes that have been painted already (this is for refresh)
|
|
long i;
|
|
long interval = 1000 / cubeCount;
|
|
if ( !interval )
|
|
interval = 1;
|
|
|
|
if (percent > 100)
|
|
percent = 100;
|
|
if (percent < 0)
|
|
percent = 0;
|
|
|
|
for ( i = 0; i < long(percent) * 1000L / interval / 100; i++ )
|
|
PaintCube( hdc, CASTINT(i) );
|
|
|
|
EndPaint(m_hWnd, &paint);
|
|
}
|
|
|
|
// Paint a single cube in the progress control
|
|
|
|
void CProgressMeterClass::PaintCube ( HDC hdc, int position )
|
|
{
|
|
if ( position <= cubeCount )
|
|
{
|
|
RECT MeterRect;
|
|
::GetClientRect(m_hWnd, &MeterRect);
|
|
RECT rect;
|
|
|
|
// cubes get painted 1 pixel less than the inside area with
|
|
// 2 pixel spaces between cubes
|
|
rect.left = EDGE_WIDTH + 2 + ( position * cubeWidth );
|
|
rect.top = EDGE_WIDTH + 3;
|
|
rect.bottom = cubeHeight;
|
|
rect.right = ( rect.left + cubeWidth ) - 2;
|
|
|
|
if (rect.right < MeterRect.right)
|
|
::FillRect(hdc, &rect, m_hbrushBlue);
|
|
}
|
|
}
|
|
|
|
void CProgressMeterClass::OnStepTo(int newPercent)
|
|
{
|
|
if (newPercent < percent) {
|
|
lastUpdate = percent = 0;
|
|
RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
|
|
}
|
|
while (percent<newPercent)
|
|
OnStep();
|
|
}
|
|
|
|
// increase the gauge by 1% and update the cubes if required
|
|
|
|
void CProgressMeterClass::OnStep()
|
|
{
|
|
HDC hdc = GetDC(m_hWnd);
|
|
|
|
// did we overstep?
|
|
if ( percent < 100 )
|
|
{
|
|
// get the spacing
|
|
long interval = 1000 / cubeCount;
|
|
if ( !interval )
|
|
interval = 1;
|
|
percent++;
|
|
|
|
// time to draw another cube?
|
|
if (long(percent) * 1000L / interval / 100 > lastUpdate)
|
|
{
|
|
PaintCube ( hdc, lastUpdate );
|
|
lastUpdate = CASTINT(long(percent) * 1000L / interval / 100);
|
|
}
|
|
}
|
|
ReleaseDC(m_hWnd, hdc);
|
|
}
|
|
|
|
LRESULT CALLBACK EXPORT
|
|
ProgressMeterWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CProgressMeterClass *pObject;
|
|
|
|
// If we've been created then create our C++ object
|
|
if (iMsg == WM_CREATE) {
|
|
pObject = new CProgressMeterClass(hwnd);
|
|
if (!pObject)
|
|
return -1;
|
|
|
|
SetWindowLong(hwnd, 0, (LONG) pObject);
|
|
return 0;
|
|
}
|
|
|
|
// Get the pointer to our C++ object
|
|
pObject = (CProgressMeterClass *)GetWindowLong(hwnd, 0);
|
|
if (!pObject)
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
|
|
switch (iMsg) {
|
|
case WM_DESTROY:
|
|
delete pObject;
|
|
SetWindowLong(hwnd, 0, 0L);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
pObject->OnPaint();
|
|
break;
|
|
|
|
case NSPM_STEP:
|
|
pObject->OnStep();
|
|
break;
|
|
|
|
case NSPM_STEPTO:
|
|
pObject->OnStepTo((int) wParam);
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Initialization routine
|
|
|
|
void CProgressMeterClass::RegisterClass()
|
|
{
|
|
WNDCLASS wndclass;
|
|
|
|
wndclass.style = 0;
|
|
wndclass.lpfnWndProc = ProgressMeterWndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = sizeof(CProgressMeterClass *);
|
|
wndclass.hInstance = AfxGetInstanceHandle();
|
|
wndclass.hIcon = NULL;
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = WC_NSPROGRESS;
|
|
|
|
::RegisterClass(&wndclass);
|
|
}
|
|
|
|
CProgressMeter::CProgressMeter()
|
|
{
|
|
m_hWnd = NULL;
|
|
}
|
|
|
|
BOOL CProgressMeter::SubclassDlgItem(UINT nID, CWnd *pParent)
|
|
{
|
|
HWND hwnd = pParent->GetDlgItem(nID)->GetSafeHwnd();
|
|
RECT rcWindow;
|
|
GetWindowRect(hwnd, &rcWindow);
|
|
MapWindowPoints(NULL, pParent->GetSafeHwnd(), (LPPOINT) &rcWindow, 2);
|
|
|
|
m_hWnd = ::CreateWindow(WC_NSPROGRESS, NULL, WS_CHILD|WS_VISIBLE,
|
|
rcWindow.left, rcWindow.top,
|
|
rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top,
|
|
pParent->GetSafeHwnd(),
|
|
(HMENU) ::GetDlgCtrlID(hwnd),
|
|
AfxGetInstanceHandle(),
|
|
NULL);
|
|
|
|
::DestroyWindow(hwnd);
|
|
return m_hWnd != NULL;
|
|
}
|
|
|
|
void CProgressMeter::StepIt()
|
|
{
|
|
if (m_hWnd)
|
|
::SendMessage(m_hWnd, NSPM_STEP, (WPARAM) 0, (LPARAM) 0);
|
|
}
|
|
|
|
void CProgressMeter::StepItTo(int newPercent)
|
|
{
|
|
if (m_hWnd)
|
|
::SendMessage(m_hWnd, NSPM_STEPTO, (WPARAM) newPercent, (LPARAM) 0);
|
|
}
|
|
|
|
#ifndef _WIN32X
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CUpDownClass
|
|
|
|
#define UDT_PAUSE 1
|
|
#define UDT_REFRESH 2
|
|
|
|
static const char szProp[] = "NSUpDown";
|
|
|
|
class CUpDownClass {
|
|
private:
|
|
HWND m_hWnd, m_hwndBuddy;
|
|
UINT m_nBase;
|
|
int m_nPos, m_nLower, m_nUpper;
|
|
DWORD m_dwStyle;
|
|
UINT m_idTimer;
|
|
int m_iHit, m_iState;
|
|
HBITMAP m_hbmArrows;
|
|
|
|
enum { udsNone, udsUp, udsDown };
|
|
|
|
void _UpdateValue(int nPos);
|
|
int _GetValue();
|
|
|
|
void _Up();
|
|
void _Down();
|
|
|
|
void _SetState(int iState);
|
|
|
|
public:
|
|
WNDPROC m_pfSuperProc;
|
|
|
|
CUpDownClass(HWND hwnd);
|
|
~CUpDownClass();
|
|
|
|
BOOL HandleEvent(UINT iMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
|
|
|
|
void OnEnable(BOOL bEnable);
|
|
void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
|
|
void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
|
|
void OnLButtonDown(UINT nFlags, POINT point);
|
|
void OnLButtonUp(UINT nFlags, POINT point);
|
|
void OnPaint();
|
|
void OnTimer(UINT nID);
|
|
|
|
BOOL SetAccel(int nAccel, UDACCEL* pAccel);
|
|
UINT GetAccel(int nAccel, UDACCEL* pAccel) const;
|
|
UINT SetBase(UINT nBase);
|
|
UINT GetBase() const;
|
|
HWND SetBuddy(HWND hwndBuddy);
|
|
HWND GetBuddy() const;
|
|
int SetPos(int nPos);
|
|
int GetPos() const;
|
|
void SetRange(int nLower, int nUpper);
|
|
DWORD GetRange() const;
|
|
|
|
static void RegisterClass();
|
|
};
|
|
|
|
// WNDPROCs
|
|
|
|
LRESULT CALLBACK
|
|
UpDownWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CUpDownClass *pObject;
|
|
POINT pt;
|
|
|
|
// If we've been created then create our C++ object
|
|
if (iMsg == WM_CREATE) {
|
|
pObject = new CUpDownClass(hwnd);
|
|
if (!pObject)
|
|
return -1;
|
|
|
|
SetWindowLong(hwnd, 0, (LONG) pObject);
|
|
return 0;
|
|
}
|
|
|
|
// Get the pointer to our C++ object
|
|
pObject = (CUpDownClass *)GetWindowLong(hwnd, 0);
|
|
if (!pObject)
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
|
|
switch (iMsg) {
|
|
case WM_DESTROY:
|
|
delete pObject;
|
|
SetWindowLong(hwnd, 0, 0L);
|
|
break;
|
|
|
|
case WM_ENABLE:
|
|
pObject->OnEnable((BOOL) wParam);
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
pObject->OnKeyDown((UINT) wParam, (UINT) LOWORD(lParam), (UINT) HIWORD(lParam));
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
pObject->OnKeyUp((UINT) wParam, (UINT) LOWORD(lParam), (UINT) HIWORD(lParam));
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
pt.x = LOWORD(lParam);
|
|
pt.y = HIWORD(lParam);
|
|
pObject->OnLButtonDown((UINT) wParam, pt);
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
pt.x = LOWORD(lParam);
|
|
pt.y = HIWORD(lParam);
|
|
pObject->OnLButtonUp((UINT) wParam, pt);
|
|
|
|
case WM_PAINT:
|
|
pObject->OnPaint();
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
pObject->OnTimer((UINT) wParam);
|
|
break;
|
|
|
|
case UDM_SETRANGE:
|
|
pObject->SetRange((int) HIWORD(lParam), (int) LOWORD(lParam));
|
|
break;
|
|
|
|
case UDM_GETRANGE:
|
|
return (LRESULT) pObject->GetRange();
|
|
|
|
case UDM_SETPOS:
|
|
pObject->SetPos((int) wParam);
|
|
|
|
case UDM_GETPOS:
|
|
return (LRESULT) pObject->GetPos();
|
|
|
|
case UDM_SETBUDDY:
|
|
pObject->SetBuddy((HWND) wParam);
|
|
break;
|
|
|
|
case UDM_GETBUDDY:
|
|
return (LRESULT) pObject->GetBuddy();
|
|
|
|
case UDM_SETACCEL:
|
|
return (LPARAM) pObject->SetAccel((int) wParam, (LPUDACCEL) lParam);
|
|
|
|
case UDM_GETACCEL:
|
|
return (LPARAM) pObject->GetAccel((int) wParam, (LPUDACCEL) lParam);
|
|
break;
|
|
|
|
case UDM_SETBASE:
|
|
pObject->SetBase((UINT) wParam);
|
|
break;
|
|
|
|
case UDM_GETBASE:
|
|
return (LRESULT) pObject->GetBase();
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CALLBACK UpDownSubWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hwndUpDown = (HWND) ::GetProp(hwnd, szProp);
|
|
if (hwndUpDown) {
|
|
CUpDownClass *pObject = (CUpDownClass *) GetWindowLong(hwndUpDown, 0);
|
|
if (pObject) {
|
|
LRESULT lResult;
|
|
if (!pObject->HandleEvent(iMsg, wParam, lParam, &lResult))
|
|
return CallWindowProc(pObject->m_pfSuperProc, hwnd, iMsg, wParam, lParam );
|
|
else
|
|
return lResult;
|
|
}
|
|
}
|
|
// Tragedy, punt
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
// Constructor/Destructor
|
|
|
|
static WORD awArrows[] = { 0xef, 0xc7, 0x83, 0x01, 0x83, 0xc7, 0xef, 0x00 };
|
|
|
|
CUpDownClass::CUpDownClass(HWND hwnd)
|
|
{
|
|
m_hWnd = hwnd;
|
|
m_dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
|
|
m_iState = m_iHit = udsNone;
|
|
|
|
m_hbmArrows = ::CreateBitmap(8, 8, 1, 1, awArrows);
|
|
|
|
m_nPos = 1;
|
|
m_nLower = 1;
|
|
m_nUpper = 100;
|
|
|
|
m_pfSuperProc = NULL;
|
|
}
|
|
|
|
CUpDownClass::~CUpDownClass()
|
|
{
|
|
if (m_idTimer)
|
|
KillTimer(m_hWnd, m_idTimer);
|
|
|
|
SetBuddy(NULL);
|
|
|
|
VERIFY(::DeleteObject(m_hbmArrows));
|
|
}
|
|
|
|
// Private methods
|
|
|
|
void CUpDownClass::_UpdateValue(int nPos)
|
|
{
|
|
m_nPos = nPos;
|
|
if (m_hwndBuddy && (m_dwStyle & UDS_SETBUDDYINT)) {
|
|
char szText[17];
|
|
_itoa(m_nPos, szText, 10);
|
|
::SendMessage(m_hwndBuddy, WM_SETTEXT, (WPARAM) 0, (LPARAM) szText);
|
|
}
|
|
}
|
|
|
|
int CUpDownClass::_GetValue()
|
|
{
|
|
int nPos = m_nPos;
|
|
if (m_hwndBuddy && (m_dwStyle & UDS_SETBUDDYINT)) {
|
|
char szText[17];
|
|
::SendMessage(m_hwndBuddy, WM_GETTEXT, (WPARAM) 17, (LPARAM) szText);
|
|
int nVal = atoi(szText);
|
|
if (nVal >= m_nLower && nVal <= m_nUpper)
|
|
nPos = nVal;
|
|
}
|
|
|
|
return nPos;
|
|
}
|
|
|
|
void CUpDownClass::_Up()
|
|
{
|
|
int nPos = _GetValue();
|
|
if (nPos < m_nUpper) {
|
|
nPos++;
|
|
} else if (m_dwStyle & UDS_WRAP) {
|
|
nPos = m_nLower;
|
|
}
|
|
_UpdateValue(nPos);
|
|
}
|
|
|
|
void CUpDownClass::_Down()
|
|
{
|
|
int nPos = _GetValue();
|
|
if (nPos > m_nLower) {
|
|
nPos--;
|
|
} else if (m_dwStyle & UDS_WRAP) {
|
|
nPos = m_nUpper;
|
|
}
|
|
_UpdateValue(nPos);
|
|
}
|
|
|
|
void CUpDownClass::_SetState(int iState)
|
|
{
|
|
if (m_iState != iState) {
|
|
m_iState = iState;
|
|
::InvalidateRect(m_hWnd, NULL, TRUE);
|
|
::UpdateWindow(m_hWnd);
|
|
}
|
|
}
|
|
|
|
BOOL CUpDownClass::HandleEvent(UINT iMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
|
|
{
|
|
*lResult = 0;
|
|
|
|
if ((iMsg == WM_KEYDOWN || iMsg == WM_KEYUP) && m_dwStyle & UDS_ARROWKEYS) {
|
|
if (((UINT) wParam) == VK_UP || ((UINT) wParam) == VK_DOWN) {
|
|
if (iMsg == WM_KEYDOWN) {
|
|
OnKeyDown((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
|
} else {
|
|
OnKeyUp((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// WM_ methods
|
|
|
|
void CUpDownClass::OnEnable(BOOL bEnable)
|
|
{
|
|
::InvalidateRect(m_hWnd, NULL, TRUE);
|
|
::UpdateWindow(m_hWnd);
|
|
}
|
|
|
|
void CUpDownClass::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (m_dwStyle & UDS_ARROWKEYS) {
|
|
if (nChar == VK_UP) {
|
|
_Up();
|
|
_SetState(udsUp);
|
|
} else if (nChar = VK_DOWN) {
|
|
_Down();
|
|
_SetState(udsDown);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CUpDownClass::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
_SetState(udsNone);
|
|
}
|
|
|
|
void CUpDownClass::OnLButtonDown(UINT nFlags, POINT point)
|
|
{
|
|
::SetCapture(m_hWnd);
|
|
RECT rcClient;
|
|
::GetClientRect(m_hWnd, &rcClient);
|
|
if (point.y < (rcClient.bottom / 2)) {
|
|
m_iHit = udsUp;
|
|
_Up();
|
|
} else {
|
|
m_iHit = udsDown;
|
|
_Down();
|
|
}
|
|
m_idTimer = ::SetTimer(m_hWnd, UDT_PAUSE, 500, NULL);
|
|
|
|
_SetState(m_iHit);
|
|
}
|
|
|
|
void CUpDownClass::OnLButtonUp(UINT nFlags, POINT point)
|
|
{
|
|
if (::GetCapture() == m_hWnd)
|
|
::ReleaseCapture();
|
|
|
|
if (m_idTimer) {
|
|
::KillTimer(m_hWnd, m_idTimer);
|
|
m_idTimer = 0;
|
|
}
|
|
m_iHit = udsNone;
|
|
_SetState(udsNone);
|
|
}
|
|
|
|
void CUpDownClass::OnPaint()
|
|
{
|
|
PAINTSTRUCT paint;
|
|
BeginPaint(m_hWnd, &paint);
|
|
HDC hdc = paint.hdc;
|
|
|
|
HDC hdcArrows = ::CreateCompatibleDC(hdc);
|
|
HBITMAP hbmOld = (HBITMAP) ::SelectObject(hdcArrows, m_hbmArrows);
|
|
COLORREF oldBk = ::SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
|
|
COLORREF oldText = ::SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
|
|
|
|
RECT rcTop, rcBottom;
|
|
::GetClientRect(m_hWnd, &rcTop);
|
|
rcBottom = rcTop;
|
|
rcTop.bottom = rcTop.bottom / 2;
|
|
rcBottom.top = rcTop.bottom + 1;
|
|
|
|
int ux, uy, dx, dy;
|
|
ux = (rcTop.right + 1) / 2 - 4;
|
|
uy = (rcTop.bottom + 1) / 2 - 2;
|
|
dx = ux;
|
|
dy = rcBottom.bottom - uy - 3;
|
|
|
|
if (m_iState == udsUp) {
|
|
ux++;
|
|
uy++;
|
|
} else if (m_iState == udsDown) {
|
|
dx++;
|
|
dy++;
|
|
}
|
|
::BitBlt(hdc, ux, uy, 8, 3, hdcArrows, 0, 0, SRCCOPY);
|
|
::BitBlt(hdc, dx, dy, 8, 3, hdcArrows, 0, 4, SRCCOPY);
|
|
|
|
WFE_Draw3DButtonRect(hdc, &rcTop, m_iState == udsUp);
|
|
WFE_Draw3DButtonRect(hdc, &rcBottom, m_iState == udsDown);
|
|
|
|
::SelectObject(hdcArrows, hbmOld);
|
|
VERIFY(::DeleteDC(hdcArrows));
|
|
::SetBkColor(hdc, oldBk);
|
|
::SetTextColor(hdc, oldText);
|
|
|
|
EndPaint(m_hWnd, &paint);
|
|
}
|
|
|
|
void CUpDownClass::OnTimer(UINT nID)
|
|
{
|
|
int iState = udsNone;
|
|
|
|
if (::GetCapture() == m_hWnd) {
|
|
if (nID == UDT_PAUSE) {
|
|
::KillTimer(m_hWnd, m_idTimer);
|
|
m_idTimer = ::SetTimer(m_hWnd, UDT_REFRESH, 100, NULL);
|
|
}
|
|
|
|
RECT rcClient;
|
|
::GetClientRect(m_hWnd, &rcClient);
|
|
POINT pt;
|
|
::GetCursorPos(&pt);
|
|
::ScreenToClient(m_hWnd, &pt);
|
|
|
|
if (::PtInRect(&rcClient, pt)) {
|
|
iState = (pt.y < rcClient.bottom / 2) ? udsUp : udsDown;
|
|
if (iState == m_iHit) {
|
|
if (iState == udsUp) {
|
|
_Up();
|
|
} else {
|
|
_Down();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
::KillTimer(m_hWnd, m_idTimer);
|
|
m_idTimer = 0;
|
|
}
|
|
_SetState(iState);
|
|
}
|
|
|
|
// UDM_ methods
|
|
|
|
BOOL CUpDownClass::SetAccel(int nAccel, UDACCEL* pAccel)
|
|
{
|
|
ASSERT(0);
|
|
return FALSE;
|
|
}
|
|
|
|
UINT CUpDownClass::GetAccel(int nAccel, UDACCEL* pAccel) const
|
|
{
|
|
ASSERT(0);
|
|
return 0;
|
|
}
|
|
|
|
UINT CUpDownClass::SetBase(UINT nBase)
|
|
{
|
|
int res = m_nBase;
|
|
m_nBase = nBase;
|
|
return res;
|
|
}
|
|
|
|
UINT CUpDownClass::GetBase() const
|
|
{
|
|
return m_nBase;
|
|
}
|
|
|
|
HWND CUpDownClass::SetBuddy(HWND hwndBuddy)
|
|
{
|
|
HWND res = m_hwndBuddy;
|
|
|
|
if (::IsWindow(m_hwndBuddy)) {
|
|
// Unsubclass the parent window
|
|
if (GetWindowLong(m_hwndBuddy, GWL_WNDPROC) == (LONG) UpDownSubWndProc) {
|
|
::SetWindowLong(m_hwndBuddy, GWL_WNDPROC, (LONG) m_pfSuperProc);
|
|
}
|
|
VERIFY(RemoveProp(m_hwndBuddy, szProp));
|
|
m_hwndBuddy = NULL;
|
|
}
|
|
if (::IsWindow(hwndBuddy)) {
|
|
m_hwndBuddy = hwndBuddy;
|
|
VERIFY(SetProp(m_hwndBuddy, szProp, (HANDLE) m_hWnd));
|
|
m_pfSuperProc = (WNDPROC) ::SetWindowLong(m_hwndBuddy, GWL_WNDPROC, (LONG) UpDownSubWndProc);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
HWND CUpDownClass::GetBuddy() const
|
|
{
|
|
return m_hwndBuddy;
|
|
}
|
|
|
|
int CUpDownClass::SetPos(int nPos)
|
|
{
|
|
int res = m_nPos;
|
|
m_nPos = nPos;
|
|
return res;
|
|
}
|
|
|
|
int CUpDownClass::GetPos() const
|
|
{
|
|
return m_nPos;
|
|
}
|
|
|
|
void CUpDownClass::SetRange(int nLower, int nUpper)
|
|
{
|
|
m_nLower = nLower;
|
|
m_nUpper = nUpper;
|
|
}
|
|
|
|
|
|
DWORD CUpDownClass::GetRange() const
|
|
{
|
|
return MAKELONG(m_nLower, m_nUpper);
|
|
}
|
|
|
|
void CUpDownClass::RegisterClass()
|
|
{
|
|
WNDCLASS wndclass;
|
|
|
|
wndclass.style = CS_PARENTDC|CS_HREDRAW|CS_VREDRAW;
|
|
wndclass.lpfnWndProc = UpDownWndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = sizeof(CUpDownClass *);
|
|
wndclass.hInstance = AfxGetInstanceHandle();
|
|
wndclass.hIcon = NULL;
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = NSUPDOWN_CLASS;
|
|
|
|
::RegisterClass(&wndclass);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef FEATURE_SPIN_BUTTON
|
|
#include "widgetry.i01"
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// AssortedWidgetInit
|
|
|
|
void AssortedWidgetInit()
|
|
{
|
|
CProgressMeterClass::RegisterClass();
|
|
#ifndef _WIN32X
|
|
CUpDownClass::RegisterClass();
|
|
#endif
|
|
}
|