MFC graphic editing interface tool

//Updated June 17, 2020

This blog seems to be very popular recently? Many younger martial brothers and younger martial sisters consulted me about the content of MFC. Well, the blogger hasn't used MFC for a long time. Now there's no development environment. In addition, at the end of the term, there are so many things. I really don't have the energy to review and help you solve the problems. This year is a special situation. I can also understand the younger martial brothers and younger martial sisters of grade 18. It's teacher Zhang Fan who teaches the practical training course, You can ask him for more advice. It seems that station B also has relevant tutorials. The methods are more difficult than the others. Come on!

1, Background

Oh, the five-day training is finally over. The name of the training course arranged by the school is advanced programming training, but in my opinion, I mainly learned the use of classes and functions provided by MFC (Microsoft Foundation Class) library provided by visual c + +. Net. The purpose of writing this blog is to make some explanations for the problems in the training, to facilitate future viewing, and to summarize this training. This training is really hard for me. The time for learning to use VS and MFC is only three days. Plus, the next week is the exam week, and there are several lessons that haven't been reviewed. These days are basically connected, and I also soak in the laboratory at noon. Alas, I'm still too busy. Finally, we need to submit a course design program. Because of the time, I chose the simplest graphical interface editing tool. This program actually has this in the course design of C + +, but I didn't know how to program the windows graphical interface at that time. Now I think these two course designs can be a copy (covering my face).
The final interface is as follows:

In terms of function:

  1. Can draw under the windows interface, can draw lines, white rectangles, rounded rectangles, hollow circles, filled rectangles, filled circles, filled rounded rectangles and text.
  2. It can change the color, lineweight, linetype of the brush and the color and font used for filling.
  3. Be able to save and open the drawing file
  4. It has menu, toolbar, right mouse button and other editing interfaces.

 

2, Procedure description

 

1. Toolbar description

2. Drawing menu


Under the drawing menu, you can choose to draw lines, hollow rectangles, hollow circles, hollow rounded rectangles, filled rectangles, filled circles, filled rounded rectangles.

3. Text menu


Under the text input menu, there are two options: text input and font setting, which correspond to two dialog boxes respectively.

The text input dialog box can locate the input position according to the specified x, y horizontal and vertical coordinates, and print the corresponding information.

For font setting, call the dialog box provided by the system to complete the setting of font type, font type and font size.




4. Brush setting menu


There are three options under the brush setting menu: brush color, brush type and brush width. The brush type includes solid line, dashed line, dotted line, dotted line and double dotted line. According to the content of the textbook and the Internet search, only when the width is 1, can other brush types be displayed except for solid lines. When the width is greater than 1, all the lines drawn are solid lines.

Color setting, call the dialog box provided by the system to complete the selection of brush and brush color. At the same time, using this dialog box can realize the custom color.

The brush width setting dialog box is a dialog box set by yourself. Input the corresponding brush width to change the brush width.




5. Right click in the interface


Right click the mouse to have the right mouse button menu. Its function options are the same as those given in the function bar. Select draw line, hollow rectangle, hollow circle, hollow rounded rectangle, fill rectangle, fill circle, fill rounded rectangle and text.

 

3, Mouse drag painting

The basic function of the program is to drag the mouse to draw a graph, which actually uses the rubber band technology. In the mouse drag, whenever the position of the mouse changes, it is necessary to clear the drawn line segments. The textbook has the code to realize the process. Of course, you need to add the message mapping of left mouse button pressing, mouse moving and left mouse button lifting in the View class.

void CShirrView::OnLButtonDown(UINT nFlags, CPoint point)
{
    //Store the left mouse button down position in the p1,p2
    p1 = p2 = point;
    b=true;               //Set drawing flag
    pdc->SetROP2(R2_NOTXORPEN);//Set drawing mode to R2_NOTXORPEN,Note white background
    CView::OnLButtonDown(nFlags, point);
}
void CShirrView::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!b)
        return;     //If not in drawing state, return to

    //P1 Press the left mouse button, P2 Last mouse position
    //That is, redraw once according to the previous position. The mode is R2_NOTXORPEN
    //The final effect is white. As the background color is white, the actual effect is to clear the last line segment
    pdc->MoveTo(p1.x,p1.y);
    pdc->LineTo(p2.x,p2.y);

    p2 = point;
    //p1 It is still the left mouse button pressed position, P2 Is the current mouse position
    pdc->MoveTo(p1.x,p1.y);
    pdc->LineTo(p2.x,p2.y);    //from P1 Draw line segments to the current position of the mouse
    CView::OnMouseMove(nFlags, point);
}
void CShirrView::OnLButtonDown(UINT nFlags, CPoint point)
{
    //Store the left mouse button down position in the p1,p2
    p1 = p2 = point;
    b=true;               //Set drawing flag
    pdc->SetROP2(R2_NOTXORPEN);//Set drawing mode to R2_NOTXORPEN,Note white background
    CView::OnLButtonDown(nFlags, point);
}
void CShirrView::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!b)
        return;     //If not in drawing state, return to

    //P1 Press the left mouse button, P2 Last mouse position
    //That is, redraw once according to the previous position. The mode is R2_NOTXORPEN
    //The final effect is white. As the background color is white, the actual effect is to clear the last line segment
    pdc->MoveTo(p1.x,p1.y);
    pdc->LineTo(p2.x,p2.y);

    p2 = point;
    //p1 It is still the left mouse button pressed position, P2 Is the current mouse position
    pdc->MoveTo(p1.x,p1.y);
    pdc->LineTo(p2.x,p2.y);    //from P1 Draw line segments to the current position of the mouse
    CView::OnMouseMove(nFlags, point);
}

The above code is used to draw a straight line, which can complete the function of drawing a straight line. Then you can draw a rectangle and a circle according to the cat and mouse. These figures need the coordinates of the starting point and the end point as the drawing parameters.

At the same time, we need to understand that these functions are executed in the current view. That is to say, as soon as we open the program, as long as we click and move the mouse in the view, these functions will actually execute accordingly. Then how can we design and select different graphics?

In fact, this is very simple, the transformation of the mouse to move the message function and the left mouse button to lift the message response function! We can give different graphics a number, press the button to select graphics, the corresponding message corresponding function will change that number, mouse move message corresponding function and left mouse button lift message response function can draw different graphics according to this number!

Does the left mouse button press the message response function not need to be modified?

It doesn't need to be modified, because the mouse is only pressed at the beginning to get the coordinates of the starting point, but not to draw a figure, so this is applicable to all figures.

Before this, we need to record the ID of each selection graphic key and the message response function, and complete the construction of pdc object pointer in the message response function.

/*
1 Draw a straight line
2 Draw rectangle
3.Draw a hollow circle
4.Draw filled rectangle
5.Draw fill circle
6.round rectangle 
7.Draw filled rectangle
 Line ID_LINE,
Rectangle ID_RECTANGLE
 Circle ID_CIRCLE
 Fill rectangle ID_TRECTANGLE
 Fill circle ID_TCIRCLE
 Rounded rectangle ID_YTRECTANGLE
 Filled rectangle ID_TYTRECTANGLE
*/
void CWkfDrawingView::OnLine()
{
    // TODO: Add command handler code here
    MyDrawStyle = 1;
    pdc=new CClientDC(this);//Construction object
    b=false;
}

void CWkfDrawingView::OnRectangle()//Draw rectangle
{
    MyDrawStyle = 2;
    pdc=new CClientDC(this);//Construction object
    b=false;
}
void CWkfDrawingView::OnCircle()//Draw a hollow circle
{
    MyDrawStyle = 3;
    pdc=new CClientDC(this);//Construction object
    b=false;
}
void CWkfDrawingView::OnTrectangle()
{
    MyDrawStyle = 4;
    pdc=new CClientDC(this);//Construction object
    b=false;
}

void CWkfDrawingView::OnTcircle()
{
    MyDrawStyle = 5;
    pdc=new CClientDC(this);//Construction object
    b=false;
}
void CWkfDrawingView::OnYtrectangle()
{
    MyDrawStyle = 6;
    pdc=new CClientDC(this);//Construction object
    b=false;
}

void CWkfDrawingView::OnTytrectangle()
{
    MyDrawStyle = 7;
    pdc=new CClientDC(this);//Construction object
    b=false;
}

 

Here is the code of the corresponding function of mouse down message, mouse move message and left mouse button up message. MyStart and MyEnd are two CPoint type member variables of view class, which are used to save the coordinates of the start and end points.

void CWkfDrawingView::OnLButtonDown(UINT nFlags, CPoint point)//Mouse down
{
    // TODO: Add message handler code and/Or call default
        MyStart = MyEnd = point;
        pdc=new CClientDC(this);
        pdc->SetROP2(R2_NOTXORPEN);
        b = true;
        CView::OnLButtonDown(nFlags, point);
}
void CWkfDrawingView::OnMouseMove(UINT nFlags, CPoint point)//Mouse movement
{
    // TODO: Add message handler code and/Or call default
    /*pdc->MoveTo(MyStart.x,MyStart.y);
    pdc->LineTo(MyEnd.x,MyEnd.y);*/
    if(!b)
    return ;
    CPen pen(GP.type, GP.width, GP.pencolor); 
    OldPen=pdc->SelectObject(&pen);
    if(MyDrawStyle==1)
    {
    pdc->SelectStockObject(NULL_BRUSH);
    pdc->MoveTo(MyStart.x,MyStart.y);
    pdc->LineTo(MyEnd.x,MyEnd.y);
    MyEnd=point;
    pdc->MoveTo(MyStart.x,MyStart.y);
    pdc->LineTo(MyEnd.x,MyEnd.y);
    }
    else if(MyDrawStyle==2)
    {
        pdc->SelectStockObject(NULL_BRUSH);
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        MyEnd = point;
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
    }
    else if(MyDrawStyle==3)
    {
        pdc->SelectStockObject(NULL_BRUSH);
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        MyEnd = point;
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
    }
    else if(MyDrawStyle==4)
    {
        //pdc->SelectObject(&newBrush);
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SelectObject(&bsh);
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        MyEnd = point;
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        bsh.DeleteObject();
    }
    else if(MyDrawStyle==5)
    {
        //pdc->SelectObject(&newBrush);
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SelectObject(&bsh);
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        MyEnd = point;
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        bsh.DeleteObject();
    }
    else if(MyDrawStyle==6)
    {
        pdc->SelectStockObject(NULL_BRUSH);
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
        MyEnd = point;
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
    }
    else if(MyDrawStyle==7)
    {
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SelectObject(&bsh);
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
        MyEnd = point;
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
        bsh.DeleteObject();
    }
    CView::OnMouseMove(nFlags, point);
}
void CWkfDrawingView::OnLButtonUp(UINT nFlags, CPoint point)//Mouse up
{
    GPen g;
    g.start = MyStart;
    g.end = MyEnd;
    g.width = MyWidth;
    g.type = type;
    g.style = MyDrawStyle;
    g.pencolor = GP.pencolor;
    if(MyDrawStyle==1)
    {
        // TODO: Add message handler code and/Or call default  
    pdc->SetROP2(R2_COPYPEN);//Current color overrides background color
    pdc->MoveTo(MyStart.x,MyStart.y);
    pdc->LineTo(point.x,point.y);
    g.c = GP.pencolor;
    b=false;//Release drawing relationship
    CView::OnLButtonUp(nFlags, point);
    }
    else if(MyDrawStyle==2)
    {
        pdc->SetROP2(R2_COPYPEN);
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        g.c = GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
    else if(MyDrawStyle==3)
    {
        pdc->SetROP2(R2_COPYPEN);
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        g.c = GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
   else if(MyDrawStyle==4)
    {

        //pdc->SelectObject(&newBrush);
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SetROP2(R2_COPYPEN);
        pdc->SelectObject(&bsh);
        pdc->Rectangle(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        g.c =GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
    else if(MyDrawStyle==5)
    {

        //pdc->SelectObject(&newBrush);
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SetROP2(R2_COPYPEN);
        pdc->SelectObject(&bsh);
        pdc->Ellipse(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y);
        g.c =GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
   else if(MyDrawStyle==6)
    {

        pdc->SetROP2(R2_COPYPEN);
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
        g.angle=a;
        g.c = GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
   else if(MyDrawStyle==7)
    {
        //pdc->SelectObject(&newBrush);
        CBrush bsh;
        bsh.CreateSolidBrush(GP.pencolor);
        pdc->SetROP2(R2_COPYPEN);
        pdc->SelectObject(&bsh);
        pdc->RoundRect(MyStart.x,MyStart.y,MyEnd.x,MyEnd.y,a.x,a.y);
        g.angle=a;
        g.c = GP.pencolor;
        b=false;//Release drawing relationship
        CView::OnLButtonUp(nFlags, point);
    }
     GetDocument()->Mylist.AddTail(g);//Save information
     Invalidate();
}

The above code also embeds the contents of the brush and the brush. Once the brush and the brush are defined and created, the drawing will be used between them. So pay attention to the use of the brush and the brush. The difference between the filled drawing and the hollow drawing is whether there is a brush or not.

CBrush bsh;//Define brush
bsh.CreateSolidBrush(GP.pencolor);//Create brush
pdc->SelectObject(&bsh);//Select brush

Use of brush

CPen pen(GP.type, GP.width, GP.pencolor);//Brush definition and creation, three parameters: brush type, brush width and brush color 
pdc->SelectObject(&pen);//Choose a brush

There are also some codes about saving and redrawing the drawing, which will be explained later.

4, File saving and reading -- document serialization

The document class provides the document serialization function, which can write the current state of the object into the hard disk by the value of the member variable, and read the state of the object from the hard disk next time, so as to rebuild the object.

But what are the objects here?

It's a graph, but there are many kinds of graphs. If we define the information of each graph through a structure, there will be many structures to represent different graphs. Here I choose a method to encapsulate all the parameters of graphs, whether unique or common, into a structure, create a chain table for this structure, and repair Change the serialization function!

//To make views and documents aware GPen This structure storing image information needs to be Stdafx.h Add code to
struct GPen//Save brush parameters global variables
{
    int type;//Brush Type 
    int width;//stroke width 
    COLORREF pencolor;//stroke color 
    COLORREF c;
    CPoint start,end;//Starting point of line, rectangle and ellipse
    int style;//Types of drawings
    CPoint angle;//Fillet rectangle angle
};

Add the linked list of Gpen for the Doc class of the document:

CList <GPen,GPen> Mylist;

Serialize function for document class:

void CWkfDrawingDoc::Serialize(CArchive& ar)
{
    int i;
    if (ar.IsStoring())//preservation
    {
        // TODO: Add storage code here
        ar<<Mylist.GetCount();
        GPen g;
        POSITION pos = Mylist.GetHeadPosition();
        for(i = 0; i<Mylist.GetCount(); i++)
        {
            g = Mylist.GetNext(pos);
            ar<<g.type<<g.width<<g.pencolor<<g.c<<g.start<<g.end<<g.style<<g.angle;
        }

    }
    else//read
    {
        // TODO: Add load code here
        int count;
        ar>>count;
        GPen g;
        POSITION pos = Mylist.GetHeadPosition();
        for(i = 0; i<count; i++)
        {
            ar>>g.type>>g.width>>g.pencolor>>g.c>>g.start>>g.end>>g.style>>g.angle;
            Mylist.AddTail(g);
        }
    }
}

There is a redraw function to save the file before opening. Previously, we only drew when the mouse moved and the left mouse button was raised. Now the drawing should be redrawn in OnDraw in the view class. This is the reason why the drawing information needs to be saved to the linked list in the previous left mouse button raised message response function. (when the mouse is raised, the figure is actually drawn.)

GetDocument()->Mylist.AddTail(g);//Save information
Invalidate();

The next line of code is to refresh and execute the OnDraw function.

void CWkfDrawingView::OnDraw(CDC* pDC)//Load file redraw function
{
    int i;
    CWkfDrawingDoc* pDoc = GetDocument();
    pdc=new CClientDC(this);
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;
    GPen g;
    POSITION pos = pDoc->Mylist.GetHeadPosition();
    for(i = 0; i<pDoc -> Mylist.GetCount(); i++)
    {
        g = pDoc -> Mylist.GetNext(pos);
        CPen p(g.type,g.width,g.pencolor);
        pdc->SelectObject(&p);
        pdc->MoveTo(g.start.x,g.start.y);
        if(g.style==1)//Draw a straight line
        {
            pdc->SelectStockObject(NULL_BRUSH);
            pdc->LineTo(g.end.x,g.end.y);
        }
        if(g.style==2)//Draw rectangle
        {
            pdc->SelectStockObject(NULL_BRUSH);
            pdc->Rectangle(g.start.x,g.start.y,g.end.x,g.end.y);
        }
        if(g.style==3)//Draw a circle
        {
            pdc->SelectStockObject(NULL_BRUSH);
            pdc->Ellipse(g.start.x,g.start.y,g.end.x,g.end.y);
        }
        if(g.style==4)//Draw filled rectangle
        {
            CBrush bsh;
            bsh.CreateSolidBrush(g.pencolor);
            pdc->SelectObject(&bsh);
            pdc->Rectangle(g.start.x,g.start.y,g.end.x,g.end.y);
            bsh.DeleteObject();
        }
        if(g.style==5)//Draw fill circle
        {
            CBrush bsh;
            bsh.CreateSolidBrush(g.pencolor);
            pdc->SelectObject(&bsh);
            pdc->Ellipse(g.start.x,g.start.y,g.end.x,g.end.y);
            bsh.DeleteObject();
        }
        if(g.style==6)//round rectangle 
        {
            pdc->SelectStockObject(NULL_BRUSH);
            pdc->RoundRect(g.start.x,g.start.y,g.end.x,g.end.y,g.angle.x,g.angle.y);
        }
        if(g.style==7)//Draw filled rectangle
        {
            CBrush bsh;
            bsh.CreateSolidBrush(g.pencolor);
            pdc->SelectObject(&bsh);
            pdc->RoundRect(g.start.x,g.start.y,g.end.x,g.end.y,g.angle.x,g.angle.y);
            bsh.DeleteObject();
        }
        pdc->SelectObject(OldPen);
    }
}

 

5, Several dialog boxes

The color dialog box and font dialog box are provided by the system. Here I give the message response function of the key. Where MyFont and Pcolor are the two member variables of the view class CFont MyFont COLORREF Pcolor

void CWkfDrawingView::OnFont()//Font settings
{
    CFontDialog dlg;
    if(IDOK==dlg.DoModal())
    {
        if(MyFont.m_hObject)
        {
            MyFont.DeleteObject();
        }
        MyFont.CreateFontIndirect(dlg.m_cf.lpLogFont);//font information
        MyFontName=dlg.m_cf.lpLogFont->lfFaceName;//The name of the font
    }
}
void CWkfDrawingView::OnPancolor()//Brush color settings
{
    CColorDialog dlg(0,CC_FULLOPEN);
    if(dlg.DoModal())
    {
        Pcolor = dlg.GetColor();//Get color information from the color dialog box
        GP.pencolor=Pcolor;
    }
    else if(dlg.DoModal()==IDCANCEL)
    {}
}

For the customized dialog box, there are pen width settings, pen type settings, text input, and the code is as follows:

void CWkfDrawingView::OnTxt()//Text input
{
    // TODO: Add command handler code here
    CTxtlog dlg;
    if(dlg.DoModal()==IDOK)
    {
        int X=dlg.MyX;
        int Y=dlg.MyY;
        CString String=dlg.MyString;
        pdc=new CClientDC(this);//Construction object
        pdc->SetTextColor(GP.pencolor);//Set file color
        pdc->SelectObject(&MyFont);
        pdc->TextOut(X,Y,String);
    }
    else if(dlg.DoModal()==IDCANCEL)
    {}
}

void CWkfDrawingView::OnLineW()//stroke width 
{
    // TODO: Add command handler code here
    CLWidth dlg;
    if(dlg.DoModal()==IDOK)
    {
        GP.width=dlg.width;//Update the width of the brush
        MyWidth=dlg.width;
    }
    else if(dlg.DoModal()==IDCANCEL)
    {}
}
/*
PS_SOLID Solid line
PS_DASH Dotted line
PS_DOT Dotted line
PS_DASHDOT Dotted line
PS_DASHDOTDOT Double dotted line
*/

void CWkfDrawingView::OnSolid()//Line type
{
    // TODO: Add command handler code here
    type=PS_SOLID;
    GP.type=type;
    pdc=new CClientDC(this);
}
void CWkfDrawingView::OnDash()
{
    // TODO: Add command handler code here
    type=PS_DASH;
    GP.type=type;
}
void CWkfDrawingView::OnDot()
{
    // TODO: Add command handler code here
    type=PS_DOT;
    GP.type=type;
}

void CWkfDrawingView::OnDashdot()
{
    // TODO: Add command handler code here
    type=PS_DASHDOT;
    GP.type=type;
}

void CWkfDrawingView::OnDashdotdot()
{
    // TODO: Add command handler code here
    type=PS_DASHDOTDOT;
    GP.type=type;
}

However, for text input and font width settings, you need to get information from the dialog box and save it to variables. This requires exchange functions. Before that, you need to set a dialog box class for the customized dialog box, which is associated with the dialog box resources. All code processing is carried out in the dialog box class. Take text input as an example to add a text input dialog class

#pragma once
// CTxtlog dialog box
class CTxtlog : public CDialog
{
    DECLARE_DYNAMIC(CTxtlog)

public:
    CTxtlog(CWnd* pParent = NULL);   // Standard Constructors 
    virtual ~CTxtlog();

// Dialog data
    enum { IDD = IDD_TEXT };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()
public:
    int MyX;
public:
    int MyY;
public:
    CString MyString;
};

Modify the data exchange function as follows:

void CTxtlog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Text(pDX, ID_TXTX, MyX);
    DDX_Text(pDX, ID_TXTY, MyY);
    DDX_Text(pDX, ID_TXTS, MyString);
}
 

Tags: Windows Programming

Posted on Fri, 26 Jun 2020 23:29:47 -0400 by Janco