GDI+ drawing speed within MFC dialog (help)

D

David Bilsby

Hi
I need to draw a raw data plot into a framed area of a bigger MFC
dialog window. The code I am updating used to use DirectDraw, but as of
the latest DirectX 9 this functionality seems to have been obsoleted
(all documentation regarding the functions within MSDN have been moved
to an archive status).

Therefore I decided to use GDI+. Before doing so I looked into the
performance of the system and found a useful set of benchmark programs
at http://www.codeproject.com/vcpp/gdiplus/gdiplusspeed.asp
From these I concluded that the initial draw speed via a cached bitmap
was sufficient for my data update rate, and the exposure redraw rate was
also excellent.

With that I added the code to my project which was an MFC based dialog
window. I created a simple static frame as the container for the GDI+
plot and timed the code. The initial draw speed into the cached bitmap
was fine (0.00024s) as was the initial cached bitmap blipt to the dialog
(0.004195s), however the blit rate for the cached bitmap if I dragged
another window over my dialog (and not even over the plot frame) was
dredful (0.315s).

Can anyone help explain why the cached bitmap blit is so slow on a
partial redraw (i.e. drag another window over the main one) and also why
the redraw is called when I don't even expose the plot frame?

The example I followed unfortunately used the WTL and the whole dialog
frame was the drawing surface. For these examples the initial draw was
slower than the exposure due to another window drag, as you would expect.

The code for OnPaint() and others is below.

Any help much appreciated.

David.

void CDataCaptureDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
DrawRawSampleData();

CDialog::OnPaint();
}
}

void CDataCaptureDlg::DrawRawSampleData(void)
{
CStatic *pRawDataFrame;
CRect rawDataFrameRect;
Graphics *pRawGraphics;
LARGE_INTEGER start, stop, freq;
double duration;
int width, height;
static bool redraw = true;
static int count = 0;


QueryPerformanceFrequency(&freq);

QueryPerformanceCounter(&start);

// Get a pointer to the static frame used to contain the raw data plot.
pRawDataFrame = (CStatic *) GetDlgItem(IDC_GRAPHIC_RAW_DATA);

// Get the size rectabgle for this frame.
pRawDataFrame->GetClientRect(rawDataFrameRect);

// Get the width and height.
width = rawDataFrameRect.Width();
height = rawDataFrameRect.Height();

// Create a GDI+ graphics object given the raw data frame window.
pRawGraphics = Graphics::FromHWND(pRawDataFrame->m_hWnd);

// See if we have already allocated an off screen bitmap.
if (m_pRawDataBitmap == NULL)
{
// Create the off screen bitmap that we will draw into.
m_pRawDataBitmap = new Bitmap(width, height, PixelFormat32bppPARGB);

// Create the off screen graphics object associated with the bitmap.
m_pRawDataGraphics = Graphics::FromImage(m_pRawDataBitmap);
}

// Draw the raw sample data into the graphics object associated with the
// off screen bitmap.
if (redraw)
{
DrawRawSampleDataChan(pData, numSamples, m_pRawDataGraphics,
rawDataFrameRect.Width(), rawDataFrameRect.Height(), 0xffff0000);

redraw = false;
}


// See if we have a valid cached bitmap of the off screen bitmap. The
// cached bitmap is basically the same, but optimised for the particular
// display device.
if (m_pCachedRawDataBitmap == NULL)
{
// Create a cached bitmap of the off screen bitmap we draw into.
m_pCachedRawDataBitmap = new CachedBitmap(m_pRawDataBitmap, pRawGraphics);
}

QueryPerformanceCounter(&stop);

duration = ((double) stop.QuadPart - (double) start.QuadPart) /
(double) freq.QuadPart;
TRACE("Upto DrawCachedBitmap %f\n", duration);

// Draw the cached bitmap to the display.
Status status = pRawGraphics->DrawCachedBitmap(m_pCachedRawDataBitmap,
0, 0);
if (status != Ok)
TRACE("Not Ok Status.\n");

QueryPerformanceCounter(&stop);

duration = ((double) stop.QuadPart - (double) start.QuadPart) /
(double) freq.QuadPart;

TRACE("Redrawing %d %f\n", count++, duration);

// Delete the graphics object for the raw data frame.
delete pRawGraphics;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top