Программа для рисования 2 (Paint)Delphi , Графика и Игры , ГрафикаПрограмма для рисования 2 (Paint)Автор: Xavier Pacheco { Copyright © 1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira } unit MainFrm; interface uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs, Buttons, ExtCtrls, ColorGrd, StdCtrls, Menus, ComCtrls; const crMove = 1; type TDrawType = (dtLineDraw, dtRectangle, dtEllipse, dtRoundRect, dtClipRect, dtCrooked); TMainForm = class(TForm) sbxMain: TScrollBox; imgDrawingPad: TImage; pnlToolBar: TPanel; sbLine: TSpeedButton; sbRectangle: TSpeedButton; sbEllipse: TSpeedButton; sbRoundRect: TSpeedButton; pnlColors: TPanel; cgDrawingColors: TColorGrid; pnlFgBgBorder: TPanel; pnlFgBgInner: TPanel; Bevel1: TBevel; mmMain: TMainMenu; mmiFile: TMenuItem; mmiExit: TMenuItem; N2: TMenuItem; mmiSaveAs: TMenuItem; mmiSaveFile: TMenuItem; mmiOpenFile: TMenuItem; mmiNewFile: TMenuItem; mmiEdit: TMenuItem; mmiPaste: TMenuItem; mmiCopy: TMenuItem; mmiCut: TMenuItem; sbRectSelect: TSpeedButton; SaveDialog: TSaveDialog; OpenDialog: TOpenDialog; stbMain: TStatusBar; pbPasteBox: TPaintBox; sbFreeForm: TSpeedButton; RgGrpFillOptions: TRadioGroup; cbxBorder: TCheckBox; procedure FormCreate(Sender: TObject); procedure sbLineClick(Sender: TObject); procedure imgDrawingPadMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure imgDrawingPadMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure imgDrawingPadMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure cgDrawingColorsChange(Sender: TObject); procedure mmiExitClick(Sender: TObject); procedure mmiSaveFileClick(Sender: TObject); procedure mmiSaveAsClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure mmiNewFileClick(Sender: TObject); procedure mmiOpenFileClick(Sender: TObject); procedure mmiEditClick(Sender: TObject); procedure mmiCutClick(Sender: TObject); procedure mmiCopyClick(Sender: TObject); procedure mmiPasteClick(Sender: TObject); procedure pbPasteBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure pbPasteBoxMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure pbPasteBoxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure pbPasteBoxPaint(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure RgGrpFillOptionsClick(Sender: TObject); public { Public declarations } MouseOrg: TPoint; // Stores mouse information NextPoint: TPoint; // Stores mouse information Drawing: Boolean; // Drawing is being performed flag DrawType: TDrawType; // Holds the draw type information: TDrawType FillSelected, // Fill shapes flag BorderSelected: Boolean; // Draw Shapes with no border flag EraseClipRect: Boolean; // Specifies whether or not to erase the // clipping rectangle Modified: Boolean; // Image modified flag FileName: String; // Holds the filename of the image OldClipViewHwnd: Hwnd; // Holds the old clipboard view window { Paste Image variables } PBoxMoving: Boolean; // PasteBox is moving flag PBoxMouseOrg: TPoint; // Stores mouse coordinates for moving PasteBox PasteBitMap: TBitmap; // Stores a bitmap image of the pasted data Pasted: Boolean; // Data pasted flag LastDot: TPoint; // Hold the TPoint coordinate for performing // free line drawing procedure DrawToImage(TL, BR: TPoint; PenMode: TPenMode); { This procedure paints the image specified by the DrawType field to imgDrawingPad } procedure SetDrawingStyle; { This procedure sets various Pen/Brush styles based on values specified by the form's controls. The Panels and color grid is used to set these values } procedure CopyPasteBoxToImage; { This procedure copies the data pasted from the Windows clipboard onto the main image component imgDrawingPad } procedure WMDrawClipBoard(var Msg: TWMDrawClipBoard); message WM_DRAWCLIPBOARD; { This message handler captures the WM_DRAWCLIPBOARD messages which is sent to all windows that have been added to the clipboard viewer chain. An application can add itself to the clipboard viewer chain by using the SetClipBoardViewer() Win32 API function as is done in FormCreate() } procedure CopyCut(Cut: Boolean); { This method copies a portion of the main image, imgDrawingPad, to the Window's clipboard. } end; var MainForm: TMainForm; implementation uses ClipBrd, Math; {$R *.DFM} procedure TMainForm.FormCreate(Sender: TObject); { This method sets the form's field to their default values. It then creates a bitmap for the imgDrawingPad. This is the image on which drawing is done. Finally, it adds this application as part of the Windows clipboard viewer chain by using the SetClipBoardViewer() function. This makes enables the form to get WM_DRAWCLIPBOARD messages which are sent to all windows in the clipboard viewer chain whenever the clipboard data is modified. } begin Screen.Cursors[crMove] := LoadCursor(hInstance, 'MOVE'); FillSelected := False; BorderSelected := True; Modified := False; FileName := ''; Pasted := False; pbPasteBox.Enabled := False; // Create a bitmap for imgDrawingPad and set its boundaries with imgDrawingPad do begin SetBounds(0, 0, 600, 400); Picture.Graphic := TBitMap.Create; Picture.Graphic.Width := 600; Picture.Graphic.Height := 400; end; // Now create a bitmap image to hold pasted data PasteBitmap := TBitmap.Create; pbPasteBox.BringToFront; { Add the form to the Windows clipboard viewer chain. Save the handle of the next window in the chain so that it may be restored by the ChangeClipboardChange() Win32 API function in this form's FormDestroy() method. } OldClipViewHwnd := SetClipBoardViewer(Handle); end; procedure TMainForm.WMDrawClipBoard(var Msg: TWMDrawClipBoard); begin { This method will be called whenever the clipboard data has changed. Because the main form was added to the clipboard viewer chain, it will receive the WM_DRAWCLIPBOARD message indicating that the clipboard's data was changed. } inherited; { Make sure that the data contained on the clipboard is actually bitmap data. } if ClipBoard.HasFormat(CF_BITMAP) then mmiPaste.Enabled := True else mmiPaste.Enabled := False; Msg.Result := 0; end; procedure TMainForm.DrawToImage(TL, BR: TPoint; PenMode: TPenMode); { This method performs the specified drawing operation. The drawing operation is specified by the DrawType field } begin with imgDrawingPad.Canvas do begin Pen.Mode := PenMode; case DrawType of dtLineDraw: begin MoveTo(TL.X, TL.Y); LineTo(BR.X, BR.Y); end; dtRectangle: Rectangle(TL.X, TL.Y, BR.X, BR.Y); dtEllipse: Ellipse(TL.X, TL.Y, BR.X, BR.Y); dtRoundRect: RoundRect(TL.X, TL.Y, BR.X, BR.Y, (TL.X - BR.X) div 2, (TL.Y - BR.Y) div 2); dtClipRect: Rectangle(TL.X, TL.Y, BR.X, BR.Y); end; end; end; procedure TMainForm.CopyPasteBoxToImage; { This method copies the image pasted from the Windows clipboard onto imgDrawingPad. It first erases any bounding rectangle drawn by PaintBox component, pbPasteBox. It then copies the data from pbPasteBox onto imgDrawingPad at the location where pbPasteBox has been dragged over imgDrawingPad. The reason we don't copy the contents of pbPasteBox's canvas and use PasteBitmap's canvas instead, is because when a portion of pbPasteBox is dragged out of the viewable area, Windows does not paint the portion pbPasteBox not visible. Therefore, it is necessary to the pasted bitmap from the off-screen bitmap } var SrcRect, DestRect: TRect; begin // First, erase the rectangle drawn by pbPasteBox with pbPasteBox do begin Canvas.Pen.Mode := pmNotXOR; Canvas.Pen.Style := psDot; Canvas.Brush.Style := bsClear; Canvas.Rectangle(0, 0, Width, Height); DestRect := Rect(Left, Top, Left+Width, Top+Height); SrcRect := Rect(0, 0, Width, Height); end; { Here we must use the PasteBitmap instead of the pbPasteBox because pbPasteBox will clip anything outside if the viewable area. } imgDrawingPad.Canvas.CopyRect(DestRect, PasteBitmap.Canvas, SrcRect); pbPasteBox.Visible := false; pbPasteBox.Enabled := false; Pasted := False; // Pasting operation is complete end; procedure TMainForm.imgDrawingPadMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Modified := True; // Erase the clipping rectangle if one has been drawn if (DrawType = dtClipRect) and EraseClipRect then DrawToImage(MouseOrg, NextPoint, pmNotXOR) else if (DrawType = dtClipRect) then EraseClipRect := True; // Re-enable cliprect erasing { If an bitmap was pasted from the clipboard, copy it to the image and remove the PaintBox. } if Pasted then CopyPasteBoxToImage; Drawing := True; // Save the mouse information MouseOrg := Point(X, Y); NextPoint := MouseOrg; LastDot := NextPoint; // Lastdot is updated as the mouse moves imgDrawingPad.Canvas.MoveTo(X, Y); end; procedure TMainForm.imgDrawingPadMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); { This method determines the drawing operation to be performed and either performs free form line drawing, or calls the DrawToImage method which draws the specified shape } begin if Drawing then begin if DrawType = dtCrooked then begin imgDrawingPad.Canvas.MoveTo(LastDot.X, LastDot.Y); imgDrawingPad.Canvas.LineTo(X, Y); LastDot := Point(X,Y); end else begin DrawToImage(MouseOrg, NextPoint, pmNotXor); NextPoint := Point(X, Y); DrawToImage(MouseOrg, NextPoint, pmNotXor) end; end; // Update the status bar with the current mouse location stbMain.Panels[1].Text := Format('X: %d, Y: %D', [X, Y]); end; procedure TMainForm.imgDrawingPadMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Drawing then { Prevent the clipping rectangle from destroying the images already on the image } if not (DrawType = dtClipRect) then DrawToImage(MouseOrg, Point(X, Y), pmCopy); Drawing := False; end; procedure TMainForm.sbLineClick(Sender: TObject); begin // First erase the cliprect if current drawing type if DrawType = dtClipRect then DrawToImage(MouseOrg, NextPoint, pmNotXOR); { Now set the DrawType field to that specified by the TSpeedButton invoking this method. The TSpeedButton's Tag values match a specific TDrawType value which is why the typecasting below successfully assigns a valid TDrawType value to the DrawType field. } if Sender is TSpeedButton then DrawType := TDrawType(TSpeedButton(Sender).Tag); // Now make sure the dtClipRect style doesn't erase previous drawings if DrawType = dtClipRect then begin EraseClipRect := False; end; // Set the drawing style SetDrawingStyle; end; procedure TMainForm.cgDrawingColorsChange(Sender: TObject); { This method draws the rectangle representing fill and border colors to indicate the users selection of both colors. pnlFgBgInner and pnlFgBgBorder are TPanels arranged one on to of the other for the desired effect } begin pnlFgBgBorder.Color := cgDrawingColors.ForeGroundColor; pnlFgBgInner.Color := cgDrawingColors.BackGroundColor; SetDrawingStyle; end; procedure TMainForm.SetDrawingStyle; { This method sets the various drawing styles based on the selections on the pnlFillStyle TPanel for Fill and Border styles } begin with imgDrawingPad do begin if DrawType = dtClipRect then begin Canvas.Pen.Style := psDot; Canvas.Brush.Style := bsClear; Canvas.Pen.Color := clBlack; end else if FillSelected then Canvas.Brush.Style := bsSolid else Canvas.Brush.Style := bsClear; if BorderSelected then Canvas.Pen.Style := psSolid else Canvas.Pen.Style := psClear; if FillSelected and (DrawType <> dtClipRect) then Canvas.Brush.Color := pnlFgBgInner.Color; if DrawType <> dtClipRect then Canvas.Pen.Color := pnlFgBgBorder.Color; end; end; procedure TMainForm.mmiExitClick(Sender: TObject); begin Close; // Terminate application end; procedure TMainForm.mmiSaveFileClick(Sender: TObject); { This method saves the image to the file specified by FileName. If FileName is blank, however, SaveAs1Click is called to get a filename.} begin if FileName = '' then mmiSaveAsClick(nil) else begin imgDrawingPad.Picture.SaveToFile(FileName); stbMain.Panels[0].Text := FileName; Modified := False; end; end; procedure TMainForm.mmiSaveAsClick(Sender: TObject); { This method launches SaveDialog to get a file name to which the image's contents will be saved. } begin if SaveDialog.Execute then begin FileName := SaveDialog.FileName; // Store the filename mmiSaveFileClick(nil) end; end; procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); { If the user attempts to close the form before saving the image, they are prompted to do so in this method. } var Rslt: Word; begin CanClose := False; // Assume fail. if Modified then begin Rslt := MessageDlg('File has changed, save?', mtConfirmation, mbYesNOCancel, 0); case Rslt of mrYes: mmiSaveFileClick(nil); mrNo: ; // no need to do anything. mrCancel: Exit; end end; CanClose := True; // Allow use to close application end; procedure TMainForm.mmiNewFileClick(Sender: TObject); { This method erases any drawing on the main image after prompting the user to save it to a file in which case the mmiSaveFileClick event handler is called. } var Rslt: Word; begin if Modified then begin Rslt := MessageDlg('File has changed, save?', mtConfirmation, mbYesNOCancel, 0); case Rslt of mrYes: mmiSaveFileClick(nil); mrNo: ; // no need to do anything. mrCancel: Exit; end end; with imgDrawingPad.Canvas do begin Brush.Style := bsSolid; Brush.Color := clWhite; // clWhite erases the image FillRect(ClipRect); // Erase the image FileName := ''; stbMain.Panels[0].Text := FileName; end; SetDrawingStyle; // Restore the previous drawing style Modified := False; end; procedure TMainForm.mmiOpenFileClick(Sender: TObject); { This method opens a bitmap file specified by OpenDialog.FileName. If a file was already created, the user is prompted to save the file in which case the mmiSaveFileClick event is called. } var Rslt: Word; begin if OpenDialog.Execute then begin if Modified then begin Rslt := MessageDlg('File has changed, save?', mtConfirmation, mbYesNOCancel, 0); case Rslt of mrYes: mmiSaveFileClick(nil); mrNo: ; // no need to do anything. mrCancel: Exit; end end; imgDrawingPad.Picture.LoadFromFile(OpenDialog.FileName); FileName := OpenDialog.FileName; stbMain.Panels[0].Text := FileName; Modified := false; end; end; procedure TMainForm.mmiEditClick(Sender: TObject); { The timer is used to determine if an area on the main image is surrounded by a bounding rectangle. If so, then the Copy and Cut menu items are enabled. Otherwise, they are disabled. } var IsRect: Boolean; begin IsRect := (MouseOrg.X <> NextPoint.X) and (MouseOrg.Y <> NextPoint.Y); if (DrawType = dtClipRect) and IsRect then begin mmiCut.Enabled := True; mmiCopy.Enabled := True; end else begin mmiCut.Enabled := False; mmiCopy.Enabled := False; end; end; procedure TMainForm.CopyCut(Cut: Boolean); { This method copies a portion of the main image to the clipboard. The portion copied is specified by a bounding rectangle on the main image. If Cut is true, the area in the bounding rectandle is erased. } var CopyBitMap: TBitmap; DestRect, SrcRect: TRect; OldBrushColor: TColor; begin CopyBitMap := TBitMap.Create; try { Set CopyBitmap's size based on the coordinates of the bounding rectangle } CopyBitMap.Width := Abs(NextPoint.X - MouseOrg.X); CopyBitMap.Height := Abs(NextPoint.Y - MouseOrg.Y); DestRect := Rect(0, 0, CopyBitMap.Width, CopyBitmap.Height); SrcRect := Rect(Min(MouseOrg.X, NextPoint.X)+1, Min(MouseOrg.Y, NextPoint.Y)+1, Max(MouseOrg.X, NextPoint.X)-1, Max(MouseOrg.Y, NextPoint.Y)-1); { Copy the portion of the main image surrounded by the bounding rectangle to the Windows clipboard } CopyBitMap.Canvas.CopyRect(DestRect, imgDrawingPad.Canvas, SrcRect); { Previous versions of Delphi required the bitmap's Handle property to be touched for the bitmap to be made available. This was due to Delphi's caching of bitmapped images. The step below may not be required. } CopyBitMap.Handle; // Assign the image to the clipboard. ClipBoard.Assign(CopyBitMap); { If cut was specified the erase the portion of the main image surrounded by the bounding Rectangle } if Cut then with imgDrawingPad.Canvas do begin OldBrushColor := Brush.Color; Brush.Color := clWhite; try FillRect(SrcRect); finally Brush.Color := OldBrushColor; end; end; finally CopyBitMap.Free; end; end; procedure TMainForm.mmiCutClick(Sender: TObject); begin CopyCut(True); end; procedure TMainForm.mmiCopyClick(Sender: TObject); begin CopyCut(False); end; procedure TMainForm.mmiPasteClick(Sender: TObject); { This method pastes the data contained in the clipboard to the paste bitmap. The reason it is pasted to the PasteBitmap, an off- screen bitmap, is so that the user can relocate the pasted image elsewhere on to the main image. This is done by having the pbPasteBox, a TPaintBox component, draw the contents of PasteImage. When the user if done positioning the pbPasteBox, the contents of TPasteBitmap is drawn to imgDrawingPad at the location specified by pbPasteBox's location.} begin { Clear the bounding rectangle } pbPasteBox.Enabled := True; if DrawType = dtClipRect then begin DrawToImage(MouseOrg, NextPoint, pmNotXOR); EraseClipRect := False; end; PasteBitmap.Assign(ClipBoard); // Grab the data from the clipboard Pasted := True; // Set position of pasted image to top left pbPasteBox.Left := 0; pbPasteBox.Top := 0; // Set the size of pbPasteBox to match the size of PasteBitmap pbPasteBox.Width := PasteBitmap.Width; pbPasteBox.Height := PasteBitmap.Height; pbPasteBox.Visible := True; pbPasteBox.Invalidate; end; procedure TMainForm.pbPasteBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); { This method set's up pbPasteBox, a TPaintBox for being moved by the user when the left mouse button is held down } begin if Button = mbLeft then begin PBoxMoving := True; Screen.Cursor := crMove; PBoxMouseOrg := Point(X, Y); end else PBoxMoving := False; end; procedure TMainForm.pbPasteBoxMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); { This method moves pbPasteBox if the PBoxMoving flag is true indicating that the user is holding down the left mouse button and is dragging PaintBox } begin if PBoxMoving then begin pbPasteBox.Left := pbPasteBox.Left + (X - PBoxMouseOrg.X); pbPasteBox.Top := pbPasteBox.Top + (Y - PBoxMouseOrg.Y); end; end; procedure TMainForm.pbPasteBoxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin { This method disables moving of pbPasteBox when the user lifts the left mouse button } if PBoxMoving then begin PBoxMoving := False; Screen.Cursor := crDefault; end; pbPasteBox.Refresh; // Redraw the pbPasteBox. end; procedure TMainForm.pbPasteBoxPaint(Sender: TObject); { The paintbox is drawn whenever the user selects the Paste option form the menu. pbPasteBox draws the contents of PasteBitmap which holds the image gotten from the clipboard. The reason for drawing PasteBitmap's contents in pbPasteBox, a TPaintBox class, is so that the user can also move the object around on top of the main image. In other words, pbPasteBox can be moved, and hidden when necessary. } var DestRect, SrcRect: TRect; begin // Display the paintbox only if a pasting operation occurred. if Pasted then begin { First paint the contents of PasteBitmap using canvas's CopyRect but only if the paintbox is not being moved. This reduces flicker } if not PBoxMoving then begin DestRect := Rect(0, 0, pbPasteBox.Width, pbPasteBox.Height); SrcRect := Rect(0, 0, PasteBitmap.Width, PasteBitmap.Height); pbPasteBox.Canvas.CopyRect(DestRect, PasteBitmap.Canvas, SrcRect); end; { Now copy a bounding rectangle to indicate that pbPasteBox is a moveable object. We use a pen mode of pmNotXOR because we must erase this rectangle when the user copies PaintBox's contents to the main image and we must preserve the original contents. } pbPasteBox.Canvas.Pen.Mode := pmNotXOR; pbPasteBox.Canvas.Pen.Style := psDot; pbPasteBox.Canvas.Brush.Style := bsClear; pbPasteBox.Canvas.Rectangle(0, 0, pbPasteBox.Width, pbPasteBox.Height); end; end; procedure TMainForm.FormDestroy(Sender: TObject); begin // Remove the form from the clipboard chain ChangeClipBoardChain(Handle, OldClipViewHwnd); PasteBitmap.Free; // Free the PasteBitmap instance end; procedure TMainForm.RgGrpFillOptionsClick(Sender: TObject); begin FillSelected := RgGrpFillOptions.ItemIndex = 0; BorderSelected := cbxBorder.Checked; SetDrawingStyle; end; end.Скачать весь проект Программа Delphi для простого программы рисования, также известной как Paint. Программа обеспечивает основные функции рисования и редактирования, включая возможность рисовать линии, прямоугольники, эллипсы и свободно-форменные формы с помощью мыши. Основные функции:
Программа обеспечивает следующие функции:
Программа использует следующие техники для улучшения своей функциональности:
В целом, это базовая программа рисования, которая обеспечивает некоторые полезные функции и техники для рисования и редактирования изображений. "Программа для рисования 2 (Paint)" - это описание программы, написанной на языке Delphi 5. Она позволяет пользователю создавать и редактировать графические изображения, используя различные инструменты, такие как линии, прямоугольники, эл Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |