In general, the program calls invalidate (FALSE) as needed to make the window client area invalid, causing the redraw, and then stabilizing the drawing in the window OnPaint function (the program based on the document view is OnDraw). However, we do multiple rendering in the OnPaint (drawing background, chessboard, chess, etc.), the contrast between front and back caused the flicker phenomenon. Previously known in Java to solve screen flicker problem is a double buffering method, now found in VC + + can do so. In short, double buffering is the first thing that needs to be drawn in a single breath in memory, and finally put the data in memory to display on the screen.
Recently do Chinese chess, draw the interface encountered some problems, drawing the screen flashing, it is estimated that the use of double buffering to solve the problem, but looked up the internet double buffering data, found that the basic MFC, converted to VC + +, the approximate code is as follows:
HOld;
Hdcmem = CreateCompatibleDC (HDC)//Dependent window DC create compatible memory DC
BMP = CreateCompatibleBitmap (HDC, 100, 100);// Create a device-compatible bitmap
SelectObject (HDCMEM, BMP) associated with the HDC environment;
HOld = SelectObject (Hdcimage, hbitmap);
StretchBlt (HDC, 0, 0, M, hdcmem, 0, 0, MB, srccopy);
SelectObject (Hdcimage, hOld);
DeleteObject (HOLD);
}
But the above code does not seem to use hbitmap, of course, there will be no output on the screen, but the information on the Internet is basically the same. Check a data, just understand if the HDC already have bitmap data, BitBlt, will direct the data in the HDC to the memory buffer. So, you need to build a DC, named Hdcimage, to select the bitmap to be drawn into the memory hdcimage, and then draw on the memory buffer.
Organize the code as follows:
void Drawbmp (HDC HDC, hbitmap hbitmap)
{
HDC hdcimage;
HDC Hdcmem; Note here that two HDC
hdcmem = CreateCompatibleDC (HDC) were created;
Hdcimage = CreateCompatibleDC (HDC);
Hbitmap bmp =:: CreateCompatibleBitmap (HDC, nwidth, nheight);//Create a device-compatible bitmap
HDC (SelectObject, BMP)
associated with the HDCMEM environment; SelectObject (Hdcimage, HBITMAP)//Note here, the bitmap to be painted is selected into Hdcimage
stretchblt (hdcmem, 0, 0, 0, 0, 100, 100, SRCCOPY); In order to properly draw, the bitmap in the hdcimage is copied directly to the memory buffer
StretchBlt (hDC, 0, 0, MB, hdcmem, 0, 0, M, srccopy); The data in the memory buffer is plotted to the screen.
DeleteObject (hdcimage);
}
Of course, the point to note is that if you want to draw more than one picture, such as two, if you call this:
Drawbmp (HDC, hBitmap1);
Drawbmp (HDC, HBITMAP2);
Flicker still occurs, as explained in the following reasons:
For example, a screen drawing is like a live painting, and if you call a drawing function two times, it's the equivalent of painting in front of the audience and first drawing the first one (for example, the background of Chinese chess). Second draw a second picture (such as a chessboard). In this way, when painting the background and the chessboard, because of color contrast, it is necessary to paste the second picture will be found flashing, so the use of double buffering is useless, but also a waste of memory space.
The principle of double buffering is: the first picture in memory is good, at this time do not turn to the screen, and then continue to draw the second in the original memory, and so on all the pictures are all finished, and then a one-time post to the screen. In that case, the memory is full of graphics, the audience can not see the process of drawing, only to see the results of the drawing, and the last is copied to the screen, of course, does not occur flashing phenomenon.
To better explain the principle of double buffering, the attached picture is as follows:
PS: The above photos from the network, only to be able to better understand, I do not intend to infringe.
Make the following changes based on the above code:
void Drawbmp (HDC HDC, hbitmap hbitmap)//Here The return type is changed to HDC
{
HDC hdcmem;
Hdcmem = CreateCompatibleDC (HDC);
SelectObject (Hdcmem, HBITMAP); Select Bitmap into memory DC
StretchBlt (hDC, 0, 0, MB, hdcmem, 0, 0, MB, srccopy); This is the only place to paint correctly, copy the bitmap from the Hdcimage directly to the memory buffer
DeleteObject (HDCMEM);
}
Call the above function to draw the first picture in memory:
Drawbmp (hdctmp, HBITMAP1);
Draw a second picture
Copy Code code as follows:
Drawbmp (hdctmp, HBITMAP2); At this time of the hdctmp, where the hdctmp already have the first picture of the data, this call will be the second picture painted on the original basis.
If you want to draw more than one diagram, call this function in turn, remember to draw all the pictures to a device DC, and finally a one-time painting to the screen, will not appear flashing phenomenon.
After drawing all the pictures into the hdctmp, the hdctmp has a complete graphic and then draws the complete graphic to the screen:
Copy Code code as follows:
BitBlt (HDC, 0, 0, M, hdctmp, 0, 0, srccopy); The first argument here is HDC, which is the window handle
At this point, double buffer painting multiple drawings completed.
Let me give you one more example:
void C****dlg::onpaint () {if (Isiconic ()) {//...}
else {//cdialog::onpaint ();//Do not call this CPAINTDC DC; the dc//of the dialog box is usually CPAINTDC used to respond to WM_PAINT messages.
CPaintDC is derived from the CDC: Cwnd::beginpaint is invoked automatically at construction time, and Cwnd::endpaint is invoked when the destructor is constructed.
RECT rect;//client Area rectangular getclientrect (&rect); Use double buffering to avoid blinking when screen refreshes CDC dcmem;//memory DC CBitmap Bmpmem; Bitmap Dcmem.createcompatibledc (NULL);//Create compatible DC Bmpmem.createcompatiblebitmap (&DC, Rect.right-rect.left, rect.b
Ottom-rect.top)//Create the same size as the customer area (empty) bitmap//bitmap selected in the device context CBitmap *pold = Dcmem.selectobject (&BMPMEM);
Dcmem.fillsolidrect (&rect, RGB (255,255,255)); This is where the drawing content is drawn to Dcmem memory (that is, replace the DC previously drawn with CPaintDC with a dcmem) drawtable (DCMEM), and/or a chessboard drawchesses (DCMEM); Draw a piece///...//So, in-memory drawing is finished/copied from memory to the device DC DC.
BitBlt (0, 0, Rect.right-rect.left, rect.bottom-rect.top, &dcmem, 0, 0, srccopy); dc.
SelectObject (Pold); Releasing Resources bmpmem.deleteobject ();
Dcmem.deletedc (); }
}
Workaround:
1) Add the member variable bgroundchanged of type bool, initialize to false;
2 before switching the background picture, call ModifyStyle (Ws_clipchildren, 0) to remove the Ws_clipchildren attribute and set the bgroundchanged to true;
3) The final increase in the OnPaint
if (TRUE = = bgroundchanged)
{
bgroundchg = FALSE;
ModifyStyle (0, Ws_clipchildren);
I hope this article can be a good grasp of the double buffer problem to help.