In the last section, the chicken pecked the rice. The CDC class and its screen drawing functions, the main content of this section is the brush CPen of GDI objects.
GDI Objects
In MFC, the CGdiObject class is the base class for GDI objects, and by looking at MSDN we can see that the CGdiObject class has six direct derived classes, and the GDI objects are mainly those six, respectively: CBitmap, CBrush, CFont, CPalette, CPen and CRgn.
Of the six GDI objects, the most common ones are brushes and brushes, the CPen class and the CBrush class. This article mainly explains the use of brushes.
Application Examples of brushes
Chicken Peck Rice Here directly through an example of a waveform diagram, to explain in detail the use of the brush.
Let's first describe what this instance does: There is a picture control on the dialog box that fills the background of the control with black, a timer is started, every time the timer is reached, all waveform data is moved forward one unit, and a random number within 80 is taken as the last data of the waveform. Then draw the waveform on the drawing control with a green brush. This enables the waveform to be drawn and changed dynamically.
Here are the specific implementation steps:
1, create a dialog-based MFC project, the name is set to "Example50".
2. In the automatically generated dialog template Idd_example50_dialog, delete "Todo:place dialog controls here." Static text box, add a picture control with ID set to Idc_wave_draw.
3. Add the CStatic variable to the picture control Idc_wave_draw and set the name to M_picdraw.
4. Add a macro definition above the Cexample50dlg class declaration in the file Example50Dlg.h file:
C + + code
- #define POINT_COUNT 100
The meaning of this symbolic constant is the number of points of the waveform, where it is defined as a symbolic constant with define to facilitate possible changes later, if we want to change the number of points to 200, then only the macro definition can be: #define POINT_COUNT 200, and if you do not use symbolic constants, If you use 100 directly in your program, you'll need to find all the 100 locations and replace them with 200, so it's not only cumbersome but also error-prone, so it's best to define them as symbolic constants.
5. Add a member array to the Cexample50dlg class in the CExample50Dlg.h file:
C + + code
- int M_nzvalues[point_count];
This array is used to hold the waveform data.
6. In the constructor of the Cexample50dlg class, the elements of the array m_nzvalues are assigned an initial value:
C + + code
- Cexample50dlg::cexample50dlg (cwnd* pparent /*=null*/)
- : CDialogEx (Cexample50dlg::idd, pparent)
- {
- M_hicon = AfxGetApp ()->loadicon (IDR_MAINFRAME);
- //Initializes the elements of the array m_nzvalues to 0
- memset (m_nzvalues, 0, sizeof (int) * point_count);
- }
7. In the initialization member function Cexample50dlg::oninitdialog () of the Cexample50dlg dialog box, construct the random number generator and start the timer. Cexample50dlg::oninitdialog () modified as follows:
C + + code
- BOOL Cexample50dlg::oninitdialog ()
- {
- Cdialogex::oninitdialog ();
- //Add "About ..." menu item to System menu.
- //Idm_aboutbox must is in the System command range.
- ASSERT ((Idm_aboutbox & 0xfff0) = = Idm_aboutbox);
- ASSERT (Idm_aboutbox < 0xf000);
- cmenu* Psysmenu = GetSystemMenu (FALSE);
- if (psysmenu! = NULL)
- {
- BOOL Bnamevalid;
- CString Straboutmenu;
- Bnamevalid = straboutmenu.loadstring (Ids_aboutbox);
- ASSERT (Bnamevalid);
- if (!straboutmenu.isempty ())
- {
- Psysmenu->appendmenu (Mf_separator);
- Psysmenu->appendmenu (mf_string, Idm_aboutbox, Straboutmenu);
- }
- }
- //Set The icon for this dialog. The framework does this automatically
- //When the application ' s main window is not a dialog
- SetIcon (M_hicon, TRUE); //Set big icon
- SetIcon (M_hicon, FALSE); //Set small icon
- //Todo:add extra initialization here
- //using time as seed to construct random number generator
- Srand ((unsigned) time (NULL));
- //start timer, ID 1, timing time is 200ms
- SetTimer (1, $, NULL);
- return TRUE; //Return TRUE unless you set the focus to a control
- }
8. Add waveform for Cexample50dlg class member function Cexample50dlg::D rawwave (CDC *PDC, CRect &rectpicture), parameters are the device context pointer and the rectangle area of the drawing.
C + + code
- void Cexample50dlg::D rawwave (CDC *PDC, CRect &rectpicture)
- {
- float Fdeltax; coordinate distance of two plot points adjacent to//x-axis
- float Fdeltay; coordinate values for each logical unit of the//y-axis
- int NX; //The horizontal axis used to store the drawing point when connected
- int NY; //The ordinate used to store the drawing point when connected
- CPen Newpen; //For creating a new brush
- CPen *poldpen; //For storing old brushes
- CBrush Newbrush; //For creating a new paint Brush
- CBrush *poldbrush; //For storing old paint brushes
- //Calculate fdeltax and Fdeltay
- Fdeltax = (float) rectpicture.width ()/(POINT_COUNT-1);
- Fdeltay = (float) rectpicture.height ()/80;
- //Create a New Black paint Brush
- Newbrush.createsolidbrush (RGB (0,0,0));
- //Select a new brush and save the old brush's pointer to Poldbrush
- Poldbrush = Pdc->selectobject (&newbrush);
- //Fill black with black brush for drawing control to form a black background
- Pdc->rectangle (rectpicture);
- //restore old painting brush
- Pdc->selectobject (Poldbrush);
- //Remove a new paint Brush
- Newbrush.deleteobject ();
- //Create a solid brush with a thickness of 1 and a green color
- Newpen.createpen (Ps_solid, 1, RGB (0,255,0));
- //Select a new brush and save the old brush's pointer to Poldpen
- Poldpen = Pdc->selectobject (&newpen);
- //Moves the current point to the lower-left corner of the Drawing Control window, which is the starting point of the waveform
- Pdc->moveto (Rectpicture.left, Rectpicture.bottom);
- //calculate the coordinate position of each point in the m_nzvalues array, connect in turn, and eventually form a curve
- For (int i=0; i<point_count; i++)
- {
- NX = Rectpicture.left + (int) (i * fdeltax);
- NY = Rectpicture.bottom-(int) (m_nzvalues[i] * fdeltay);
- Pdc->lineto (NX, NY);
- }
- //restore old brushes
- Pdc->selectobject (Poldpen);
- //delete new brushes
- Newpen.deleteobject ();
- }
9, with the timer and the drawing member function, we can add to the response function of the WM_TIMER message to the waveform data timing processing and the timing of the waveform drawing. How to add a timer and Wm_timer message processing function If you forget, you can go to the VS2010/MFC Programming 44 (MFC Common class: Timer timer) review.
The processing function of the WM_TIMER message is modified as follows:
C + + code
- void Cexample50dlg::ontimer (uint_ptr nidevent)
- {
- //Todo:add your message handler code here and/or call default
- CRect rectpicture;
- //Move all elements in the array forward one unit, the first element discarded
- For (int i=0; i<point_count-1; i++)
- {
- M_nzvalues[i] = m_nzvalues[i+1];
- }
- //Assign a random value of 80 or less for the last element (integer type)
- M_NZVALUES[POINT_COUNT-1] = rand ()% 80;
- //Gets the client area coordinates of the Drawing Control
- //(customer area coordinates are the origin in the upper-left corner of the window, which differs from the screen coordinates of the origin in the upper -left corner of the screen)
- M_picdraw.getclientrect (&rectpicture);
- //Draw waveform diagram
- Drawwave (M_picdraw.getdc (), rectpicture);
- Cdialogex::ontimer (nidevent);
- }
10, when the dialog box is destroyed, the timer should be closed. So add a handler for the Wm_destroy message for the Cexample50dlg class and modify it as follows:
C + + code
- void Cexample50dlg::ondestroy ()
- {
- Cdialogex::ondestroy ();
- //Todo:add your message Handler code here
- //Off timer
- KillTimer (1);
- }
11, all ready, compile and run. The final effect is as follows:
About the brush, Chicken peck rice is here, the next section will be a brief talk about the use of painting brush. Thank you for your attention!
Original address: http://www.jizhuomi.com/software/246.html
(reprint) VS2010/MFC Programming Primer 50 (Graphic Image: GDI object brush CPen)