(***************************************************) (* The Color Window *) (*-------------------------------------------------*) (* Copyright (c) 1995-`97 UNIVERSAL SOFTWARE Inc *) (* All Rights Reserved *) (***************************************************) { example program at the end !! } unit ColorWin; {$S-} INTERFACE uses WinTypes, WinProcs, oWindows; (************************************************************) (****************** TpCrt types, consts, vars ***************) (************************************************************) type { the color window object } pColorWin=^tColorWin; tColorWin=object(tWindow) ScreenSize:tPoint; CharBuffer:pChar; AttrBuffer:pChar; TextAttr:byte; TextChar:char; CharSize:tPoint; CharAscent:integer; Range:tPoint; { scrollbar ranges } Origin:tPoint; { client area origin } ClientSize:tPoint; { client area dimensions } { colorwin methods } procedure Byte2bkRgb(c:byte; var bkRGB:tColorRef); procedure Byte2fgRgb(c:byte; var fgRGB:tColorRef); procedure Byte2rgb(c:byte; var bkRGB:tColorRef; var fgRGB:tColorRef); constructor Init(AParent:pWindowsObject; aTitle:pChar); destructor Done; virtual; procedure SetupWindow; virtual; function GetClassName: pChar; virtual; procedure GetWindowClass(var aWndClass: tWndClass); virtual; procedure wmSize(var Msg:tMessage); virtual wm_First+wm_Size; {---} function GetNewPos(Action:word; Pos,Page,_Range, Thumb:integer):integer; procedure wmVScroll(var Msg:tMessage); virtual wm_First+wm_VScroll; procedure wmHScroll(var Msg:tMessage); virtual wm_First+wm_HScroll; {---} procedure SetScrollBars; function CharPtr(X,Y:integer):pChar; function AttrPtr(X,Y:integer):pChar; procedure Paint(PaintDC:hDC; var PS:tPaintStruct); virtual; procedure ClrScr; {\-clear current window} procedure ScrollTo(X,Y:integer); procedure FastWrite(St:string; Row,Col,_Attr:byte); {\-write St at Row,Col in Attr (video attribute)} procedure FastFill(Number:word; Ch:char; Row,Col,_Attr:byte); {\-fill Number chs at Row,Col in Attr (video attribute)} procedure FastCenter(St:string; Row,_Attr:byte); {\-write St centered on window Row in Attr (video attribute)} end; IMPLEMENTATION { Double word record } type LongRec=record Lo,Hi:integer; end; const vgaColor:array[0..15] of tColorRef=( $00000000, { Black } $00800000, { Dark Cyan } $00008000, { Dark Green} $00808000, { Dark Blue } $00000080, { Dark red } $00800080, { Dark violet } $00008080, { Brown } $00C0C0C0, { light Gray } $00808080, { Dark Gray } $00FF0000, { light blue } $0000FF00, { light green } $00FFFF00, { Blue } $000000FF, { light red } $00FF00FF, { violet } $0000FFFF, { yellow } $00FFFFFF { White } ); type BufPtr=^BufferArray; BufferArray=array[0..MaxInt] of char; function Min(X,Y:integer):integer; {Return the smaller of two integer values} begin if X Y then Max:=X else Max:=Y; end; (*** colorwin ***) constructor tColorWin.Init(aParent:pWindowsObject; aTitle:pChar); begin inherited Init(aParent,aTitle); Attr.Style:=Attr.Style or ws_HScroll or ws_VScroll or cs_ByteAlignClient; {ws_Border or ws_Child or ws_Visible or ws_HScroll or ws_VScroll or cs_ByteAlignClient;} with ScreenSize do begin X:=80; { screen width \ in chars } Y:=25; { screen height/ } TextAttr:=$03; TextChar:='*'; CharSize.X:=0; CharSize.Y:=0; CharAscent:=0; Origin.X:=0; Origin.Y:=0; Range.X:=0; Range.Y:=0; GetMem(CharBuffer,(ScreenSize.X*ScreenSize.Y)+1); GetMem(AttrBuffer,(ScreenSize.X*ScreenSize.Y)+1); FillChar(CharBuffer^,ScreenSize.X*ScreenSize.Y,TextChar); FillChar(AttrBuffer^,ScreenSize.X*ScreenSize.Y,char(TextAttr)); end; end; destructor tColorWin.Done; begin with ScreenSize do begin FreeMem(CharBuffer, X*Y); FreeMem(AttrBuffer, X*Y); end; inherited Done; end; procedure tColorWin.SetupWindow; var DC:hDC; Metrics:tTextMetric; begin inherited SetupWindow; DC:=GetDC(hWindow); SelectObject(DC,GetStockObject(System_Fixed_Font)); GetTextMetrics(DC,Metrics); with Metrics, CharSize do begin X:=tmMaxCharWidth; Y:=tmHeight+tmExternalLeading; CharAscent:=tmAscent; end; DeleteDC(DC); SetScrollRange(hWindow,sb_Horz,0,ScreenSize.X-1,false); SetScrollRange(hWindow,sb_Vert,0,ScreenSize.Y-1,false); end; function tColorWin.GetClassName:pChar; begin GetClassName:='ColorWin'; end; procedure tColorWin.GetWindowClass(var aWndClass:tWndClass); begin inherited GetWindowClass(aWndClass); aWndClass.hIcon:=LoadIcon(0,idi_Application); end; procedure tColorWin.wmSize(var Msg:tMessage); var x,y:integer; begin with Msg do begin x:=LoWord(Msg.lParam); y:=HiWord(Msg.lParam); end; ClientSize.X:=X div CharSize.X; ClientSize.Y:=Y div CharSize.Y; Range.X:=Max(0,ScreenSize.X-ClientSize.X); Range.Y:=Max(0,ScreenSize.Y-ClientSize.Y); Origin.X:=Min(Origin.X, Range.X); Origin.Y:=Min(Origin.Y, Range.Y); SetScrollBars; end; function tColorWin.CharPtr(X,Y:integer):pChar; {Return pointer to the Char at (X,Y) in the screen buffer} begin CharPtr:=@CharBuffer[Y*ScreenSize.X+X]; end; function tColorWin.AttrPtr(X,Y:integer):pChar; {Return pointer to the Attr at (X,Y) in the screen buffer} begin AttrPtr:=@AttrBuffer[Y*ScreenSize.X+X]; end; procedure tColorWin.SetScrollBars; {Update scroll bars} begin SetScrollRange(hWindow, sb_Horz, 0, Max(0,Range.X), false); SetScrollPos(hWindow, sb_Horz, Origin.X, true); SetScrollRange(hWindow, sb_Vert, 0, Max(0,Range.Y), false); SetScrollPos(hWindow, sb_Vert, Origin.Y, true); end; procedure tColorWin.ScrollTo(X,Y:integer); {Scroll window to given origin} begin X:=Max(0,Min(X,Range.X)); Y:=Max(0,Min(Y,Range.Y)); if (X <>Origin.X) or (Y <>Origin.Y) then begin if X <>Origin.X then SetScrollPos(hWindow,sb_Horz,X,true); if Y <>Origin.Y then SetScrollPos(hWindow,sb_Vert,Y,true); ScrollWindow(hWindow,(Origin.X-X)*CharSize.X,(Origin.Y-Y)*CharSize.Y, nil,nil); Origin.X:=X; Origin.Y:=Y; UpdateWindow(hWindow); end; end; procedure tColorWin.Byte2bkRgb(c:byte; var bkRGB:tColorRef); begin bkRGB:=vgaColor[c shr 4]; end; procedure tColorWin.Byte2fgRgb(c:byte; var fgRGB:tColorRef); begin fgRGB:=vgaColor[c and $F]; end; procedure tColorWin.Byte2rgb(c:byte; var bkRGB:tColorRef; var fgRGB:tColorRef); begin bkRGB:=vgaColor[c shr 4]; fgRGB:=vgaColor[c and $F]; end; procedure tColorWin.ClrScr; {Clear the screen} var _y:integer; begin FillChar(CharBuffer^,ScreenSize.X*ScreenSize.Y,TextChar); FillChar(AttrBuffer^,ScreenSize.X*ScreenSize.Y,char(TextAttr)); Longint(Origin):=0; SetScrollBars; InvalidateRect(hWindow,nil,false {true}); UpdateWindow(hWindow); end; procedure tColorWin.Paint(PaintDC:hDC; var PS:tPaintStruct); {wm_Paint message handler} var X1,X2,Y1,Y2:integer; bkRGB,fgRGB:tColorRef; i:integer; begin SelectObject(PaintDC, GetStockObject(System_Fixed_Font)); {---} MoveTo(PaintDC, ScreenSize.X*CharSize.X,0); LineTo(PaintDC, ScreenSize.X*CharSize.X,ScreenSize.Y*CharSize.Y); LineTo(PaintDC, 0,ScreenSize.Y*CharSize.Y); X1:=Max(0, PS.rcPaint.left div CharSize.X+Origin.X); X2:=Min((PS.rcPaint.right+CharSize.X-1) div CharSize.X+Origin.X,ScreenSize.X); Y1:=Max(0, PS.rcPaint.top div CharSize.Y+Origin.Y-1); Y2:=Min((PS.rcPaint.bottom+CharSize.Y-1) div CharSize.Y+Origin.Y,ScreenSize.Y); while Y1 (ScreenSize.X*ScreenSize.Y-(Row*ScreenSize.X+Col)) then Number:=ScreenSize.X*ScreenSize.Y-(Row*ScreenSize.X+Col); FillChar(CharPtr(pred(Col),pred(Row))^,Number,Ch); FillChar(AttrPtr(pred(Col),pred(Row))^,Number,_Attr); end; procedure tColorWin.FastCenter(St:string; Row,_Attr:byte); var sL:byte absolute St; begin if sL >succ(ScreenSize.X-ScreenSize.X) then sL:=succ(ScreenSize.X-ScreenSize.X); FastWrite(St,ScreenSize.Y+Row,ScreenSize.X+ succ((succ(ScreenSize.X-ScreenSize.X)-sL) shr 1),_Attr); end; function tColorWin.GetNewPos(Action:word; Pos,Page,_Range, Thumb:integer):integer; begin case Action of sb_LineUp: GetNewPos:=Pos-1; sb_LineDown: GetNewPos:=Pos+1; sb_PageUp: GetNewPos:=Pos-Page; sb_PageDown: GetNewPos:=Pos+Page; sb_Top: GetNewPos:=0; sb_Bottom: GetNewPos:=_Range; sb_ThumbPosition: GetNewPos:=Thumb; else GetNewPos:=Pos; end; end; procedure tColorWin.wmHScroll(var Msg:tMessage); {wm_HScroll handler} var X:integer; begin X:=Origin.X; X:=GetNewPos(Msg.wParam, X, ClientSize.X div 2, Range.X, Msg.lParamLo); ScrollTo(X, Origin.Y); end; procedure tColorWin.wmVScroll(var Msg:tMessage); {wm_VScroll handler} var Y:integer; begin Y:=Origin.Y; Y:=GetNewPos(Msg.wParam, Y, ClientSize.Y, Range.Y, Msg.lParamLo); ScrollTo(Origin.X, Y); end; end. { ---------------------- CUT ----------------------- } (************************************************) (* The Demostration Module for tColorWin object *) (************************************************) uses WinTypes, WinProcs, oWindows, ColorWin; {-tColorWin object} const AppName:pChar='tColorWin demo'; CaptionText:pChar='Color Window test..'; {===[ This application does nothing but shows you ]===} {===[ how to use tColorWin object ]===} type tMyApp=object(tApplication) procedure InitMainWindow; virtual; end; pMyWin=^tMyWin; tMyWin=object(tColorWin) procedure SetupWindow; virtual; end; procedure tMyWin.SetupWindow; var i:byte; begin inherited SetupWindow; for i:=1 to 15 do FastWrite('Test string for check ColorWin. Don`t panic! ;-)',i,2,i); end; procedure tMyApp.InitMainWindow; begin MainWindow:=New(pMyWin,Init(nil,CaptionText)); end; var MyApp:tMyApp; begin MyApp.Init(AppName); MyApp.Run; MyApp.Done; end.