home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-05-09 | 18.2 KB | 550 lines | [TEXT/PJMM] |
- { *** Main unit for the "IngisWDEF" WDEF building package *** }
-
- {© 1994-1997 by Ingemar Ragnemalm}
- {You may use it freely as long as credits are given in the final program.}
-
-
- {*** IngisWDEF ***}
- {}
- {Version 1.3}
- {}
- {This WDEF is written in order to be as easily customized as possible, in order to produce new}
- {interesting WDEFs. The code consists of two parts, IngisWDEF.p and CustomStubs.p. The idea is}
- {to separate code that must be changed from code that can remain the same.}
- {}
- {The code in IngisWDEF will seldom have to be modified when making a new WDEF.}
- {}
- {CustomStub (which comes in several versions, one for each demo and one with empty stubs)}
- {is where your code goes. You create a grow region, a close box, draw the drag bar and create the}
- {contents and drag regions.}
- {}
- {An important point with IngisWDEF is that it uses regions rather than rectangles wherever possible.}
- {This makes it very easy to modify it for making windows with non-rectangular shapes. Few other}
- {WDEF samples do that - surprisingly few! Also, I have seen only a single WDEF that allowed}
- {resizing with color windows, and that was rectangular.}
- {}
- {BTW, I found the best way to develop a WDEF with Think Pascal: use a working application (small -}
- {Skel is perfect) as its resource file! The application should be configured to use our WDEF for one}
- {window. That way, "build code resource" makes a copy of that application with our WDEF in it.}
- {Build, switch to Finder and run. Simple! Who needs a special "WDEF tester"? (OK, perhaps for}
- {changing the variant code.)}
- {}
- {Close box is assumed to be rectangular - could perhaps be generalized. Lots and lots of out of}
- {memory checks! (All those regions that can take our last byte!) Better rules for deciding color/BW.}
- {Standard colors from the appropriate resource instead of the standard blue tint. Better routine}
- {and variable names.}
- {}
- {ASSUMPTIONS that are not necessarily right:}
- {- Close/zoom boxes always rectangular and only one of each.}
- {- All the window is contents, drag area, frame or shadow - no "dead" parts.}
-
- {Version 1.1:}
- {Adds support for CodeWarrior.}
- {Version 1.2:}
- {Updated for CW9.}
- {Version 1.3:}
- {Fixes a serious bug that could lead to problems when hiding the application.}
- {Adds support for user defined globals.}
-
- {On the wish list, perhaps for a future release:}
- {- Separate handling of parts in different screens}
- {- Fat binary}
-
-
- unit IngisWDEF;
-
- interface
- uses
- {$IFC UNDEFINED THINK_PASCAL}
- Types, QuickDraw, ToolUtils, Windows, Events, Memory, OSUtils,
- {$ENDC}
- CustomStubs, IngisWDEFUtils;
-
- {$MAIN}
- function main (varCode: integer; macWindow: WindowPeek; theMessage: integer; param: longint): longint;
-
- implementation
-
- type
- RectPtr = ^Rect; {For passing the parameter to DrawGrow}
-
- {******************************************************}
- { GetDragBar }
- { }
- { Pass back a region which encloses the drag bar of the window }
- { Note: dragRgn must already be initialized! }
- { You can probably leave this routine without change! }
- { We assume that the contRgn minus the strucRgn, frame and shadow is the dragRgn!}
- { *****************************************************}
-
- procedure GetDragBar (varCode: integer; macWindow: WindowPeek; var dragRgn: RgnHandle);
- var
- radius: integer;
- dragBar: Rect;
- begin
- CopyRgn(macWindow^.strucRgn, dragRgn);
- OffsetRgn(dragRgn, -kShadowLength, -kShadowLength);
- SectRgn(dragRgn, macWindow^.strucRgn, dragRgn);
- DiffRgn(dragRgn, macWindow^.contRgn, dragRgn);
- InsetRgn(dragRgn, kFrameWidth, kFrameWidth);
- end;
-
-
- {*****************************************************************************}
- { DrawFrame}
- {}
- { Draw the entire window frame. Calls several custom routines!}
- { *****************************************************************************}
-
- procedure DrawFrame (varCode: integer; macWindow: WindowPeek);
- var
- wFrame: Rect; { Window frame around content rgn }
-
- wFrameRgn: RgnHandle;
- tmpPt: Point;
- dragBar: RgnHandle; { Drag bar of window }
- savePen: PenState; { Current pen characteristics }
- saveForeColor, saveBackColor: RGBColor;
- colorFlag: Boolean;
- closeBox, zoomBox: Rect;
- begin
- SaveColors(saveForeColor, saveBackColor);
- GetPenState(savePen); { Save the current pen state }
-
- { Structure region of a window has four parts: }
- { (1) Frame around the content region }
- { (2) Drop shadow }
- { (3) Drag bar }
- { (4) Close box inside the drag bar }
-
- { (1) Frame around content region }
- wFrameRgn := NewRgn;
- CopyRgn(macWindow^.contRgn, wFrameRgn);
- InsetRgn(wFrameRgn, -kFrameWidth, -kFrameWidth);
- PenSize(kFrameWidth, kFrameWidth);
- FrameRgn(wFrameRgn);
- {DisposeRgn(wFrameRgn); Not yet- we'll reuse it}
-
- { (2) Drop shadow below and to the right of content region }
- PenSize(kShadowLength, kShadowLength);
-
- CopyRgn(macWindow^.strucRgn, wFrameRgn);
- OffsetRgn(wFrameRgn, -kShadowLength, -kShadowLength);
- DiffRgn(macWindow^.strucRgn, wFrameRgn, wFrameRgn);
- ForeColor(blackColor);
- PaintRgn(wFrameRgn);
- DisposeRgn(wFrameRgn);
-
- dragBar := NewRgn;
- GetDragBar(varCode, macWindow, dragBar);
-
- colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
- if colorFlag then
- colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
- DrawDragBar(varCode, macWindow, dragBar, colorFlag);
-
- DefaultColors;
-
- if macWindow^.hilited then
- if macWindow^.goAwayFlag then
- begin { Make sure window has a close box }
- GetCloseBox(varCode, dragBar, closeBox);
- DrawCloseBox(varCode, macWindow, closeBox, colorFlag);
- end;
- if macWindow^.hilited then
- if macWindow^.spareFlag then
- begin { Make sure window has a zoom box }
- GetZoomBox(varCode, dragBar, zoomBox);
- DrawZoomBox(varCode, macWindow, zoomBox, colorFlag);
- end;
-
- InsetRgn(dragBar, -kFrameWidth, -kFrameWidth);
- PenSize(kFrameWidth, kFrameWidth);
- DefaultColors;
- FrameRgn(dragBar);
- DisposeRgn(dragBar);
-
- SetPenState(savePen); { Restore original pen state }
- RestoreColors(saveForeColor, saveBackColor);
- end;
-
-
- {*****************************************************************************}
- { DoToggleCloseBox}
- {}
- { Toggle hiliting of the close box.}
- { *****************************************************************************}
-
- procedure DoToggleCloseBox (varCode: integer; macWindow: WindowPeek);
- var
- dragBar: RgnHandle; { Rectangle enclosing drag bar }
- closeBox: Rect; { Rectangle enclosing close box }
- colorFlag: Boolean;
- saveForeColor, saveBackColor: RGBColor;
- pt: Point;
- begin
- dragBar := NewRgn;
- GetDragBar(varCode, macWindow, dragBar);
- SetRect(closeBox, 0, 0, 0, 0); {If GetCloseBox does nothing, we want an empty rect.}
- if macWindow^.goAwayFlag then
- begin
- GetCloseBox(varCode, dragBar, closeBox);
-
- colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
- if colorFlag then
- colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
-
- GetMouse(pt); {Get a point for PtInRect}
- if colorFlag then
- SaveColors(saveForeColor, saveBackColor);
- if PtInRect(pt, closeBox) and Button then
- DrawHitCloseBox(varCode, macWindow, closeBox, colorFlag)
- else
- DrawCloseBox(varCode, macWindow, closeBox, colorFlag);
- if colorFlag then
- RestoreColors(saveForeColor, saveBackColor);
- end;
- DisposeRgn(dragBar);
- end; {DoToggleCloseBox}
-
- { Same as above, but for the zoom box! }
- procedure DoToggleZoomBox (varCode: integer; macWindow: WindowPeek);
- var
- dragBar: RgnHandle; { Rectangle enclosing drag bar }
- zoomBox: Rect; { Rectangle enclosing close box }
- colorFlag: Boolean;
- saveForeColor, saveBackColor: RGBColor;
- pt: Point;
- begin
- dragBar := NewRgn;
- GetDragBar(varCode, macWindow, dragBar);
- SetRect(zoomBox, 0, 0, 0, 0); {If GetZoomBox does nothing, we want an empty rect.}
- if macWindow^.spareFlag then
- begin
- GetZoomBox(varCode, dragBar, zoomBox);
-
- colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
- if colorFlag then
- colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
-
- GetMouse(pt); {Get a point for PtInRect}
- if colorFlag then
- SaveColors(saveForeColor, saveBackColor);
- if PtInRect(pt, zoomBox) and Button then
- DrawHitZoomBox(varCode, macWindow, zoomBox, colorFlag)
- else
- DrawZoomBox(varCode, macWindow, zoomBox, colorFlag);
- if colorFlag then
- RestoreColors(saveForeColor, saveBackColor);
- end;
- DisposeRgn(dragBar);
- end; {DoToggleZoomBox}
-
-
- {A little padding around LocalToGlobal.}
- procedure MyLocalToGlobal (macWindow: univ WindowPtr; var p: Point);
- var
- savePort: GrafPtr;
- begin
- GetPort(savePort);
- SetPort(macWindow);
- LocalToGlobal(p);
- SetPort(savePort);
- end;
-
-
- {*****************************************************************************}
- { FindPart}
- {}
- { Find which part of the window was hit by a mouse click at the}
- { specified location.}
- { *****************************************************************************}
-
- function FindPart (varCode: integer; macWindow: WindowPeek; location: longint): integer;
- var
- theClick: Point; { Global coords of mouse click }
- dragBar, growRgn: RgnHandle;
- closeBox, zoomBox, portR: Rect;
- begin
- theClick.h := LoWord(location); { Extract horizontal component }
- theClick.v := HiWord(location); { Extract vertical component }
-
- { Are we inside the window structure at all?}
- if not PtInRgn(theClick, macWindow^.strucRgn) then
- begin
- FindPart := wNoHit;
- Exit(FindPart);
- end;
-
- {Must check grow before contRgn, since grow is (often) a part of the contRgn.}
- growRgn := NewRgn;
- GetGrowRgn(varCode, macWindow, growRgn);
- if PtInRgn(theClick, growRgn) then
- begin
- FindPart := wInGrow;
- DisposeRgn(growRgn);
- exit(FindPart);
- end;
- DisposeRgn(growRgn);
-
- if PtInRgn(theClick, macWindow^.contRgn) then
- begin
- FindPart := wInContent; { Content region }
- Exit(FindPart);
- end;
-
- dragBar := NewRgn;
- { Drag bar? }
- GetDragBar(varCode, macWindow, dragBar);
- if PtInRgn(theClick, dragBar) then
- begin { Drag bar or close box! }
- SetRect(closeBox, 0, 0, 0, 0); {If GetCloseBox does nothing, we want an empty rect.}
- if macWindow^.goAwayFlag then
- GetCloseBox(varCode, dragBar, closeBox);
- SetRect(zoomBox, 0, 0, 0, 0); {If GetZoomBox does nothing, we want an empty rect.}
- if macWindow^.spareFlag then
- GetZoomBox(varCode, dragBar, zoomBox);
- if macWindow^.goAwayFlag and PtInRect(theClick, closeBox) then
- FindPart := wInGoAway { Close box! }
- else if macWindow^.spareFlag and PtInRect(theClick, zoomBox) then
- begin
- {Compare the size of portRect with stdState!}
- portR := macWindow^.port.portRect;
- with WStateDataHandle(macWindow^.dataHandle)^^ do
- if ((portR.right - portR.left) = (stdState.right - stdState.left)) and ((portR.bottom - portR.top) = (stdState.bottom - stdState.top)) then
- begin
- FindPart := wInZoomIn;
- end
- else
- begin {Not match - save the portRect as the userState}
- FindPart := wInZoomOut;
- MyLocalToGlobal(macWindow, portR.topLeft);
- MyLocalToGlobal(macWindow, portR.botRight);
- WStateDataHandle(macWindow^.dataHandle)^^.userState := portR;
- end;
- end
- else
- FindPart := wInDrag; { Drag bar and NOT close box! }
- end
- else
- FindPart := wNoHit; { Click somewhere else. Don't bother. }
- DisposeRgn(dragBar);
- end;
-
- {*****************************************************************************}
- { BuildRegions}
- {}
- { Build the structure and content region of a window.}
- { *****************************************************************************}
-
- procedure BuildRegions (varCode: integer; macWindow: WindowPeek);
- var
- theRect: Rect; { Window regions are rectangular }
- theRgn: RgnHandle; { Region defining drop shadow - and everything else we need a temprary region for }
- begin
- {The content region should be calculated from the port rectangle - but, of course, does not}
- {have to be identical to it.}
-
- {Init the region.}
- theRgn := NewRgn; { Define region for the shadow }
-
- theRect := macWindow^.port.portRect;
-
- MyLocalToGlobal(macWindow, theRect.topLeft);
- MyLocalToGlobal(macWindow, theRect.botRight);
-
- {CUSTOM: Given the varCode and rectangle, create contRgn and dragRgn (returned in strucRgn)!}
- BuildCustomRegions(varCode, theRect, macWindow^.contRgn, macWindow^.strucRgn);
-
- {Build struc, add frame and shadow:}
-
- {struc := cont + drag}
- UnionRgn(macWindow^.contRgn, macWindow^.strucRgn, macWindow^.strucRgn);
- {Expand struc to include frame}
- InsetRgn(macWindow^.strucRgn, -kFrameWidth, -kFrameWidth);
-
- {Make a copy}
- CopyRgn(macWindow^.strucRgn, theRgn);
- {Offset it for the shadow}
- OffsetRgn(theRgn, kShadowLength, kShadowLength);
- {struc := struc + shadow}
- UnionRgn(macWindow^.strucRgn, theRgn, macWindow^.strucRgn);
-
- DisposeRgn(theRgn); { All thru with region }
- end; {BuildRegions}
-
-
- {*****************************************************************************}
- { DrawGrowFrame - Drawing the frame during window resizing. }
- { *****************************************************************************}
-
- procedure DrawGrowFrame (varCode: integer; macWindow: WindowPeek; theRect: Rect);
- var
- tmpContRgn, tmpDragRgn: RgnHandle;
- saveForeColor, saveBackColor: RGBColor;
- begin
- SaveColors(saveForeColor, saveBackColor);
- with theRect do
- begin
- if right - left < kMinWidth then
- right := left + kMinWidth;
- if bottom - top < kMinHeight then
- bottom := top + kMinHeight;
- end;
-
- tmpContRgn := NewRgn;
- tmpDragRgn := NewRgn;
- BuildCustomRegions(varCode, theRect, tmpContRgn, tmpDragRgn);
- InsetRgn(tmpContRgn, -kFrameWidth, -kFrameWidth);
- InsetRgn(tmpDragRgn, -kFrameWidth, -kFrameWidth);
- FrameRgn(tmpContRgn);
- FrameRgn(tmpDragRgn);
- DisposeRgn(tmpContRgn);
- DisposeRgn(tmpDragRgn);
- {The above is well enough, but we also provide a stub for some extra:}
- DrawScrollFrame(varCode, macWindow, theRect);
- RestoreColors(saveForeColor, saveBackColor);
- end;
-
- {*****************************************************************************}
- { PrepareGrowIcon - Sets up for the custom routine that draws the grow icon. }
- {*****************************************************************************}
-
- procedure PrepareGrowIcon (varCode: integer; macWindow: WindowPeek; theRect: Rect);
- var
- tmpRect, smallRect, largeRect: Rect;
- var
- tempClip, saveClip, growRgn: RgnHandle;
- savePort: GrafPtr;
- saveForeColor, saveBackColor: RGBColor;
- colorFlag: Boolean;
- begin
- SaveColors(saveForeColor, saveBackColor);
- theRect := macWindow^.port.portRect;
- MyLocalToGlobal(macWindow, theRect.topLeft);
- MyLocalToGlobal(macWindow, theRect.botRight);
-
- tempClip := NewRgn;
- saveClip := NewRgn;
- growRgn := NewRgn;
-
- GetGrowRgn(varCode, macWindow, growRgn);
-
- SectRgn(macWindow^.port.visRgn, macWindow^.port.clipRgn, tempClip);
- GetClip(saveClip);
- OffsetRgn(tempClip, -macWindow^.port.portRect.left + theRect.left, -macWindow^.port.portRect.top + theRect.top);
- SetClip(tempClip);
-
- DrawScrollFrame(varCode, macWindow, theRect); {Standard eller fritt val?}
- DefaultColors;
-
- colorFlag := BitAnd(macWindow^.port.portBits.rowBytes, $8000) <> 0;
- if colorFlag then
- colorFlag := CGrafPtr(macWindow)^.portPixMap^^.pixelSize >= kMinDepthForColor;
-
- DrawTheGrowIcon(varCode, WindowPeek(macWindow), theRect, growRgn, colorFlag);
-
- RestoreColors(saveForeColor, saveBackColor);
- SetClip(saveClip);
- DisposeRgn(saveClip);
- DisposeRgn(tempClip);
- DisposeRgn(growRgn);
- end;
-
-
- {*****************************************************************************}
- { SyncPorts - the ugly patch for making it work with Color QD. ONLY called when CQD i available! }
- { *****************************************************************************}
-
- procedure SyncPorts;
- var
- bwPort: GrafPtr;
- colorPort: CGrafPtr;
- begin
- GetWMgrPort(bwPort);
- GetCWMgrPort(colorPort);
- SetPort(GrafPtr(colorPort));
- {Copy some fields:}
- BlockMove(@bwPort^.pnLoc, @colorPort^.pnLoc, 10);
- BlockMove(@bwPort^.pnVis, @colorPort^.pnVis, 14);
- PenPat(bwPort^.pnPat);
- BackPat(bwPort^.bkPat);
- end;
-
-
- {*****************************************************************************}
- { Main Function}
- { *****************************************************************************}
-
- {$MAIN}
- function main (varCode: integer; macWindow: WindowPeek; theMessage: integer; param: longint): longint;
- var
- needSyncPorts: Boolean;
- savePort: GrafPtr;
- theRect: Rect;
- begin
- main := 0;
-
- GetPort(savePort);
-
- {Must sync ports on all QuickDraw-dependent routines!}
- if HasCQDraw then {and (theMessage in [wDraw, wHit, wGrow, wDrawGIcon, wCalcRgns])}
- SyncPorts;
-
- case theMessage of { Take appropriate action }
-
- wNew:
- begin
- if macWindow^.dataHandle = nil then
- macWindow^.dataHandle := NewHandleClear(Sizeof(MyDataRecord)); {Allocate space for WStateData AND custom globals!}
- with WStateDataHandle(macWindow^.dataHandle)^^ do
- begin
- stdState := macWindow^.port.portRect;
- MyLocalToGlobal(macWindow, stdState.topLeft);
- MyLocalToGlobal(macWindow, stdState.botRight);
- userState := stdState;
- end;
- InitMyWindow(varCode, WindowPeek(macWindow));
- end;
- wDispose:
- begin
- DisposeMyWindow(varCode, macWindow);
- if macWindow^.dataHandle <> nil then
- DisposeHandle(macWindow^.dataHandle);
- macWindow^.dataHandle := nil;
- end;
-
- wDraw: { Draw the window frame }
- if macWindow^.visible then { Only draw if window is visible }
- case BAnd(param, $0000FFFF) of { Find out which part to draw }
-
- wNoHit: { Draw the entire frame }
- begin
- DrawFrame(varCode, macWindow);
- end;
-
- wInGoAway: { Toggle hiliting of the close box }
- DoToggleCloseBox(varCode, macWindow);
-
- wInZoomIn, wInZoomOut: { Toggle hiliting of the close box }
- DoToggleZoomBox(varCode, macWindow);
- end;
-
- wHit: { Find part of window clicked in }
- main := FindPart(varCode, macWindow, param);
-
- wCalcRgns: { Build structure & content rgns }
- BuildRegions(varCode, macWindow);
-
- wGrow:
- DrawGrowFrame(varCode, macWindow, RectPtr(param)^);
-
- wDrawGIcon:
- PrepareGrowIcon(varCode, macWindow, theRect); {Set up and calls DrawTheGrowIcon}
- end; {case}
-
- SetPort(savePort);
-
- end; {main}
-
- end.