In the previous articles, I have introduced how to use GDI + for drawing and made an example. In this article, I will introduce how to use a tool similar to windows for drawing.
I personally think that if you want to create a powerful drawing tool, it is far from enough to simply master GDI. At present, I can only do a simple drawing tool. you are welcome to discuss the shortcomings!
Let's take a look at the final effect:
Main functions: draw a straight line, rectangle, eraser, circle, switch the color, open the image, save the image, clear the image, and manually adjust the size of the canvas. When the software is started, it is a blank canvas, we can draw images directly on the canvas, or import an image through "open" in the menu, and then draw the image.
Platform: VS2005 WINFORM
As there are too many codes, here we will only briefly introduce the production steps and provide you with project downloads.
1. layout the entire interface.
2. Implement the functions of the drawing tool
3. Implement the color picking function. Here we use the custom control written last time.
4. Implement menu functions
5. the canvas size can be adjusted manually.
6. Test
Implement the functions of the drawing tool
In order to make the code fit a little bit, some design patterns are used, because it is not very good, so the code is still a bit messy, hey! All the functional blocks of the drawing tool are written in the DrawTools class. in the main form, you only need to call this class to complete the painting, instead of involving too much specific drawing code. This class provides the main tools: pencil, eraser, straight line, rectangle, circle, solid rectangle, solid circle. The Code of these functional blocks is not difficult. As long as you carefully read the previous articles, you should be able to understand them.
Pay attention to the following points:
1. How can we prevent unnecessary traces in the drawing process from being recorded?
This problem occurs
Article 3As mentioned above, you may wish to take a look at that article first. To make the Code look highly readable, I set two Image variables, finishingImg to save traces in the drawing process, and orginalImg to save the completed drawing process and the background Image at the beginning.
2. How does this class communicate with the main form?
Of course, if you directly write these functional blocks in the main form, this problem does not occur. But the code will look very mixed. If there is a problem with the tool code, you need to change the entire project. Here, I define methods and attributes so that the main form can pass the canvas and color information to this tool class by assigning values to the attributes, and then call the corresponding tool methods to use these tools.
3. Key attributes
To make these tools work properly, you must pass the following items to them: Target canvas (picturebox), drawing color, and original canvas.
Implement menu functions
Here we need to know a little about file operations. You can check the relevant information.
The main difficulty is the implementation of the menu item "open ".
To save the opened image after modification, you must enable the file to be closed after it is opened. Otherwise, the original file cannot be overwritten because the file is opened. This will cause a "GDI general error" during compilation ". Therefore, based on the practice of other friends on the Internet, the open image is first painted to another canvas through GDI +, and then the opened image and the canvas used to draw the image are closed in time.
Copy codeThe Code is as follows: private void openPic_Click (object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog (); // The instantiate file opening dialog box.
Ofd. Filter = "JPG | *. jpg | Bmp | *. bmp | all files | *. *"; // The display name of the file opened in the dialog box
If (ofd. ShowDialog () = DialogResult. OK)
{
Bitmap BMP file = new Bitmap (ofd. FileName); // obtain the opened file
Panel2.AutoScrollPosition = new Point (0, 0); // reset the scroll bar
PbImg. Size = BMP file. Size; // adjust the Size of the drawing area to the image Size.
ReSize. Location = new Point (BMP file. Width, BMP file. Height); // reSize is used to manually adjust the size of the canvas.
// Because the size of the blank canvas is limited at the beginning, the "open" operation may change the size of the canvas. Therefore, you must re-import the canvas to the tool class.
Dt. DrawTools_Graphics = pbImg. CreateGraphics ();
Bitmap bmp = new Bitmap (pbImg. Width, pbImg. Height );
Graphics g = Graphics. FromImage (bmp );
G. fillRectangle (new SolidBrush (pbImg. backColor), new Rectangle (0, 0, pbImg. width, pbImg. height); // if this sentence is not used, the background of the bmp is transparent.
G. DrawImage (BMP file, 0, 0, BMP file. Width, BMP file. Height); // draw the image to the canvas.
G. Dispose (); // release resources occupied by the canvas
// PbImg. Image = Image. FormFile (ofd. FileName) is not directly used because it keeps the Image open and cannot save the modified Image.
BMP formfile. Dispose (); // release resources occupied by images
G = pbImg. CreateGraphics ();
G. DrawImage (bmp, 0, 0 );
G. Dispose ();
Dt. OrginalImg = bmp;
Bmp. Dispose ();
SFileName = ofd. FileName; // stores the detailed path of the opened image file, which can be overwritten later.
Ofd. Dispose ();
}
}
To clear an image, fill the entire canvas with white.
The rest are relatively simple, so we will not discuss it in detail.
Adjust the canvas size manually
Some people on the Internet say that the API is used, but I personally think it is relatively easy to use other controls to help, at least we can understand it.
Idea: place a picturebox1 (5x5 in size), place it in the lower right corner of the main canvas, and then change the Cursor to the arrow shape when entering, set the event when the mouse is pressed to move the picturebox1 following the mouse. When you release the mouse, adjust the coordinates in the lower right corner of the main canvas to the coordinates of picturebox1.
Let's take a look at the code below:
The reSize is the picturebox control that we use for help.Copy codeThe Code is as follows: private bool bReSize = false; // whether to change the canvas size
Private void reSize_MouseDown (object sender, MouseEventArgs e)
{
BReSize = true; // when you press the mouse, it indicates you want to adjust the size.
}
Private void reSize_MouseMove (object sender, MouseEventArgs e)
{
If (bReSize)
{
ReSize. Location = new Point (reSize. Location. X + e. X, reSize. Location. Y + e. Y );
}
}
Private void reSize_MouseUp (object sender, MouseEventArgs e)
{
BReSize = false; // The End of the change in size
// Adjust the size of the canvas to exceed the screen area. Therefore, set autoScroll to true in advance.
// However, the appearance of the scroll bar increases the difficulty, because the scroll bar does not automatically help us adjust the coordinates of the image.
// This is because there are more than one Coordinate System in the GDI plot. It seems that there are three coordinate systems, not carefully understood. One is the screen coordinate, the other is the client area coordinate, and the other is the document coordinate.
// The up/down movement of the scroll bar changes the coordinates of the document, but the coordinates of the customer zone remain unchanged, and the location attribute belongs to the coordinates of the customer zone. Therefore, an error occurs during direct calculation.
// In this case, we need to know the offset between the coordinate of the document and the coordinate of the customer zone. This is what AutoScrollPostion can provide.
PbImg. Size = new Size (reSize. Location. X-(this. panel2.AutoScrollPosition. X), reSize. Location. Y-(this. panel2.AutoScrollPosition. Y ));
Dt. DrawTools_Graphics = pbImg. CreateGraphics (); // The value must be assigned again because the size of the canvas is changed.
// In addition, the canvas is changed, so the value must be assigned again.
Bitmap bmp = new Bitmap (pbImg. Width, pbImg. Height );
Graphics g = Graphics. FromImage (bmp );
G. FillRectangle (new SolidBrush (Color. White), 0, 0, pbImg. Width, pbImg. Height );
G. DrawImage (dt. OrginalImg, 0, 0 );
G. Dispose ();
G = pbImg. CreateGraphics ();
G. DrawImage (bmp, 0, 0 );
G. Dispose ();
Dt. OrginalImg = bmp;
Bmp. Dispose ();
}
The effect is as follows (check the bottom right corner of the white area ):
In this case, you can drag the small block to adjust the image size.
In this way, the main problem has almost been solved, but there are still some shortcomings. We welcome your valuable comments.