It is often seen that the dual cache is used to achieve non-blinking plotting, but it has always been like a sensible and not actually used. One day, when I saw the timer application in VC, I wanted to write a clock program. With reference to other people's Code, some of them are well-drawn, and one of them is a digital clock. After reading the code, the Drawn Part is very complicated, so I want to implement it myself. That's exactly how you exercise yourself.
Because the painting part is not the focus, it is only related to the Double Cache. When the number part is painted and displayed, it is found that the flash is really amazing. At this moment, I suddenly thought of the Double Cache Technology that I often mention online. I failed to use it. I found no answers online for a long time. It seems that the image is not drawn to the memory DC. But it has not been solved, and I always think it is painted. It can be displayed at the beginning. Why is it not displayed after a DC is changed. Later, we found out that the coordinates were inconsistent. The screen coordinates were transmitted from the dialog box, but the customer zone coordinates were used when the canvas was created for drawing. Then the two coordinates are unified, and the problem of blinking is solved.
In fact, I have a better understanding of Dual-cache. Next I will post the code of Dual-Cache implementation in my program:Cpaintdc DC (this); // device context for painting <br/> getclientrect (& m_rect); <br/> crect rect = m_rect; <br/> m_dcmemory.deletedc (); <br/> If (m_dcmemory.m_hdc = NULL) <br/>{< br/> m_dcmemory.createcompatibledc (& DC); <br/> m_bmp .deleteobject (); <br/> m_bmp .createcompatiblebitmap (& DC, rect. width (), rect. height (); <br/> m_dcmemory.selectobject (& m_bmp); <br/> drawclock (& m_dcmemory); <br/> DC. bitblt (0, 0, rect. width (), rect. height (), & m_dcmemory, 0, 0, srccopy); </P> <p>}
On the Internet, we can see that everyone else is using the cmemdc class. As a result, I want to study the content in this area. You can also see how to use it ..
It is very convenient to find out after use. For example:
CDC * PDC = This-> getdc (); <br/> cmemdc * pmemdc = NULL; <br/> PDC = pmemdc = new cmemdc (PDC ); <br/> // The drawing part is the same as the usual drawing <br/> // <br/> Delete pmemdc; <br/> This-> releasedc (PDC );
Now we can implement non-blinking plotting.
Next, let's repeat other people's introduction to the non-blinking plot. It is also convenient for you to read later. ^_^
Implementation of VC non-flashing screen Flushing Technology
In the process of drawing, the displayed image will always flash. I have been suffering from this problem for a long time. By asking experts for help, searching for materials, the problem is basically solved, now we will sort out the documents for your reference.
1. Why does the displayed image flash?
Most of our drawing processes are stored in the ondraw or onpaint functions. ondraw calls onpaint for screen display. When the window needs to be re-painted for any reason, the display area is always cleared with the background color before onpaint is called. The background color is often in a large contrast with the drawing content, in this way, the background color and the display image appear alternately in a short period of time, making the display window appear flashing. If you set the background to null, the duplicate drawing will not flash. Of course, this will make the display of the window messy, because during the re-painting, there is no background color to clear the original drawing, and a new image is superimposed. Some people may say that the blinking is caused by the drawing speed being too slow or the display graphics being too complex. In fact, this is not true. The influence of the display speed of the drawing on the flashing is not fundamental. For example, in ondraw (CDC * PDC), write as follows:
PDC-> moveTo (0, 0 );
PDC-> lineto (100,100 );
This drawing process should be very simple and fast, but it will still flash when pulling the window changes. In fact, in principle, the more complex the process of drawing, the slower the process, and the fewer flashes it should be, because the larger the ratio of the time used for drawing to the time used to clear the screen with the background, the less obvious the person will feel. For example, when the screen time is 1 s, the drawing time is also 1 s, so that the continuous re-painting within 10 s will flash 5 times; if the screen time is 1 s, the drawing time is 9 s, so that the continuous re-painting within 10 s will only Flash once. This can also be tested by writing in ondraw (CDC * PDC) as follows:
For (INT I = 0; I <100000; I ++)
{
PDC-> moveTo (0, I );
PDC-> lineto (1000, I );
}
The program is a bit extreme, but it can explain the problem.
Some people may want to talk about it again. Why does a simple image look like a complex one? This is because the area occupied by complex images is large, and the contrast caused by the re-painting is relatively large, so I feel that the flash is more severe, but the flash frequency is lower. So why does the animation appear non-flashing when its re-painting frequency is high? Here, I want to emphasize again, what is flashing? Flashing means contrast. The larger the contrast, the more powerful the blinking. The animation does not seem to flash because the difference between two consecutive frames is very small. If you don't believe it, you can add a pure white frame in the middle of each frame of the animation.
2. How to Avoid blinking
After you know why the image flash, you can do the right thing. The first step is to remove the background rendering process provided by MFC. There are many implementation methods:
* When the window is formed, you can pay NULL for the registration background of the window.
* You can also modify the background after the formation.
Static cbrush brush (RGB (255, 0, 0 ));
Setclasslong (this-> m_hwnd, gcl_hbrbackground, (long) (hbrush) brush );
* You can also load onerasebkgnd (CDC * PDC) to return true directly.
The background is gone, and the result graphic display does not flash, but the display is also messy as mentioned above. What should I do? This requires the dual-Cache method. In addition to displaying images on the screen, the dual-buffer mode also displays images in the memory. We can plot the image to be displayed in the memory first, and then overwrite the image in the memory to the screen one by one point at a time (this process is very fast, because it is a very regular copy of memory ). In this way, when drawing in the memory, any background color with a large contrast will not flash, because it cannot be seen. When it is attached to the screen, the final image in the memory is slightly different from the screen display image (if there is no motion, of course there is no difference), so that it will not flash.
3. How to implement dual Buffering
The implementation program is provided first, and then explained again, also in ondraw (CDC * PDC:
CDC memdc; // define a display device object
Cbitmap membitmap; // defines a bitmap object.
// Create a memory display device compatible with Screen Display
Memdc. createcompatibledc (null );
// No drawing yet, because there is no place to draw
// A bitmap compatible with screen display is created below. The size of the bitmap can be set to the size of the window.
Membitmap. createcompatiblebitmap (PDC, nwidth, nheight );
// Select the bitmap to the memory display device.
// Only the memory display device with the bitmap selected can draw a local image and draw it to the specified bitmap.
Cbitmap * poldbit = memdc. SelectObject (& membitmap );
// Use the background color to clear the bitmap. Here, I use white as the background color.
// You can also use your own color
Memdc. fillsolidrect (255,255,255, nwidth, nheight, RGB ));
// Drawing
Memdc. moveTo (......);
Memdc. lineto (......);
// Copy the image in the memory to the screen for display
PDC-> bitblt (0, 0, nwidth, nheight, & memdc, 0, srccopy );
// Cleanup after drawing is complete
Membitmap. deleteobject ();
Memdc. deletedc ();
See annotations.
4. How to Improve the drawing efficiency
In fact, not all charts drawn in ondraw (CDC * PDC) are displayed. For example, you have drawn two rectangles in ondraw, although the painting functions of the two rectangles are executed in one painting, there may be only one display. This is because MFC sets the cropping area to improve the repainting efficiency. The purpose of the cropping area is to ensure that only the plotting process in this area is valid and that the plotting function is not displayed even if it is executed outside the area. In most cases, the re-painting of a window is mostly due to partial occlusion of the window or scrolling of the window. The changed area is not the whole graph but only a small part, this part needs to be changed in the cutting area of the PDC. Because the display (display to memory or video memory) is much more time-consuming than the calculation of the drawing process, only the display part should be displayed after the cropping area, greatly improving the display efficiency. However, this cropping area is set by MFC, which has improved the display efficiency. How can we further improve the efficiency when drawing complex images? Then, only the plotting process outside the cropping area is removed. You can first use PDC-> getclipbox () to obtain the cropping area, and then determine whether your image is in this area during the drawing. If you are painting it, you will not draw it if you are not.
If your drawing process is not complex, this may not improve your drawing efficiency.
For specific procedures, you can refer to the following source code:
5. Implementation of the code for creating a non-blinking background image
//////////// No blinking background image rendering //////////
/// Program Design: icemen (warm ice)
//////////////////////////////////////// //////
Bool cstrucview: onerasebkgnd (CDC * PDC)
{Int nwidth;
Int nheight;
// Cview: onerasebkgnd (PDC );
Cstrucdoc * pdoc = getdocument ();
Assert_valid (pdoc );
Crect rect;
Getwindowrect (& rect );
Nwidth = rect. Width ();
Nheight = rect. Height ();
CDC memdc;
Cbitmap membitmap;
Memdc. createcompatibledc (null );
Membitmap. createcompatiblebitmap (PDC, nwidth, nheight );
Cbitmap * poldbit = memdc. SelectObject (& membitmap );
Memdc. fillsolidrect (255,255,255, nwidth, nheight, RGB ));
//////////////////////////////////////// ///////////////
//// The background color is displayed //////////////
//// The following figure shows the background image //////////////
//////////////////////////////////////// ///////////////
Getclientrect (rect );
Bitmap bm;
CDC dcmem;
Verify (m_bmp .getobject (sizeof (BM), (lpvoid) & BM ));
Dcmem. createcompatibledc (PDC );
Cbitmap * poldbmp = (cbitmap *) dcmem. SelectObject (& m_bmp );
Memdc. bitblt (rect. Right-BM. bmwidth)/2,
(Rect. Bottom-BM. bmheight)/2,
BM. bmwidth, BM. bmheight, & dcmem, 0,0, srccopy );
Dcmem. SelectObject (poldbmp );
//////////////////////////////////////// ///////////////
//// The above is the background image //////////////
//////////////////////////////////////// ///////////////
PDC-> bitblt (0, 0, nwidth, nheight, & memdc, 0, srccopy );
Membitmap. deleteobject ();
Memdc. deletedc ();
Return true;
}
//////////// No blinking background image rendering //////////
//////////////////////////////////////// /////
Note: m_bmp is defined in strucview. h In the program and is a bitmap Resource class.
Protected:
Cbitmap m_bmp;
Add the following sections. Of course, you can add loadbitmap or file resources at any time!
Cstrucview: cstrucview ()
{
Verify (m_bmp .loadbitmap (idb_bitmap3 ));
}