Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Create Bitmap of a Dialog that is not in view

Posted on 2003-11-28
9
Medium Priority
?
659 Views
Last Modified: 2013-11-20

This is a similar question to "bitmap of a window"  09/18/2001, but this question was not answered fully and a refund of points was issued.  I don't think it is particulalry difficult for an expert, but I need to solve it urgently.

I am drawing graphs in a dialog box, and can save these to a bitmap file.

However, my application can run in batch mode, so when I do this automatically I end up saving a bitmap of the topmost window rather than of the dialog which is drawing itself in the background.

I think the solution has something to do with using CMetaFileDC, but am out of my depth on this.

What I am looking for is some example code that will do this.  Here (below) is the code I am using at the moment, which works fine for saving the dialog when it is in view.

Thank you in advance for any help on this.

Richard


bool CGraph::SaveBitmap()
{

      CLiftsimDoc* pDoc=CLiftsimDoc::GetDoc();

      CString FileName= pDoc->m_ResultsFile.GetFileName() + "_" + GetGraphID() + ".bmp";

      int x, y,W,H;

    CRect rect;
    GetClientRect(&rect);

      CPoint pt=rect.TopLeft();
      x=pt.x;
      y=pt.y+3*nTH;
      W=rect.Width();
      H=rect.Height()-3*nTH;

      CDC* pDC;
      CDC tDC;
      HBITMAP Bitmap, oBitmap;

      pDC=GetDC();
      tDC.CreateCompatibleDC(pDC);

      Bitmap=CreateCompatibleBitmap(pDC->m_hDC, W, H);

      oBitmap=(HBITMAP )SelectObject(tDC.m_hDC, Bitmap);
      tDC.BitBlt(0, 0, W, H, pDC, x, y, SRCCOPY);

      SelectObject(tDC.m_hDC, oBitmap);
      ReleaseDC(pDC);

      bool success;
    CFile file(FileName.GetBuffer(0), CFile::modeCreate|CFile::modeWrite);
    CDIBitmap DIBitmap;
    success=DIBitmap.AssignDDP(Bitmap);
      if (!success) return (false);
    success=DIBitmap.Save(file);
      if (!success) return (false);
    file.Close();

      return(true);
}

 
0
Comment
Question by:richardpeters
  • 4
  • 4
9 Comments
 
LVL 13

Expert Comment

by:SteH
ID: 9837291
The window is only repainted when in foreground. I am not sure whether the following lines will bring it to the foreground but at least they repaint it.

Invalidate ();
UpdateWindow ();

You then only need to wait for the paint to finish before using the client DC. Another way would be to use something similar as OnPaint but to draw into the given DC. This could be done using the Print command.

0
 

Author Comment

by:richardpeters
ID: 9837564
Hi

Invalidate ();
UpdateWindow ();

Does not bring the dialog to the foreground.  It is my understanding that Windows does not allow an application in the background to bring itself to the top (although in the old days 16 bit Windows did).  You can only bring something to the top within your own application.  Actaully I would prefer for it all to happen in the background anyway, rather than interrupt the user.

So, I have to draw somewhere which is not currently visible.

Richard


0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 9837581
You have a DC in memory, compatible with your screen DC and the size you want.
Now draw your graph into that memory DC (as you do normally to screen).  You should then be able to save to file.

eg Have a graph drawing function DrawGraph(CDC* pDC) so you just plug in the screenDC when drawing to the dialog and this memoryDC when you want to save.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:richardpeters
ID: 9837951
Yes, this seems a good approach.  But I think I am using the memoryDC wrong as I am still getting a bitmap of the other application window on top.  Here is my code below.

Richard


CDC* pDC;
pDC=GetDC();

if (m_Mode==MAKE_BITMAPS)
{
      CMetaFileDC * pMDC = new CMetaFileDC();
      pMDC->CreateCompatibleDC(pDC);
      PlotCurrentGraph(pMDC);
}
else
{
      PlotCurrentGraph(pDC);
}

0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 9838308
Use a CDC instead of a CMetaFileDC.
Does it work now?
0
 

Author Comment

by:richardpeters
ID: 9838571
Actually, it was capturing the top screen because, even though I was passing pDC to SaveBitmap, I had forgot to delete the line pDC=GetDC();  Sorry.

Now,

     CMetaFileDC * pMDC = new CMetaFileDC();
     pMDC->CreateCompatibleDC(pDC);
     PlotCurrentGraph(pMDC);

gives me a bitmap that is all back.  And I get the same if I subsitute CDC for CMetaFileDC.

All this is still happenning within the dialog box class.  So, I am still firing up a DoModal() even when I am in make_bitmap mode.  Perhaps the dialog is the problem, and I need to plot the graphs from within my CScrollView?

Richard
0
 
LVL 45

Accepted Solution

by:
AndyAinscow earned 2000 total points
ID: 9839219
If you mean you draw the graph on screen (without dialog) then it would be sensible to do that.
Does PlotCurrentGraph work and display the graph to screen?  If it does then it should also work when drawing to the bitmap.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 9839302
This is something I answered another question re drawing to bitmaps some time ago

/*Also in the OnInitialUpdate I did 3 different coloured pens to help see the lines you draw
     m_mainLine.CreatePen(PS_INSIDEFRAME, 2, RGB(192,0,0));
     m_mediumLine.CreatePen(PS_INSIDEFRAME,1, RGB(0,0,192));
     m_interLine.CreatePen(PS_DOT, 1, RGB(0,192,0));
*/

#define WIN_HEIGHT 400
#define WIN_WIDTH 300

void CMyView::OnDraw(CDC* pDC)
{
     CRect rect;
     GetClientRect(rect);

    pDC->SetMapMode(MM_ANISOTROPIC);    
     pDC->SetWindowExt(WIN_WIDTH, WIN_HEIGHT);
     pDC->SetViewportExt(rect.Width(), rect.Height());
     pDC->SetViewportOrg(0, 0);


    CBitmap bitmap;
     CBitmap* pOldBitmap;
    CDC* pMemDC = pDC;
     bool bUseSepMemDC = true;     //set to false to see effect in drawing direct to DC
     if(bUseSepMemDC)
     {
         pMemDC = new CDC;
          pMemDC->CreateCompatibleDC(pDC);
          pMemDC->SetMapMode(pDC->GetMapMode());
          pMemDC->SetWindowExt(pDC->GetWindowExt());
          pMemDC->SetWindowOrg(pDC->GetWindowOrg());
          pMemDC->SetViewportExt(pDC->GetViewportExt());
          pMemDC->SetViewportOrg(pDC->GetViewportOrg());

          bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
          pOldBitmap = pMemDC->SelectObject(&bitmap);
     }

    pMemDC->FillRect(CRect(0, 0, WIN_WIDTH, WIN_HEIGHT), &m_Brush);

     int iMax = ((m_nYWinOrg < WIN_HEIGHT) ? m_nYWinOrg : WIN_HEIGHT);
     int iOffset = 0;
     if(m_nYWinOrg > WIN_HEIGHT)
          iOffset = (m_nYWinOrg - WIN_HEIGHT) % 80;

     for(int j, i = 0; i <= iMax; i+=2)
     {
          bool bDraw = false;
          j = i - iOffset;
          if(j % 80 == 0)
          {
               bDraw = true;
               pMemDC->SelectObject(m_mainLine);
          }
          else if(j % 40 == 0)
          {
               bDraw = true;
               pMemDC->SelectObject(m_mediumLine);
          }
          else if(j % 8 == 0)
          {
               bDraw = true;
               pMemDC->SelectObject(m_interLine);
          }
          if(bDraw)
          {
               pMemDC->MoveTo(0,i);pMemDC->LineTo(WIN_WIDTH / 3, i);
               pMemDC->MoveTo(WIN_WIDTH - (WIN_WIDTH / 3),i);pMemDC->LineTo(WIN_WIDTH, i);
          }
     }


     if(bUseSepMemDC)
     {
          pDC->BitBlt(0,0, WIN_WIDTH, WIN_HEIGHT, pMemDC, 0, 0, SRCCOPY);
          pMemDC->SelectObject(pOldBitmap);
          delete pMemDC;
     }
}

Maybe that could help you?
0
 

Author Comment

by:richardpeters
ID: 9840526
Just for the record, the accepted answer gave me the clue to make my code work.

"Does PlotCurrentGraph work and display the graph to screen?  If it does then it should also work when drawing to the bitmap."

Yes, it was displaying to the screen.  But in the save bitmap mode I was drawing on the CMetaFileDC rather than the bitmap.  I am still doing this all within my dialog class.  Anyway, my working code was....

bool CGraph::SaveBitmap(CDC* pDC)
{

      CLiftsimDoc* pDoc=CLiftsimDoc::GetDoc();

      CString FileName= pDoc->m_ResultsFile.GetFileName() + "_" + GetGraphID() + ".bmp";

      int x, y,W,H;

    CRect rect;
    GetClientRect(&rect);

      CPoint pt=rect.TopLeft();
      x=pt.x;
      y=pt.y+3*nTH;
      W=rect.Width();
      H=rect.Height()-3*nTH;

      CDC tDC;
      HBITMAP Bitmap, oBitmap;
      tDC.CreateCompatibleDC(pDC);
      Bitmap=CreateCompatibleBitmap(pDC->m_hDC, W, H);
      oBitmap=(HBITMAP )SelectObject(tDC.m_hDC, Bitmap);
      tDC.FillRect(rect,&WhiteBrush);

      //*******
      PlotCurrentGraph(&tDC);
      //*******

      tDC.BitBlt(0, 0, W, H, pDC, x, y, SRCCOPY);
      SelectObject(tDC.m_hDC, oBitmap);

      bool success;
    CFile file(FileName.GetBuffer(0), CFile::modeCreate|CFile::modeWrite);
    CDIBitmap DIBitmap;
    success=DIBitmap.AssignDDP(Bitmap);
      if (!success) return (false);
    success=DIBitmap.Save(file);
      if (!success) return (false);
    file.Close();

      return(true);
}



Thank you for your help.  10 out of 10.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Screencast - Getting to Know the Pipeline
Suggested Courses

782 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question