Keyword memory buffer, drawing the original author's name
This section describes the flicker when drawing with dual buffers.
Text use VC to do programs, how to draw a lot, but it is difficult to understand, because in the package of MFC, there is no ready-made picture function to be called directly, like VB, etc. Point, often make people feel that there is no way. These two days helped people solved a problem with the memory burst picture, and they also talked about these things, and they were also summarized.
Let me first explain the key to the device environment descriptor in the MFC, which is the so-called DC (Device Context).
Still from history, the DOS era, if we want to draw, you must start the graphics environment through a series of system functions (there should be impressions with Turbo Pascal or Turbo C), this is a variety of hardware The initialization parameters are different. Very annoying, often referring to the hardware manual, then the program is smart to write for the most popular hardware, there is no way to incompetence. The Windows operating system has taken a series of methods to block the different hardware environments, and take a series of methods to produce a series of methods. Simply put, the equipment descriptor abstracts different hardware environments for standard environments, using this virtual standard environment when writing, rather than real hardware, and is generally handed over to system and drivers. (This also explains why we need to update the driver frequently.). Using the Windows Graphics System (GDI, not including Direct X), it is reflected in a series of graphics DCs, if we want to draw on the GDI, you must first get the handle of the graphics DC, then specify the handle. Graphical operation is performed on a basis.
I will recall it, how do we draw in the SDK environment, I think this everyone is not very clear, but it is really found. In the Windows SDK environment, we use traditional C writing programs to do this in needed drawings (such as branch responding to WM_Paint messages):
HDC = getDC (hwnd); OldGDiobject = selectObject (HDC, newgdiobject); ... Drawing operation ... SelectObject (HDC, OldGDiObject); deleteObject (newgdiobject); ReleaseDC (HDC);
Or so
Beginpaint (hwnd, & ps); // PaintStruct PS - PS Is a Paint Struct ... Drawing operation ... Endpaint (hwnd)
This is a probably process, we see the application of the HDC (graphics DC handle), in the drawing part, each draw function is basically used to use this handle, and finally we must also release it, otherwise it will seriously affect performance. Every time we have to call the getDC this API function (can not be reused with the global variable save result, I explained later). These are the most basic Windows graphics operations, compared to the DOS era, but some concepts are difficult to understand. The simple Point function in VB is actually in the end, it is also converted to this way, and the system helps a lot of things.
Inside the MFC, because of the package, all HDC is hidden in the object as a hidden parameters pass (that is, the THIS ~~), so our key topics turn to how to get the desired DC class, This process is actually small. In the process of message response, WM_PAINT is converted to onDraw (), onpaint () a series of functions, which generally have a parameter CDC * PDC incoming, so we only need direct drawing in these functions. Yes, as before SDK. However, the frequency of the WM_PAINT message response is too high, such as minimizing maximizing, mobile forms, coverage, etc., which are often renovated, often such drawing, is very consuming; in some occasions, such as random motion, Each time it changes, it also leads to the unautover of the program. How to solve the latter problem.
MS is handed over to our Document / View's classic solution in an example of MSDN, and the data of the data is stored in the Document class, and the View class is only drawn according to these data. For example, you have to draw a circle, just put the center and radius in Document, the View class resembles the data inside this on the screen. So, we only need to randomly generate a data.
This is still a problem with performance, so we have begun to consider additional solutions. We know that it is very fast to output the image in memory to the screen. This is also what we often do in the DOS Times. Can you still reuse in Windows? The answer is the memory buffering drawing, our topic today.
We still returned to the DC. Since the DC is a drawing object, we can also make one of them in memory, let it wait for the figure we want, the picture (CBITMAP) can be stored in the Document class, each refresh screen Just output this picture to the top of the screen, each mapping is drawn in memory, saved in the Document chart, and you can output the figure to the deposit save. This guarantees the speed and solves random problems. In the case of complex mapping, the overhead of memory is not large (always a pair of pictures). This is a good solution, now let us implement them.
We save a picture in the Document class
CBITMAP M_BMPBUF; // This saves our maps, exists in memory
In the View class, we need to copy this graph to the screen in the OnDraw (CDC * PDC) function:
CDC dcMem; // The following is the standard operation of the output bitmap CBitmap * pOldBitmap = NULL; dcMem.CreateCompatibleDC (NULL); pOldBitmap = dcMem.SelectObject (& pDoc-> m_bmpBuf); BITMAP bmpinfo; pDoc-> m_bmpBuf.GetBitmap (& bmpinfo) PDC-> Bitblt (0, 0, Bmpinfo.bmwidth, Bmpinfo.Bmheight, & DCMEM, 0, 0, Srcopy); DCMem.selectObject (PoldbitMap); DcMem.deletedc ();
In our functions we need to draw, we complete the drawing work
CBMPDRAWDOC * PDOC = getDocument (); // Get the Bitmap object CDC * PDC = getdc (); CDC DcMem; DcMem.createCompAtibleDC (NULL); // We will virtualize DCPDOC-> m_BMPBUF in memory. DeleteObject (); pDoc-> m_bmpBuf.CreateCompatibleBitmap (pDC, 100,100); // create dependency DC bitmapCBitmap * pOldBitmap = dcMem.SelectObject (& pDoc-> m_bmpBuf); // we transferred our bitmap goal dcMem.FillSolidRect (0, 0, 100, 100, RGB (255, 255, 255)); // That time drawing operation, cassels you ^ _ ^ DcMem.Textout (0, 0, "Hello, World!"); DcMem.Rectangle (20, 20, 40, 40); DCMEM .FillsolidRect (40, 40, 50, 50, RGB (255, 0));
PDC-> Bitblt (0, 0, 100, 100, & DCMEM, 0, 0, Srcopy); // Copy to the screen DCMem.selectObject (Poldbitmap); DcMem.deletedc ();
All processes are like this, it is very simple. With this as an example, two buffers or multiple buffers, etc., depending on the specific situation. Of course, many advanced graphics operations can also be achieved, such as transparency, synthesis, etc.
Let's explain why the previously said to save DC issues with global variables. In fact, the DC is also identified by the handle, so there is also the uncertainty of the handle, that is, only the same use, different times, different times, different times (using the file handle, should be readily understood). Then, the DC that we have saved with global variables is not meaningful. The next time I use only anything else. (This understanding can be said: DC needs to take a certain amount of memory, then in frequent page scheduling, the location is inevitable, so the handle used to mark the pointer is different).