Advertisement
anticlown

Lab.5.2.Full(Delphi)

Mar 17th, 2023 (edited)
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 26.42 KB | None | 0 0
  1. Unit UnitMain;
  2.  
  3. Interface
  4.  
  5. Uses
  6.   Winapi.Windows,
  7.   Winapi.Messages,
  8.   System.SysUtils,
  9.   System.Variants,
  10.   System.Classes,
  11.   Vcl.Graphics,
  12.   Vcl.Controls,
  13.   Vcl.Forms,
  14.   Vcl.Dialogs,
  15.   Vcl.Buttons,
  16.   Vcl.ExtCtrls,
  17.   Vcl.StdCtrls,
  18.   Vcl.Menus,
  19.   System.ImageList,
  20.   Vcl.ImgList,
  21.   Vcl.VirtualImageList,
  22.   Vcl.AppEvnts,
  23.   Vcl.Grids,
  24.   ClipBrd,
  25.   Math;
  26.  
  27. Type
  28.   TLabeledEdit = Class(Vcl.ExtCtrls.TLabeledEdit)
  29.   Protected
  30.     Procedure WMPaste(Var Msg:TMessage); Message WM_PASTE;
  31.   End;
  32.   TArr = Array Of Integer;
  33.   TfrmMain = Class(TForm)
  34.     pButtons: TPanel;
  35.     sdbtOpenFromFile: TSpeedButton;
  36.     sdbtStart: TSpeedButton;
  37.     sdbtSaveToFile: TSpeedButton;
  38.     sdbtHelp: TSpeedButton;
  39.     pBack: TPanel;
  40.     lbWelcome: TLabel;
  41.     lbTaskInfo: TLabel;
  42.     lbIncorrectPatricipants: TLabel;
  43.     lbeSize: TLabeledEdit;
  44.     btConfirmSize: TButton;
  45.     mmMainMenu: TMainMenu;
  46.     miFileMenu: TMenuItem;
  47.     miOpenFromFile: TMenuItem;
  48.     miSaveToFile: TMenuItem;
  49.     miHelp: TMenuItem;
  50.     miInfoAboutDeveloper: TMenuItem;
  51.     BalloonHint: TBalloonHint;
  52.     svdSaveToFileDialog: TSaveDialog;
  53.     opdOpenFromFileDialog: TOpenDialog;
  54.     strgrSequence: TStringGrid;
  55.     btFind: TButton;
  56.     vilImages_48: TVirtualImageList;
  57.     btDraw: TButton;
  58.     lbFinalResult: TLabel;
  59.     lbAnswer: TLabel;
  60.     Procedure FormCloseQuery(Sender: TObject; Var CanClose: Boolean);
  61.     Procedure miHelpClick(Sender: TObject);
  62.     Procedure miInfoAboutDeveloperClick(Sender: TObject);
  63.     Procedure miOpenFromFileClick(Sender: TObject);
  64.     Procedure sdbtOpenFromFileClick(Sender: TObject);
  65.     Procedure lbeSizeChange(Sender: TObject);
  66.     Procedure btConfirmSizeClick(Sender: TObject);
  67.     Procedure FormCreate(Sender: TObject);
  68.     Procedure btFindClick(Sender: TObject);
  69.     Procedure sdbtStartClick(Sender: TObject);
  70.     Procedure lbeSizeKeyPress(Sender: TObject; Var Key: Char);
  71.     Procedure btDrawClick(Sender: TObject);
  72.     Procedure sdbtSaveToFileClick(Sender: TObject);
  73.     Procedure miSaveToFileClick(Sender: TObject);
  74.     Procedure strgrSequenceGetEditText(Sender: TObject; ACol, ARow: Integer;
  75.       Var Value: String);
  76.     Procedure strgrSequenceKeyPress(Sender: TObject; Var Key: Char);
  77.     Procedure strgrSequenceSetEditText(Sender: TObject; ACol, ARow: Integer;
  78.       Const Value: String);
  79.     Procedure strgrSequenceSelectCell(Sender: TObject; ACol, ARow: Integer;
  80.       Var CanSelect: Boolean);
  81.   End;
  82.  
  83. Var
  84.   frmMain: TfrmMain;
  85.   PreviousSize: Integer;
  86.  
  87. Implementation
  88.  
  89. {$R *.dfm}
  90.  
  91. Uses UnitData, UnitDraw;
  92.  
  93. Type
  94.     PNode = ^TNode;
  95.     TNode = Record
  96.       Number : Integer;
  97.       Left, Right : PNode;
  98.     End;
  99.  
  100. Var
  101.     IsAlreadySubclassing: Boolean = False;
  102.     LastValue: String;
  103.  
  104. Function IsFileOfArrCorrect(Path: String): Boolean; Stdcall; External 'anticlown.dll';
  105.  
  106. Procedure GetSizeFromFile(Path: String; Var Size: Single; Var IsCorrect: Boolean); Stdcall; External 'anticlown.dll';
  107.  
  108. Function GetSequenceFromFile(Path: String; Size: Integer; Sequence: TArr; Var IsCorrect: Boolean): TArr; Stdcall;  External 'anticlown.dll';
  109.  
  110. Function CheckOnSimilar(Sequence: TArr): Boolean;
  111. Var
  112.     I, J, Temp: Integer;
  113.     IsSimilar: Boolean;
  114. Begin
  115.     IsSimilar := False;
  116.     For I := Low(Sequence) To High(Sequence) - 1 Do
  117.     Begin
  118.         Temp := Sequence[I];
  119.         For J := I + 1 To High(Sequence) Do
  120.             If Temp = Sequence[J] Then
  121.                 IsSimilar := True;
  122.     End;
  123.     CheckOnSimilar := IsSimilar;
  124. End;
  125.  
  126. Procedure AddElem(Var Tree: PNode; Num: Integer);
  127. Var
  128.     IsCorrect : Boolean;
  129. Begin
  130.     IsCorrect := True;
  131.  
  132.     If Tree = nil Then
  133.     Begin
  134.         New(Tree);
  135.         Tree^.Left := nil;
  136.         Tree^.Right := nil;
  137.         Tree^.Number := Num;
  138.  
  139.         IsCorrect := False;
  140.     End;
  141.     If (IsCorrect) Then
  142.     Begin
  143.         If Num < Tree^.Number Then
  144.             AddElem(Tree^.Left, Num)
  145.         Else
  146.             AddElem(Tree^.Right, Num);
  147.     End;
  148. End;
  149.  
  150. Function CreateBinaryTree(Arr: TArr): PNode;
  151. Var
  152.     I: Integer;
  153.     Tree: PNode;
  154. Begin
  155.     For I := Low(Arr) To High(Arr) Do
  156.         AddElem(Tree, Arr[I]);
  157.  
  158.     CreateBinaryTree := Tree;
  159. End;
  160.  
  161. Function TakeBinaryTree(): PNode;
  162. Var
  163.     I, Size: Integer;
  164.     Arr: TArr;
  165.     Head: PNode;
  166. Begin
  167.     Size := StrToInt(frmMain.lbeSize.Text);
  168.     SetLength(Arr, Size);
  169.  
  170.     For I := 1 To Size Do
  171.     Begin
  172.         Arr[I - 1] := StrToInt(frmMain.strgrSequence.Cells[I, 1]);
  173.     End;
  174.  
  175.     Head := CreateBinaryTree(Arr);
  176.     TakeBinaryTree := Head;
  177. End;
  178.  
  179. Function FindMaxLengthWay(Var Tree: PNode; Var MaxLength: Integer): Integer;
  180. Var
  181.     LengthLeft, LengthRight, CurrentLength: Integer;
  182. Begin
  183.     Result := 0;
  184.     If Tree <> nil Then
  185.     Begin
  186.         LengthLeft := FindMaxLengthWay(Tree.Left, MaxLength);
  187.         LengthRight := FindMaxLengthWay(Tree.Right, MaxLength);
  188.  
  189.         If Tree.Left = nil Then
  190.         begin
  191.             FindMaxLengthWay := LengthRight + 1;
  192.             Exit;
  193.         end;
  194.  
  195.         If Tree.Right = nil Then
  196.         Begin
  197.             FindMaxLengthWay := LengthLeft + 1;
  198.             Exit;
  199.         End;
  200.  
  201.         CurrentLength := LengthLeft + LengthRight;
  202.  
  203.         MaxLength := Max(CurrentLength, MaxLength);
  204.  
  205.         FindMaxLengthWay := Max(LengthRight, LengthLeft) + 1;
  206.     End
  207. End;
  208.  
  209. Function IsTreeUnary(Var Tree: PNode; IsUnary: Boolean): Boolean;
  210. Begin
  211.     If Tree <> nil Then
  212.     Begin
  213.         If Tree.Right = nil Then
  214.             IsTreeUnary(Tree.Left, IsUnary)
  215.         Else
  216.             IsTreeUnary := False;
  217.     End;
  218. End;
  219.  
  220. Function FindMaxWay(Var Tree: PNode): Integer;
  221. Var
  222.     MaxLength, Counter: Integer;
  223.     IsUnary: Boolean;
  224. Begin
  225.     MaxLength := 0;
  226.     Counter := 0;
  227.     IsUnary := True;
  228.     MaxLength := FindMaxLengthWay(Tree, MaxLength);
  229.  
  230.     If MaxLength > 0 Then
  231.     Begin
  232.         IsUnary := IsTreeUnary(Tree, IsUnary);
  233.         If IsUnary Then
  234.             FindMaxWay := MaxLength - 1
  235.         Else
  236.             FindMaxWay := MaxLength;
  237.     End;
  238. End;
  239.  
  240. Procedure TfrmMain.FormCloseQuery(Sender: TObject; Var CanClose: Boolean);
  241. Begin
  242.     If Application.MessageBox(PChar('Вы уверены, что хотите выйти?'), PChar('Выход'),
  243.         MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON1 + MB_TASKMODAL) = IDYES Then
  244.             CanClose := True
  245.         Else
  246.             CanClose := False;
  247. End;
  248.  
  249. Procedure TfrmMain.FormCreate(Sender: TObject);
  250. Begin
  251.     UnitMain.PreviousSize := 0;
  252.     strgrSequence.Cells[0, 0] := '№';
  253.     strgrSequence.Cells[0, 1] := 'Эл.';
  254. End;
  255.  
  256. Procedure TfrmMain.miHelpClick(Sender: TObject);
  257. Const
  258.     FIRST_MESSAGE = '- Вводимыми значениями могут являться только целые числа!' + #13#10;
  259.     SECOND_MESSAGE = '- Диапазон ввода количество элементов: 2...10' + #13#10;
  260.     THIRD_MESSAGE = '- Диапазон вводимых значений элементов: -99...99. ' + #13#10;
  261.     FOURTH_MESSAGE = '- Для ввода из файла используйте вкладку ''Файл'' - ''Открыть''.' + #13#10;
  262.     FIFTH_MESSAGE = '- Для сохранения в файл используйте вкладку ''Файл'' - ''Сохранить''.' + #13#10;
  263.     SIXTH_MESSAGE = '- Для удобного использования программы представлена панель кнопок на левой панели.';
  264. Begin
  265.     Application.MessageBox(FIRST_MESSAGE + SECOND_MESSAGE + THIRD_MESSAGE +
  266.                             FOURTH_MESSAGE + FIFTH_MESSAGE + SIXTH_MESSAGE, 'Справка');
  267. End;
  268.  
  269. Procedure TfrmMain.miInfoAboutDeveloperClick(Sender: TObject);
  270. Const
  271.     FIRST_MESSAGE = 'Ф.И.О.: Карась А.С. a.k.a Clownfish' + #13#10;
  272.     SECOND_MESSAGE = 'Группа: 251004' + #13#10;
  273.     THIRD_MESSAGE = 'Контакты: предварительная запись вживую по адресу' + #13#10;
  274.     FOURTH_MESSAGE = 'г.Гродно, ул.Мостовая, д.31';
  275. Begin
  276.     Application.MessageBox(FIRST_MESSAGE + SECOND_MESSAGE + THIRD_MESSAGE + FOURTH_MESSAGE,'О разработчике');
  277. End;
  278.  
  279. Procedure TfrmMain.miOpenFromFileClick(Sender: TObject);
  280. Var
  281.     SizeFromFile: Single;
  282.     IsCorrect: Boolean;
  283.     Size, I: Integer;
  284.     Sequence, SequenceFromFile: TArr;
  285. Begin
  286.     opdOpenFromFileDialog.Filter := 'Text files (*.txt)|*.txt|All files (*.*)|*.*';
  287.     If opdOpenFromFileDialog.Execute() Then
  288.         If IsFileOfArrCorrect(opdOpenFromFileDialog.FileName) Then
  289.         Begin
  290.             GetSizeFromFile(opdOpenFromFileDialog.FileName, SizeFromFile, IsCorrect);
  291.             Size := Round(SizeFromFile);
  292.  
  293.             SetLength(Sequence, Size);
  294.             SetLength(SequenceFromFile, Size);
  295.             SequenceFromFile := GetSequenceFromFile(opdOpenFromFileDialog.FileName, Size, Sequence, IsCorrect);
  296.  
  297.             If (IsCorrect) Then
  298.             Begin
  299.                 lbeSize.Text := SizeFromFile.ToString;
  300.                 btConfirmSizeClick(Sender);
  301.             End;
  302.             For I := 1 To Size Do
  303.             Begin
  304.                 strgrSequence.Cells[I, 1] := IntToStr(SequenceFromFile[I - 1]);
  305.             End;
  306.         End
  307.         Else
  308.             Application.MessageBox('Данные в файле некорректны, попробуйте ещё раз.', 'Ошибка!', MB_ICONERROR);
  309. End;
  310.  
  311. Procedure TfrmMain.sdbtOpenFromFileClick(Sender: TObject);
  312. Begin
  313.     miOpenFromFileClick(Sender);
  314. End;
  315.  
  316. Procedure TLabeledEdit.WMPaste(Var Msg: TMessage);
  317. Const
  318.     MIN_VALUE = 2;
  319.     MAX_VALUE = 10;
  320. Begin
  321.     If Clipboard.HasFormat(CF_TEXT) Then  // TryStrToInt(ClipBoard.AsText, TempVar)  тоже подойдет
  322.     Begin
  323.         Try
  324.             If (StrToInt(Clipboard.AsText) < MIN_VALUE) Or (StrToInt(Clipboard.AsText) > MAX_VALUE) Then
  325.             Begin
  326.                 Application.MessageBox(Pchar('В буфере обмена содержится неподходящее значение!'), 'Ошибка', MB_ICONWARNING);
  327.                 Exit; //ReadOnly := True мб тоже подойдет, не тестил
  328.             End;
  329.         Except
  330.             Application.MessageBox(Pchar('При чтении из буфера произошла ошибка!'), 'Ошибка', MB_ICONWARNING);
  331.             Exit;
  332.         End;
  333.     End
  334.     Else
  335.     Begin
  336.         Application.MessageBox(Pchar('В буфере обмена содержатся некорректные данные!'), 'Ошибка', MB_ICONWARNING);
  337.         Exit;
  338.     End;
  339.     inherited;
  340. End;
  341.  
  342. Procedure TfrmMain.lbeSizeChange(Sender: TObject);
  343. Const
  344.     MIN_VALUE = 2;
  345.     MAX_VALUE = 10;
  346. Begin
  347.     btDraw.Enabled := False;
  348.     btFind.Enabled := False;
  349.     If (lbeSize.Text <> '') Then
  350.     Begin
  351.         If (StrToInt(lbeSize.Text) < MIN_VALUE) Or (StrToInt(lbeSize.Text) > MAX_VALUE) Then
  352.         Begin
  353.             lbIncorrectPatricipants.Visible := True;
  354.             btConfirmSize.Enabled := False;
  355.         End
  356.         Else
  357.         Begin
  358.             lbIncorrectPatricipants.Visible := False;
  359.             btConfirmSize.Enabled := True;
  360.         End;
  361.     End
  362.     Else
  363.     Begin
  364.         btConfirmSize.Enabled := False;
  365.         sdbtStart.Enabled := False;
  366.     End;
  367. End;
  368.  
  369. Procedure TfrmMain.lbeSizeKeyPress(Sender: TObject; Var Key: Char);
  370. Begin
  371.     If (Not (Key In ['0'..'9', #08, #127])) Then
  372.         Key := #0;
  373.     If (lbeSize.Text = '0') And (Key = '0') Then
  374.         Key := #0;
  375. End;
  376.  
  377. Procedure TfrmMain.btConfirmSizeClick(Sender: TObject);
  378. Const
  379.     MIN_VALUE = 2;
  380.     MAX_VALUE = 10;
  381.     MIN_VISIBLE_COLS = 3;
  382.     MAX_VISIBLE_COLS = 7;
  383. Var
  384.     IsCorrect: Boolean;
  385.     Value, I: Integer;
  386. Begin
  387.     IsCorrect := True;
  388.  
  389.     Try
  390.         Value := StrToInt(lbeSize.Text);
  391.  
  392.         If (Value < MIN_VALUE) Or (Value > MAX_VALUE) Then
  393.             IsCorrect := False;
  394.     Except
  395.         IsCorrect := False;
  396.     End;
  397.  
  398.     If IsCorrect Then
  399.     Begin
  400.         btFind.Visible := True;
  401.         strgrSequence.Visible := True;
  402.  
  403.         If UnitMain.PreviousSize <> StrToInt(lbeSize.Text) Then
  404.         Begin
  405.             For I := 1 To strgrSequence.ColCount - 1 Do
  406.                 strgrSequence.Cells[I, 1] := '';
  407.         End;
  408.         UnitMain.PreviousSize := StrToInt(lbeSize.Text);
  409.  
  410.         btConfirmSize.Default := False;
  411.         btFind.Default := True;
  412.         btFind.Enabled := True;
  413.  
  414.         strgrSequence.ColCount := UnitMain.PreviousSize + 1;
  415.         If UnitMain.PreviousSize < MIN_VISIBLE_COLS Then
  416.         Begin
  417.             strgrSequence.Width := strgrSequence.DefaultColWidth * (UnitMain.PreviousSize + 1);
  418.         End;
  419.  
  420.         If (UnitMain.PreviousSize > MIN_VISIBLE_COLS - 1) And (UnitMain.PreviousSize < MAX_VISIBLE_COLS) Then
  421.             strgrSequence.Width := strgrSequence.DefaultColWidth * UnitMain.PreviousSize + 10;
  422.         If UnitMain.PreviousSize > MAX_VISIBLE_COLS  Then
  423.             strgrSequence.Width := strgrSequence.DefaultColWidth * MAX_VISIBLE_COLS + 10;
  424.  
  425.         For I := 1 To UnitMain.PreviousSize + 1 Do
  426.             strgrSequence.Cells[I, 0] := IntToStr(I);
  427.  
  428.         strgrSequence.Enabled := True;
  429.     End
  430.     Else
  431.     Begin
  432.         Application.MessageBox('Проверьте корректность данных и повторите попытку!', 'Ошибка');
  433.         btConfirmSize.Default := True;
  434.         btFind.Default := False;
  435.         btFind.Enabled := False;
  436.         strgrSequence.Enabled := False;
  437.         btFind.Enabled := False;
  438.         sdbtStart.Enabled := False;
  439.     End;
  440. End;
  441.  
  442. Procedure TfrmMain.strgrSequenceKeyPress(Sender: TObject; Var Key: Char);
  443. Begin
  444.     If Not(Key In ['0'..'9', #08, #45, #127]) Then
  445.         Key := #0;
  446. End;
  447.  
  448. Procedure TfrmMain.strgrSequenceSetEditText(Sender: TObject; ACol,
  449.   ARow: Integer; Const Value: String);
  450. Const
  451.     MAX_VALUE = 99;
  452. Var
  453.     Temp: String;
  454. Begin
  455.     btDraw.Enabled := False;
  456.     btFind.Enabled := True;
  457.     If Abs(StrToIntDef(Value, 0)) > MAX_VALUE Then
  458.     Begin
  459.         strgrSequence.Cells[ACol, ARow] := UnitMain.LastValue;
  460.     End;
  461. End;
  462.  
  463. Procedure TfrmMain.strgrSequenceSelectCell(Sender: TObject; ACol, ARow: Integer; Var CanSelect: Boolean);
  464. Begin
  465.     UnitMain.LastValue := strgrSequence.Cells[ACol, ARow];
  466. End;
  467.  
  468. Function NewEditProc(Window: HWND; uMsg: UINT; WindowParametr: WPARAM; lParam:LPARAM): Integer; Stdcall;
  469. Const
  470.     MIN_VALUE = -99;
  471.     MAX_VALUE = 99;
  472. Var
  473.     Col, Row: Integer;
  474. Begin
  475.     Col := frmMain.strgrSequence.Col;
  476.     Row := frmMain.strgrSequence.Row;
  477.  
  478.     If uMsg = WM_PASTE Then
  479.     Begin
  480.         Try
  481.             If (StrToInt(Clipboard.AsText) < MIN_VALUE) Or (StrToInt(Clipboard.AsText) > MAX_VALUE) Then
  482.             Begin
  483.                 Application.MessageBox(Pchar('В буфере обмена содержится неподходящее значение!'), 'Ошибка', MB_ICONWARNING);
  484.                 Exit;
  485.             End
  486.             Else
  487.             Begin
  488.                 frmMain.strgrSequence.Cells[Col, Row] := Clipboard.AsText;
  489.                 Exit;
  490.             End;
  491.         Except
  492.             Application.MessageBox(Pchar('В буфере обмена находятся неподходящие данные!'), 'Ошибка', MB_ICONWARNING);
  493.             Exit;
  494.         End;
  495.     End
  496.     Else
  497.         Result := CallWindowProc(Pointer(GetWindowLong(Window,GWL_USERDATA)), Window, uMsg, WindowParametr, lParam);
  498. End;
  499.  
  500. Procedure TfrmMain.strgrSequenceGetEditText(Sender: TObject; ACol, ARow: Integer; Var Value: String);
  501. Var
  502.     Window: HWND;
  503. Begin
  504.     If Not IsAlreadySubclassing Then
  505.     Begin
  506.         Window := GetWindow(strgrSequence.Handle, GW_CHILD);
  507.         If IsWindow(Window) Then
  508.             SetWindowLong(Window,GWL_USERDATA,SetWindowLong(Window, GWL_WNDPROC, LPARAM(@NewEditProc)));
  509.         IsAlreadySubclassing := True;
  510.     End;
  511. End;
  512.  
  513. Procedure TfrmMain.btFindClick(Sender: TObject);
  514. Const
  515.     MAX_VALUE = 99;
  516. Var
  517.     I, TempElem, MaxLength: Integer;
  518.     IsBlanc, IsSimilar, IsCorrect: Boolean;
  519.     BinaryTree: PNode;
  520.     TempSequence: TArr;
  521. Begin
  522.     IsBlanc := False;
  523.     IsSimilar := False;
  524.     SetLength(TempSequence, StrToInt(lbeSize.Text));
  525.  
  526.     For I := 1 To strgrSequence.ColCount - 1 Do
  527.         If strgrSequence.Cells[I, 1] = '' Then
  528.             IsBlanc:= True;
  529.  
  530.     If IsBlanc Then
  531.         Application.MessageBox('Вы не заполнили последовательность полностью. Пожалуйста, заполните пустые поля!','Ошибка')
  532.     Else
  533.     Begin
  534.         For I := 1 To strgrSequence.ColCount - 1 Do
  535.         TempSequence[I - 1] := StrToInt(strgrSequence.Cells[I, 1]);
  536.  
  537.         IsSimilar := CheckOnSimilar(TempSequence);
  538.  
  539.         If IsSimilar Then
  540.             Application.MessageBox('В последовательности присутствуют одинаковые элементы. Пожалуйста, измените последовательность!','Ошибка')
  541.         Else
  542.         Begin
  543.             I := 1;
  544.             IsCorrect := True;
  545.             While IsCorrect And (I < strgrSequence.ColCount) Do
  546.             Begin
  547.                 Try
  548.                     TempElem := StrToInt(strgrSequence.Cells[I, 1]);
  549.                     If (Abs(TempElem) > MAX_VALUE) Then
  550.                         IsCorrect := False;
  551.                 Except
  552.                     IsCorrect := False;
  553.                 End;
  554.                 Inc(I);
  555.                 If Not IsCorrect Then
  556.                 Begin
  557.                     Application.MessageBox('Вы допустили ошибку в ячейке.', 'Ошибка!', MB_ICONERROR);
  558.                     strgrSequence.SetFocus;
  559.                 End;
  560.             End;
  561.  
  562.             If IsCorrect Then
  563.             Begin
  564.                 BinaryTree := TakeBinaryTree();
  565.                 MaxLength := FindMaxWay(BinaryTree);
  566.  
  567.                 lbAnswer.Visible := True;
  568.                 lbFinalResult.Visible := True;
  569.                 lbFinalResult.Caption := IntToStr(MaxLength);
  570.                 btDraw.Visible := True;
  571.                 btDraw.Enabled := True;
  572.                 sdbtStart.Enabled := True;
  573.                 miSaveToFile.Enabled := True;
  574.                 sdbtSaveToFile.Enabled := True;
  575.             End;
  576.         End;
  577.     End;
  578. End;
  579.  
  580. Procedure TfrmMain.btDrawClick(Sender: TObject);
  581. Begin
  582.     frmDraw := TfrmDraw.Create(Application);
  583.     frmDraw.ShowModal;
  584. End;
  585.  
  586. Procedure TfrmMain.sdbtStartClick(Sender: TObject);
  587. Begin
  588.     btDrawClick(Sender);
  589. End;
  590.  
  591. Procedure TfrmMain.miSaveToFileClick(Sender: TObject);
  592. Var
  593.     OutputFile: TextFile;
  594.     I: Integer;
  595. Begin
  596.     If svdSaveToFileDialog.Execute() And FileExists(svdSaveToFileDialog.FileName) Then
  597.     Begin
  598.         AssignFile(OutputFile, svdSaveToFileDialog.FileName);
  599.  
  600.         Try
  601.             Try
  602.                 Rewrite(OutputFile);
  603.  
  604.                 Writeln(OutputFile, 'Входные данные: ');
  605.                 Writeln(OutputFile, lbeSize.Text);
  606.                 For I := 1 To strgrSequence.ColCount - 1 Do
  607.                     Write(OutputFile, strgrSequence.Cells[I, 1], ' -> ');
  608.  
  609.                 Write(OutputFile, ' Конец последовательности.' + #13#10 + 'Ответ: ' + #13#10);
  610.                 Writeln(OutputFile, lbFinalResult.Caption);
  611.  
  612.                 Application.MessageBox('Данные успешно записаны в файл!', 'Сохранение', MB_ICONINFORMATION);
  613.             Finally
  614.                 CloseFile(OutputFile);
  615.             End;
  616.         Except
  617.             Application.MessageBox('Отказано в доступе! Измените параметры файла! ', 'Ошибка!', MB_ICONERROR);
  618.         End;
  619.     End
  620.     Else
  621.     Application.MessageBox('Введено некорректное имя файла или закрыто окно сохранения!', 'Ошибка!', MB_ICONERROR);
  622. End;
  623.  
  624. Procedure TfrmMain.sdbtSaveToFileClick(Sender: TObject);
  625. Begin
  626.     miSaveToFileClick(Sender);
  627. End;
  628.  
  629. End.
  630.  
  631. Unit UnitDraw;
  632.  
  633. Interface
  634.  
  635. Uses
  636.   Winapi.Windows,
  637.   Winapi.Messages,
  638.   System.SysUtils,
  639.   System.Variants,
  640.   System.Classes,
  641.   Vcl.Graphics,
  642.   Vcl.Controls,
  643.   Vcl.Forms,
  644.   Vcl.Dialogs,
  645.   Vcl.ExtCtrls,
  646.   Vcl.Menus,
  647.   Vcl.Imaging.jpeg;
  648.  
  649. Type
  650.   TArr = Array Of Integer;
  651.   TfrmDraw = Class(TForm)
  652.     imTree: TImage;
  653.     mmMainMenu: TMainMenu;
  654.     miFileMenu: TMenuItem;
  655.     miSaveToFile: TMenuItem;
  656.     svdSaveToFileDialog: TSaveDialog;
  657.     imLoad: TImage;
  658.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  659.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  660.     procedure FormShow(Sender: TObject);
  661.     procedure miSaveToFileClick(Sender: TObject);
  662.   End;
  663.  
  664. Var
  665.   frmDraw: TfrmDraw;
  666.  
  667. Implementation
  668.  
  669. {$R *.dfm}
  670.  
  671. Uses UnitMain, UnitData;
  672.  
  673. Type
  674.     PNode = ^TNode;
  675.     TNode = Record
  676.       Number : integer;
  677.       Left, Right : PNode;
  678.     End;
  679.  
  680. Procedure Delay(Value: Cardinal);
  681. Var
  682.     F, N: Cardinal;
  683. Begin
  684.     N := 0;
  685.     While N <= (Value Div 10) Do
  686.     Begin
  687.         SleepEx(1, True);
  688.         Application.ProcessMessages;
  689.         Inc(N);
  690.     End;
  691.  
  692.     F := GetTickCount;
  693.  
  694.     Repeat
  695.         Application.ProcessMessages;
  696.         N := GetTickCount;
  697.     Until (N - F >= (Value Mod 10)) Or (N < F);
  698. End;
  699.  
  700. Procedure AddElem(Var Tree: PNode; Num: Integer);
  701. Var
  702.     IsCorrect : Boolean;
  703. Begin
  704.     IsCorrect := True;
  705.  
  706.     If Tree = nil Then
  707.     Begin
  708.         New(Tree);
  709.         Tree^.Left := nil;
  710.         Tree^.Right := nil;
  711.         Tree^.Number := Num;
  712.  
  713.         IsCorrect := False;
  714.     End;
  715.     If(IsCorrect) Then
  716.     Begin
  717.         If Num < Tree^.Number Then
  718.             AddElem(Tree^.Left, Num)
  719.         Else
  720.             AddElem(Tree^.Right, Num);
  721.     End;
  722. End;
  723.  
  724. Function CreateBinaryTree(Arr: TArr): PNode;
  725. Var
  726.     I: Integer;
  727.     Tree: PNode;
  728. Begin
  729.     For I := Low(Arr) To High(Arr) Do
  730.         AddElem(Tree, Arr[I]);
  731.  
  732.     CreateBinaryTree := Tree;
  733. End;
  734.  
  735. Function TakeBinaryTree: PNode;
  736. Var
  737.     I, Size: Integer;
  738.     Arr: TArr;
  739.     Head: PNode;
  740. Begin
  741.     Size := PreviousSize;
  742.     SetLength(Arr, Size);
  743.  
  744.     For I := 1 To Size Do
  745.     Begin
  746.         Arr[I - 1] := StrToInt(frmMain.strgrSequence.Cells[I, 1]);
  747.     End;
  748.  
  749.     Head := CreateBinaryTree(Arr);
  750.     TakeBinaryTree := Head;
  751. End;
  752.  
  753. Procedure DrawLine(X1, Y1, X2, Y2: Integer);
  754. Begin
  755.     frmDraw.imTree.Canvas.MoveTo(X1, Y1);
  756.     frmDraw.imTree.Canvas.LineTo(X2, Y2);
  757. End;
  758.  
  759. Procedure DrawBinaryTree(Head: Pnode; X1, Y1, X2, Y2, Rad, Diam, Shift: Integer);
  760. Var
  761.     Tree: PNode;
  762. Begin
  763.     Tree := Head;
  764.  
  765.     frmDraw.imTree.Canvas.Pen.Color := clGreen;
  766.     frmDraw.imTree.Canvas.Pen.Width := 4;
  767.     frmDraw.imTree.Canvas.Ellipse(X1, Y1, X2, Y2);
  768.  
  769.     frmDraw.imTree.Canvas.Pen.Color := clBlue;
  770.     frmDraw.imTree.Canvas.Font.Size := 10;
  771.     frmDraw.imTree.Canvas.Font.Style := [fsBold];
  772.     Case Length(IntToStr(Tree^.Number)) Of
  773.         1:
  774.         Begin
  775.             frmDraw.imTree.Canvas.TextOut(X1 + 15, Y1 + 10, IntToStr(Tree^.Number));
  776.         End;
  777.         2:
  778.         Begin
  779.             frmDraw.imTree.Canvas.TextOut(X1 + 10, Y1 + 10, IntToStr(Tree^.Number));
  780.         End;
  781.         3:
  782.         Begin
  783.             frmDraw.imTree.Canvas.TextOut(X1 + 5, Y1 + 10, IntToStr(Tree^.Number));
  784.         End;
  785.     End;
  786.  
  787.     If Tree <> nil Then
  788.     Begin
  789.         frmDraw.imTree.Canvas.Pen.Color := clGreen;
  790.         frmDraw.imTree.Canvas.Pen.Width := 2;
  791.  
  792.         If Tree.Left <> nil Then
  793.         Begin
  794.             DrawLine(X1 + Rad, Y1 + Diam, X1 - 3 * Shift Div 2 + Rad, Y2 + Diam);
  795.             DrawBinaryTree(Tree.Left, X1 - 3 * Shift Div 2, Y1 + 2 * Diam, X2 - 3 * Shift Div 2, Y2 +  2 * Diam, Rad, Diam, 4* Shift Div 10);
  796.         End;
  797.         If Tree.Right <> nil Then
  798.         Begin
  799.             DrawLine(X2 - Rad, Y1 + Diam, X2 + 3 * Shift Div 2 - Rad, Y2 + Diam);
  800.             DrawBinaryTree(Tree.Right, X1 + 3 * Shift Div 2, Y1 + 2 * Diam, X2 + 3 * Shift Div 2, Y2 + 2 * Diam, Rad, Diam, 4 * Shift Div 10);
  801.         End;
  802.     End;
  803. End;
  804.  
  805. Procedure TfrmDraw.FormShow(Sender: TObject);
  806. Const
  807.     Rad = 20;
  808. Var
  809.     Tree: PNode;
  810.     X1, Y1, X2, Y2, Shift, Diam: Integer;
  811. Begin
  812.     Diam := 2 * Rad;
  813.     Shift := 4 * Diam;
  814.  
  815.     X1 := frmDraw.imTree.Width Div 2 - Rad;
  816.     X2 := frmDraw.imTree.Width Div 2 + Rad;
  817.     Y1 := 20;
  818.     Y2 := Y1 + Diam;
  819.  
  820.     Tree := TakeBinaryTree;
  821.     DrawBinaryTree(Tree, X1, Y1, X2, Y2, Rad, Diam, Shift);
  822. End;
  823.  
  824. Procedure TfrmDraw.FormClose(Sender: TObject; Var Action: TCloseAction);
  825. Begin
  826.     Action := CaFree;
  827. End;
  828.  
  829. Procedure TfrmDraw.miSaveToFileClick(Sender: TObject);
  830. Const
  831.     PIC_WIDTH_COEF = 100;
  832.     PIC_HEIGHT_COEF = 100;
  833. Var
  834.     I, OutFileChoice: Integer;
  835.     SaveJpeg: TJPEGImage;
  836.     BitMap : TBitMap;
  837. Begin
  838.     If svdSaveToFileDialog.Execute() And FileExists(svdSaveToFileDialog.FileName) Then
  839.     Begin
  840.         Try
  841.             Try
  842.                 SaveJpeg := TjpegImage.Create;
  843.  
  844.                 BitMap := TBitMap.Create;
  845.                 BitMap.Width := imTree.Width * PIC_WIDTH_COEF Div 100;
  846.                 BitMap.Height := imTree.Height * PIC_HEIGHT_COEF Div 100;
  847.                 BitMap.Canvas.CopyRect(BitMap.Canvas.ClipRect, imTree.Canvas, imTree.Canvas.ClipRect);
  848.  
  849.                 SaveJpeg.Assign(Bitmap);
  850.                 SaveJpeg.CompressionQuality := 100;
  851.                 SaveJpeg.PixelFormat := jf24Bit;
  852.                 SaveJpeg.Compress;
  853.                 SaveJpeg.SaveToFile(svdSaveToFileDialog.FileName);
  854.  
  855.                 Application.MessageBox('Изображение успешно сохранено в файл!', 'Сохранение', MB_ICONINFORMATION);
  856.             Finally
  857.                 BitMap.Free;
  858.                 SaveJpeg.Free;
  859.             End;
  860.         Except
  861.             Application.MessageBox('Отказано в доступе! Измените параметры файла! ', 'Ошибка!', MB_ICONERROR);
  862.         End;
  863.     End
  864.     Else
  865.         Application.MessageBox('Введено некорректное имя файла или закрыто окно сохранения!', 'Ошибка!', MB_ICONERROR);
  866. End;
  867.  
  868. Procedure TfrmDraw.FormCloseQuery(Sender: TObject; Var CanClose: Boolean);
  869. Begin
  870.     If Application.MessageBox(PChar('Вы уверены, что хотите выйти из режима просмотра?'), PChar('Выход'),
  871.         MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON1 + MB_TASKMODAL) = IDYES Then
  872.             CanClose := True
  873.         Else
  874.             CanClose := False;
  875. End;
  876.  
  877. End.
  878.  
  879. Unit UnitData;
  880.  
  881. Interface
  882.  
  883. Uses
  884.   System.SysUtils,
  885.   System.Classes,
  886.   Vcl.BaseImageCollection,
  887.   Vcl.ImageCollection,
  888.   System.ImageList,
  889.   Vcl.ImgList,
  890.   Vcl.Controls;
  891.  
  892. Type
  893.   TdtmdData = Class(TDataModule)
  894.     imcImages: TImageCollection;
  895.     imlIcons: TImageList;
  896.   End;
  897.  
  898. Var
  899.   dtmdData: TdtmdData;
  900.  
  901. Implementation
  902.  
  903. {%CLASSGROUP 'Vcl.Controls.TControl'}
  904.  
  905. {$R *.dfm}
  906.  
  907. End.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement