VC Drops Heavy Painting

xiaoxiao2021-03-06  77

Basic knowledge:

1. OnPaint and OnDRAW functions

The onpaint function of the VIEW's parent class calls the onDraw function. If the sub-class is the WM_PAINT message, the onDraw function will not be called.

2. CPAINTDC and CClietndc

BeginPaint (), the despaint (), and the despaint () in the destructor are called in the constructor of the CPAINTDC;

CClieTNDC's constructor called getDC (), and ReleaseDC () is called in the destructor.

Beginpaint (), endpaint () can only be used to respond to the WM-PAINT message, otherwise it will be wrong.

Second, using dynamic arrays:

1. Define structural lines for saving the data.

Struct Line

{

Cpoint M_PT1;

CPOINT M_PT2;

}

2. Define a dynamic array in View to save each line.

CPTRARRAY M_PTRLINES;

Define two CPOINT members variables, save the start and end points of the line:

Cpoint m_ptold;

Cpoint m_ptnew;

3. Add WM_LBUTTONDOWN, WM_LBUTTONUP in View, assign values ​​for m_ptnew in ONLBUTTONDOWN.

M_ptold = POINT;

4. Add code in ONLBUTTONUP:

m_ptnew = point;

CClientDC DC (this);

Dc.moveto (M_PTOLD);

Dc.Lineto (Point);

Line * Pln = new line;

PLN-> m_pt1 = m_ptold;

PLN-> m_pt2 = m_ptnew;

m_ptrlines.Add (PLN);

5. Add in onDraw ():

Int sum = m_ptrlines.getsize ();

For (int i = 0; i

{

PDC-> MoveTo ((line *) m_ptrlines.getat (i)) -> m_pt1);

PDC-> LINETO ((LINE *) M_Ptrlines.getat (i)) -> m_pt2);

}

6. Join the scroll bar: replace all the CVIEW in the VIEW to CScrollView.

7. Add virtual functions onInitialUpdate () in View, this function is called before the VIEW first refreshed, adding the code in it:

Setscrollsizes (MM_Text, CSIZE (1024, 768));

This function can also be called in the configuration function of the View.

8. Add DC in ONLBUTTONUP

OnPreparedc (& DC);

DC.DPTOLP (& M_PTOLD);

Dc.dptolp;

Third, use cmetafiled to re-painted

1. Define member variables in View:

Cmetafiledc m_dcmetafile;

2. Add code to the onCreate of View:

m_dcmetafile.create ();

3. In the view of View's ONLBUTTONUP, annotate the code about the array, join:

m_dcmetafile.moveto (m_ptold);

m_dcmetafile.lineto (m_ptnew);

4. In OnDraw ()

Hmetafile hmetafile; hmetafile = m_dcmetafile.close ();

PDC-> Playmetafile (Hmetafile);

m_dcmetafile.create ();

m_dcmetafile.playmetafile (Hmetafile);

:: Deletemetafile (Hmetafile);

5. save document:

Add menu response function, onfilesave, join the code:

Hmetafile hmetafile;

Hmetafile = m_dcmetafile.close ();

:: CopyMetafile (Hmetafile, "C: //2.ddd");

m_dcmetafile.create ();

m_dcmetafile.playmetafile (Hmetafile);

:: Deletemetafile (Hmetafile);

6. Read the file:

Add menu response function, ONFileLoad, join the code:

Hmetafile hmetafile;

Hmetafile = :: GetMetafile ("c: //2.ddd");

m_dcmetafile.playmetafile (Hmetafile);

:: Deletemetafile (Hmetafile);

Invalidate ();

Fourth, using a compatible DC redraw:

1. Define member variables in View:

CDC M_DCCMPA;

2. Add code in ONLBUTTONDOWN:

CClientDC DC (this);

IF (! m_dccompa.m_hdc)

{

m_dccompa.createcompatibleDC (& DC);

CBITMAP BMP;

CRECT RECT;

GetClientRect (& RECT);

Bmp.createCompaPatiBitmap (& DC, Rect.width (), Rect.Height ());

m_dccompa.selectObject (& BMP);

M_dccompa.bitblt (0, 0, Rect.width (), Rect.Height (), & DC, 0, 0, SRCCopy;

}

m_dccompa.moveto (m_ptold);

m_dccompa.lineto (m_ptnew);

3. Add in OnDraw:

CRECT RECT;

GetClientRect (& RECT);

PDC-> Bitblt (0, 0, Rect.width (), Rect.Height (), & M_DCCOMPA, 0, 0, SRCCOPY;

The CWND object is initialized to 0 in the constructor. However, CPOINT, CRECT, etc. do not do this in the constructor. The class written by the MFC is generally initialized in the constructor, unless it makes special instructions.

The message issued by the API function is a SendMessage mode.

Picture in CXXView, when we draw a graph, modify the size of the window, cover the window, minimize, maximize these operations, because the window is to be re-displayed, so the defined brush of the window will window Brush it out. After the window is re-drawn, a WM_Paint is reported to inform you, and the default use of the parent class onpainT response message, the parent class onpaint to call a function onDRAW. If we have to draw a line in the onDraw, even if the window is redrawged, the line can be seen, but when we cover the onpaint of the parent class, the discovery line is not. The reason why CXXVIEW's onpaint did not call the onDraw for you. We can track the implementation of ONPAINT to view the parent class. In fact, we can also call out the line in the onpain of the subclass, but it is best to call in OnDraw, why we override a virtual function onprint (install a printer) for CXXVIEW, discover its parent class, also call ONDRAW OnDraw is a virtual function, its parameter DC can accept the DC of any device (here you can accept the DC of the printer, the window of the window, the DC of the ONPAINT window, the ONPRINT-free DC), your DC's operation is Output on the corresponding device, such as output to the window or output to the printer, so that the written graphic output in the onDRAW can be output to the window while outputting it onto the printer, achieving the uniformity of the operation (virtual function) Principle) and the reuse of the code. A cpaintdc produced in OnPain, which is the difference between it and cclientdc

View the description of CPAINTDC. CclientDC packages are different.

WM_LBUTTONDOWN and WM_LBUTTONUP in the Winmain program have no problem with GetDC and ReleaseDC line, but use BeginPaint and Endpaint Picture Picture. Also in the WM_PAINT message, you cannot use the getDC and releasedc line, which is easy to make mistakes, so CPAINTDC can only be used in a function in response to the WM_PAINT message, CclientDC can only be used in a function of non-WM_PAINT messages.

An Application SHOULD NOT CALINT EXCEPT IN RESPONSE TO A WM_PAINT Message. Each Call To Beginpaint Must Have a Corresponding Call To The Endpaint Function.

Case WM_Paint:

HDC DC1;

// PainTStruct PS1;

// DC1 = :: beginpaint (hwnd, & ps1);

DC1 = :: getDC (hwnd);

:: Textout (DC1, 100, 100, "Hello World", Strlen ("Hello World");

// :: MoveToex (DC, 20, 20, NULL);

// :: LINETO (DC, 100, 100);

// DC = :: getdc (hwnd);

// :: MoveToex (DC, X1, Y1, NULL);

// :: LINETO (DC, X2, Y2);

:: ReleaseDC (HWND, DC1);

// :: EndPaint (hwnd, & ps1);

Break;

Case WM_LBUTTONDOWN:

X1 = loword (lparam);

Y1 = HiWord (LPARAM);

Break;

Case WM_LBUTTONUP:

X2 = loword (lparam);

Y2 = HiWord (LPARAM);

HDC DC;

Paintstruct PS;

DC = :: beginpaint (hwnd, & ps); // DC = :: getDC (hwnd);

:: MoveToex (DC, X1, Y1, NULL);

:: LINETO (DC, X2, Y2);

//: ReleaseDC (HWND, DC);

:: Endpaint (hwnd, & ps);

Break;

The graphics just saved can be saved down to save some elements of the original drawing operation, and then after the window is refreshed, then according to the saved elements, the graphics are heavy in the onDraw (the elements include origin, end point), it gives me After brushing, I will draw the graphics again. We can save the elements just once after each draw. It is best to save these elements here. But we have to keep these types of objects to use the number of groups. If we cannot determine the size of the array, we use a collection class, such a set class has three types (can dynamically allocate the dynamic array of spaces, Lin tables, MAP). The functionality of similar linked lists can be realized to dynamically generate space. Map is a bit like a collection of VBs, which can define keywords to facilitate user access, which can dynamically generate memory. Look for a word from a pointer from a pointer. Find a COLLECTION instructions by a COBARRY, then view the choosing a collection class to analyze the advantages and disadvantages of these collection classes, ARRAY dynamic implementation is actually allocated in the growth space, and the array space than the original element, then putting data To copy, kill the original space, so it is slow to increase the elements. Today we use dynamic arrays Cobarray.

Basically, the members of these collection classes are similar.

After the drawing operation, you can delete these pointers in the PostncDestroy of CXXView.

The members of this class are the data we have to save. And define a configuration function with parameters to initiate an object. New class (CGRAPH), Class Type is Generic Class. Define member variables and constructor with parameters for this new class. Define a CGRAPH variable in ONLBUTTONUP in CXXView, define member variables in CXXView, Cobarray (these are linked tables) m_obarray. Use m_obarray to save this object, pay attention to COBJECT *. Then we call the graphics over again in the CXXView's onDraw function. After we found these operations, the test found that the graphics did not save. The reason is that:

In the ONLBUTTONUP function

m_obarray.add (& graph) CGRAPH GRAPH; (address is 0x0012FF7C)

0x0012FF7C Graph occurs during Graph exceeds the scope of action, and its memory is recovered by the operating system.

Here, consider allocating this CGRAPH object on the heap and then saves its pointer to redraw and release the memory on the heap. To explain the principle of this object, taking a turtle with a stump, tie this turtle with two ropes and two stumps, although a stump is rushing, but another stump can still find this turtle .

Void CMYREDRAWVIEW :: ONLBUTTONUP (UINT NFLAGS, CPOINT)

{

// Todo: add your message handler code here and / or call default

m_ptend = Point;

CClientDC DC (this);

Dc.moveto (m_ptorigin);

Dc.LineTo (m_ptend);

CGRAPH * pgraph = new cgraph (m_ptorigin, m_ptend);

M_obarray.add (cobject *) pgraph); cview :: ONLBUTTONUP (NFLAGS, POINT);

}

Void CMYREDRAWVIEW :: OnDRAW (CDC * PDC)

{

CMYREDRAWDOC * PDOC = getDocument ();

Ask_VALID (PDOC);

// Todo: Add Draw Code for Native Data HERE

For (int i = 0; i

{

PDC-> MoveTo ((CGRAPH *) M_OBARRAY.GETAT (I)) -> m_ptorigin;

PDC-> LINETO ((CGRAPH *) M_OBARRAY.GETAT (I)) -> m_ptend);

}

}

Void CMYREDRAWVIEW :: Postncdestroy ()

{

// Todo: Add Your Specialized Code Here and / or Call The Base Class

For (int i = 0; i

{

Delete (cgraph *) m_obarray.getat (i); / / must be converted, otherwise the error will be cleared, because DELETE wants to call the destructor of the COBJECT, there will be unknown exceptions.

}

m_obarray.removeall (); // In fact, it is not deleted. This does not cause memory leaks. If this work is not cleared, this work is completed by the system, but it is best to do this.

CView :: postncdestroy ();

}

If you want to make the window of the drawing becomes bigger, this requires a window with a roll bar. You can specify the parent class of CXXVIEW as CScrollView when generating the project.

CeditView will generate a notepad.

CFormView results in a FORM window in VB

ChtmlView generates IE browser

ClistView generates the part of the right side of the resource manager.

CtreeView results in the part of the left side of the resource manager.

CRICHEDITVIEW generates a writing board.

Here you can demonstrate chtmlview. Modify the connection site of OnInitUpdate in CXXVIEW to get the web page. This function is called before the View first and Document, is called before the View displayed.

Here we can also replace the CView in the project to CScrollView, replace, xxView.cpp, and xxview.h in two files. Running discovery programs have been reported, because after adding scroll bars, it seems to have one after CXXView. A larger window (logic window), pull the scroll bar to display a part of the big window, how much the big window behind this operation is needed, I can display a part of the big window, come before the CXXView display Tell it, you can set in the constructor or set in the onInitUpdate of CXXVIEW.

Setscrollsizes (MM_Text, CSIZE (1024, 768));

MM_Text is pixel, with different pixels at different resolutions. A pixel of 800 * 600 is larger than 1024 * 786.

MM_HIMETRIC is 0.01 mm, an absolute value, no matter what resolution, the size is consistent. When we want to output onto the printer, it is defined to be an absolute value, and the results played on different printers (also resolution).

Positive Y-axis extends. Defining the positive axis direction mm_text in Y is positive.

Sizetotal specifies how big behind the window.

SizePage Specifies the size of the CXXVIEW moving (page) when the mouse click the rolling rod of the scroll bar. The default is specified by the previous CX and CY,. Sizeline Specifies the size of the CXXView movement (line number) when the mouse click the arrow of the scroll bar. The default is specified by the previous CX and CY.

After the scroll bar is generated, when we draw lines in the bottom right corner of CXXVIEW, the display of the line is problematic. This is because, when the drawing, the DC is used as the origin in the upper left corner of the current CXXView client area. When the window is re-drawn, the DC is the origin of the upper left corner of the large window. So when we draw, set the origin of the DC to the origin of the big window. The purpose of this is mainly to adjust the point of the obtained mouse to the value obtained relative to the coordinate of the upper left corner of the large window.

We can also see the explanation of ONLBUTTONDOWN knows:

Specifier the x- y-coordinate of the cursor. These Coordinates Are Always Relative to the Upper-Left Corner of The Window.

OnPreParedc is the origin of the DC according to the position of the scroll bar. After calling this function, the original origin is (0, 0), when you pull the scroll bar, the origin of the DC will become (-50, -50), so that the origin of the DC is always in the upper left corner of the big window. 0,0) points.

DPTOLP adjusts the device coordinates to logical coordinates, which can change the value of the ONLBUTTONDOWN point to the reference value of the original point (logic window).

Big window (0,0) m_ptend = Point;

Small window (-50, -50) CclientDC DC (this);

Cpoint pt = dc.getViewportorg ();

Small window (VIEW Currently displayed window) this-> onpreparedc (& DC);

Pt = dc.getViewPortorg ();

DC.DPTOLP (& M_ptorigin);

DC.DPTOLP (& M_Ptend);

You can debug a change in viewing.

The coordinates of the converted point are always referred to with the origin of the coordinate in the upper left corner of the large window.

If we are graphically reproduced in CXXView's onpain, we also want to call overpreparedc.

Next, the operation of retention graphics is performed with a DC of a meta file.

Cmetafiled:

A Windows Metafile Contains a Sequence of Graphics Device Interface (GDI) Commands That You Can Replay to create a design port or text.

A Windows metafile contains a series of GDI commands, then you can replay the created graphics and text.

To implement a Windows metafile, first create a CMetaFileDC object. Invoke the CMetaFileDC constructor, then call the Create member function, which creates a Windows metafile device context and attaches it to the CMetaFileDC object.

We draw with cmetafiledc, which will record all your drawing operations so that you can redo the graphics in a replayed manner.

After creating CMetafiled, a series of GDI commands to send CMetafiledc so you can replay. Such as Moveto and Lineto, etc. NEXT sent the cmetafiledc Object The sequence of cdc gdi command the sequence of cdc gdi commit. Only Those GDI Commands That Create Output, Such as Moveto and Lineto, Can Be Used.

After you send a desired command on this meta file, call the Close member function, which will turn off the metafile DC and return a handle of a meta file. Then discard this cmetafiled Object.

First define a meta file DC member cmetafiledc m_metafile in cxxView; create it in the constructor: calling its CREATE function, parameter description: Point to a backslash character tail string. Specifies the name of the created meta file, this, this metafile will be generated in the hard disk. If fill in empty, there will be a meta file in the memory being created. Next, all the drawing operations just used with DC will be operated again with the yuan file DC.

Then in CXXView's onDraw

Void CMYREDRAWVIEW :: OnDRAW (CDC * PDC)

{

CMYREDRAWDOC * PDOC = getDocument ();

Ask_VALID (PDOC);

// Todo: Add Draw Code for Native Data HERE

Hmetafile hmetafile = m_metafile.close (); // The report draws, turn off the canvas, and can be displayed.

PDC-> Playmetafile (Hmetafile);

m_metafile.create ();

m_metafile.playmetafile (Hmetafile);

: Deletemetafile (Hmetafile); // If there is no such thing, memory leaks can be viewed through the task manager.

}

M_metafile (C Object) yuan file DC entity (Windows resources)

The relationship after close is disconnected.

You must destroy, otherwise memory leaks appear.

Create before destroying the previous one, replay the original graphics in this new top.

New yuan file DC entity (Windows resources)

The metafile has a good place to generate meta files in memory, or the meta files in the hard disk can also be copied to the meta files in the memory as a metafile reservation. If the hard disk is generated, it can be The program is loaded in the hard disk next time to reproduce the graphics.

Void CMYREDRAWVIEW :: Onsave ()

{

// Todo: add your command handler code here

Hmetafile hmetafile = m_metafile.close ();

Copymetafile (Hmetafile, "C: // 200");

m_metafile.create ();

m_metafile.playmetafile (Hmetafile);

:: Deletemetafile (Hmetafile);

}

Void CMYREDRAWVIEW :: ONLOAD ()

{

// Todo: add your command handler code here

Hmetafile hmetafile = :: getMetafile ("C: // 200");

M_metafile.playmetafile (Hmetafile) ;: DeleteMetafile (Hmetafile);

Invalidate ();

}

Note that there is no content behind the ordinary DC painting.

During graphic reproduction with compatible DC.

The principle is to draw a graphic in a compatible DC when the drawing is drawn. After the window is re-painted, the graphic drawn in the compatible DC is copied to the DC associated with the window. Thereby, graphic reproduction is achieved. Unlike the meta DC DC, that is to record your operation.

First create a compatible DC:

When a memory device context is created, GDI automatically selects a 1-by-1 monochrome stock bitmap for it. GDI output functions can be used with a memory device context only if a bitmap has been created and selected into that context.

When a memory DC (compatible DC) is created, GDI automatically selects a bitmap of 1 * 1 pixel monochrome inventory, the GDI output function can be used by memory DC, only one bitmap is created and the memory is selected. DC.

To make our bitmap information in our compatible DC (CXXVIEW window is a pair map) (because we must finalize the graphic of the compatible DC to copy to the source DC). We also want to generate compatible bitmaps through the source DC, and this compatible bitmap is selected to be compatible with DC. Since the bitmap contains two information of the header information and the pixel block, it is only the header information of the DC bitmap and the source DC bitmap (the width of the image on the two DCs is consistent), The pixel block is copied to call Bitblt with a compatible DC, and the data is copied from the source DC.

Define a compatible DC, which is a member CDC m_comdc of CXXView; note that because it is a compatible DC of a window source DC, its generation must be generated after the window is generated, because only when a Windows window resource is generated Ok, you can get the source DC, which cannot generate this compatible DC in the constructor of the CXXVIEW. This is different from our previous meta DC, which is not associated with the window, so it can be generated when the window has not yet occurred.

Void CMYREDRAWVIEW :: OnDRAW (CDC * PDC)

{

CMYREDRAWDOC * PDOC = getDocument ();

Ask_VALID (PDOC);

// Todo: Add Draw Code for Native Data HERE

CRECT RECT;

GetClientRect (& RECT);

IF (! COMDC.M_HDC)

{

COMDC.CREATECOMPALEDC (PDC);

CBITMAP BMP;

Bmp.createCompaBitmap (PDC, Rect.width (), Rect.Height ());

COMDC.SELECTOBJECT (& BMP);

Comard.bitblt (0, 0, Rect.width (), Rect.height (), PDC, 0, 0, SRCCOPY;

}

PDC-> Bitblt (0, 0, Rect.width (), Rect.Height (), & COMDC, 0, 0, SRCCPY;

}

Void CMYREDRAWVIEW :: ONLBUTTONUP (UINT NFLAGS, CPOINT)

{

// Todo: add your message handler code here and / or call default

M_Ptend = Point; CclientDC DC (this);

Cpoint pt = dc.getViewportorg ();

This-> Onpreparedc (& DC);

Pt = dc.getViewPortorg ();

DC.DPTOLP (& M_ptorigin);

DC.DPTOLP (& M_Ptend);

Dc.moveto (m_ptorigin);

Dc.LineTo (m_ptend);

COMDC.MOVETO (M_ptorigin);

COMDC.LINETO (M_Ptend);

CscrollView :: ONLBUTTONUP (NFLAGS, POINT);

}

All CXXView's onDraw generates a compatible DC's judgment statement on the above-ONLBUTTONDOWN's compatible DC drawing, which is to flexibly change the window generated by the source DC generated in ONLBUTTONDOWN, and we don't change the PDC in OnDRAW. That is the system is transmitted to me, because it is a pointer, it is necessary to return to make it back. If you want to grab your desktop. You can change the window of the source DC generated in ONLBUTTONDOWN to CClientDC DC (NULL); if you want to grasp the customer's main window: cclientdc DC (getParent ()); if you want to grasp the entire window of the program main window : CWindowDC DC (getParent ());

Void CredrawTestView :: ONLBUTTONUP (Uint Nflags, Cpoint Point)

{

// Todo: add your message handler code here and / or call default

m_ptend = Point;

CClientDC DC (NULL);

OnPreparedc (& DC);

DC.DPTOLP (& M_ptorigin);

DC.DPTOLP (& M_Ptend);

Dc.moveto (m_ptorigin);

Dc.LineTo (m_ptend);

//m_metafile.moveto (M_ptorigin);

//m_metafile.lineto (M_Ptend);

// cgraph * pgraph = new cgraph (m_ptorigin, m_ptend);

//m_obarray.add (( (COBJECT*) PGRAPH);

CRECT RECT;

GetClientRect (& RECT);

IF (! m_comdc.m_hdc)

{

CBITMAP BMP;

Bmp.createCompaPatiBitmap (& DC, Rect.width (), Rect.Height ());

m_comdc.createcompatibleDC (& DC);

m_comdc.selectobject (& BMP);

M_comdc.bitblt (0, 0, Rect.width (), Rect.Height (), & DC, 0, 0, SRCCopy;

}

m_comdc.moveto (m_ptorigin);

m_comdc.lineto (m_ptend);

CscrollView :: ONLBUTTONUP (NFLAGS, POINT);

}

Comprehensive comparison discovery yuan file DC redraw graphics fastest

转载请注明原文地址:https://www.9cbs.com/read-120582.html

New Post(0)