home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
pascal
/
tpwinst
/
tddemo.pak
/
TDWDEMOB.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1991-05-21
|
15KB
|
446 lines
{*********************************************************************
* Copyright (c) 1991 by Borland International, Inc. *
* *
* TDWDEMOB.PAS *
* *
* This program is the second of two buggy versions of TDWDEMO.PAS. *
* It has only one of the two bugs in TDWDEMOA.PAS; the first bug *
* from that program is corrected in this one. The purpose of these *
* two buggy programs is to show how to use TDW to debug a simple *
* Windows graphics program written in Turbo Pascal. *
*********************************************************************}
uses WinProcs, WinTypes;
{$R TDWDEMO.RES}
{**************************************************************
* Globals
**************************************************************}
const
szAppName = 'SimplePaint';
id_Line = 1;
id_Ellipse = 2;
id_Rectangle = 3;
mid_Quit = 100;
mid_Line = 201;
mid_Ellipse = 202;
mid_Rectangle = 203;
mid_Thin = 301;
mid_Regular = 302;
mid_Thick = 303;
mid_Red = 304;
mid_Green = 305;
mid_Black = 306;
{ Maintains the status of the shape the user is drawing. }
{ Default is to draw with a line. }
CurrentShape : Integer = id_Line;
{ Maintains the current pen width. Default width is medium. }
PenWidth : Integer = 3;
{ Maintains the current pen color. Default color is red. }
PenColor : TColorRef = $00FF0000;
{ Record definition to track }
{ what shapes have been drawn. }
type
Shape = record
Points: Trect; { Location of the shape. }
PenWidth: Integer; { Pen width for the shape. }
theShape: Integer; { Shape this structure represents. }
PenColor: TcolorRef; { Color of the shape. }
{ Used to determine direction lines should be drawn. If }
{ slope > 0 then draw from UpperLeft to LowerRight. Else }
{ draw from LowerLeft to UpperRight. }
Slope: Integer;
end;
const
nPoints = 100;
{ Indicates the number of shapes the user has drawn. }
CurrentPoint : Integer = -1;
var
{ Array that stores the shapes the user draws. }
thisShape: array[0..nPoints - 1] of Shape;
function Min(a, b: LongInt): LongInt;
begin
if a < b then Min := a
else Min := b;
end;
function Max(a, b: LongInt): LongInt;
begin
if a > b then Max := a
else Max := b;
end;
{****************************************************************
* procedure DrawShape
*
* Draws the shape given by Shape parameter using PenWidth
* and PenColor in the rectangle bounded by x,y,x2,y2. The
* Slope parameter is used with line shapes to determine if
* lines should be drawn with a negative or positive slope.
****************************************************************}
procedure DrawShape(HandleDC: HDC; x, y, x2, y2, Shape,
PenWidth: Integer; PenColor: TColorRef; Slope: Integer);
var
SaveObject: THandle;
SaveROP: Integer;
begin
{ Create the proper pen for this shape. Save }
{ the previously selected object from this DC. }
SaveObject := SelectObject(HandleDC, CreatePen(ps_Solid,
PenWidth, PenColor));
case Shape of
id_Line:
{ Rectangles that save a shape's position must be stored }
{ as upper-left and lower-right. To draw a line from }
{ upper-right to lower-left, the line must have a negative }
{ slope. }
if Slope > 0 then
begin
MoveTo(HandleDC, x, y);
LineTo(HandleDC, x2, y2);
end
else
begin
MoveTo(HandleDC, x, y2);
LineTo(HandleDC, x2, y);
end;
id_Ellipse:
Ellipse(HandleDC, x, y, x2, y2);
id_Rectangle:
Rectangle(HandleDC, x, y, x2, y2);
end;
{ Select whatever object was currently selected when }
{ we entered this routine. }
SelectObject(HandleDC, SaveObject);
end;
{***************************************************************
* procedure DoPaint
* Processes wm_Paint messages. wm_Paint is generated
* whenever UpdateWindow is called or another window is moved,
* revealing a portion of the window receiving this message.
***************************************************************}
procedure DoPaint(HWindow: HWnd);
var
i, SaveROP: Integer;
HandleDC, hMemDC: HDC;
theRect, DestRect: TRect;
theBitmap: HBitMap;
ps: TPaintStruct;
begin
HandleDC := BeginPaint(HWindow, ps);
if CurrentPoint >= 0 then
begin
{ Determine which rectangle on the window is invalid. }
{ If no rectangle is marked invalid, it will be a full }
{ window repaint. }
GetUpdateRect(HWindow, theRect, False);
if IsRectEmpty(theRect) then GetClientRect(HWindow, theRect);
{ Create a memory DC and bitmap the same size as the update rectangle. }
hMemDC := CreateCompatibleDC(HandleDC);
theBitmap := CreateCompatibleBitmap(HandleDC,
theRect.Right - theRect.Left, theRect.Bottom - theRect.Top);
SelectObject(hMemDC,theBitmap);
{ Erase the memBitmap. }
BitBlt(hMemDC, 0, 0,
theRect.Right - theRect.Left, theRect.Bottom - theRect.Top,
HandleDC, 0, 0, SRCCopy);
{ Draw only those shapes that lie within the update rectangle. }
for i := 0 to CurrentPoint do
begin
IntersectRect(DestRect, thisShape[i].Points, theRect);
if not IsRectEmpty(destRect) then
DrawShape(hMemDC,
thisShape[i].Points.Left - theRect.Left,
thisShape[i].Points.Top - theRect.Top,
thisShape[i].Points.Right - theRect.Left,
thisShape[i].Points.Bottom - theRect.Top,
thisShape[i].theShape, thisShape[i].PenWidth,
thisShape[i].PenColor, thisShape[i].Slope);
{ Note that when drawing the shape, the shape's }
{ position was transformed so that the origin was }
{ at the upper-left corner of the update rectangle. }
{ This is the point (0,0) on the bitmap that will }
{ map onto (theRect.Left, theRect.Right). }
end;
{ Finally, copy the bitmap onto the update rectangle. }
BitBlt(HandleDC, theRect.Left, theRect.Top,
theRect.Right - theRect.Left, theRect.Bottom - theRect.Top,
hMemDC, 0, 0, SRCCopy);
DeleteDC(hMemDC);
DeleteObject(theBitmap);
end;
ReleaseDC(HWindow, HandleDC);
EndPaint(HWindow, ps);
end;
{*********************************************************
* static variables oldx, oldy, mouseDown
* Used to maintain both the state of the mouse position
* and the button status between mouse messages.
*********************************************************}
const
Oldx: Integer = -1;
Oldy: Integer = -1;
MouseDown : Boolean = False;
{*****************************************************************
* procedure DoLButtonDown
* DoLButtonDown process wm_LButtonDown messages, generated when
* the user presses the left mouse button. This routine
* saves the origin of this shape, the current pen parameters,
* and the current shape into the shapes array. The mouse
* button is also marked as pressed.
*****************************************************************}
procedure DoLButtonDown(HWindow: HWnd; lParam: LongInt);
begin
{ Redirect all subsequent mouse movements to this }
{ window until the mouse button is released. }
SetCapture(HWindow);
Inc(CurrentPoint);
thisShape[CurrentPoint].Points.Top := HiWord(lParam);
thisShape[CurrentPoint].Points.Left := LoWord(lParam);
Oldy := HiWord(lParam);
Oldx := LoWord(lParam);
thisShape[CurrentPoint].theShape := CurrentShape;
thisShape[CurrentPoint].PenWidth := PenWidth;
thisShape[CurrentPoint].PenColor := PenColor;
MouseDown := True;
end;
{*****************************************************************
* procedure DoLButtonUp
* DoLButtonUp processes wm_LButtonUp messages, generated when
* the user releases the left mouse button. This routine
* allows other windows to receive mouse messages and saves
* the position of the mouse as the other corner of a bounding
* rectangle for the shape.
*****************************************************************}
procedure DoLButtonUp(HWindow: HWnd; lParam: LongInt);
begin
ReleaseCapture;
{ For rectangles to work with the IntersectRect function, }
{ they must be stored as left, top, right, bottom. }
SetRect(thisShape[CurrentPoint].Points,
Min(thisShape[CurrentPoint].Points.Left, LoWord(lParam)),
Min(thisShape[CurrentPoint].Points.Top, HiWord(lParam)),
Max(thisShape[CurrentPoint].Points.Left, LoWord(lParam)),
Max(thisShape[CurrentPoint].Points.Top, HiWord(lParam)));
{ if the origin of the line has changed, it should be drawn }
{ from upper-right to lower left and therefore has negative }
{ slope. Otherwise it will have positive slope. }
if CurrentShape = id_Line then
begin
if (thisShape[CurrentPoint].Points.Left = LoWord(lParam)) or
(thisShape[CurrentPoint].Points.Top = HiWord(lParam)) then
thisShape[CurrentPoint].Slope := -1
else
thisShape[CurrentPoint].Slope := 1;
end;
{ Mark this region on the window as needing }
{ redrawing and force an update. }
InvalidateRect(HWindow, @thisShape[CurrentPoint].Points, False);
UpdateWindow(HWindow);
MouseDown := False;
Oldx := -1;
Oldy := -1;
end;
var
SaveROP: Integer;
{*********************************************************************
* procedure DoMouseMove
* DoMouseMove processes wm_MouseMove messages, generated when the
* user moves the mouse. When the user moves the mouse and holds the
* button down, this procedure draws the current shape by using the
* raster operation NOTXORPEN. When this mode is used, drawing the
* same image twice returns the image to its original state.
* NOTXORPEN turns black on black white, black on white black
* and white on white white.
*********************************************************************}
procedure DoMouseMove(HWindow: HWnd; lParam: LongInt);
var
HandleDC: HDC;
begin
if MouseDown then
begin
HandleDC := GetDC(HWindow);
{ Erase the old shape. }
SaveROP := SetROP2(HandleDC, r2_NotXORPen);
DrawShape(HandleDC, thisShape[CurrentPoint].Points.Left,
thisShape[CurrentPoint].Points.top, Oldx, Oldy,
thisShape[CurrentPoint].theShape,
thisShape[CurrentPoint].PenWidth,
thisShape[CurrentPoint].PenColor, 1);
{ At this point, the slope must be positive because }
{ the coordinates could not have been switched. }
{ The next step is to draw the new shape. }
Oldx := LoWord(lParam);
Oldy := HiWord(lParam);
DrawShape(HandleDC, thisShape[CurrentPoint].Points.Left,
thisShape[CurrentPoint].Points.Top, Oldx, Oldy,
thisShape[CurrentPoint].theShape,
thisShape[CurrentPoint].PenWidth,
thisShape[CurrentPoint].PenColor, 1);
SetROP2(HandleDC, SaveROP);
ReleaseDC(HWindow, HandleDC);
end;
end;
{********************************************************************
* function DoWMCommand
* DoWMCommand processes wm_Command messages. wm_Command
* is generated when the user selects something from the menu.
* This function changes the current state of shape selections
* to match the user's menu selection.
******************************************************************}
function DoWMCommand(wParam: Word): Integer;
begin
DoWMCommand := 1;
case wParam of
mid_QUIT:
PostQuitMessage(0);
mid_Line:
CurrentShape := id_Line;
mid_Ellipse:
CurrentShape := id_Ellipse;
mid_Rectangle:
CurrentShape := id_Rectangle;
mid_Thin:
PenWidth := 1;
mid_Regular:
PenWidth := 3;
mid_Thick:
PenWidth := 5;
mid_Red:
PenColor := RGB(255, 0, 0);
mid_Green:
PenColor := RGB(0, 255, 0);
mid_Black:
PenColor := RGB(0, 0, 0);
else
DoWMCommand := 0;
end;
end;
{******************************************************
* function WndProc
* WndProc is the callback function (window proc)
* for the Simple Paint class of windows. It
* handles all messages received by the window
******************************************************}
function WndProc (HWindow : HWnd; Message: Word;
wParam: Word; lParam: LongInt): LongInt; export;
begin
WndProc := 0;
case Message of
wm_Command:
WndProc := DoWMCommand(wParam);
wm_LButtonDown:
DoLButtonDown(HWindow,lParam);
wm_LButtonUp:
DoLButtonUp(HWindow,lParam);
wm_MouseMove:
DoMouseMove(HWindow,lParam);
wm_Paint:
DoPaint(HWindow);
else
WndProc := DefWindowProc(HWindow, Message, wParam, lParam);
end;
end;
var
theWndClass: TWndClass;
theMessage: TMsg;
HWindow: HWnd;
begin
{ Register window class style if first instance of this program. }
if hPrevInst = 0 then
begin
theWndClass.style := cs_HRedraw or cs_VRedraw ;
theWndClass.lpfnWndProc := @WndProc;
theWndClass.cbClsExtra := 0;
theWndClass.cbWndExtra := 0;
theWndClass.hInstance := hInstance;
theWndClass.hIcon := LoadIcon(0, 'ide_SimplePaint');
theWndClass.hCursor := LoadCursor(0, idc_Arrow );
theWndClass.hbrBackground := GetStockObject(White_Brush);
theWndClass.lpszMenuName := szAppName;
theWndClass.lpszClassName := szAppName;
if not RegisterClass(theWndClass) then Halt;
end;
{ Create and display the window. }
HWindow := CreateWindow(szAppName,'Simple Paint',
ws_OverLappedWindow, cw_UseDefault, 0,
cw_UseDefault, 0, 0, 0, hInstance, nil);
ShowWindow(HWindow, CmdShow);
UpdateWindow(HWindow);
while GetMessage(theMessage, 0, 0, 0) do
begin
TranslateMessage(theMessage );
DispatchMessage(theMessage );
end;
end.