Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 480065
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T00:51:19+00:00 2026-05-13T00:51:19+00:00

Im using GDI+ in C++ to draw a chart control. I want to know

  • 0

Im using GDI+ in C++ to draw a chart control. I want to know if there is any performance difference between the above 2 functions. I am not lazy to write code for DrawLines() but it is that doing so makes my code complex. So im weighin the chances of whether to make code execution faster at the expense of reducing readability and potentially increasing errors and bugs.

Any help wud be appreciated.
Eraj.

  • 1 1 Answer
  • 1 View
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T00:51:19+00:00Added an answer on May 13, 2026 at 12:51 am

    There shouldn’t be a significant difference between the two for most drawing activities, but to be sure, I wrote up a test project to compare the difference between them (well, actually 3 of them).

    For a very large number of lines (x25000) on my machine, DrawLines() (640ms) was about 50% faster over DrawLine() (420ms). To be honest here, I also misread the question the first time around and wrote my initial test in C#. Performance was about the same between the two, which is to be expected as .NET Graphics are based upon GDI+.

    Just out of curiosity, I tried regular GDI, which I expect would be faster. Using the win32 PolyLine() (530ms) function was about 20% faster, with 45000 lines. This is 116% faster than using GDI+ DrawLines(). Even more stunning, perhaps, is that using win32 LineTo() instead of GDI+ DrawLine() results in times under 125ms. With an assumed time of 125ms and 45000 lines, this method is at least 800% faster. (Timer resolution and thread timing make it difficult to measure performance in this threshold without resorting to QueryPerformanceCounter and other timing methods of higher frequency.)

    However, I should caution against making the assumption that this is a significant bottleneck in drawing code. Many of the performance improvements that can be made will have nothing to do with what objects have to be drawn. I would guess that your requirements will probably dictate that a few hundred items may need to be drawn in normal operation for your control. In that case, I would recommend you write your drawing code to be as straightforward and bug-free as you can, as debugging drawing issues can be an expensive use of time and potentially less beneficial as improving the rest of your control or your application.

    Also, if you need to actively update thousands of items, you will see much higher performance gains by moving to a back-buffered solution. This should also make it easier to develop code to draw your control, aside from managing the off-screen buffer.

    Here are my source code examples. Each of them handles mouse clicks to alternate between using bulk drawing versus itemized drawing.

    GDI+, hosted in a barebones MFC SDI App

    This assumes that someone has already declared GDI+ headers and written code to initialize/teardown GDI+.

    In ChildView.h

    // Attributes
    public:
      bool m_bCompositeMode;
    
    // Operations
    public:
      void RedrawScene(Graphics &g, int lineCount, int width, int height);
      PointF *CreatePoints(int lineCount, int width, int height);
      void ReportTime(Graphics &g, int lineCount, DWORD tickSpan);
    
    public:
      afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    

    In ChildView.cpp, added to PreCreateWindow()

    m_bCompositeMode = false;

    Remainder of ChildView.cpp, including OnPaint() and Message Map changes.

    BEGIN_MESSAGE_MAP(CChildView, CWnd)
      ON_WM_PAINT()
      ON_WM_LBUTTONUP()
    END_MESSAGE_MAP()
    
    void CChildView::OnPaint() 
    {
      CPaintDC dc(this); // device context for painting
      RECT rcClient;
      ::GetClientRect(this->GetSafeHwnd(), &rcClient);
    
      Graphics g(dc.GetSafeHdc());
      g.Clear(Color(0, 0, 0));
    
      RedrawScene(g, 25000, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
    }
    
    void CChildView::RedrawScene(Graphics &g, int lineCount, int width, int height)
    {
      DWORD tickStart = 0;
      DWORD tickEnd = 0;
    
        Pen p(Color(0, 0, 0x7F));
        PointF *pts = CreatePoints(lineCount, width, height);
        tickStart = GetTickCount();
        if (m_bCompositeMode)
        {
            g.DrawLines(&p, pts, lineCount);
        }
        else
        {
            int i = 0;
            int imax = lineCount - 1;
            for (i = 0; i < imax; i++)
            {
                g.DrawLine(&p, pts[i], pts[i + 1]);
            }
        }
        tickEnd = GetTickCount();
      delete[] pts;
        ReportTime(g, lineCount, tickEnd - tickStart);
    }
    
    void CChildView::ReportTime(Graphics &g, int lineCount, DWORD tickSpan)
    {
      CString strDisp;
      if(m_bCompositeMode)
      {
        strDisp.Format(_T("Graphics::DrawLines(Pen *, PointF *, INT) x%d took %dms"), lineCount, tickSpan);
      }
      else
      {
        strDisp.Format(_T("Graphics::DrawLine(Pen *, PointF, PointF) x%d took %dms"), lineCount, tickSpan);
      }
    
        // Note: sloppy, but simple.
      Font font(L"Arial", 14.0f);
      PointF ptOrigin(0.0f, 0.0f);
      SolidBrush br(Color(255, 255, 255));
        Status s = g.DrawString(strDisp, -1, &font, ptOrigin, &br);
    }
    
    PointF* CChildView::CreatePoints(int lineCount, int width, int height)
    {
      if(lineCount <= 0)
      {
        PointF *ptEmpty = new PointF[2];
        ptEmpty[0].X = 0;
        ptEmpty[0].Y = 0;
        ptEmpty[1].X = 0;
        ptEmpty[1].Y = 0;
        return ptEmpty;
      }
    
      PointF *pts = new PointF[lineCount + 1];
      int i = 1;
      while(i < lineCount)
      {
        pts[i].X = (float)(rand() % width);
        pts[i].Y = (float)(rand() % height);
        i++;
      }
      return pts;
    }
    
    void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
    {
      m_bCompositeMode = !m_bCompositeMode;
      this->Invalidate();
    
      CWnd::OnLButtonUp(nFlags, point);
    }
    

    C#.NET, hosted in a basebones WinForms App, with default class Form1

    Set a default size for the form, equal to the size of the MFC version if you are comparing the two. A size-change handler could be added as well.

    public Form1()
    {
        InitializeComponent();
        bCompositeMode = false;
    }
    
    bool bCompositeMode;
    
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.Clear(Color.Black);
        RedrawScene(e.Graphics, 25000, this.ClientRectangle.Width, this.ClientRectangle.Height);
    }
    
    private void RedrawScene(Graphics g, int lineCount, int width, int height)
    {
        DateTime dtStart = DateTime.MinValue;
        DateTime dtEnd = DateTime.MinValue;
        using (Pen p = new Pen(Color.Navy))
        {
            Point[] pts = CreatePoints(lineCount, width, height);
            dtStart = DateTime.Now;
            if (bCompositeMode)
            {
                g.DrawLines(p, pts);
            }
            else
            {
                int i = 0;
                int imax = pts.Length - 1;
                for (i = 0; i < imax; i++)
                {
                    g.DrawLine(p, pts[i], pts[i + 1]);
                }
            }
            dtEnd = DateTime.Now;
        }
        ReportTime(g, lineCount, dtEnd - dtStart);
    }
    
    private void ReportTime(Graphics g, int lineCount, TimeSpan ts)
    {
        string strDisp = null;
        if (bCompositeMode)
        {
            strDisp = string.Format("DrawLines(Pen, Point[]) x{0} took {1}ms", lineCount, ts.Milliseconds);
        }
        else
        {
            strDisp = string.Format("DrawLine(Pen, Point, Point) x{0} took {1}ms", lineCount, ts.Milliseconds);
        }
    
        // Note: sloppy, but simple.
        using (Font font = new Font(FontFamily.GenericSansSerif, 14.0f, FontStyle.Regular))
        {
            g.DrawString(strDisp, font, Brushes.White, 0.0f, 0.0f);
        }
    }
    
    private Point[] CreatePoints(int count, int width, int height)
    {
        Random rnd = new Random();
        if (count <= 0) { return new Point[] { new Point(0,0), new Point(0,0)}; }
        Point[] pts = new Point[count + 1];
        pts[0] = new Point(0, 0);
        int i = 1;
        while (i <= count)
        {
            pts[i] = new Point(rnd.Next(width), rnd.Next(height));
            i++;
        }
        return pts;
    }
    
    private void Form1_Click(object sender, EventArgs e)
    {
        bCompositeMode = !bCompositeMode;
        Invalidate();
    }
    

    Regular GDI, hosted in a barebones MFC SDI App

    In ChildView.h

    // Attributes
    public:
      bool m_bCompositeMode;
    
    // Operations
    public:
      void RedrawScene(HDC hdc, int lineCount, int width, int height);
      POINT *CreatePoints(int lineCount, int width, int height);
      void ReportTime(HDC hdc, int lineCount, DWORD tickSpan);
    
    public:
      afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    

    In ChildView.cpp

    Update PreCreateWindow() just as in the GDI+ sample.

    BEGIN_MESSAGE_MAP(CChildView, CWnd)
      ON_WM_PAINT()
      ON_WM_LBUTTONUP()
    END_MESSAGE_MAP()
    
    void CChildView::OnPaint() 
    {
      CPaintDC dc(this); // device context for painting
      HDC hdc = dc.GetSafeHdc();
    
      HBRUSH brClear = (HBRUSH)::GetStockObject(BLACK_BRUSH);
      RECT rcClient;
      ::GetClientRect(this->m_hWnd, &rcClient);
      ::FillRect(hdc, &rcClient, brClear);
      ::DeleteObject(brClear);
    
      RedrawScene(hdc, 45000, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
    }
    
    void CChildView::RedrawScene(HDC hdc, int lineCount, int width, int height)
    {
      DWORD tickStart = 0;
      DWORD tickEnd = 0;
    
      HPEN p = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0x7F));
      POINT *pts = CreatePoints(lineCount, width, height);
      HGDIOBJ prevPen = SelectObject(hdc, p);
      tickStart = GetTickCount();
      if(m_bCompositeMode)
      {
        ::Polyline(hdc, pts, lineCount);
      }
      else
      {
        ::MoveToEx(hdc, pts[0].x, pts[0].y, &(pts[0]));
        int i = 0;
        int imax = lineCount;
        for(i = 1; i < imax; i++)
        {
          ::LineTo(hdc, pts[i].x, pts[i].y);
        }
      }
      tickEnd = GetTickCount();
      ::SelectObject(hdc, prevPen);
      delete pts;
      ::DeleteObject(p);
    
      ReportTime(hdc, lineCount, tickEnd - tickStart);
    }
    
    POINT *CChildView::CreatePoints(int lineCount, int width, int height)
    {
      if(lineCount <= 0)
      {
        POINT *ptEmpty = new POINT[2];
        memset(&ptEmpty, 0, sizeof(POINT) * 2);
        return ptEmpty;
      }
    
      POINT *pts = new POINT[lineCount + 1];
      int i = 1;
      while(i < lineCount)
      {
        pts[i].x = rand() % width;
        pts[i].y = rand() % height;
        i++;
      }
      return pts;
    }
    
    void CChildView::ReportTime(HDC hdc, int lineCount, DWORD tickSpan)
    {
      CString strDisp;
      if(m_bCompositeMode)
      {
        strDisp.Format(_T("PolyLine(HDC, POINT *, int) x%d took %dms"), lineCount, tickSpan);
      }
      else
      {
        strDisp.Format(_T("LineTo(HDC, HPEN, int, int) x%d took %dms"), lineCount, tickSpan);
      }
    
      HFONT font = (HFONT)::GetStockObject(SYSTEM_FONT);
      HFONT fontPrev = (HFONT)::SelectObject(hdc, font);
    
      RECT rcClient;
      ::GetClientRect(this->m_hWnd, &rcClient);
      ::ExtTextOut(hdc, 0, 0, ETO_CLIPPED, &rcClient, strDisp.GetString(), strDisp.GetLength(), NULL);
      ::SelectObject(hdc, fontPrev);
      ::DeleteObject(font);
    }
    
    void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
    {
      m_bCompositeMode = !m_bCompositeMode;
      this->Invalidate();
    
      CWnd::OnLButtonUp(nFlags, point);
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am using gdi c++, StretchDIBits function sometimes failed if I draw large Images
I'm using the RoundRect GDI function to draw a rounded rectangle following this example:
I'm using directx to draw my string, directx uses GDI to draw the string..
I have winform with a TextBox and I want to draw some GDI graphics
I'm attempting to display some text in my program using (say) Windows GDI and
I'm attempting to display some text in my program using (say) Windows GDI and
I noticed using task manager that the following code has a GDI leak in
Using online interfaces to a version control system is a nice way to have
Using ASP.NET MVC there are situations (such as form submission) that may require a
Using TortoiseSVN against VisualSVN I delete a source file that I should not have

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.