1, the problem of flashing screen
In the GDI drawing system, each time a zone drawing operation is called, such as FillRect, BitBlt, and so on, the graphical display system will perform a refresh operation on the specified area in the screen. If the operation of the area drawing operation is frequent, we will find that the splash screen will appear.
Using the following code to test the splash screen problem, the XP system splash screen is particularly serious, in the Win7 system, the splash screen problem has improved. The WIN7 system has been improved in drawing efficiency.
void Cdoublebufferview::D rawdirect (cdc* PDC)
{
assert_valid (PDC);
/* Paint background with gradient *
/CRect rect (0,0,0,0);
CSize sztotal = Gettotalsize ();
for (int i = 0; I <= sztotal.cy; i++)
{
rect.left = 0;
Rect.right = sztotal.cx;
Rect.top = i*10;
Rect.bottom = (i+1) *10;
Pdc->fillsolidrect (&rect, RGB ((i*10)%255,0,0));
}
/* Draw Pictures */
CDC dcpic;
Dcpic.createcompatibledc (PDC);
CBitmap Bmpimport;
Bmpimport.loadbitmap (IDB_BITMAP1);
cbitmap* poldbmp = Dcpic.selectobject (&bmpimport);
BITMAP BITMAP;
Bmpimport.getbitmap (&BITMAP);
Intiwidth = Bitmap.bmwidth;
Intiheight = bitmap.bmheight;
Pdc->bitblt (0, 0, iwidth, iheight,
&dcpic, 0, 0, srccopy);
Dcpic.selectobject (poldbmp);
/* Release resources *
/Bmpimport.deleteobject ();
Dcpic.deletedc ();
}
2, double cache
The cause of the splash screen is similar to the multi-process communication problem, each time the DC drawing operation, the relevant display data should be sent to the video card, the graphics card processing, on the display. The solution to improve the communication efficiency between multiple threads can improve the efficiency of drawing by reducing the number of interactions with the video card. This is the idea of double caching. The principle of double caching is to first write all the data in the update operation to memory before calling BitBlt or StretchBlt to send all the data to the video card once.
in a metaphor, there's no double cache. As the teacher used chalk on the blackboard to write blackboard, students can see the teacher writing on the whole process, if the blackboard as a screen, the teacher in the process of writing a blackboard, is a splash screen process. The
uses the double cache, just like the teacher uses the multimedia teaching, the teacher can advance the blackboard in the writing with the PPT to do at home, in the class as long as one page one page of the PPT can, the student is not to see the PPT production process, also will have the flashing screen question. The
can use the following code to implement a double cache.
void Cdoublebufferview::D rawwithbufferinefficient (cdc* PDC)
{
assert_valid (PDC);
/* Create memory dc*/
CDC dcmemory;
Dcmemory.createcompatibledc (PDC);
Dcmemory.setbkcolor (Pdc->getbkcolor ());
/* Set the memory DC's artboard to the same size as the entire window *
/CSize sztotal = Gettotalsize ();
CBitmap bmpmemory;
Bmpmemory.createcompatiblebitmap (PDC,
sztotal.cx, sztotal.cy);
Dcmemory.selectobject (&bmpmemory);
/* Set the starting point of the memory DC *
/dcmemory.setviewportorg (0, 0);
/* Paint background *
/dcmemory.fillsolidrect (0, 0, sztotal.cx, sztotal.cy, Pdc->getbkcolor ());
Drawdirect (&dcmemory);
/* Copy the memory DC into the input DC *
/pdc->bitblt (0, 0, sztotal.cx, sztotal.cy,
&dcmemory, 0, 0, srccopy);
/* Release resources *
/Bmpmemory.deleteobject ();
Dcmemory.deletedc ();
}
3. Cancel Erase Background
When we used the above dual-cache technology, we saw the splash screen problem eased, but some operations still caused the splash screen, such as when the scroll bar in the View window with the scroll bar was dragged. Why does it have such a reason? First to analyze the interface drawing principle.
When we need to draw on the window, we can call functions such as UpdateWindow, RedrawWindow, invalidate, or invalidaterect. By looking at these functions in MSDN, there is an option to erase the background in some window drawing functions. If you want to erase the background, the drawing is going to do two operations, that is, to interact with the video card two times, one is to erase the background, one is to redraw the graphics, the role of the dual cache is lost.
If we paint the background once again, we don't need to erase the background, and we can also guarantee the effect of the double cache.
There are two main ways to cancel wiping Beijing:
(1) Remove the erase option when redrawing.
If you use Invalidate (FALSE).
While this approach works, it is difficult to completely erase the background by processing all the redraw functions.
(2) Truncate the erase message.
The erase of the background is done by WM_ERASEBKGND messages. As a result, we can simply intercept the message and completely cancel the erase background.
You can provide a message response function for WM_ERASEBKGND in a window class, and then return true directly.
BOOL cdoublebufferview::onerasebkgnd (cdc* PDC)
{
//todo:add your message handler code here and/or call default
returntrue;
Return Cscrollview::onerasebkgnd (PDC);
}
4, drawing efficiency promotion
When refreshing the interface, the smaller the refresh area, refresh more efficient, therefore, in the refresh interface, we should try to minimize unnecessary refresh. The operating system also optimizes the refresh operation of the interface, such as pulling the scroll bar, instead of refreshing the entire interface, just swapping new graphics into areas that are already invalid, and then resizing the graphics area on the screen. Therefore, there is the concept of a cropped area, in which only the cropped area needs to be redrawn. Therefore, we only need to redraw the cropping area in the double cache. The size of the cropping area can be obtained by Cdc::getclipbox.
Therefore, the optimization code for the double cache is as follows:
void Cdoublebufferview::D rawwithbufferefficient (cdc* PDC)
{
assert_valid (PDC);
/* Create memory dc*/
CDC dcmemory;
Dcmemory.createcompatibledc (PDC);
Dcmemory.setbkcolor (Pdc->getbkcolor ());
/* Set the artboard of the memory DC to the same size as the input DC's cropping area *///
///////////CRect Rectclip (0,0,0,0);
Pdc->getclipbox (&rectclip);
CBitmap bmpmemory;
Bmpmemory.createcompatiblebitmap (PDC,
rectclip.width (), Rectclip.height ());
Dcmemory.selectobject (&bmpmemory);
/* Set the starting point of the memory DC *
/dcmemory.setviewportorg ( -1*rectclip.left, -1*rectclip.top);
/* Paint background *
/Dcmemory.fillsolidrect (&rectclip, Pdc->getbkcolor ());
Drawdirect (&dcmemory);
/* Copy the memory DC into the input DC *
/Pdc->bitblt (Rectclip.left, Rectclip.top, Rectclip.width (), Rectclip.height (),
&dcmemory, Rectclip.left, Rectclip.top, srccopy);
/* Release resources *
/Bmpmemory.deleteobject ();
Dcmemory.deletedc ();
}
5. Project source code Download
Http://files.cnblogs.com/xianyunhe/DoubleBuffer.rar