home *** CD-ROM | disk | FTP | other *** search
- {***************************************************************************
-
- Percent Control Window Procedure Unit $Version$
- Window Function Unit
- $Author$ $Date$
-
- Copyright 1991 Anthony M. Vitabile
-
- Unit Description
-
- This Turbo Pascal for Windows unit contains the code that
- implements the window function for a new kind of control window
- for use in dialog boxes. The behavior of the control is
- determined by the code contained in this function.
-
- The library uses straight Windows calls and does NOT use Object-
- Windows. This is to allow the control to be used by ANY Windows
- program.
-
- ***************************************************************************}
-
- Unit WndFnPercentCtrl;
- Interface
- Uses WinTypes;
-
- function PercentCtrlWndFn(HWindow: HWnd;
- Message,
- wParam : word;
- lParam : longint
- ): longint; export;
-
- Implementation
- Uses CtrlCommonDefs, Strings, WinProcs;
-
- function GetPercentage(HWindow: HWnd): integer;
- begin { GetPercentage }
- GetPercentage := GetWindowWord(HWindow, Pct_Percentage);
- end { GetPercentage };
-
- procedure DrawAxis(HWindow: HWnd;
- DC : HDC;
- var Rect : TRect;
- BorderW: integer;
- Style : longint);
- var
- Extent ,
- i ,
- Mult ,
- NoTicks,
- Percent,
- X : word;
- Width : single;
- Txt : array [0 .. 3] of char;
- Temp : string[3];
-
- begin { DrawAxis }
- if Style and Pct_Decades <> 0 { Determine how many points between ticks }
- then Mult := 10
- else
- if Style and Pct_Quarters <> 0
- then Mult := 25
- else Mult := 50;
- NoTicks := 100 div Mult; { Determine the number of ticks on the bar }
- Width := (Rect.right - Rect.left - 2 * BorderW) / NoTicks;
- X := Rect.left + BorderW;
- for i := 0 to NoTicks do
- begin
- Percent := i * Mult; { Compute the current percentage to print }
- Str(Percent:1, Temp);
- StrPCopy(Txt, Temp);
- Extent := LoWord(GetTextExtent(DC, Txt, StrLen(Txt)));
- Rect.left := round(i * Width - Extent / 2) + X;
- Rect.right := Rect.left + Extent;
- DrawText(DC, Txt, 3, Rect, dt_Left)
- end
- end { DrawAxis };
-
- procedure DrawShadow(HWindow: HWnd;
- DC : HDC;
- var Rect : TRect;
- Up : boolean;
- Offset : integer);
- var
- NewPen,
- OldPen: HPen;
-
- begin { DrawShadow }
- if Up { Set up Working rectangle for drawing shadows, etc }
- then NewPen := CreatePen(ps_Solid, 1, GetSysColor(color_Window))
- else NewPen := CreatePen(ps_Solid, 1, GetSysColor(color_BtnShadow));
- if NewPen = 0
- then OldPen := 0
- else OldPen := SelectObject(DC, NewPen);
- MoveTo(DC, Rect.left + (Offset + 1), Rect.bottom - (Offset + 2));
- LineTo(DC, Rect.left + (Offset + 1), Rect.top + (Offset + 1));
- LineTo(DC, Rect.right - (Offset + 2), Rect.top + (Offset + 1));
- MoveTo(DC, Rect.left + (Offset + 2), Rect.bottom - (Offset + 3));
- LineTo(DC, Rect.left + (Offset + 2), Rect.top + (Offset + 2));
- LineTo(DC, Rect.right - (Offset + 3), Rect.top + (Offset + 2));
- if OldPen <> 0
- then DeleteObject(SelectObject(DC, OldPen));
- if Up { Set up Working rectangle for drawing shadows, etc }
- then NewPen := CreatePen(ps_Solid, 1, GetSysColor(color_BtnShadow))
- else NewPen := CreatePen(ps_Solid, 1, GetSysColor(color_Window));
- if NewPen = 0
- then OldPen := 0
- else OldPen := SelectObject(DC, NewPen);
- MoveTo(DC, Rect.right - (Offset + 2), Rect.top + (Offset + 1));
- LineTo(DC, Rect.right - (Offset + 2), Rect.bottom - (Offset + 2));
- LineTo(DC, Rect.left + (Offset + 1), Rect.bottom - (Offset + 2));
- MoveTo(DC, Rect.right - (Offset + 3), Rect.top + (Offset + 2));
- LineTo(DC, Rect.right - (Offset + 3), Rect.bottom - (Offset + 3));
- LineTo(DC, Rect.left + (Offset + 2), Rect.bottom - (Offset + 3));
- if OldPen <> 0
- then DeleteObject(SelectObject(DC, OldPen))
- end { DrawShadow };
-
- procedure DrawButton(HWindow: HWnd;
- DC : HDC;
- var Rect : TRect;
- Up : boolean);
- var
- NewBrush,
- OldBrush: HBrush;
- NewPen ,
- OldPen : HPen;
- Offset : integer;
-
- begin { DrawButton }
- NewBrush := CreateSolidBrush(GetSysColor(color_BtnFace));
- if NewBrush = 0 { Use the new brush if it was made }
- then OldBrush := 0
- else OldBrush := SelectObject(DC, NewBrush);
- NewPen := CreatePen(ps_Solid, 1, GetSysColor(color_WindowFrame));
- if NewPen = 0
- then OldPen := 0
- else OldPen := SelectObject(DC, NewPen);
- Rectangle(DC, Rect.left, Rect.top, Rect.right, Rect.bottom);
- if OldBrush <> 0 { Restore the original brush now! }
- then
- begin
- SelectObject(DC, OldBrush);
- DeleteObject(NewBrush)
- end;
- if OldPen <> 0
- then
- begin
- SelectObject(DC, OldPen);
- DeleteObject(NewPen)
- end;
- if Up
- then Offset := 0
- else Offset := 2;
- DrawShadow(HWindow, DC, Rect, Up, Offset)
- end { DrawButton };
-
- procedure DrawBar(HWindow: HWnd; DC: HDC; var Rect: TRect);
- var
- Percent: integer;
- PctRect: TRect;
-
- begin { DrawBar }
- { First draw the rectangle for the bar }
- DrawButton(HWindow, DC, Rect, FALSE);
-
- { Draw the percentage rectangle }
-
- Percent := GetPercentage(HWindow);
- if Percent > 0 { If there's something to be displayed }
- then { then draw the rectangle }
- begin
- PctRect := Rect; { Percent rectangle is inside bar rectangle }
- PctRect.right := PctRect.left + { Compute how far to the right the bar is! }
- round((Rect.right - Rect.left) *
- GetPercentage(HWindow) / 100) + 1;
- if PctRect.right > Rect.right
- then PctRect.right := Rect.right;
- DrawButton(HWindow, DC, PctRect, TRUE)
- end
- end { DrawBar };
-
- procedure DrawDigits(HWindow: HWnd; DC: HDC; var Rect: TRect);
- var
- i : integer;
- Txt : array [0 .. 4] of char;
- Temp: string[4];
-
- begin { DrawDigits }
- i := GetPercentage(HWindow);
- Str(i:3, Temp);
- Temp := Temp + '%';
- StrPCopy(Txt, Temp);
- i := SetBkMode(DC, Transparent);
- DrawText(DC, Txt, length(Temp), Rect, dt_Center or dt_VCenter);
- if i <> 0
- then SetBkMode(DC, i)
- end { DrawDigits };
-
- procedure DrawTicks(HWindow: HWnd;
- DC : HDC;
- var Rect : TRect;
- Style : longint);
- var
- i ,
- Mult ,
- NoTicks,
- X : word;
- Width : single;
-
- begin { DrawTicks }
- if Style and Pct_Decades <> 0 { Determine how many points between ticks }
- then Mult := 10
- else
- if Style and Pct_Quarters <> 0
- then Mult := 25
- else Mult := 50;
- NoTicks := 100 div Mult; { Determine the number of ticks on the bar }
- Width := (Rect.right - Rect.left) / NoTicks;
- for i := 0 to NoTicks do
- begin
- X := round(i * Width + Rect.left);
- if (X >= Rect.right)
- then X := Rect.right - 1;
- MoveTo(DC, X, Rect.top);
- LineTo(DC, X, Rect.bottom)
- end
- end { DrawTicks };
-
- procedure DrawTitle(HWindow: HWnd;
- DC : HDC;
- var Rect : TRect);
- var
- len : integer;
- Temp: array [0 .. ctlTitle] of char;
-
- begin { DrawTitle }
- len := GetWindowText(HWindow, Temp, sizeof(Temp));
- if len > 0
- then DrawText(DC, Temp, len, Rect, dt_Center or dt_VCenter)
- end { DrawTitle };
-
- procedure EraseBackground(HWindow: HWnd; DC: hDC);
- var
- Brush ,
- OBrush,
- NBrush,
- WBrush: hBrush;
- Parent: HWnd;
- LBrush: TLogBrush;
- CRect : TRect;
-
- begin { EraseBackground }
- WBrush := GetStockObject(White_Brush); { We may need this! }
- OBrush := SelectObject(DC, WBrush); { Get the currently selected brush }
- SelectObject(DC, OBrush); { Put the original brush back }
- Parent := GetParent(HWindow); { Get the window's parent }
- if Parent <> 0 { If the control is indeed a child window }
- then { Have the parent tell us what brush to use }
- Brush := LoWord(SendMessage(Parent, wm_CtlColor, DC, MakeLong(HWindow, ctlcolor_Static)))
- else Brush := WBrush; { Otherwise use the white brush }
- GetObject(Brush, sizeof(LBrush), @LBrush);{ Get the brush's data }
- NBrush := CreateBrushIndirect(LBrush); { Create a brand new brush from data returned above }
- UnrealizeObject(NBrush); { Align the brush pattern }
- SelectObject (DC, NBrush); { Select the brush }
- GetClientRect (HWindow, CRect); { Get the area to be erased }
- FillRect (DC, CRect, Brush); { Erase the background }
- if Brush <> WBrush { If the background isn't white, draw the shadow }
- then DrawShadow(HWindow, DC, CRect, FALSE, 0);
- DeleteObject(SelectObject(DC, OBrush)) { Restore the original brush & delete our temp one }
- end { EraseBackground };
-
- procedure PaintPercentCtrl(HWindow: HWnd);
- var
- HasAxis ,
- HasPct ,
- HasTicks,
- HasTitle: boolean;
- DC : HDC;
- AxisH ,
- BarH ,
- BarW ,
- BorderW ,
- CharH ,
- CharW ,
- Height ,
- TickH ,
- TitleH ,
- WhiteH ,
- Width : integer;
- Style : longint;
- Paint : TPaintStruct;
- CRect ,
- Rect : TRect;
-
- begin { PaintPercentCtrl }
- DC := BeginPaint(HWindow, Paint); { Begin the painting process }
- GetClientRect(HWindow, CRect); { Get the area covered by the window }
- Style := GetDialogBaseUnits; { Get the dialog base units }
- CharH := HiWord(Style); { Store the height of a character }
- CharW := LoWord(Style); { Store the width of a character }
-
- { Set up the variables for drawing the 3 parts of the control }
-
- Height := CRect.bottom - CRect.top; { Compute the client rectangle's height }
- Width := CRect.right - CRect.left; { Compute the client rectangle's width }
- Style := GetWindowLong(HWindow, gwl_Style); { Get the window's style bits }
-
- HasAxis := Style and Pct_Axis <> 0;
- HasPct := Style and Pct_Digits <> 0;
- HasTicks := Style and (Pct_Decades or Pct_Quarters or Pct_Halves) <> 0;
- HasTitle := GetWindowTextLength(HWindow) > 0;
-
- if not HasAxis { Determine the width of the border }
- then BorderW := 0
- else BorderW := CharW * 5 div 2;
- if BorderW >= Width div 4
- then BorderW := 0;
-
- BarW := Width - BorderW * 2; { Determine the width of the percentage bar }
- if BarW < BorderW
- then BarW := Width;
-
- if not HasAxis { Determine the height of the axis }
- then AxisH := 0
- else AxisH := CharH;
- if not HasTicks { Determine the height of the ticks }
- then TickH := 0
- else TickH := CharH div 2;
- WhiteH := CharH div 4; { Compute white space height }
- if not HasTitle
- then TitleH := 0
- else TitleH := CharH;
-
- BarH := Height; { Compute bar height }
- if HasTitle and { If the control has a title }
- (BarH - TitleH - WhiteH * 2 > 0) { And it fits in the space we have }
- then BarH := BarH - TitleH - WhiteH * 2;{ Then adjust the bar height for the title }
- if HasTicks and { If the control has tick marks }
- (BarH - TickH - WhiteH div 2 > 0) { And they fit in the space we have }
- then BarH := BarH - TickH - WhiteH div 2;{ Then adjust the bar height for the tick marks }
- if HasAxis and { If the control has an axis }
- (BarH - AxisH - WhiteH > 0) { And it fits in the space we have }
- then BarH := BarH - AxisH - WhiteH;
-
- { Draw the Title }
-
- Rect.top := CRect.top; { Compute the top coordinate of the rectangle }
- Rect.left := CRect.left + BorderW; { Compute the left coordinate of the rectangle }
- Rect.right := CRect.right - BorderW; { Compute the right coordinate of the rectangle }
- if HasTitle
- then
- begin
- Rect.top := Rect.top + WhiteH; { Compute the top coordinate of the Title rectangle }
- Rect.bottom := Rect.top + TitleH; { Compute the bottom coordinate of the Title rectangle }
- DrawTitle(HWindow, DC, Rect);
- Rect.top := Rect.bottom + WhiteH { Prepare the top coordinate of the bar rectangle }
- end;
-
- { Draw the % bar }
-
- Rect.bottom := Rect.top + BarH; { Compute the bottom coordinate of the bar rectangle }
- DrawBar(HWindow, DC, Rect); { Draw the bar on the display }
- if HasPct { Draw the percent digits if this style is on }
- then
- begin
- Rect.top := Rect.top + { Compute the bounding rect for the percent display }
- (BarH - CharH) div 2;
- Rect.bottom := Rect.top + CharH;
- DrawDigits(HWindow, DC, Rect);
- Rect.top := Rect.top - { Restore the rectangle }
- (BarH - CharH) div 2
- end;
-
- if HasTicks { Draw the axis tickmarks }
- then
- begin
- Rect.top := Rect.top + BarH; { Compute the top coordinate of the ticks rectangle }
- Rect.bottom := Rect.top + TickH; { Compute the bottom coordinate of the ticks rectangle }
- DrawTicks(HWindow, DC, Rect, Style) { Draw the tick marks }
- end;
-
- if HasAxis { Draw the axis labels }
- then
- begin
- Rect.top := Rect.bottom + { Compute the top coordinate of the ticks rectangle }
- WhiteH div 2;
- Rect.bottom := Rect.top + AxisH; { Compute the bottom coordinate of the ticks rectangle }
- Rect.left := CRect.left;
- Rect.right := CRect.right;
- DrawAxis(HWindow, DC, Rect, BorderW, Style) { Draw the axis labels }
- end;
-
- EndPaint(HWindow, Paint)
- end { PaintPercentCtrl };
-
- procedure SetPercentage(HWindow: HWnd; Pct: integer);
- begin { SetPercentage }
- SetWindowWord (HWindow, Pct_Percentage, Pct)
- end { SetPercentage };
-
- function PercentCtrlWndFn(HWindow: HWnd;
- Message,
- wParam : word;
- lParam : longint
- ): longint;
- var
- x : integer;
- result: longint;
-
- begin { PercentCtrlWndFn }
- result := ord(TRUE);
- case Message of
- wm_Create :
- begin
- SetPercentage(HWindow, 0);
- result := word(FALSE)
- end;
- wm_Paint : PaintPercentCtrl(HWindow);
- wm_NCHitTest : result := htTransparent;
- wm_EraseBkgnd : EraseBackground(HWindow, wParam);
- pcm_ResetPercent:
- begin
- SetPercentage (HWindow, 0);
- InvalidateRect(HWindow, nil, TRUE)
- end;
- pcm_AddPercent :
- begin
- x := integer(wParam);
- x := x + GetPercentage(HWindow);
- if x < 0
- then x := 0;
- if x > 100
- then x := 100;
- SetPercentage (HWindow, x);
- InvalidateRect(HWindow, nil, TRUE)
- end;
- pcm_GetPercent : result := GetPercentage(HWindow);
- pcm_SetPercent :
- begin
- x := integer(wParam);
- if x < 0
- then x := 0;
- if x > 100
- then x := 100;
- SetPercentage (HWindow, x);
- InvalidateRect(HWindow, nil, TRUE)
- end;
- else result := DefWindowProc(HWindow, Message, wParam, lParam)
- end;
- PercentCtrlWndFn := result
- end { PercentCtrlWndFn };
-
- end.