home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / BPASCAL.700 / D11 / RWDEMOS.ZIP / RWPWND.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-01  |  28.3 KB  |  1,155 lines

  1. {************************************************}
  2. {                                                }
  3. {   Resource Workshop Demo                       }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. unit RWPWnd;
  9.  
  10. {$R-}
  11.  
  12. interface
  13.  
  14. uses RWPDlgs, WinProcs, WinTypes, Objects, OWindows, ODialogs, OMemory,
  15.   Strings, OStdDlgs, RWPDemoC, WinDOS;
  16.  
  17. const
  18.   OpenEditWindows: Word = 0;
  19.   OpenWindows: Word = 0;
  20.  
  21. type
  22.   PBaseMDIChildWindow = ^TBaseMDIChildWindow;
  23.   TBaseMDIChildWindow = object(TWindow)
  24.     TheMenu: HMenu;
  25.     constructor Init(aParent: PWindowsObject; ATitle: PChar);
  26.     destructor Done; virtual;
  27.     function GetPopupMenu: HMenu; virtual;
  28.     function GetPopupTitle: PChar; virtual;
  29.     procedure SetEditPopup(Style: Word);
  30.     procedure SetWindowPopup(Style: Word);
  31.     procedure SetupWindow; virtual;
  32.     procedure WMMDIActivate(var Msg: TMessage); virtual wm_MDIActivate;
  33.     procedure WMRButtonDown(var Msg: TMessage); virtual wm_RButtonUp;
  34.   end;
  35.  
  36.   { TDocument }
  37.   PDocument = ^TDocument;
  38.   TDocument = object(TBaseMDIChildWindow)
  39.     Changed: Boolean;
  40.     FileName: PChar;
  41.     IsNewFile: Boolean;
  42.  
  43.     constructor Init(AParent: PWindowsObject; AFileName: PChar);
  44.     constructor Load(var S: TStream);
  45.     destructor Done; virtual;
  46.     function CanClear: Boolean; virtual;
  47.     function CanClose: Boolean; virtual;
  48.     procedure ClearModify;
  49.     procedure ClearWindow; virtual;
  50.     procedure CMFileSave(var Msg: TMessage); virtual cm_First + cm_Save;
  51.     procedure CMFileSaveAs(var Msg: TMessage); virtual cm_First + cm_SaveAs;
  52.     function GetTitlePrefix: PChar; virtual;
  53.     function IsModified: Boolean; virtual;
  54.     procedure Read; virtual;
  55.     function Save: Boolean; virtual;
  56.     function SaveAs: Boolean; virtual;
  57.     procedure SetFileName(AFileName: PChar);
  58.     procedure SetupWindow; virtual;
  59.     procedure Store(var S: TStream);
  60.     procedure Write; virtual;
  61.   end;
  62.  
  63.   { TEditWindow  }
  64.   PEditWindow = ^TEditWindow;
  65.   TEditWindow = object(TDocument)
  66.     Editor: PEdit;
  67.     constructor Init(AParent: PWindowsObject; ATitle: PChar);
  68.     constructor Load(var S: TStream);
  69.     destructor Done; virtual;
  70.     procedure ClearModify; virtual;
  71.     procedure ClearWindow; virtual;
  72.     function  GetTitlePrefix: PChar; virtual;
  73.     function IsModified: Boolean; virtual;
  74.     procedure Read; virtual;
  75.     procedure Store(var S: TStream);
  76.     procedure WMSize(var Msg: TMessage); virtual wm_First + wm_Size;
  77.     procedure WMSetFocus(var Msg: TMessage); virtual wm_First + wm_SetFocus;
  78.     procedure Write; virtual;
  79.   end;
  80.  
  81.  
  82. type
  83.   PGraphObject = ^TGraphObject;
  84.   TGraphObject = object(TObject)
  85.     X1, Y1, X2, Y2: Integer;
  86.     TheColor: TColorRef;
  87.     ThePen: THandle;
  88.     OldPen: THandle;
  89.     constructor Init(R: TRect; AColor: TColorRef);
  90.     constructor Load(var S: TStream);
  91.     procedure Assign(R: TRect);
  92.     procedure Draw(HandleDC: HDC); virtual;
  93.     procedure DrawRect(HandleDC: HDC; R: TRect);
  94.     procedure EndDraw(HandleDC: HDC);
  95.     procedure Store(var S: TStream);
  96.   end;
  97.  
  98.   PRectangle = ^TRectangle;
  99.   TRectangle = object(TGraphObject)
  100.     procedure Draw(HandleDC: HDC); virtual;
  101.   end;
  102.  
  103.   PCircle = ^TCircle;
  104.   TCircle = object(TGraphObject)
  105.     procedure Draw(HandleDC: HDC); virtual;
  106.   end;
  107.  
  108. const
  109.   ShapeCircle = 1;
  110.   ShapeRectangle = 2;
  111.  
  112. type
  113.   PGraphWindow = ^TGraphWindow;
  114.   TGraphWindow = object(TDocument)
  115.     ButtonDown: Boolean;
  116.     CurrentShape: PGraphObject;
  117.     HandleDC: HDC;
  118.     MenuShape: Integer;
  119.     MenuColor: TColorRef;
  120.     OldROP: Word;
  121.     Rect: TRect;
  122.     TheShapes: PCollection;
  123.     constructor Init(AParent: PWindowsObject; ATitle: PChar);
  124.     destructor Done; virtual;
  125.     procedure Clear; virtual;
  126.     procedure CMBlue(var Msg: TMessage); virtual cm_First + cm_Blue;
  127.     procedure CMCircle(var Msg: TMessage); virtual cm_First + cm_Circle;
  128.     procedure CMClear(var Msg: TMessage); virtual cm_First + cm_ClearShape;
  129.     procedure CMGreen(var Msg: TMessage); virtual cm_First + cm_Green;
  130.     procedure CMRectangle(var Msg: TMessage); virtual cm_First + cm_Rectangle;
  131.     procedure CMRed(var Msg: TMessage); virtual cm_First + cm_Red;
  132.     function GetPopupMenu: HMenu; virtual;
  133.     function GetPopupTitle: PChar; virtual;
  134.     function GetTitlePrefix: PChar; virtual;
  135.     procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct); virtual;
  136.     procedure Read; virtual;
  137.     procedure WMLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown;
  138.     procedure WMLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonUp;
  139.     procedure WMMouseMove(var Msg: TMessage); virtual wm_First + wm_MouseMove;
  140.     procedure Write; virtual;
  141.   end;
  142.  
  143. type
  144.   PPointCollection = ^TPointCollection;
  145.   TPointCollection = object(TCollection)
  146.     destructor Done; virtual;
  147.     function GetItem(var S: TStream): Pointer; virtual;
  148.     procedure PutItem(var S: TStream; Item: Pointer); virtual;
  149.   end;
  150.  
  151. type
  152.   PLine = ^TLine;
  153.   TLine = object(TObject)
  154.     X,Y: Integer;
  155.     LineColor: TColorRef;
  156.     PointCollection: PPointCollection;
  157.     LineThickness: Byte;
  158.     constructor Init(AColor: TColorRef; AThickness: Byte);
  159.     constructor Load(var S: TStream);
  160.     destructor Done; virtual;
  161.     procedure Store(var S: TStream);
  162.   end;
  163.  
  164. type
  165.   PScribbleWindow = ^TScribbleWindow;
  166.   TScribbleWindow = object(TDocument)
  167.     ButtonDown: Boolean;
  168.     CurrentLine: PLine;
  169.     HandleDC: HDC;
  170.     LineCollection: PCollection;
  171.     MenuColor: TColorRef;
  172.     MenuThickness: Byte;
  173.     OldPen: THandle;
  174.  
  175.     constructor Init(aParent: PWindowsObject; ATitle: PChar);
  176.     constructor Load(var S: TStream);
  177.     destructor Done; virtual;
  178.     procedure Clear; virtual;
  179.     procedure CMBlue(var Msg: TMessage); virtual cm_First + cm_Blue;
  180.     procedure CMClear(var Msg: TMessage); virtual cm_First + cm_ClearShape;
  181.     procedure CMGreen(var Msg: TMessage); virtual cm_First + cm_Green;
  182.     procedure CMNormal(var Msg: TMessage); virtual cm_First + cm_Normal;
  183.     procedure CMRed(var Msg: TMessage); virtual cm_First + cm_Red;
  184.     procedure CMThick(var Msg: TMessage); virtual cm_First + cm_Thick;
  185.     procedure CMThin(var Msg: TMessage); virtual cm_First + cm_Thin;
  186.     function GetPopupMenu: HMenu; virtual;
  187.     function GetPopupTitle: PChar; virtual;
  188.     function GetTitlePrefix: PChar; virtual;
  189.     procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct); virtual;
  190.     procedure Read; virtual;
  191.     procedure Store(var S: TStream); virtual;
  192.     procedure WMLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown;
  193.     procedure WMLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonUp;
  194.     procedure WMMouseMove(var Msg: TMessage); virtual wm_First + wm_MouseMove;
  195.     procedure Write; virtual;
  196.   end;
  197.  
  198. implementation
  199.  
  200. function Min(a, b: Word): Word;
  201. begin
  202.   if a < b then Min := a
  203.   else Min := b;
  204. end;
  205.  
  206. function Max(a, b: Word): Word;
  207. begin
  208.   if a > b then Max := a
  209.   else Max := b;
  210. end;
  211.  
  212. {---------------- TBaseMDIChildWindow implementation ------------------}
  213.  
  214. constructor TBaseMDIChildWindow.Init(aParent: PWindowsObject; ATitle: PChar);
  215. begin
  216.   TWindow.Init(aParent, ATitle);
  217.   TheMenu := 0;
  218. end;
  219.  
  220. procedure TBaseMDIChildWindow.SetupWindow;
  221. begin
  222.   TWindow.SetupWindow;
  223.   if (OpenWindows = 0) then
  224.     SetWindowPopup(mf_Enabled);
  225.   Inc(OpenWindows);
  226. end;
  227.  
  228. destructor TBaseMDIChildWindow.Done;
  229. begin
  230.   TWindow.Done;
  231.   Dec(OpenWindows);
  232.   if OpenWindows = 0 then
  233.     SetWindowPopup(mf_Disabled or mf_Grayed);
  234. end;
  235.  
  236.  
  237. function TBaseMDIChildWindow.GetPopupMenu: HMenu;
  238. begin
  239.   GetPopupMenu := 0;
  240. end;
  241.  
  242. function TBaseMDIChildWindow.GetPopupTitle: PChar;
  243. begin
  244.   GetPopupTitle := nil;
  245. end;
  246.  
  247. procedure TBaseMDIChildWindow.SetEditPopup(Style: Word);
  248. var
  249.   AMenu: HMenu;
  250. begin
  251.   if Application^.MainWindow^.HWindow <> 0 then
  252.   begin
  253.     AMenu := GetMenu(Application^.MainWindow^.HWindow);
  254.     if AMenu <> 0 then
  255.     begin
  256.       EnableMenuItem(AMenu, cm_EditUndo, mf_ByCommand or Style);
  257.       EnableMenuItem(AMenu, cm_EditCut, mf_ByCommand or Style);
  258.       EnableMenuItem(AMenu, cm_EditCopy, mf_ByCommand or Style);
  259.       EnableMenuItem(AMenu, cm_EditPaste, mf_ByCommand or Style);
  260.       EnableMenuItem(AMenu, cm_EditClear, mf_ByCommand or Style);
  261.       EnableMenuItem(AMenu, cm_EditDelete, mf_ByCommand or Style);
  262.    end;
  263.   end;
  264. end;
  265.  
  266. procedure TBaseMDIChildWindow.SetWindowPopup(Style: Word);
  267. var
  268.   AMenu: HMenu;
  269. begin
  270.   if Application^.MainWindow^.HWindow <> 0 then
  271.   begin
  272.     AMenu := GetMenu(Application^.MainWindow^.HWindow);
  273.     if AMenu <> 0 then
  274.     begin
  275.       EnableMenuItem(AMenu, cm_CloseChildren, mf_ByCommand or Style);
  276.       EnableMenuItem(AMenu, cm_TileChildren, mf_ByCommand or Style);
  277.       EnableMenuItem(AMenu, cm_CascadeChildren, mf_ByCommand or Style);
  278.       EnableMenuItem(AMenu, cm_ArrangeIcons, mf_ByCommand or Style);
  279.       EnableMenuItem(AMenu, cm_Save, mf_ByCommand or Style);
  280.       EnableMenuItem(AMenu, cm_SaveAs, mf_ByCommand or Style);
  281.       EnableMenuItem(AMenu, cm_Print, mf_ByCommand or Style);
  282.     end;
  283.   end;  
  284. end;
  285.  
  286.  
  287. procedure TBaseMDIChildWindow.WMMDIActivate(var Msg: TMessage);
  288. begin
  289.   DefWndProc(Msg);
  290.   if Typeof(Self) = TypeOf(TEditWindow) then
  291.     SetEditPopup(mf_Enabled)
  292.   else
  293.     SetEditPopup(mf_Grayed);
  294. end;
  295.  
  296. procedure TBaseMDIChildWindow.WMRButtonDown(var Msg: TMessage);
  297. var
  298.   AMenu: HMenu;
  299.   AName: PChar;
  300. begin
  301.   AMenu := CreatePopupMenu;
  302.   AName := GetPopupTitle;
  303.  
  304.   if AName <> nil then
  305.   begin
  306.     AppendMenu(AMenu, mf_Popup, GetPopupMenu, AName);
  307.     ClientToScreen(HWindow, MakePoint(Msg.LParam));
  308.     TrackPopupMenu(AMenu, 0, Msg.LParamLo, Msg.LParamHi, 0, HWindow, nil);
  309.     DestroyMenu(AMenu);
  310.   end;
  311. end;
  312.  
  313. {------------------------- TDocument Implementation ---------------------}
  314. constructor TDocument.Init(AParent: PWindowsObject; AFileName: PChar);
  315. begin
  316.   TBaseMDIChildWindow.Init(AParent, AFileName);
  317.   IsNewFile := True;
  318.   Changed := False;
  319.   if AFileName = nil then
  320.     FileName := nil
  321.   else
  322.     FileName := StrNew(AFileName);
  323. end;
  324.  
  325. constructor TDocument.Load(var S: TStream);
  326. begin
  327.   TBaseMDIChildWindow.Load(S);
  328.   FileName := S.StrRead;
  329.   IsNewFile := FileName = nil;
  330. end;
  331.  
  332. destructor TDocument.Done;
  333. begin
  334.   StrDispose(FileName);
  335.   TBaseMDIChildWindow.Done;
  336. end;
  337.  
  338. function TDocument.CanClear: Boolean;
  339. var
  340.   S: array[0..fsPathName+27] of Char;
  341.   P: PChar;
  342.   Rslt: Integer;
  343. begin
  344.   CanClear := True;
  345.   if IsModified then
  346.   begin
  347.     if FileName = nil then StrCopy(S, 'Untitled file has changed. Save?')
  348.     else
  349.     begin
  350.       P := FileName;
  351.       WVSPrintF(S, 'File "%s" has changed.  Save?', P);
  352.     end;
  353.     Rslt := MessageBox(HWindow, S, 'File Changed',
  354.                mb_YesNoCancel or mb_IconQuestion);
  355.     if Rslt = id_Yes then CanClear := Save
  356.     else CanClear := Rslt <> id_Cancel;
  357.   end;
  358. end;
  359.  
  360. function TDocument.CanClose: Boolean;
  361. begin
  362.   CanClose := CanClear;
  363. end;
  364.  
  365. procedure TDocument.ClearWindow;
  366. begin
  367. end;
  368.  
  369. procedure TDocument.ClearModify;
  370. begin
  371. end;
  372.  
  373. procedure TDocument.CMFileSave(var Msg: TMessage);
  374. begin
  375.   Save;
  376. end;
  377.  
  378. procedure TDocument.CMFileSaveAs(var Msg: TMessage);
  379. begin
  380.   SaveAs;
  381. end;
  382.  
  383. function TDocument.GetTitlePrefix: PChar;
  384. begin
  385.   GetTitlePrefix := nil;
  386. end;
  387.  
  388. function TDocument.IsModified: Boolean;
  389. begin
  390.   IsModified := Changed;
  391. end;
  392.  
  393. procedure TDocument.Read;
  394. begin
  395.   IsNewFile := False;
  396. end;
  397.  
  398. function TDocument.Save: Boolean;
  399. begin
  400.   Save := True;
  401.   if IsModified then
  402.     if IsNewFile then Save := SaveAs
  403.     else Write;
  404. end;
  405.  
  406. function TDocument.SaveAs: Boolean;
  407. var
  408.   TmpName: array[0..fsPathName] of Char;
  409. begin
  410.   SaveAs := False;
  411.   if FileName <> nil then StrCopy(TmpName, FileName)
  412.   else TmpName[0] := #0;
  413.   if Application^.ExecDialog(New(PFileDialog,
  414.     Init(@Self, PChar(sd_FileSave), TmpName))) = id_Ok then
  415.   begin
  416.     SetFileName(TmpName);
  417.     Write;
  418.     SaveAs := True;
  419.   end;
  420. end;
  421.  
  422. procedure TDocument.SetFileName(AFileName: PChar);
  423. var
  424.   NewCaption: array[0..80] of Char;
  425. begin
  426.   if FileName <> AFileName then
  427.   begin
  428.     if FileName <> nil then
  429.       StrDispose(FileName);
  430.     FileName := StrNew(AFileName);
  431.   end;
  432.  
  433.   StrCopy(NewCaption, GetTitlePrefix);
  434.   if FileName = nil then
  435.     StrLCat(NewCaption,'(Untitled)',SizeOf(NewCaption) - StrLen(NewCaption))
  436.   else
  437.     StrLCat(NewCaption, AFileName, SizeOf(NewCaption) - StrLen(NewCaption));
  438.   SetWindowText(HWindow, NewCaption);
  439. end;
  440.  
  441. procedure TDocument.SetupWindow;
  442. begin
  443.   TBaseMDIChildWindow.SetupWindow;
  444.   SetFileName(FileName);
  445.   if FileName <> nil then Read;
  446. end;
  447.  
  448. procedure TDocument.Store(var S: TStream);
  449. begin
  450.   TBaseMDIChildWindow.Store(S);
  451.   S.StrWrite(FileName);
  452. end;
  453.  
  454. procedure TDocument.Write;
  455. begin
  456.   Changed := False;
  457. end;
  458.  
  459. {------------------------- TEditWindow Implementation ---------------------}
  460.  
  461. constructor TEditWindow.Init(AParent: PWindowsObject; ATitle: PChar);
  462. var
  463.   Temp: array [0..50] of Char;
  464. begin
  465.   TDocument.Init(AParent, ATitle);
  466.   Editor := New(PEdit, Init(@Self, 200, nil, 0, 0, 0, 0, 0, True));
  467.   with Editor^.Attr do
  468.     Style := Style or es_NoHideSel;
  469.   Inc(OpenEditWindows);
  470. end;
  471.  
  472. constructor TEditWindow.Load(var S: TStream);
  473. begin
  474.   TDocument.Load(S);
  475.   GetChildPtr(S, Editor);
  476. end;
  477.  
  478. destructor TEditWindow.Done;
  479. begin
  480.   TDocument.Done;
  481.   Dec(OpenEditWindows);
  482.   if OpenEditWindows = 0 then
  483.     SetEditPopup(mf_Disabled or mf_Grayed);
  484. end;
  485.  
  486. procedure TEditWindow.ClearModify;
  487. begin
  488.   Editor^.ClearModify;
  489. end;
  490.  
  491. procedure TEditWindow.ClearWindow;
  492. begin
  493.   Editor^.Clear;
  494. end;
  495.  
  496. function TEditWindow.GetTitlePrefix: PChar;
  497. begin
  498.   GetTitlePrefix := 'Text: ';
  499. end;
  500.  
  501. function TEditWindow.IsModified: Boolean;
  502. begin
  503.   IsModified := Editor^.IsModified;
  504. end;
  505.  
  506. procedure TEditWindow.Read;
  507. const
  508.   BufferSize = 1024;
  509. var
  510.   CharsToRead: LongInt;
  511.   BlockSize: Integer;
  512.   AStream: PDosStream;
  513.   ABuffer: PChar;
  514. begin
  515.   TDocument.Read;
  516.   AStream := New(PDosStream, Init(FileName, stOpen));
  517.   ABuffer := MemAlloc(BufferSize + 1);
  518.   CharsToRead := AStream^.GetSize;
  519.   if ABuffer <> nil then
  520.   begin
  521.     Editor^.Clear;
  522.     while CharsToRead > 0 do
  523.     begin
  524.       if CharsToRead > BufferSize then BlockSize := BufferSize
  525.       else BlockSize := CharsToRead;
  526.       AStream^.Read(ABuffer^, BlockSize);
  527.       ABuffer[BlockSize] := Char(0);
  528.       Editor^.Insert(ABuffer);
  529.       CharsToRead := CharsToRead - BlockSize;
  530.     end;
  531.     IsNewFile := False;
  532.     Editor^.ClearModify;
  533.     Editor^.SetSelection(0, 0);
  534.     FreeMem(ABuffer, BufferSize + 1);
  535.   end;
  536.   Dispose(AStream, Done);
  537. end;
  538.  
  539. procedure TEditWindow.Store(var S: TStream);
  540. begin
  541.   TDocument.Store(S);
  542.   PutChildPtr(S, Editor);
  543. end;
  544.  
  545. procedure TEditWindow.WMSetFocus(var Msg: TMessage);
  546. begin
  547.   SetFocus(Editor^.HWindow);
  548. end;
  549.  
  550. procedure TEditWindow.WMSize(var Msg: TMessage);
  551. begin
  552.   TDocument.WMSize(Msg);
  553.   SetWindowPos(Editor^.HWindow, 0, -1, -1, Msg.LParamLo+2, Msg.LParamHi+2,
  554.     swp_NoZOrder);
  555. end;
  556.  
  557. procedure TEditWindow.Write;
  558. const
  559.   BufferSize = 1024;
  560. var
  561.   CharsToWrite, CharsWritten: LongInt;
  562.   BlockSize: Integer;
  563.   AStream: PDosStream;
  564.   ABuffer: pointer;
  565.   NumLines: Integer;
  566. begin
  567.   TDocument.Write;
  568.   NumLines := Editor^.GetNumLines;
  569.   CharsToWrite := Editor^.GetLineIndex(NumLines-1) +
  570.     Editor^.GetLineLength(NumLines-1);
  571.   AStream := New(PDosStream, Init(FileName, stCreate));
  572.   ABuffer := MemAlloc(BufferSize + 1);
  573.   CharsWritten := 0;
  574.   if ABuffer <> nil then
  575.   begin
  576.     while CharsWritten < CharsToWrite do
  577.     begin
  578.       if CharsToWrite - CharsWritten > BufferSize then
  579.         BlockSize := BufferSize
  580.       else BlockSize := CharsToWrite - CharsWritten;
  581.       Editor^.GetSubText(ABuffer, CharsWritten, CharsWritten + BlockSize);
  582.       AStream^.Write(ABuffer^, BlockSize);
  583.       CharsWritten := CharsWritten + BlockSize;
  584.     end;
  585.     Editor^.ClearModify;
  586.     FreeMem(ABuffer, BufferSize + 1);
  587.   end;
  588.  
  589.   Dispose(AStream, Done);
  590. end;
  591.  
  592. {------------------------- TGraphObject Implementation ---------------------}
  593.  
  594. constructor TGraphObject.Init(R: TRect; AColor: TColorRef);
  595. begin
  596.   TObject.Init;
  597.   TheColor := AColor;
  598.   Assign(R);
  599. end;
  600.  
  601. constructor TGraphObject.Load(var S: TStream);
  602. begin
  603.   TObject.Init;
  604.   S.Read(X1, SizeOf(X1));
  605.   S.Read(X2, SizeOf(X2));
  606.   S.Read(Y1, SizeOf(Y1));
  607.   S.Read(Y2, SizeOf(Y2));
  608.   S.Read(TheColor, SizeOf(TheColor));
  609. end;
  610.  
  611. procedure TGraphObject.Assign(R: TRect);
  612. begin
  613.   with R do
  614.   begin
  615.     X1 := Left;
  616.     X2 := Right;
  617.     Y1 := Top;
  618.     Y2 := Bottom;
  619.   end;
  620. end;
  621.  
  622. procedure TGraphObject.Draw(HandleDC: HDC);
  623. begin
  624.   ThePen := CreatePen(ps_Solid, 1, TheColor);
  625.   OldPen := SelectObject(HandleDC, ThePen);
  626. end;
  627.  
  628. procedure TGraphObject.DrawRect(HandleDC: HDC; R: TRect);
  629. begin
  630.   with R do
  631.     SetRect(R, Min(Right, Left), Min(Bottom, Top),
  632.       Max(Right, Left), Max(Top, Bottom));
  633.   Assign(R);
  634.   Draw(HandleDC);
  635. end;
  636.  
  637. procedure TGraphObject.EndDraw(HandleDC: HDC);
  638. begin
  639.   DeleteObject(SelectObject(HandleDC, OldPen));
  640. end;
  641.  
  642.  
  643. procedure TGraphObject.Store(var S: TStream);
  644. begin
  645.   S.Write(X1, SizeOf(X1));
  646.   S.Write(X2, SizeOf(X2));
  647.   S.Write(Y1, SizeOf(Y1));
  648.   S.Write(Y2, SizeOf(Y2));
  649.   S.Write(TheColor, SizeOf(TheColor));
  650. end;
  651.  
  652. {------------------ TRectangle, TCircle Implementations ---------------}
  653.  
  654. procedure TRectangle.Draw(HandleDC: HDC);
  655. begin
  656.   TGraphObject.Draw(HandleDC);
  657.   Rectangle(HandleDC, X1, Y1, X2, Y2);
  658.   EndDraw(HandleDC);
  659. end;
  660.  
  661. procedure TCircle.Draw(HandleDC: HDC);
  662. begin
  663.   TGraphObject.Draw(HandleDC);
  664.   Ellipse(HandleDC, X1, Y1, X2, Y2);
  665.   EndDraw(HandleDC);
  666. end;
  667.  
  668. {------------------------ TGraphWindow Implementation ------------------}
  669.  
  670. constructor TGraphWindow.Init(AParent: PWindowsObject; ATitle: PChar);
  671. begin
  672.   TDocument.Init(AParent, ATitle);
  673.   ButtonDown := False;
  674.   MenuShape := ShapeRectangle;
  675.   MenuColor := RGB(255, 0, 0);
  676.   New(TheShapes, Init(5, 5));
  677. end;
  678.  
  679. destructor TGraphWindow.Done;
  680. begin
  681.   TDocument.Done;
  682.   Dispose(TheShapes, Done);
  683. end;
  684.  
  685. procedure TGraphWindow.Clear;
  686. begin
  687.   TheShapes^.FreeAll;
  688.   InvalidateRect(HWindow, nil, True);
  689.   UpdateWindow(HWindow);
  690. end;
  691.  
  692. procedure TGraphWindow.CMBlue(var Msg: TMessage);
  693. begin
  694.   MenuColor := RGB(0, 0, 255);
  695. end;
  696.  
  697. procedure TGraphWindow.CMCircle(var Msg: TMessage);
  698. begin
  699.   MenuShape := ShapeCircle;
  700. end;
  701.  
  702. procedure TGraphWindow.CMClear(var Msg: TMessage);
  703. begin
  704.   Clear;
  705. end;
  706.  
  707. procedure TGraphWindow.CMGreen(var Msg: TMessage);
  708. begin
  709.   MenuColor := RGB(0, 255, 0);
  710. end;
  711.  
  712. procedure TGraphWindow.CMRectangle(var Msg: TMessage);
  713. begin
  714.   MenuShape := ShapeRectangle;
  715. end;
  716.  
  717. procedure TGraphWindow.CMRed(var Msg: TMessage);
  718. begin
  719.   MenuColor := RGB(255, 0, 0);
  720. end;
  721.  
  722. function TGraphWindow.GetPopupMenu: HMenu;
  723. begin
  724.   GetPopupMenu := LoadMenu(HInstance, MakeIntResource(1001));
  725. end;
  726.  
  727. function TGraphWindow.GetPopupTitle: PChar;
  728. begin
  729.   GetPopupTitle:= 'Graph';
  730. end;
  731.  
  732. function TGraphWindow.GetTitlePrefix: PChar;
  733. begin
  734.   GetTitlePrefix := 'Graph: ';
  735. end;
  736.  
  737. procedure TGraphWindow.Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
  738.  
  739.   procedure DoPaint(GraphObject: PGraphObject); far;
  740.   begin
  741.     GraphObject^.Draw(PaintDC);
  742.   end;
  743.  
  744. begin
  745.   TheShapes^.ForEach(@DoPaint);
  746. end;
  747.  
  748. procedure TGraphWindow.Read;
  749. var
  750.   AStream: PDosStream;
  751.   NewShapes: PCollection;
  752. begin
  753.   TDocument.Read;
  754.   AStream := New(PDosStream, Init(FileName, stOpenRead));
  755.   NewShapes := PCollection(AStream^.Get);
  756.   if AStream^.Status <> 0 then
  757.     Status := ste_InvalidGraphFileMsg
  758.   else
  759.   begin
  760.     if TheShapes <> nil then
  761.       Dispose(TheShapes, Done);
  762.     TheShapes := NewShapes;
  763.   end;
  764.   Dispose(AStream, Done);
  765. end;
  766.  
  767. procedure TGraphWindow.WMLButtonDown(var Msg: TMessage);
  768. begin
  769.   if not ButtonDown then
  770.   begin
  771.     ButtonDown := True;
  772.     Changed := True;
  773.     SetCapture(hWindow);
  774.     HandleDC := GetDC(hWindow);
  775.     OldROP := SetROP2(HandleDC, r2_NotXORPen);
  776.     with Msg do
  777.       SetRect(Rect, LParamLo, LParamHi, LParamLo, LParamHi);
  778.     case MenuShape of
  779.       ShapeRectangle:  CurrentShape := New(PRectangle, Init(Rect, MenuColor));
  780.       ShapeCircle: CurrentShape := New(PCircle, Init(Rect, MenuColor));
  781.     end;
  782.   end;
  783. end;
  784.  
  785. procedure TGraphWindow.WMLButtonUp(var Msg: TMessage);
  786. begin
  787.   if ButtonDown then
  788.   begin
  789.     ReleaseCapture;
  790.     with Msg do
  791.     begin
  792.       SetRect(Rect, Min(LParamLo, Rect.Left), Min(LParamHi, Rect.Top),
  793.         Max(LParamLo, Rect.Left), Max(LParamHi, Rect.Top));
  794.       SetROP2(HandleDC, OldROP);
  795.       CurrentShape^.Assign(Rect);
  796.       CurrentShape^.Draw(HandleDC);
  797.     end;
  798.     ReleaseDC(HWindow,HandleDC);
  799.     TheShapes^.Insert(CurrentShape);
  800.     ButtonDown := False;
  801.   end;
  802. end;
  803.  
  804. procedure TGraphWindow.WMMouseMove(var Msg: TMessage);
  805. begin
  806.   if ButtonDown then
  807.   with Msg do
  808.   begin
  809.     CurrentShape^.DrawRect(HandleDC, Rect);
  810.     SetRect(Rect, Rect.Left, Rect.Top,
  811.       LParamLo, LParamHi);
  812.     CurrentShape^.DrawRect(HandleDC, Rect);
  813.   end;
  814. end;
  815.  
  816. procedure TGraphWindow.Write;
  817. var
  818.   AStream: PDosStream;
  819. begin
  820.   TDocument.Write;
  821.   AStream := New(PDosStream, Init(FileName, stCreate));
  822.   AStream^.Put(TheShapes);
  823.   Dispose(AStream, Done);
  824. end;
  825.  
  826. {----------------------- TPointCollection Implementation -----------------}
  827.  
  828. destructor TPointCollection.Done;
  829.  
  830.   procedure GoodBye(Point: PPoint); far;
  831.   begin
  832.     Dispose(Point);
  833.   end;
  834.  
  835. begin
  836.   ForEach(@GoodBye);
  837.   DeleteAll;
  838.   TCollection.Done;
  839. end;
  840.  
  841. function TPointCollection.GetItem(var S: TStream): Pointer;
  842. var
  843.   P: PPoint;
  844. begin
  845.   New(P);
  846.   with P^ do
  847.   begin
  848.     S.Read(X, SizeOf(X));
  849.     S.Read(Y, SizeOf(Y));
  850.   end;
  851.   GetItem := P;
  852. end;
  853.  
  854. procedure TPointCollection.PutItem(var S: TStream; Item: Pointer);
  855. begin
  856.   with PPoint(Item)^ do
  857.   begin
  858.     S.Write(X, SizeOf(X));
  859.     S.Write(Y, SizeOf(Y));
  860.   end;
  861. end;
  862.  
  863. {---------------- TLine Implementation -------------------}
  864.  
  865. constructor TLine.Init(AColor: TColorRef; AThickness: Byte);
  866. begin
  867.   TObject.Init;
  868.   LineColor := AColor;
  869.   LineThickness := AThickness;
  870.   New(PointCollection, Init(100, 50));
  871. end;
  872.  
  873. constructor TLine.Load(var S: TStream);
  874. begin
  875.   S.Read(X, SizeOf(X));
  876.   S.Read(Y, SizeOf(Y));
  877.   S.Read(LineColor, SizeOf(LineColor));
  878.   S.Read(LineThickness, SizeOf(LineThickness));
  879.   PointCollection := PPointCollection(S.Get);
  880. end;
  881.  
  882. destructor TLine.Done;
  883. begin
  884.   TObject.Done;
  885.   Dispose(PointCollection, Done);
  886. end;
  887.  
  888. procedure TLine.Store(var S: TStream);
  889. begin
  890.   S.Write(X, SizeOf(X));
  891.   S.Write(Y, SizeOf(Y));
  892.   S.Write(LineColor, SizeOf(LineColor));
  893.   S.Write(LineThickness, SizeOf(LineThickness));
  894.   S.Put(PointCollection);
  895. end;
  896.  
  897. {---------------------- TScribbleWindow Implementation ---------------}
  898.  
  899. constructor TScribbleWindow.Init(AParent: PWindowsObject; ATitle: PChar);
  900. begin
  901.   TDocument.Init(aParent, ATitle);
  902.   ButtonDown := False;
  903.   MenuColor := RGB(255, 0, 0);
  904.   MenuThickness := 3;
  905.   New(LineCollection, Init(5, 5));
  906. end;
  907.  
  908. constructor TScribbleWindow.Load(var S: TStream);
  909. begin
  910.   TDocument.Load(S);
  911.   LineCollection := PCollection(S.Get);
  912. end;
  913.  
  914. destructor TScribbleWindow.Done;
  915. begin
  916.   TDocument.Done;
  917.   Dispose(LineCollection, Done);
  918. end;
  919.  
  920. procedure TScribbleWindow.Clear;
  921. begin
  922.   LineCollection^.FreeAll;
  923.   InvalidateRect(HWindow, nil, True);
  924.   UpdateWindow(HWindow);
  925. end;
  926.  
  927. procedure TScribbleWindow.CMBlue(var Msg: TMessage);
  928. begin
  929.   MenuColor := RGB(0, 0, 255);
  930. end;
  931.  
  932. procedure TScribbleWindow.CMClear(var Msg: TMessage);
  933. begin
  934.   Clear;
  935. end;
  936.  
  937. procedure TScribbleWindow.CMGreen(var Msg: TMessage);
  938. begin
  939.   MenuColor := RGB(0, 255, 0);
  940. end;
  941.  
  942. procedure TScribbleWindow.CMNormal(var Msg: TMessage);
  943. begin
  944.   MenuThickness := 3;
  945. end;
  946.  
  947. procedure TScribbleWindow.CMRed(var Msg: TMessage);
  948. begin
  949.   MenuColor := RGB(255, 0, 0);
  950. end;
  951.  
  952. procedure TScribbleWindow.CMThick(var Msg: TMessage);
  953. begin
  954.   MenuThickness := 5;
  955. end;
  956.  
  957. procedure TScribbleWindow.CMThin(var Msg: TMessage);
  958. begin
  959.   MenuThickness := 1;
  960. end;
  961.  
  962. function TScribbleWindow.GetPopupMenu: HMenu;
  963. begin
  964.   GetPopupMenu := LoadMenu(HInstance, MakeIntResource(1000));
  965. end;
  966.  
  967. function TScribbleWindow.GetPopupTitle: PChar;
  968. begin
  969.   GetPopupTitle:= 'Scribble';
  970. end;
  971.  
  972. function TScribbleWindow.GetTitlePrefix: PChar;
  973. begin
  974.   GetTitlePrefix := 'Scribble: ';
  975. end;
  976.  
  977. procedure TScribbleWindow.Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
  978.  
  979.   procedure DrawLine(Line: PLine); far;
  980.  
  981.     procedure DrawSegments(Segment: PPoint); far;
  982.     begin
  983.       LineTo(PaintDC, Segment^.X, Segment^.Y);
  984.     end;
  985.  
  986.   begin
  987.     with Line^ do
  988.     begin
  989.       OldPen := SelectObject(PaintDC, CreatePen(ps_Solid, LineThickness,
  990.         LineColor));
  991.       MoveTo(PaintDC, X, Y);
  992.       PointCollection^.ForEach(@DrawSegments);
  993.       DeleteObject(SelectObject(PaintDC, OldPen));
  994.     end;
  995.   end;
  996.  
  997. begin
  998.   LineCollection^.ForEach(@DrawLine);
  999. end;
  1000.  
  1001. procedure TScribbleWindow.Read;
  1002. var
  1003.   AStream: PDosStream;
  1004.   NewLines: PCollection;
  1005. begin
  1006.   TDocument.Read;
  1007.   AStream := New(PDosStream, Init(FileName, stOpenRead));
  1008.   NewLines := PCollection(AStream^.Get);
  1009.   if AStream^.Status <> 0 then
  1010.     Status := ste_InvalidScribbleFileMsg
  1011.   else
  1012.   begin
  1013.     if LineCollection <> nil then
  1014.       Dispose(LineCollection, Done);
  1015.     LineCollection := NewLines;
  1016.   end;
  1017.   Dispose(AStream, Done);
  1018. end;
  1019.  
  1020. procedure TScribbleWindow.Store(var S: TStream);
  1021. begin
  1022.   TDocument.Store(S);
  1023.   S.Put(LineCollection);
  1024. end;
  1025.  
  1026. procedure TScribbleWindow.WMLButtonDown(var Msg: TMessage);
  1027. begin
  1028.   if not ButtonDown then
  1029.   begin
  1030.     ButtonDown := True;
  1031.     Changed := True;
  1032.     SetCapture(HWindow);
  1033.     HandleDC := GetDC(HWindow);
  1034.     OldPen := SelectObject(HandleDC, CreatePen(ps_Solid, MenuThickness,
  1035.       MenuColor));
  1036.     MoveTo(HandleDC, Msg.LParamLo, Msg.LParamHi);
  1037.     New(CurrentLine, Init(MenuColor, MenuThickness));
  1038.     CurrentLine^.X := Msg.LParamLo;
  1039.     CurrentLine^.Y := Msg.LParamHi;
  1040.   end;
  1041. end;
  1042.  
  1043. procedure TScribbleWindow.WMLButtonUp(var Msg: TMessage);
  1044. begin
  1045.   if ButtonDown then
  1046.   begin
  1047.     ReleaseCapture;
  1048.     DeleteObject(SelectObject(HandleDC, OldPen));
  1049.     ReleaseDC(HWindow,HandleDC);
  1050.     ButtonDown := False;
  1051.     LineCollection^.Insert(CurrentLine);
  1052.   end;
  1053. end;
  1054.  
  1055. procedure TScribbleWindow.WMMouseMove(var Msg: TMessage);
  1056. var
  1057.   APoint: PPoint;
  1058. begin
  1059.   if ButtonDown then
  1060.   begin
  1061.     LineTo(HandleDC, Msg.LParamLo, Msg.LParamHi);
  1062.     New(APoint);
  1063.     APoint^.X := Msg.LParamLo;
  1064.     APoint^.Y := Msg.LParamHi;
  1065.     CurrentLine^.PointCollection^.Insert(APoint);
  1066.   end;
  1067. end;
  1068.  
  1069. procedure TScribbleWindow.Write;
  1070. var
  1071.   AStream: PDosStream;
  1072. begin
  1073.   TDocument.Write;
  1074.   AStream := New(PDosStream, Init(FileName, stCreate));
  1075.   AStream^.Put(LineCollection);
  1076.   Dispose(AStream, Done);
  1077. end;
  1078.  
  1079. {------------------ Stream Registration Records -----------------------}
  1080. const
  1081.   REditWindow: TStreamRec = (
  1082.     ObjType: 80;
  1083.     VmtLink: Ofs(TypeOf(TEditWindow)^);
  1084.     Load:    @TEditWindow.Load;
  1085.     Store:   @TEditWindow.Store);
  1086.  
  1087. const
  1088.   RDocument: TStreamRec = (
  1089.     ObjType: 81;
  1090.     VmtLink: Ofs(TypeOf(TDocument)^);
  1091.     Load:    @TDocument.Load;
  1092.     Store:   @TDocument.Store);
  1093.  
  1094. const
  1095.   RScribbleWindow: TStreamRec = (
  1096.     ObjType: 82;
  1097.     VmtLink: Ofs(TypeOf(TScribbleWindow)^);
  1098.     Load:    @TScribbleWindow.Load;
  1099.     Store:   @TScribbleWindow.Store);
  1100.  
  1101. const
  1102.   RGraphWindow: TStreamRec = (
  1103.     ObjType: 83;
  1104.     VmtLink: Ofs(TypeOf(TGraphWindow)^);
  1105.     Load:    @TGraphWindow.Load;
  1106.     Store:   @TGraphWindow.Store);
  1107.  
  1108. const
  1109.   RPointCollection: TStreamRec = (
  1110.     ObjType: 84;
  1111.     VmtLink: Ofs(TypeOf(TPointCollection)^);
  1112.     Load:    @TPointCollection.Load;
  1113.     Store:   @TPointCollection.Store);
  1114.  
  1115. const
  1116.   RLine: TStreamRec = (
  1117.     ObjType: 85;
  1118.     VmtLink: Ofs(TypeOf(TLine)^);
  1119.     Load:    @TLine.Load;
  1120.     Store:   @TLine.Store);
  1121.  
  1122. const
  1123.   RGraphObject: TStreamRec = (
  1124.     ObjType: 86;
  1125.     VmtLink: Ofs(TypeOf(TGraphObject)^);
  1126.     Load:    @TGraphObject.Load;
  1127.     Store:   @TGraphObject.Store);
  1128.  
  1129. const
  1130.   RRectangle: TStreamRec = (
  1131.     ObjType: 87;
  1132.     VmtLink: Ofs(TypeOf(TRectangle)^);
  1133.     Load:    @TRectangle.Load;
  1134.     Store:   @TRectangle.Store);
  1135. const
  1136.   RCircle: TStreamRec = (
  1137.     ObjType: 88;
  1138.     VmtLink: Ofs(TypeOf(TCircle)^);
  1139.     Load:    @TCircle.Load;
  1140.     Store:   @TCircle.Store);
  1141.  
  1142. begin
  1143.   RegisterWObjects;
  1144.   RegisterType(REditWindow);
  1145.   RegisterType(RDocument);
  1146.   RegisterType(RScribbleWindow);
  1147.   RegisterType(RGraphWindow);
  1148.   RegisterType(RPointCollection);
  1149.   RegisterType(RLine);
  1150.   RegisterType(RGraphObject);
  1151.   RegisterType(RRectangle);
  1152.   RegisterType(RCircle);
  1153. end.
  1154.  
  1155.