使用多色GDI C ++绘制线条

时间:2014-03-28 16:35:14

标签: c++ gdi

#include <windows.h>
#include <iostream>

using namespace std;

#define ID_DDA 9001
#define ID_MID 9002
#define ID_UNDO 9003
#define ID_REDO 9004

HPEN hPen;
PAINTSTRUCT ps ;
int firstX , firstY , lastX , lastY;
int numClicks = 0;

class algo
{
    HWND hwnd;
    int algorithm;
    int x,y,size,sizeRemoved;
    int *x1Data;
    int *y1Data;
    int *x2Data;
    int *y2Data;
    int *x1Removed;
    int *y1Removed;
    int *x2Removed;
    int *y2Removed;

    void Draw()
    {
        for (int i=0;i<size;i++)
        {
            if (algorithm == 0)
            {
                BeginPaint(hwnd , &ps );
                hPen = CreatePen(PS_SOLID,3,RGB(0,0,255));
                SelectObject(ps.hdc, hPen);
                MoveToEx(ps.hdc, x1Data[i], y1Data[i], NULL);
                LineTo(ps.hdc, x2Data[i], y2Data[i]);
                EndPaint(hwnd , & ps);
            }

            else
            {
                BeginPaint(hwnd , &ps );
                hPen = CreatePen(PS_SOLID,3,RGB(255,0,0));
                SelectObject(ps.hdc, hPen);
                MoveToEx(ps.hdc, x1Data[i], y1Data[i], NULL);
                LineTo(ps.hdc, x2Data[i], y2Data[i]);
                EndPaint(hwnd , & ps);
            }   
        }
    }

    public:

    algo(HWND hwnd)
    {
        this->hwnd = hwnd;
        x1Data = new int [1];
        y1Data = new int [1];
        x2Data = new int [1];
        y2Data = new int [1];
        x1Removed = new int [1];
        y1Removed = new int [1];
        x2Removed = new int [1];
        y2Removed = new int [1];
        size=0;
        sizeRemoved=0;
        algorithm = 0;
    }

    void setHWND (HWND hwnd)
    {
        this->hwnd = hwnd;
    }   

    void ChangeAlgo(int num)
    {
        algorithm = num;

        size = 0;
        sizeRemoved = 0;

        int * tempx1 = new int [1];
        int * tempy1 = new int [1];
        int * tempx2 = new int [1];
        int * tempy2 = new int [1];
        int * tx1 = new int [1];
        int * ty1 = new int [1];
        int * tx2 = new int [1];
        int * ty2 = new int [1];

        x1Data = tempx1;
        y1Data = tempy1;
        x2Data = tempx2;
        y2Data = tempy2;

        x1Removed = tx1;
        y1Removed = ty1;
        x2Removed = tx2;
        y2Removed = ty2;
    }

    int getAlgo ()
    {
        return algorithm;
    }

    void undo ()
    {   
        x1Removed[sizeRemoved] = x1Data[size];
        y1Removed[sizeRemoved] = y1Data[size];
        x2Removed[sizeRemoved] = x2Data[size];
        y2Removed[sizeRemoved] = y2Data[size];

        sizeRemoved++;

        int * tempx1 = new int [size];
        int * tempy1 = new int [size];
        int * tempx2 = new int [size];
        int * tempy2 = new int [size];

        for (int i=0;i<size;i++)
        {
            tempx1[i] = x1Data[i];
            tempy1[i] = y1Data[i];
            tempx2[i] = x2Data[i];
            tempy2[i] = y2Data[i];
        }

        x1Data = tempx1;
        y1Data = tempy1;
        x2Data = tempx2;
        y2Data = tempy2;
        size--;

        int * tx1 = new int [sizeRemoved + 1];
        int * ty1 = new int [sizeRemoved + 1];
        int * tx2 = new int [sizeRemoved + 1];
        int * ty2 = new int [sizeRemoved + 1];

        for (int i=0;i<sizeRemoved;i++)
        {
            tx1[i] = x1Removed[i];
            ty1[i] = y1Removed[i];
            tx2[i] = x2Removed[i];
            ty2[i] = y2Removed[i];
        }

        x1Removed = tx1;
        y1Removed = ty1;
        x2Removed = tx2;
        y2Removed = ty2;

        Draw();
    }

    void redo ()
    {
        x1Data[size] = x1Removed[sizeRemoved - 1];
        y1Data[size] = y1Removed[sizeRemoved - 1];
        x2Data[size] = x2Removed[sizeRemoved - 1];
        y2Data[size] = y2Removed[sizeRemoved - 1];
        size++;
        int * tempx1 = new int [size+1];
        int * tempy1 = new int [size+1];
        int * tempx2 = new int [size+1];
        int * tempy2 = new int [size+1];

        for (int i=0;i<size;i++)
        {
            tempx1[i] = x1Data[i];
            tempy1[i] = y1Data[i];
            tempx2[i] = x2Data[i];
            tempy2[i] = y2Data[i];
        }

        tempx1 = x1Data;
        tempy1 = y1Data;
        tempx2 = x2Data;
        tempy2 = y2Data;

        int * tx1 = new int [sizeRemoved];
        int * ty1 = new int [sizeRemoved];
        int * tx2 = new int [sizeRemoved];
        int * ty2 = new int [sizeRemoved];


        for (int i=0;i<sizeRemoved;i++)
        {
            tx1[i] = x1Removed[i];
            ty1[i] = y1Removed[i];
            tx2[i] = x2Removed[i];
            ty2[i] = y2Removed[i];
        }

        sizeRemoved--;

        x1Removed = tx1;
        y1Removed = ty1;
        x2Removed = tx2;
        y2Removed = ty2;

        Draw();


    }

    void Draw (int x1, int y1 , int x2 , int y2)
    {
        BeginPaint(hwnd , &ps );
        for (int i=0;i<size;i++)
        {
            if (algorithm == 0)
            {
                hPen = CreatePen(PS_SOLID,3,RGB(0,0,255));
                SelectObject(ps.hdc, hPen);
                MoveToEx(ps.hdc, x1Data[i], y1Data[i], NULL);
                LineTo(ps.hdc, x2Data[i], y2Data[i]);
            }

            else
            {
                //BeginPaint(hwnd , &ps );
                hPen = CreatePen(PS_SOLID,3,RGB(255,0,0));
                SelectObject(ps.hdc, hPen);
                MoveToEx(ps.hdc, x1Data[i], y1Data[i], NULL);
                LineTo(ps.hdc, x2Data[i], y2Data[i]);
                //EndPaint(hwnd , & ps);
            }   
        }

        if (algorithm == 0)
        {
            //BeginPaint(hwnd , &ps );
            hPen = CreatePen(PS_SOLID,3,RGB(0,0,255));
            SelectObject(ps.hdc, hPen);
            MoveToEx(ps.hdc, x1, y1, NULL);
            LineTo(ps.hdc, x2, y2);
            //EndPaint(hwnd , & ps);
        }

        else
        {
            //BeginPaint(hwnd , &ps );
            hPen = CreatePen(PS_SOLID,3,RGB(255,0,0));
            SelectObject(ps.hdc, hPen);
            MoveToEx(ps.hdc, x1, y1, NULL);
            LineTo(ps.hdc, x2, y2);
            //EndPaint(hwnd , & ps);
        }
        EndPaint(hwnd , & ps);

        x1Data[size] = x1;
        y1Data[size] = y1;
        x2Data[size] = x2;
        y2Data[size] = y2;
        size++;
        int * tempx1 = new int [size+1];
        int * tempy1 = new int [size+1];
        int * tempx2 = new int [size+1];
        int * tempy2 = new int [size+1];

        for (int i=0;i<size;i++)
        {
            tempx1[i] = x1Data[i];
            tempy1[i] = y1Data[i];
            tempx2[i] = x2Data[i];
            tempy2[i] = y2Data[i];
        }

        tempx1 = x1Data;
        tempy1 = y1Data;
        tempx2 = x2Data;
        tempy2 = y2Data;

    }
};

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Graphics",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    algo Object(hwnd);
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
        {
            HMENU hMenu, hSubMenu;

            hMenu = CreateMenu();

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_DDA, "DDA");
            AppendMenu(hSubMenu, MF_STRING, ID_MID, "Mid-Point");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, "Algorithm");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_UNDO, "Undo");
            AppendMenu(hSubMenu, MF_STRING, ID_REDO, "Redo");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, "Edit");

            SetMenu(hwnd, hMenu);
        }
        break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_DDA:
                    Object.ChangeAlgo(0);
                    LPCSTR name;
                    if (Object.getAlgo() == 0)
                    {
                        name = "DDA";
                    }
                     MessageBox(hwnd, name, "Algorithm Changed", MB_OK);
                break;
                case ID_MID:
                    Object.ChangeAlgo(1);
                    if (Object.getAlgo() == 1)
                    {
                        name = "Mid-point";
                    }
                    MessageBox(hwnd, name, "Algorithm Changed", MB_OK);
                break;
            }
        break;

        case WM_LBUTTONDOWN : 
        {
            int XPos  = LOWORD(lParam);
            int YPos = HIWORD(lParam);
            if(numClicks == 0)
            {
                firstX = XPos ;
                firstY = YPos ;
                numClicks++;

            }
            else if(numClicks == 1)
            {
                lastX = XPos ;
                lastY = YPos ;
                numClicks = 0;
                InvalidateRect(hwnd , NULL , true );
                Object.Draw(firstX , firstY , lastX , lastY);
                Object.setHWND(hwnd);

            }
            break ;
        }

        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

现在,我正在做代码绘制线,如果我选择DDA它将用蓝色笔绘制它,如果我选择中点它将用红线绘制

并且根据变量算法,算法变量的问题发生了变化,但是线颜色没有改变,代码中的某些东西是不逻辑但我无法检测到它。

任何帮助?

1 个答案:

答案 0 :(得分:2)

每次将消息分派到窗口过程时,您都会创建一个新的algo实例。一旦窗口过程返回,就会丢弃对响应用户事件的算法的任何更改。

还有其他各种问题:

  • 您永远不会释放您分配的int数组,并且在现代C ++中通常不需要手动分配内存(直接使用new[])。请尝试使用std::vector<int>代替。
  • 您的if (algorithm == 0)else块看起来几乎相同。复制代码很糟糕。
  • 您创建一个新笔(并且从不释放它)并在每次迭代时调用BeginPaint / EndPaint。这很慢并且泄漏了GDI资源。