Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1414 lines
37 KiB

/////////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
//
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
//
// Other brand and product names used herein are trademarks of their respective owners.
//
// The entire program and user interface including the structure, sequence, selection,
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
// by "1" and "2," and each dialog message are protected by copyrights registered in
// the United States and by international treaties.
//
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
//
// Active Voice Corporation
// Seattle, Washington
// USA
//
/////////////////////////////////////////////////////////////////////////////////////////
////
// tmeter.c - TrackMeter custom control
////
#include "tmeter.h"
#include "resource.h"
#include <commctrl.h>
#include <custcntl.h>
#include "trace.h"
#include "mem.h"
////
// public
////
BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved);
UINT DLLEXPORT CALLBACK CustomControlInfoA(LPCCINFOA acci);
BOOL DLLEXPORT CALLBACK TrackMeter_Style(HWND hWndParent, LPCCSTYLEA pccs);
INT DLLEXPORT CALLBACK TrackMeter_SizeToText(
DWORD flStyle, DWORD flExtStyle, HFONT hFont, LPSTR pszText);
LRESULT DLLEXPORT CALLBACK TrackMeter_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
////
// private
////
static HINSTANCE g_hInstLib;
#define GWL_USER 0
#define TRACKMETER_DESCRIPTION "TrackBar with level meter"
#define TRACKMETER_DEFAULTTEXT "[===||=======]"
// control styles
//
#define SS_HORIZONTAL 0x0001
#define SS_VERTICAL 0x0002
CCSTYLEFLAGA aTrackMeterStyleFlags[] =
{
{ TMS_HORZ, 0, "TMS_HORZ" },
{ TMS_VERT, 0, "TMS_VERT" },
{ TMS_NOTHUMB, 0, "TMS_NOTHUMB" }
};
// number of extra bytes for control window
//
#define TRACKMETER_EXTRABYTES (1*sizeof(DWORD_PTR))
// tmeter control struct
//
typedef struct TMETER
{
HWND hwnd;
HWND hwndParent;
HDC hdcCompat;
HBITMAP hbmpSave;
HBITMAP hbmpCompat;
long lPosition;
long lMinimum;
long lMaximum;
long lLevel;
long lLineSize;
long lPageSize;
BOOL fHasFocus;
BOOL fIsEnabled;
BOOL fIsThumbPressed;
DWORD dwFlags;
RECT rcCtrl;
RECT rcTrack;
RECT rcMeter;
RECT rcLevel;
POINT aptThumb[5];
COLORREF acr[TMCR_MAX];
} TMETER, FAR *LPTMETER;
// helper functions
//
static BOOL TrackMeter_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
static void TrackMeter_OnNCDestroy(LPTMETER lptm);
static BOOL TrackMeter_OnCreate(LPTMETER lptm, CREATESTRUCT FAR* lpCreateStruct);
static void TrackMeter_OnDestroy(LPTMETER lptm);
static void TrackMeter_OnSize(LPTMETER lptm, UINT state, int cx, int cy);
static BOOL TrackMeter_OnEraseBkgnd(LPTMETER lptm, HDC hdc);
static void TrackMeter_OnPaint(LPTMETER lptm);
static int TrackMeter_Draw(LPTMETER lptm, HDC hdc);
static void TrackMeter_OnCommand(LPTMETER lptm, int id, HWND hwndCtl, UINT codeNotify);
static void TrackMeter_OnSetFocus(LPTMETER lptm, HWND hwndOldFocus);
static void TrackMeter_OnKillFocus(LPTMETER lptm, HWND hwndNewFocus);
static void TrackMeter_OnEnable(LPTMETER lptm, BOOL fEnable);
static UINT TrackMeter_OnGetDlgCode(LPTMETER lptm, LPMSG lpmsg);
static void TrackMeter_OnKey(LPTMETER lptm, UINT vk, BOOL fDown, int cRepeat, UINT flags);
static void TrackMeter_OnLButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags);
static void TrackMeter_OnLButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags);
static void TrackMeter_OnRButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags);
static void TrackMeter_OnRButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags);
static void TrackMeter_OnMouseMove(LPTMETER lptm, int x, int y, UINT keyFlags);
static void TrackMeter_OnCaptureChanged(LPTMETER lptm, HWND hwndNewCapture);
static void TrackMeter_NotifyParent(LPTMETER lptm, UINT code, UINT nPos);
static LONG TrackMeter_OnTMMGetPos(LPTMETER lptm);
static void TrackMeter_OnTMMSetPos(LPTMETER lptm, LONG lPosition, BOOL fRedraw);
static LONG TrackMeter_OnTMMGetLevel(LPTMETER lptm);
static void TrackMeter_OnTMMSetLevel(LPTMETER lptm, LONG lLevel, BOOL fRedraw);
static LONG TrackMeter_OnTMMGetRangeMin(LPTMETER lptm);
static void TrackMeter_OnTMMSetRangeMin(LPTMETER lptm, LONG lMinimum, BOOL fRedraw);
static LONG TrackMeter_OnTMMGetRangeMax(LPTMETER lptm);
static void TrackMeter_OnTMMSetRangeMax(LPTMETER lptm, LONG lMaximum, BOOL fRedraw);
static void TrackMeter_OnTMMSetRange(LPTMETER lptm, LONG lMinimum, LONG lMaximum, BOOL fRedraw);
static COLORREF TrackMeter_OnTMMGetColor(LPTMETER lptm, UINT elem);
static void TrackMeter_OnTMMSetColor(LPTMETER lptm, COLORREF cr, UINT elem, BOOL fRedraw);
#define TrackMeter_DefProc(hwnd, msg, wParam, lParam) \
DefWindowProc(hwnd, msg, wParam, lParam)
static int TrackMeter_Recalc(LPTMETER lptm, DWORD dwFlags);
#define TMR_TRACK 0x00000001
#define TMR_METER 0x00000002
#define TMR_LEVEL 0x00000004
#define TMR_THUMB 0x00000008
#define TMR_COLORS 0x00000010
#define TMR_PAGESIZE 0x00000020
#define TMR_ALL (TMR_TRACK | TMR_METER | TMR_LEVEL | TMR_THUMB | TMR_COLORS | TMR_PAGESIZE)
static int TrackMeter_PositionToX(LPTMETER lptm, long lPosition);
static long TrackMeter_XToPosition(LPTMETER lptm, int xPosition);
static BOOL TrackMeter_PtInThumb(LPTMETER lptm, int x, int y);
// for some reason this is not in windowsx.h
//
#ifndef HANDLE_WM_CAPTURECHANGED
/* void Cls_OnCaptureChanged(HWND hwnd, HWND hwndNewCapture) */
#define HANDLE_WM_CAPTURECHANGED(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (HWND)(wParam)), 0L)
#define FORWARD_WM_CAPTURECHANEGED(hwnd, hwndNewCapture, fn) \
(void)(fn)((hwnd), WM_CAPTURECHANGED, (WPARAM)(HWND)(hwndNewCapture), 0L)
#endif
////
// public
////
BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
{
BOOL fSuccess = TRUE;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
WNDCLASS wc;
g_hInstLib = hModule;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
wc.lpfnWndProc = TrackMeter_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = TRACKMETER_EXTRABYTES;
wc.hInstance = hModule;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = (LPTSTR) NULL;
wc.lpszClassName = (LPTSTR) TRACKMETER_CLASS;
if (!RegisterClass (&wc))
{
fSuccess = TraceFALSE(NULL);
return FALSE;
}
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (!UnregisterClass ((LPTSTR) TRACKMETER_CLASS, hModule))
fSuccess = TraceFALSE(NULL);
break;
default:
break;
}
return fSuccess;
}
// CustomControlInfoA
// <lpacci> (i/o) pointer to array of CCINFOA structs
// returns number of controls supported by this DLL
// NOTE: see CUSTCNTL.H for more info
//
UINT DLLEXPORT CALLBACK CustomControlInfoA(LPCCINFOA acci)
{
UINT uControls = 1;
if (acci != NULL)
{
// calculate width and height of dialog units (in pixels)
//
DWORD dw = GetDialogBaseUnits();
WORD cxBaseUnits = LOWORD(dw);
WORD cyBaseUnits = HIWORD(dw);
// fill in a CCINFOA struct for each supported control
//
strncpy(acci[0].szClass, TRACKMETER_CLASS_A,
sizeof(acci[0].szClass));
acci[0].flOptions = CCF_NOTEXT;
strncpy(acci[0].szDesc, TRACKMETER_DESCRIPTION,
sizeof(acci[0].szDesc));
acci[0].cxDefault = (120 * 4) / max(1, cxBaseUnits);
acci[0].cyDefault = (18 * 8) / max(1, cyBaseUnits);
acci[0].flStyleDefault = WS_CHILD | WS_VISIBLE | SS_HORIZONTAL;
acci[0].flExtStyleDefault = 0;
acci[0].flCtrlTypeMask = 0;
strncpy(acci[0].szTextDefault, TRACKMETER_DEFAULTTEXT,
sizeof(acci[0].szTextDefault));
acci[0].cStyleFlags = (sizeof(aTrackMeterStyleFlags) / sizeof(aTrackMeterStyleFlags[0]));
acci[0].aStyleFlags = aTrackMeterStyleFlags;
acci[0].lpfnStyle = TrackMeter_Style;
acci[0].lpfnSizeToText = TrackMeter_SizeToText;
acci[0].dwReserved1 = 0;
acci[0].dwReserved2 = 0;
}
// return the number of controls that the DLL supports
//
return uControls;
}
// TrackMeter_Style - do modal dialog for custom control style
// <hwndParent> (i) parent window (dialog editor)
// <pccs> (i/o) pointer to CCSTYLE struct
// returns TRUE if success, otherwise FALSE
//
BOOL DLLEXPORT CALLBACK TrackMeter_Style(HWND hWndParent, LPCCSTYLEA pccs)
{
BOOL fSuccess = TRUE;
#if 0
if (DialogBox(g_hInstLib, MAKEINTRESOURCE(IDD_TMETERSTYLE),
hWndParent, TrackMeter_DlgProc) == -1)
fSuccess = TraceFALSE(NULL);
#else
fSuccess = TraceFALSE(NULL);
#endif
return fSuccess;
}
// TrackMeter_SizeToText
// <flStyle> (i) control style
// <flExtStyle> (i) control extended style
// <hFont> (i) handle of font used to draw text
// <pszText> (i) control text
// returns control width (pixels) needed to accomodate text, -1 if error
//
INT DLLEXPORT CALLBACK TrackMeter_SizeToText(
DWORD flStyle, DWORD flExtStyle, HFONT hFont, LPSTR pszText)
{
// this control has no text to resize, so do nothing
//
return -1;
}
LRESULT DLLEXPORT CALLBACK TrackMeter_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
BOOL fSuccess = TRUE;
LPTMETER lptm = (LPTMETER) GetWindowLongPtr(hwnd, GWL_USER);
#if 0
TracePrintf_1(NULL, 1,
TEXT("msg 0x%X\n"),
(unsigned int) msg);
#endif
switch (msg)
{
HANDLE_MSG(hwnd, WM_NCCREATE, TrackMeter_OnNCCreate);
HANDLE_MSG(lptm, WM_NCDESTROY, TrackMeter_OnNCDestroy);
HANDLE_MSG(lptm, WM_CREATE, TrackMeter_OnCreate);
HANDLE_MSG(lptm, WM_DESTROY, TrackMeter_OnDestroy);
HANDLE_MSG(lptm, WM_SIZE, TrackMeter_OnSize);
HANDLE_MSG(lptm, WM_ERASEBKGND, TrackMeter_OnEraseBkgnd);
HANDLE_MSG(lptm, WM_PAINT, TrackMeter_OnPaint);
HANDLE_MSG(lptm, WM_COMMAND, TrackMeter_OnCommand);
HANDLE_MSG(lptm, WM_SETFOCUS, TrackMeter_OnSetFocus);
HANDLE_MSG(lptm, WM_KILLFOCUS, TrackMeter_OnKillFocus);
HANDLE_MSG(lptm, WM_ENABLE, TrackMeter_OnEnable);
HANDLE_MSG(lptm, WM_GETDLGCODE, TrackMeter_OnGetDlgCode);
HANDLE_MSG(lptm, WM_KEYDOWN, TrackMeter_OnKey);
HANDLE_MSG(lptm, WM_KEYUP, TrackMeter_OnKey);
HANDLE_MSG(lptm, WM_LBUTTONDOWN, TrackMeter_OnLButtonDown);
HANDLE_MSG(lptm, WM_LBUTTONUP, TrackMeter_OnLButtonUp);
// HANDLE_MSG(lptm, WM_RBUTTONDOWN, TrackMeter_OnRButtonDown);
// HANDLE_MSG(lptm, WM_RBUTTONUP, TrackMeter_OnRButtonUp);
HANDLE_MSG(lptm, WM_MOUSEMOVE, TrackMeter_OnMouseMove);
HANDLE_MSG(lptm, WM_CAPTURECHANGED, TrackMeter_OnCaptureChanged);
HANDLE_MSG(lptm, TMM_GETPOS, TrackMeter_OnTMMGetPos);
HANDLE_MSG(lptm, TMM_SETPOS, TrackMeter_OnTMMSetPos);
HANDLE_MSG(lptm, TMM_GETRANGEMIN, TrackMeter_OnTMMGetRangeMin);
HANDLE_MSG(lptm, TMM_SETRANGEMIN, TrackMeter_OnTMMSetRangeMin);
HANDLE_MSG(lptm, TMM_GETRANGEMAX, TrackMeter_OnTMMGetRangeMax);
HANDLE_MSG(lptm, TMM_SETRANGEMAX, TrackMeter_OnTMMSetRangeMax);
HANDLE_MSG(lptm, TMM_SETRANGE, TrackMeter_OnTMMSetRange);
HANDLE_MSG(lptm, TMM_GETLEVEL, TrackMeter_OnTMMGetLevel);
HANDLE_MSG(lptm, TMM_SETLEVEL, TrackMeter_OnTMMSetLevel);
HANDLE_MSG(lptm, TMM_GETCOLOR, TrackMeter_OnTMMGetColor);
HANDLE_MSG(lptm, TMM_SETCOLOR, TrackMeter_OnTMMSetColor);
default:
return TrackMeter_DefProc(hwnd, msg, wParam, lParam);
}
return (LRESULT) TRUE;
}
////
// helper functions
////
static BOOL TrackMeter_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
BOOL fSuccess = TRUE;
LPTMETER lptm;
// create control struct and associate it with window
//
if ((lptm = (LPTMETER) GetWindowLongPtr(hwnd, GWL_USER)) == NULL &&
(lptm = (LPTMETER) MemAlloc(NULL, sizeof(TMETER), 0)) == NULL)
{
fSuccess = TraceFALSE(NULL);
return FALSE;
}
else
{
lptm->hwnd = hwnd;
SetWindowLongPtr(hwnd, GWL_USER, (LONG_PTR) lptm);
}
return FORWARD_WM_NCCREATE(hwnd, lpCreateStruct, DefWindowProc);
}
static void TrackMeter_OnNCDestroy(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
// destroy control struct and disassociate it from window
//
if (lptm != NULL)
{
HWND hwnd = lptm->hwnd;
SetWindowLongPtr(hwnd, GWL_USER, (LPARAM) NULL);
if ((lptm = MemFree(NULL, lptm)) != NULL)
fSuccess = TraceFALSE(NULL);
FORWARD_WM_NCDESTROY(hwnd, DefWindowProc);
}
}
static BOOL TrackMeter_OnCreate(LPTMETER lptm, CREATESTRUCT FAR* lpCreateStruct)
{
BOOL fSuccess = TRUE;
HWND hwnd = lptm->hwnd;
LPVOID lpParam = (LPVOID) lpCreateStruct->lpCreateParams;
HDC hdc = NULL;
if ((hdc = GetDC(hwnd)) == NULL)
fSuccess = TraceFALSE(NULL);
else if ((lptm->hdcCompat = CreateCompatibleDC(hdc)) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->hwndParent = lpCreateStruct->hwndParent;
lptm->hdcCompat = lptm->hdcCompat; // recalc during WM_CREATE
lptm->hbmpSave = NULL;
lptm->hbmpCompat = NULL;
lptm->lPosition = 0;
lptm->lMinimum = 0;
lptm->lMaximum = 100;
lptm->lLevel = 0;
lptm->lLineSize = 1;
lptm->lPageSize = lptm->lPageSize; // recalc later
lptm->fHasFocus = FALSE;
lptm->fIsEnabled = TRUE;
lptm->fIsThumbPressed = FALSE;
lptm->dwFlags = 0;
TrackMeter_Recalc(lptm, TMR_ALL);
}
if (hdc != NULL)
ReleaseDC(hwnd, hdc);
return fSuccess ? 1 : -1;
}
static void TrackMeter_OnDestroy(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
SelectObject(lptm->hdcCompat, lptm->hbmpSave);
if (lptm->hbmpCompat != NULL && !DeleteObject(lptm->hbmpCompat))
fSuccess = TraceFALSE(NULL);
else
lptm->hbmpCompat = NULL;
if (lptm->hdcCompat != NULL && !DeleteDC(lptm->hdcCompat))
fSuccess = TraceFALSE(NULL);
else
lptm->hdcCompat = NULL;
}
static void TrackMeter_OnSize(LPTMETER lptm, UINT state, int cx, int cy)
{
BOOL fSuccess = TRUE;
HWND hwnd = lptm->hwnd;
TracePrintf_3(NULL, 6,
TEXT("WM_SIZE, state=%u, cx=%d, cy=%d\n"),
(unsigned) state,
(int) cx,
(int) cy);
switch (state)
{
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
{
HDC hdc = NULL;
HBITMAP hbmpTemp = NULL;
if ((hdc = GetDC(hwnd)) == NULL)
fSuccess = TraceFALSE(NULL);
else if (TrackMeter_Recalc(lptm, TMR_TRACK | TMR_METER | TMR_LEVEL | TMR_THUMB) != 0)
fSuccess = TraceFALSE(NULL);
else if ((hbmpTemp = CreateCompatibleBitmap(hdc, cx, cy)) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->hbmpSave = SelectObject(lptm->hdcCompat, hbmpTemp);
if (lptm->hbmpCompat != NULL && !DeleteObject(lptm->hbmpCompat))
fSuccess = TraceFALSE(NULL);
else
lptm->hbmpCompat = hbmpTemp;
}
if (hdc != NULL)
ReleaseDC(hwnd, hdc);
InvalidateRect(hwnd, NULL, FALSE);
}
break;
default:
break;
}
}
static BOOL TrackMeter_OnEraseBkgnd(LPTMETER lptm, HDC hdc)
{
BOOL fSuccess = TRUE;
// we do nothing
//
return fSuccess;
}
static void TrackMeter_OnPaint(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
PAINTSTRUCT ps;
BOOL fBitBlt = TRUE;
HDC hdc;
//
// We have tot ake care for EndPaint
//
if (!BeginPaint(lptm->hwnd, &ps))
{
fSuccess = TraceFALSE(NULL);
}
else
{
if ((hdc = (fBitBlt ? lptm->hdcCompat : ps.hdc)) == NULL)
{
EndPaint( lptm->hwnd, &ps);
fSuccess = TraceFALSE(NULL);
}
else if (TrackMeter_Draw(lptm, hdc))
{
EndPaint( lptm->hwnd, &ps);
fSuccess = TraceFALSE(NULL);
}
else if (!EndPaint(lptm->hwnd, &ps))
fSuccess = TraceFALSE(NULL);
else if (fBitBlt && !BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
lptm->hdcCompat, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY))
{
fSuccess = TraceFALSE(NULL);
}
}
}
static int TrackMeter_Draw(LPTMETER lptm, HDC hdc)
{
BOOL fSuccess = TRUE;
HPEN hpenOld = GetCurrentObject(hdc, OBJ_PEN);
HBRUSH hbrushOld = GetCurrentObject(hdc, OBJ_BRUSH);
LONG_PTR LPStyle = GetWindowLongPtr(lptm->hwnd, GWL_STYLE);
BOOL fDrawThumb = !(LPStyle & TMS_NOTHUMB);
// draw background of control
//
if (1)
{
HBRUSH hbrushCtrlBackground;
if ((hbrushCtrlBackground = CreateSolidBrush(lptm->acr[TMCR_CTRLBACKGROUND])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
if (!FillRect(hdc, &lptm->rcCtrl, hbrushCtrlBackground))
fSuccess = TraceFALSE(NULL);
if (!DeleteObject(hbrushCtrlBackground))
fSuccess = TraceFALSE(NULL);
}
}
// draw background of track
//
if (1)
{
HBRUSH hbrushTrackBackground;
if ((hbrushTrackBackground = CreateSolidBrush(lptm->acr[TMCR_TRACKBACKGROUND])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
if (!FillRect(hdc, &lptm->rcTrack, hbrushTrackBackground))
fSuccess = TraceFALSE(NULL);
if (!DeleteObject(hbrushTrackBackground))
fSuccess = TraceFALSE(NULL);
}
}
// draw track light
//
if (1)
{
HPEN hpenTrackLight;
if ((hpenTrackLight = CreatePen(PS_SOLID, 1, lptm->acr[TMCR_TRACKLIGHT])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
SelectObject(hdc, hpenTrackLight);
MoveToEx(hdc, lptm->rcTrack.right, lptm->rcTrack.top, NULL);
LineTo(hdc, lptm->rcTrack.right, lptm->rcTrack.bottom + 1);
MoveToEx(hdc, lptm->rcTrack.right, lptm->rcTrack.bottom, NULL);
LineTo(hdc, lptm->rcTrack.left - 1, lptm->rcTrack.bottom);
if (!DeleteObject(hpenTrackLight))
fSuccess = TraceFALSE(NULL);
}
}
// draw track shadow
//
if (1)
{
HPEN hpenTrackShadow;
if ((hpenTrackShadow = CreatePen(PS_SOLID, 1,
lptm->fIsEnabled ? lptm->acr[TMCR_TRACKSHADOW] :
lptm->acr[TMCR_CTRLBACKGROUND])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
SelectObject(hdc, hpenTrackShadow);
MoveToEx(hdc, lptm->rcTrack.left, lptm->rcTrack.top, NULL);
LineTo(hdc, lptm->rcTrack.right, lptm->rcTrack.top);
MoveToEx(hdc, lptm->rcTrack.left, lptm->rcTrack.top, NULL);
LineTo(hdc, lptm->rcTrack.left, lptm->rcTrack.bottom);
if (!DeleteObject(hpenTrackShadow))
fSuccess = TraceFALSE(NULL);
}
}
// draw track dark shadow
//
if (1)
{
HPEN hpenTrackDkShadow;
if ((hpenTrackDkShadow = CreatePen(PS_SOLID, 1,
lptm->fIsEnabled ? lptm->acr[TMCR_TRACKDKSHADOW] :
lptm->acr[TMCR_TRACKSHADOW])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
SelectObject(hdc, hpenTrackDkShadow);
MoveToEx(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.top + 1, NULL);
LineTo(hdc, lptm->rcTrack.right - 1, lptm->rcTrack.top + 1);
MoveToEx(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.top + 1, NULL);
LineTo(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.bottom - 1);
if (!DeleteObject(hpenTrackDkShadow))
fSuccess = TraceFALSE(NULL);
}
}
// fill track up to current level
//
if (lptm->fIsEnabled && lptm->lLevel > lptm->lMinimum)
{
HBRUSH hbrushLevel;
if ((hbrushLevel = CreateSolidBrush(lptm->acr[TMCR_LEVEL])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
FillRect(hdc, &lptm->rcLevel, hbrushLevel);
if (!DeleteObject(hbrushLevel))
fSuccess = TraceFALSE(NULL);
}
}
// fill thumb region
//
if (fDrawThumb)
{
HRGN hrgnThumb;
if ((hrgnThumb = CreatePolygonRgn(lptm->aptThumb,
(sizeof(lptm->aptThumb)/sizeof(lptm->aptThumb[0])), WINDING)) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
HBRUSH hbrushThumbFace;
if ((hbrushThumbFace = CreateSolidBrush(lptm->acr[lptm->fIsThumbPressed ?
TMCR_THUMBFACEPRESSED : TMCR_THUMBFACE])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
if (!FillRgn(hdc, hrgnThumb, hbrushThumbFace))
fSuccess = TraceFALSE(NULL);
if (!DeleteObject(hbrushThumbFace))
fSuccess = TraceFALSE(NULL);
}
if (!DeleteObject(hrgnThumb))
fSuccess = TraceFALSE(NULL);
}
}
// draw thumb light
//
if (fDrawThumb)
{
HPEN hpenThumbLight;
if ((hpenThumbLight = CreatePen(PS_SOLID, 1,
lptm->fIsEnabled ? lptm->acr[TMCR_THUMBLIGHT] :
lptm->acr[TMCR_THUMBSHADOW])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
SelectObject(hdc, hpenThumbLight);
MoveToEx(hdc, lptm->aptThumb[0].x, lptm->aptThumb[0].y, NULL);
LineTo(hdc, lptm->aptThumb[1].x - 1, lptm->aptThumb[1].y + 1);
MoveToEx(hdc, lptm->aptThumb[1].x, lptm->aptThumb[1].y, NULL);
LineTo(hdc, lptm->aptThumb[2].x, lptm->aptThumb[2].y);
if (!DeleteObject(hpenThumbLight))
fSuccess = TraceFALSE(NULL);
}
}
// draw thumb dark shadow
//
if (fDrawThumb)
{
HPEN hpenThumbDkShadow;
if ((hpenThumbDkShadow = CreatePen(PS_SOLID, 1,
lptm->fIsEnabled ? lptm->acr[TMCR_THUMBDKSHADOW] :
lptm->acr[TMCR_THUMBLIGHT])) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
SelectObject(hdc, hpenThumbDkShadow);
MoveToEx(hdc, lptm->aptThumb[2].x, lptm->aptThumb[2].y, NULL);
LineTo(hdc, lptm->aptThumb[3].x + 1, lptm->aptThumb[3].y);
MoveToEx(hdc, lptm->aptThumb[3].x, lptm->aptThumb[3].y, NULL);
LineTo(hdc, lptm->aptThumb[4].x, lptm->aptThumb[4].y - 1);
MoveToEx(hdc, lptm->aptThumb[4].x, lptm->aptThumb[4].y, NULL);
LineTo(hdc, lptm->aptThumb[0].x, lptm->aptThumb[0].y);
if (!DeleteObject(hpenThumbDkShadow))
fSuccess = TraceFALSE(NULL);
}
}
// draw focus border, if necessary
//
if (lptm->fHasFocus)
{
COLORREF crBkColorOld = SetBkColor(hdc, lptm->acr[TMCR_FOCUSBACKGROUND]);
if (!DrawFocusRect(hdc, &lptm->rcCtrl))
fSuccess = TraceFALSE(NULL);
SetBkColor(hdc, crBkColorOld);
}
// cleanup
//
if (hpenOld != NULL)
SelectObject(hdc, hpenOld);
if (hbrushOld != NULL)
SelectObject(hdc, hbrushOld);
return fSuccess ? 0 : -1;
}
static void TrackMeter_OnCommand(LPTMETER lptm, int id, HWND hwndCtl, UINT codeNotify)
{
}
static void TrackMeter_OnSetFocus(LPTMETER lptm, HWND hwndOldFocus)
{
BOOL fSuccess = TRUE;
TracePrintf_0(NULL, 6,
TEXT("WM_SETFOCUS\n"));
lptm->fHasFocus = TRUE;
if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
static void TrackMeter_OnKillFocus(LPTMETER lptm, HWND hwndNewFocus)
{
BOOL fSuccess = TRUE;
TracePrintf_0(NULL, 6,
TEXT("WM_KILLFOCUS\n"));
lptm->fHasFocus = FALSE;
if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
static void TrackMeter_OnEnable(LPTMETER lptm, BOOL fEnable)
{
BOOL fSuccess = TRUE;
TracePrintf_1(NULL, 6,
TEXT("WM_ENABLE, fEnable=%d\n"),
(int) fEnable);
lptm->fIsEnabled = fEnable;
if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
static UINT TrackMeter_OnGetDlgCode(LPTMETER lptm, LPMSG lpmsg)
{
return DLGC_WANTARROWS;
}
static void TrackMeter_OnKey(LPTMETER lptm, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
UINT code = 0;
UINT nPos = 0;
LONG lPosition;
switch (vk)
{
case VK_UP:
case VK_RIGHT:
lPosition = lptm->lPosition + lptm->lLineSize;
code = TB_LINEDOWN;
break;
case VK_DOWN:
case VK_LEFT:
lPosition = lptm->lPosition - lptm->lLineSize;
code = TB_LINEUP;
break;
case VK_NEXT:
lPosition = lptm->lPosition + lptm->lPageSize;
code = TB_PAGEDOWN;
break;
case VK_PRIOR:
lPosition = lptm->lPosition - lptm->lPageSize;
code = TB_PAGEUP;
break;
case VK_HOME:
lPosition = lptm->lMinimum;
code = TB_TOP;
break;
case VK_END:
lPosition = lptm->lMaximum;
code = TB_BOTTOM;
break;
default:
return;
}
// Adjust position of thumb
if (fDown)
{
// we change the current position for WM_KEYDOWN only
TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
TrackMeter_NotifyParent(lptm, code, 0);
}
TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
}
static void TrackMeter_OnLButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
SetFocus(lptm->hwnd);
SetCapture(lptm->hwnd);
TracePrintf_3(NULL, 6,
TEXT("WM_LBUTTONDOWN, fDoubleClick=%d, x=%d, y=%d\n"),
(int) fDoubleClick,
(int) x,
(int) y);
if (TrackMeter_PtInThumb(lptm, x, y))
{
lptm->fIsThumbPressed = TRUE;
TrackMeter_OnMouseMove(lptm, x, y, 0);
}
else if (x < lptm->aptThumb[0].x)
TrackMeter_OnKey(lptm, VK_PRIOR, TRUE, 1, 0);
else if (x > lptm->aptThumb[0].x)
TrackMeter_OnKey(lptm, VK_NEXT, TRUE, 1, 0);
}
static void TrackMeter_OnLButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags)
{
TracePrintf_2(NULL, 6,
TEXT("WM_LBUTTONUP, x=%d, y=%d\n"),
(int) x,
(int) y);
ReleaseCapture();
if (lptm->fIsThumbPressed)
{
LONG lPosition = TrackMeter_XToPosition(lptm, x);
lptm->fIsThumbPressed = FALSE;
TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, TRUE); // just redraw
if (lPosition >= lptm->lMinimum && lPosition <= lptm->lMaximum)
TrackMeter_NotifyParent(lptm, TB_THUMBPOSITION, lptm->lPosition);
}
TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
}
static void TrackMeter_OnRButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
SetFocus(lptm->hwnd);
SetCapture(lptm->hwnd);
TracePrintf_3(NULL, 6,
TEXT("WM_RBUTTONDOWN, fDoubleClick=%d, x=%d, y=%d\n"),
(int) fDoubleClick,
(int) x,
(int) y);
if (TrackMeter_PtInThumb(lptm, x, y))
{
LONG lPosition = TrackMeter_XToPosition(lptm, x);
lptm->fIsThumbPressed = TRUE;
TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
TrackMeter_OnMouseMove(lptm, lptm->aptThumb[0].x, y, 0);
TrackMeter_NotifyParent(lptm, TB_THUMBPOSITION, lptm->lPosition);
}
}
static void TrackMeter_OnRButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags)
{
TracePrintf_2(NULL, 6,
TEXT("WM_RBUTTONUP, x=%d, y=%d\n"),
(int) x,
(int) y);
ReleaseCapture();
if ( lptm->fIsThumbPressed )
TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
}
static void TrackMeter_OnMouseMove(LPTMETER lptm, int x, int y, UINT keyFlags)
{
if (lptm->fIsThumbPressed)
{
LONG lPosition = TrackMeter_XToPosition(lptm, x);
TracePrintf_2(NULL, 6,
TEXT("WM_MOUSEMOVE, x=%d, y=%d\n"),
(int) x,
(int) y);
if (lPosition != lptm->lPosition)
{
TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
TrackMeter_NotifyParent(lptm, TB_THUMBTRACK, lptm->lPosition);
}
}
}
static void TrackMeter_OnCaptureChanged(LPTMETER lptm, HWND hwndNewCapture)
{
TracePrintf_0(NULL, 6,
TEXT("WM_CAPTURECHANGED\n"));
}
static void TrackMeter_NotifyParent(LPTMETER lptm, UINT code, UINT nPos)
{
if (TraceGetLevel(NULL) >= 6)
{
LPTSTR lpszCode;
switch (code)
{
case TB_LINEUP:
lpszCode = TEXT("LB_LINEUP");
break;
case TB_LINEDOWN:
lpszCode = TEXT("LB_LINEDOWN");
break;
case TB_PAGEUP:
lpszCode = TEXT("LB_PAGEUP");
break;
case TB_PAGEDOWN:
lpszCode = TEXT("LB_PAGEDOWN");
break;
case TB_TOP:
lpszCode = TEXT("LB_TOP");
break;
case TB_BOTTOM:
lpszCode = TEXT("LB_BOTTOM");
break;
case TB_ENDTRACK:
lpszCode = TEXT("LB_ENDTRACK");
break;
case TB_THUMBTRACK:
lpszCode = TEXT("LB_THUMBTRACK");
break;
case TB_THUMBPOSITION:
lpszCode = TEXT("LB_THUMBPOSITION");
break;
default:
lpszCode = TEXT("***unknown***");
break;
}
TracePrintf_4(NULL, 6,
TEXT("WM_HSCROLL, %s, code=%u, nPos=%u, lPosition=%ld\n"),
(LPTSTR) lpszCode,
(unsigned) code,
(unsigned) nPos,
(long) lptm->lPosition);
}
if (1) // $FIXUP - check for horizontal style here
{
FORWARD_WM_HSCROLL(lptm->hwndParent,
lptm->hwnd, code, nPos, SendMessage);
}
else
{
FORWARD_WM_VSCROLL(lptm->hwndParent,
lptm->hwnd, code, nPos, SendMessage);
}
}
static LONG TrackMeter_OnTMMGetPos(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
LONG lPosition = 0;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
lPosition = lptm->lPosition;
return lPosition;
}
static void TrackMeter_OnTMMSetPos(LPTMETER lptm, LONG lPosition, BOOL fRedraw)
{
BOOL fSuccess = TRUE;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->lPosition = max(lptm->lMinimum,
min(lPosition, lptm->lMaximum));
if (TrackMeter_Recalc(lptm, TMR_THUMB) != 0)
fSuccess = TraceFALSE(NULL);
if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
}
static LONG TrackMeter_OnTMMGetRangeMin(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
LONG lMinimum = 0;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
lMinimum = lptm->lMinimum;
return lMinimum;
}
static void TrackMeter_OnTMMSetRangeMin(LPTMETER lptm, LONG lMinimum, BOOL fRedraw)
{
BOOL fSuccess = TRUE;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->lMinimum = lMinimum;
// adjust position and level if necessary
//
TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, FALSE);
TrackMeter_OnTMMSetLevel(lptm, lptm->lLevel, FALSE);
if (TrackMeter_Recalc(lptm, TMR_PAGESIZE) != 0)
fSuccess = TraceFALSE(NULL);
if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
}
static LONG TrackMeter_OnTMMGetRangeMax(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
LONG lMaximum = 0;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
lMaximum = lptm->lMaximum;
return lMaximum;
}
static void TrackMeter_OnTMMSetRangeMax(LPTMETER lptm, LONG lMaximum, BOOL fRedraw)
{
BOOL fSuccess = TRUE;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->lMaximum = lMaximum;
// adjust position and level if necessary
//
TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, FALSE);
TrackMeter_OnTMMSetLevel(lptm, lptm->lLevel, FALSE);
if (TrackMeter_Recalc(lptm, TMR_PAGESIZE) != 0)
fSuccess = TraceFALSE(NULL);
if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
}
static void TrackMeter_OnTMMSetRange(LPTMETER lptm, LONG lMinimum, LONG lMaximum, BOOL fRedraw)
{
TrackMeter_OnTMMSetRangeMin(lptm, lMinimum, FALSE);
TrackMeter_OnTMMSetRangeMax(lptm, lMaximum, fRedraw);
}
static LONG TrackMeter_OnTMMGetLevel(LPTMETER lptm)
{
BOOL fSuccess = TRUE;
LONG lLevel = 0;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
lLevel = lptm->lLevel;
return lLevel;
}
static void TrackMeter_OnTMMSetLevel(LPTMETER lptm, LONG lLevel, BOOL fRedraw)
{
BOOL fSuccess = TRUE;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->lLevel = max(lptm->lMinimum,
min(lLevel, lptm->lMaximum));
if (TrackMeter_Recalc(lptm, TMR_LEVEL) != 0)
fSuccess = TraceFALSE(NULL);
if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
}
static COLORREF TrackMeter_OnTMMGetColor(LPTMETER lptm, UINT elem)
{
BOOL fSuccess = TRUE;
COLORREF cr = RGB(0, 0, 0);
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
cr = lptm->acr[elem];
return cr;
}
static void TrackMeter_OnTMMSetColor(LPTMETER lptm, COLORREF cr, UINT elem, BOOL fRedraw)
{
BOOL fSuccess = TRUE;
if (lptm == NULL)
fSuccess = TraceFALSE(NULL);
else
{
lptm->acr[elem] = cr;
if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
fSuccess = TraceFALSE(NULL);
}
}
static int TrackMeter_Recalc(LPTMETER lptm, DWORD dwFlags)
{
BOOL fSuccess = TRUE;
if (!GetClientRect(lptm->hwnd, &lptm->rcCtrl))
fSuccess = TraceFALSE(NULL);
else
{
int cxCtrl = lptm->rcCtrl.right - lptm->rcCtrl.left;
int cyCtrl = lptm->rcCtrl.bottom - lptm->rcCtrl.top;
int cxBorder = 2;
int cyBorder = 2;
int cxThumb = ((cyCtrl - cyBorder - cyBorder) / 2) * 2 - 1;
int cyThumb = cxThumb - 2;
int cyTrackTopBorder = 2;
int cxTrackLeftBorder = 2;
int cxTrackRightBorder = 2;
int cyTrackBottomBorder = 1;
int xTrack = cxThumb / 2 - cxTrackLeftBorder + cxBorder;
int yTrack = cyBorder;
int cxTrack = cxCtrl - xTrack - xTrack;
int cyTrack = (cyCtrl - cyBorder - cyBorder) / 2 + 1;
int xMeter = xTrack + cxTrackLeftBorder;
int yMeter = yTrack + cyTrackTopBorder;
int cxMeter = cxTrack - cxTrackLeftBorder - cxTrackRightBorder;
int cyMeter = cyTrack - cyTrackTopBorder - cyTrackBottomBorder;
if (dwFlags & TMR_TRACK)
{
lptm->rcTrack.left = xTrack;
lptm->rcTrack.top = yTrack;
lptm->rcTrack.right = xTrack + cxTrack - 1;
lptm->rcTrack.bottom = yTrack + cyTrack - 1;
}
if (dwFlags & TMR_METER)
{
lptm->rcMeter.left = xMeter;
lptm->rcMeter.top = yMeter;
lptm->rcMeter.right = xMeter + cxMeter - 1;
lptm->rcMeter.bottom = yMeter + cyMeter;
}
if (dwFlags & TMR_LEVEL)
{
lptm->rcLevel.left = xMeter;
lptm->rcLevel.top = yMeter;
lptm->rcLevel.right = TrackMeter_PositionToX(lptm, lptm->lLevel) + 1;
lptm->rcLevel.bottom = yMeter + cyMeter;
}
if (dwFlags & TMR_THUMB)
{
lptm->aptThumb[0].x = TrackMeter_PositionToX(lptm, lptm->lPosition);
lptm->aptThumb[0].y = cyCtrl - cyBorder - cyThumb;
lptm->aptThumb[1].x = lptm->aptThumb[0].x - (cxThumb / 2);
lptm->aptThumb[1].y = lptm->aptThumb[0].y + (cyThumb / 2) + 1;
lptm->aptThumb[2].x = lptm->aptThumb[1].x;
lptm->aptThumb[2].y = lptm->aptThumb[0].y + cyThumb - 1;
lptm->aptThumb[3].x = lptm->aptThumb[2].x + cxThumb - 1;
lptm->aptThumb[3].y = lptm->aptThumb[2].y;
lptm->aptThumb[4].x = lptm->aptThumb[3].x;
lptm->aptThumb[4].y = lptm->aptThumb[1].y;
}
if (dwFlags & TMR_COLORS)
{
COLORREF crWindow = GetSysColor(COLOR_WINDOW);
COLORREF cr3DFace = GetSysColor(COLOR_3DFACE);
COLORREF cr3DLight = GetSysColor(COLOR_3DLIGHT);
COLORREF cr3DHilight = GetSysColor(COLOR_3DHILIGHT);
COLORREF cr3DShadow = GetSysColor(COLOR_3DSHADOW);
COLORREF cr3DDkShadow = GetSysColor(COLOR_3DDKSHADOW);
COLORREF crGreen = RGB(0, 128, 0);
// try to make cr3DLight distinctive
//
if (cr3DLight == cr3DFace || cr3DLight == cr3DHilight)
{
HDC hdc = NULL;
int nColors;
if ((hdc = GetDC(NULL)) == NULL)
fSuccess = TraceFALSE(NULL);
// make sure screen device has more than 8 bits per pixel
//
else if ((nColors = GetDeviceCaps(hdc, NUMCOLORS)) == -1)
{
cr3DLight = RGB((GetRValue(cr3DFace) + GetRValue(cr3DHilight)) / 2,
(GetGValue(cr3DFace) + GetGValue(cr3DHilight)) / 2,
(GetBValue(cr3DFace) + GetBValue(cr3DHilight)) / 2);
}
else
{
cr3DLight = cr3DHilight;
}
if (hdc != NULL && !ReleaseDC(NULL, hdc))
fSuccess = TraceFALSE(NULL);
}
lptm->acr[TMCR_CTRLBACKGROUND] = cr3DFace;
lptm->acr[TMCR_FOCUSBACKGROUND] = crWindow;
lptm->acr[TMCR_TRACKBACKGROUND] = cr3DLight;
lptm->acr[TMCR_TRACKLIGHT] = cr3DHilight;
lptm->acr[TMCR_TRACKSHADOW] = cr3DShadow;
lptm->acr[TMCR_TRACKDKSHADOW] = cr3DDkShadow;
lptm->acr[TMCR_THUMBFACE] = cr3DFace;
lptm->acr[TMCR_THUMBFACEPRESSED] = cr3DLight;
lptm->acr[TMCR_THUMBLIGHT] = cr3DHilight;
lptm->acr[TMCR_THUMBSHADOW] = cr3DShadow;
lptm->acr[TMCR_THUMBDKSHADOW] = cr3DDkShadow;
lptm->acr[TMCR_LEVEL] = crGreen;
}
if (dwFlags & TMR_PAGESIZE)
{
lptm->lPageSize = max(1, (lptm->lMaximum - lptm->lMinimum) / 5);
}
}
return fSuccess ? 0 : -1;
}
// given lPosition between lptm->lMinimum and lptm->lMaximum,
// return x coordinate between lptm->rcMeter.left and lptm->rcMeter.right
//
static int TrackMeter_PositionToX(LPTMETER lptm, long lPosition)
{
long lPos = max(lptm->lMinimum, min(lPosition, lptm->lMaximum));
long lPct = ((1000 * (lPos - lptm->lMinimum) /
max(1, lptm->lMaximum - lptm->lMinimum)) + 5) / 10;
int cxMeter = lptm->rcMeter.right - lptm->rcMeter.left + 1;
long cxPosition = ((10 * max(0, min(100, lPct)) * cxMeter / 100) + 5) / 10;
int xPosition = max(lptm->rcMeter.left, lptm->rcMeter.left + min(cxPosition, cxMeter) - 1);
return xPosition;
}
// given x coordinate between lptm->rcMeter.left and lptm->rcMeter.right,
// return lPosition between lptm->lMinimum and lptm->lMaximum
//
static long TrackMeter_XToPosition(LPTMETER lptm, int xPosition)
{
int x = max(lptm->rcMeter.left, min(xPosition, lptm->rcMeter.right));
long lPct = ((1000 * (x - lptm->rcMeter.left) /
max(1, lptm->rcMeter.right - lptm->rcMeter.left)) + 5) / 10;
long lRange = lptm->lMaximum - lptm->lMinimum + 1;
long cxPosition = ((10 * max(0, min(100, lPct)) * lRange / 100) + 5) / 10;
long lPosition = max(lptm->lMinimum, lptm->lMinimum + min(cxPosition, lRange) - 1);
return lPosition;
}
static BOOL TrackMeter_PtInThumb(LPTMETER lptm, int x, int y)
{
BOOL fSuccess = TRUE;
BOOL fInThumb = FALSE;
HRGN hrgnThumb;
if ((hrgnThumb = CreatePolygonRgn(lptm->aptThumb,
(sizeof(lptm->aptThumb) / sizeof(lptm->aptThumb[0])), WINDING)) == NULL)
fSuccess = TraceFALSE(NULL);
else
{
if (PtInRegion(hrgnThumb, x, y))
fInThumb = TRUE;
if (!DeleteObject(hrgnThumb))
fSuccess = TraceFALSE(NULL);
}
return fInThumb;
}