Category : Files from Magazines
Archive   : WDFEB92.ZIP
Filename : 3N02018A

 
Output of file : 3N02018A contained in archive : WDFEB92.ZIP
/* fader.c - main code for fader custom control */

#include
#include "fader.h"

#define NO_DRAG 0 /* Values of FADER_THUMBSTATE */
#define DRAG 1

#define FADER_THUMB_OFFSET 2 /* Distance in pixels from edge */

/* Window extra bytes */
#define FADER_RANGE 0 /* logical range values returned */
#define FADER_VALUE 4 /* Current logical value */
#define FADER_THUMBSTATE 6 /* DRAG or NO_DRAG */
#define FADER_WNDEXTRA 8 /* Total # of window extra bytes */

HANDLE hGlobFaderInstance = NULL;
char szGlobControlName[] = "Fader";

/* Forward declarations for completeness */

static BOOL NEAR PASCAL RegisterControlClass (HANDLE hInstance);
LONG FAR PASCAL FaderWndFn (HWND hWnd, WORD wMsg,
WORD wParam, LONG lParam);
int GetThumbHeight(int iTotalHeight);
void GetFaderThumbRect(HWND hWnd, LPRECT pRc, LPRECT pThumbRect,
int iCurPos);
int XlatPosPhysicalToLogical(LONG lLogRange, int iPhysMax,
int iPhysMin, int iCurPos);
int XlatPosLogicalToPhysical(LONG lLogRange, int iPhysMax,
int iPhysMin, int iLogPos);
static void DrawCaret(HDC hDC, LPRECT lprc);
static void PaintFader(HWND hWnd);

/* These are DLL initialization and control functions */

BOOL FAR PASCAL LibMain (HANDLE hModule, WORD wDataSeg,
WORD wHeapSize, LPSTR lpszCmdLine)
{
hGlobFaderInstance = hModule;
if (wHeapSize != 0) /* Moveable DS */
UnlockData(0);
return RegisterControlClass(hModule);
}


int FAR PASCAL WEP (int nSystemExit)
{
UnregisterClass(szGlobControlName, hGlobFaderInstance);
return 1; /* never fails */
}


/* This function can be static if you only plan to use it
in a DLL */

BOOL NEAR PASCAL RegisterControlClass (HANDLE hInstance)
{
WNDCLASS wc;

wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = FaderWndFn;
wc.cbClsExtra = 0;
wc.cbWndExtra = FADER_WNDEXTRA;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_SIZENS);
wc.hbrBackground = COLOR_WINDOW + 1;
wc.lpszMenuName = NULL;
wc.lpszClassName = szGlobControlName;
return RegisterClass(&wc);
}


/* This function is handy for sending the FDRN_... messages
back to the parent. Note that FDRN_THUMBTRACK is disabled
unless FDRS_TRACK is enabled */

static LONG NEAR PASCAL NotifyParent (HWND hWnd,
WORD wNotifyCode)
{
BOOL bSend=TRUE;

if (wNotifyCode == FDRN_THUMBTRACK)
bSend = (BOOL) (GetWindowLong(hWnd, GWL_STYLE) & FDRS_TRACK);

if (bSend)
return SendMessage(GetParent(hWnd), WM_COMMAND,
GetWindowWord(hWnd, GWW_ID),
MAKELONG(hWnd, wNotifyCode));
else
return 0;
}


/* This is the main "window function" procedure, it is called
sometimes by the SDK Dialog box editor */

LONG FAR PASCAL FaderWndFn (HWND hWnd, WORD wMsg,
WORD wParam, LONG lParam)
{
LONG lResult = 0;
HDC hDC;
POINT pt;
RECT rc;
int iLogPos;
int iOldLogPos;
int iPhyPos;
int iMaxLog;
int iMinLog;
RECT thumb_rect;
LONG lLogRange;
int iThumbHalf;
HANDLE hNewBrush, hOldBrush;

switch (wMsg) {
case WM_CREATE:
SendMessage(hWnd, FDRM_SETRANGE, 0, MAKELONG(0, 100));
SendMessage(hWnd, FDRM_SETLOGVALUE, 0, 0);
break;

case WM_GETDLGCODE: /* interface query by dialog manager */
lResult = DLGC_WANTARROWS;
break;

case WM_PAINT:
PaintFader(hWnd);
break;

case WM_SETFOCUS: /* receiving the keyboard focus */
case WM_KILLFOCUS: /* losing the keyboard focus */
/* calculate update region */
GetClientRect(hWnd, &rc);
iLogPos = GetWindowWord(hWnd, FADER_VALUE);
GetFaderThumbRect(hWnd, (LPRECT)&rc, (LPRECT)&thumb_rect,
iLogPos);
if (thumb_rect.left == rc.left)
break;

/* force a repaint */
hDC = GetDC( hWnd );
if (hDC) {
/* define appropriate brush & text colors */
if (hNewBrush = (HBRUSH)SendMessage( GetParent(hWnd),
WM_CTLCOLOR, hDC, MAKELONG(hWnd,CTLCOLOR_BTN) ) )
hOldBrush = SelectObject(hDC,hNewBrush);
else
hOldBrush = NULL;

/* draw caret */
DrawCaret(hDC, (LPRECT)&thumb_rect);

/* restore original brush */
if ( hNewBrush ) {
SelectObject( hDC, hOldBrush );
DeleteObject( hNewBrush );
}

/* release display context */
ReleaseDC( hWnd, hDC );
}
break;

case WM_KEYDOWN: /* process virtual key code */
GetClientRect(hWnd, &rc);
iLogPos = (int)GetWindowWord(hWnd, FADER_VALUE);
iOldLogPos = iLogPos;
lLogRange = GetWindowLong(hWnd, FADER_RANGE);
iMaxLog = HIWORD(lLogRange);
iMinLog = LOWORD(lLogRange);

switch (wParam) {
case VK_HOME : /* home key */
iLogPos = iMinLog;
break;

case VK_END : /* end key */
iLogPos = iMaxLog;
break;

case VK_LEFT : /* cursor left key */
case VK_DOWN : /* cursor down key */
if (iLogPos < iMaxLog)
iLogPos++;
break;

case VK_UP : /* cursor up key */
case VK_RIGHT : /* cursor right key */
if (iLogPos > iMinLog)
iLogPos--;
break;

case VK_PRIOR : /* page up key */
iLogPos -= (iMaxLog - iMinLog) / 8;
if (iLogPos < iMinLog)
iLogPos = iMinLog;
break;

case VK_NEXT : /* page down key */
iLogPos += (iMaxLog - iMinLog) / 8;
if (iLogPos > iMaxLog)
iLogPos = iMaxLog;
break;

default : /* something else */
break;
}

if (iLogPos != iOldLogPos) /* did it change? */
{
SendMessage(hWnd, FDRM_SETLOGVALUE, iLogPos, 0);
NotifyParent(hWnd, FDRN_THUMBTRACK);

/* Invalidate old position */
GetFaderThumbRect(hWnd, (LPRECT)&rc,
(LPRECT)&thumb_rect, iOldLogPos);
InvalidateRect(hWnd, (LPRECT)&thumb_rect, TRUE);

/* Invalidate new position */
GetFaderThumbRect(hWnd, (LPRECT)&rc,
(LPRECT)&thumb_rect, iLogPos);
InvalidateRect(hWnd, (LPRECT)&thumb_rect, TRUE);
}
break;

case WM_LBUTTONDOWN:
GetClientRect(hWnd, &rc);
iLogPos = GetWindowWord(hWnd, FADER_VALUE);
GetFaderThumbRect(hWnd, (LPRECT)&rc, (LPRECT)&thumb_rect, iLogPos);
pt = MAKEPOINT(lParam);
/* is the mouse in the "hot" rectangle? */
if ((thumb_rect.top <= pt.y) && (thumb_rect.bottom >= pt.y) &&
(thumb_rect.left <= pt.x) && (thumb_rect.right >= pt.x)) {
SetWindowWord(hWnd, FADER_THUMBSTATE, DRAG);
hDC = GetDC(hWnd);
InvertRect(hDC, (LPRECT)&thumb_rect);
ReleaseDC(hWnd, hDC);

NotifyParent(hWnd, FDRN_THUMBTRACK);
/* grab focus if necessary */
if ( GetFocus() != hWnd )
SetFocus( hWnd );
/* Lock mouse on to this window */
SetCapture(hWnd);
}
break;

case WM_MOUSEMOVE:
case WM_LBUTTONUP:
/* Nothing to do if not in drag! */
if ((wMsg == WM_MOUSEMOVE) &&
(GetWindowWord(hWnd, FADER_THUMBSTATE) != DRAG) ) {
lResult = DefWindowProc(hWnd, wMsg, wParam, lParam);
break;
}

/* set the new current position and ask for redraw */
pt = MAKEPOINT(lParam);
GetClientRect(hWnd, &rc);
iLogPos = GetWindowWord(hWnd, FADER_VALUE);
lLogRange = GetWindowLong(hWnd, FADER_RANGE);

/* Invalidate old position */
GetFaderThumbRect(hWnd, (LPRECT)&rc, (LPRECT)&thumb_rect, iLogPos);
InvalidateRect(hWnd, (LPRECT)&thumb_rect, TRUE);

iPhyPos = pt.y;
iThumbHalf = GetThumbHeight(rc.bottom)/2;
if (iPhyPos < iThumbHalf)
iPhyPos = iThumbHalf;
if (iPhyPos > rc.bottom-iThumbHalf)
iPhyPos = rc.bottom-iThumbHalf;

iLogPos = XlatPosPhysicalToLogical(lLogRange,
rc.bottom-iThumbHalf, rc.top+iThumbHalf, iPhyPos);
GetFaderThumbRect(hWnd, (LPRECT)&rc, (LPRECT)&thumb_rect, iLogPos);
InvalidateRect(hWnd, (LPRECT)&thumb_rect, TRUE);

SetWindowWord(hWnd, FADER_VALUE, iLogPos);
NotifyParent(hWnd, FDRN_THUMBTRACK);

if (wMsg == WM_LBUTTONUP) {
SetWindowWord(hWnd, FADER_THUMBSTATE, NO_DRAG);
NotifyParent(hWnd, FDRN_ENDFADER);
ReleaseCapture();
}
break;

case FDRM_SETRANGE:
GetClientRect(hWnd, &rc);
InvalidateRect(hWnd, (LPRECT)&rc, TRUE);
SetWindowLong(hWnd, FADER_RANGE, lParam);
break;

case FDRM_GETRANGE:
lResult = GetWindowLong(hWnd, FADER_RANGE);
break;

case FDRM_SETLOGVALUE:
GetClientRect(hWnd, &rc);
InvalidateRect(hWnd, (LPRECT)&rc, TRUE);
SetWindowWord(hWnd, FADER_VALUE, wParam);
break;

case FDRM_GETLOGVALUE:
lResult = GetWindowWord(hWnd, FADER_VALUE);
break;

case FDRM_GETPHYSVALUE:
GetClientRect(hWnd, &rc);
iThumbHalf = GetThumbHeight(rc.bottom)/2;
lLogRange = GetWindowLong(hWnd, FADER_RANGE);
iLogPos = GetWindowWord(hWnd, FADER_VALUE);
lResult = (long) XlatPosLogicalToPhysical(lLogRange,
rc.bottom-iThumbHalf, rc.top+iThumbHalf, iLogPos);
break;

case FDRM_SETPHYSVALUE:
GetClientRect(hWnd, &rc);
iThumbHalf = GetThumbHeight(rc.bottom)/2;
lLogRange = GetWindowLong(hWnd, FADER_RANGE);
iLogPos = XlatPosPhysicalToLogical(lLogRange,
rc.bottom-iThumbHalf, rc.top+iThumbHalf, wParam);
SetWindowWord(hWnd, FADER_VALUE, iLogPos);
InvalidateRect(hWnd, NULL, TRUE);
break;

default:
lResult = DefWindowProc(hWnd, wMsg, wParam, lParam);
break;
}
return(lResult);
}



/* This is a "helper" function which draws the entire fader */

static void PaintFader(HWND hWnd)
{
PAINTSTRUCT ps;
HANDLE hOldPen;
HANDLE hNewBrush, hOldBrush;
HANDLE hMyParent;
RECT thumb_rect;
int x_center, y_coord;
int iLogPos;
int iPhyPos;
int iThumbHalf;
LONG lLogRange;
HDC hDC;
RECT rc;

/* Default system color is COLOR_BTNFACE from WNDCLASS structure */
hDC = BeginPaint(hWnd, &ps);

GetClientRect(hWnd, &rc);

hOldPen = SelectObject( hDC,
CreatePen(PS_SOLID,1,GetSysColor(COLOR_WINDOWFRAME)) );

/* define appropriate brush & text colors */
hMyParent = GetParent(hWnd);
if (hNewBrush = (HBRUSH)SendMessage( hMyParent, WM_CTLCOLOR,
ps.hdc, MAKELONG(hWnd,CTLCOLOR_FADER) ) )
hOldBrush = SelectObject(ps.hdc,hNewBrush);
else
hOldBrush = NULL;

/* Draws with horizontal symmetry */
x_center = rc.right / 2;

/* draw fader slot (clockwise) */
MoveTo(hDC, x_center, 1);
LineTo(hDC, x_center+1, 2);
LineTo(hDC, x_center+1, rc.bottom-2);
LineTo(hDC, x_center, rc.bottom-1);
LineTo(hDC, x_center-1, rc.bottom-2);
LineTo(hDC, x_center-1, 2);
LineTo(hDC, x_center, 1);

/* draw gridlines (top to bottom, left to right) */
for (y_coord=3; y_coord < rc.bottom-3; y_coord+=3) {
/* Left half first */
MoveTo(hDC, 1, y_coord);
LineTo(hDC, x_center-1, y_coord);
/* Then right half */
MoveTo(hDC, x_center+2, y_coord);
LineTo(hDC, rc.right-1, y_coord);
}

/* draw filled box and then dividing line */
iThumbHalf = GetThumbHeight(rc.bottom)/2;
iLogPos = GetWindowWord(hWnd, FADER_VALUE);
lLogRange = GetWindowLong(hWnd, FADER_RANGE);
iPhyPos = XlatPosLogicalToPhysical(lLogRange, rc.bottom-iThumbHalf,
rc.top+iThumbHalf, iLogPos);

GetFaderThumbRect(hWnd, (LPRECT)&rc, (LPRECT)&thumb_rect, iLogPos);

/* restore original brush */
DeleteObject( SelectObject(hDC,hOldBrush) );

/* now go to 3D button face brush */
hOldBrush = SelectObject( hDC,
CreateSolidBrush(GetSysColor(COLOR_BTNFACE)) );

Rectangle(hDC, thumb_rect.left, thumb_rect.top,
thumb_rect.right, thumb_rect.bottom);

DeleteObject( SelectObject(hDC,hOldBrush) );
if (iThumbHalf > 2) /* Big enough for 3D paint */
{
DeleteObject( SelectObject(hDC,hOldPen) );
hOldPen = SelectObject( hDC,
CreatePen(PS_SOLID,1,GetSysColor(COLOR_WINDOW)) );
MoveTo(hDC, thumb_rect.left+1, thumb_rect.bottom-1);
LineTo(hDC, thumb_rect.left+1, thumb_rect.top+1);
LineTo(hDC, thumb_rect.right-1, thumb_rect.top+1);
DeleteObject( SelectObject(hDC,hOldPen) );

hOldPen = SelectObject( hDC,
CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW)) );
MoveTo(hDC, thumb_rect.right-1, thumb_rect.top+1);
LineTo(hDC, thumb_rect.right-1, thumb_rect.bottom-1);
LineTo(hDC, thumb_rect.left+1, thumb_rect.bottom-1);
}
/* restore original pen */
DeleteObject( SelectObject(hDC,hOldPen) );
DeleteObject( SelectObject(hDC,hOldBrush) );


EndPaint(hWnd, &ps);
}



/* Thumb height is magically 1/8th of window height */

int GetThumbHeight(int iTotalHeight)
{
return max(iTotalHeight/8, 2);
}


/* The fader button is always 1/8th the heighth of the window
and 1/2 the width of the window */

void GetFaderThumbRect(HWND hWnd, LPRECT pRc,
LPRECT pThumbRect, int iLogPos)
{
int x_center;
int iPhyPos;
int iThumbHalf;
LONG lLogRange;

lLogRange = GetWindowLong(hWnd, FADER_RANGE);
iThumbHalf = GetThumbHeight(pRc->bottom) / 2;
iPhyPos = XlatPosLogicalToPhysical(lLogRange,
pRc->bottom - iThumbHalf, pRc->top + iThumbHalf,
iLogPos);
x_center = pRc->right / 2;
pThumbRect->left = x_center / 2;
pThumbRect->top = iPhyPos - iThumbHalf;
pThumbRect->right = (3 * x_center) / 2;
pThumbRect->bottom = iPhyPos + iThumbHalf;
}


/* This "helper" function maps from pixel coordinates to
logical positions */

int XlatPosPhysicalToLogical(LONG lLogRange, int iPhysMax,
int iPhysMin, int iPhyPos)
{
int iLogMin;
int iLogMax;
int iResult;
double dScale;

iLogMax = HIWORD(lLogRange);
iLogMin = LOWORD(lLogRange);
dScale = (double)(iPhysMax - iPhyPos) /
(double)(iPhysMax - iPhysMin);
iResult = (int) ((double)iLogMin + (iLogMax-iLogMin)*(1-dScale));
return iResult;
}


/* This "helper" function maps from logical positions to
physical pixel coordinates */

int XlatPosLogicalToPhysical(LONG lLogRange, int iPhysMax,
int iPhysMin, int iLogPos)
{
int iLogMin;
int iLogMax;
int iResult;
double dScale;

iLogMax = HIWORD(lLogRange);
iLogMin = LOWORD(lLogRange);

dScale = (double)(iLogMax - iLogPos) /
(double)(iLogMax - iLogMin);
iResult = (int) ((double)iPhysMin + (iPhysMax-iPhysMin)*(1-dScale));
return iResult;
}



/* The "caret" is a way of highlighting the controls which are
active and inactive. Note that a ones-complement is used so we
don't need to know the previous state */

void DrawCaret(HDC hDC, LPRECT lprc)
{
HBRUSH hOldBrush;
int iWidth;
int iHeight;

if (lprc->bottom - lprc->top < 4)
return;

/* initialize display context */
hOldBrush = (HBRUSH)SelectObject( hDC,
GetStockObject(GRAY_BRUSH) );

/* draw caret */
iWidth = lprc->right - lprc->left;
iHeight = lprc->bottom - lprc->top;

PatBlt( hDC, lprc->left+1, lprc->top+1, iWidth-2, 3, PATINVERT );
PatBlt( hDC, lprc->right-4, lprc->top+1, 3, iHeight-2, PATINVERT );
PatBlt( hDC, lprc->left+1, lprc->bottom-4, iWidth-2, 3, PATINVERT );
PatBlt( hDC, lprc->left+1, lprc->top+1, 3, iHeight-2, PATINVERT );

/* restore display context */
SelectObject( hDC, hOldBrush );
}


  3 Responses to “Category : Files from Magazines
Archive   : WDFEB92.ZIP
Filename : 3N02018A

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/