Solved

Saving View as Bitmap

Posted on 2000-03-29
12
359 Views
Last Modified: 2013-12-03
I want to save my current document view as a .BMP file. The view is a Excel like grid created with 3rd party softare (Dundas). Somehow I want to grab the entire view (including the portion that is scrolled off screen and save that to a file in BMP format.

I've been looking at CDC, GDI, etc but am new new Windows and MFC so am a bit mind boggled.

Certainly this can be done with just a few lines of code, no?

Thanks,
NC
0
Comment
Question by:nchenkin
  • 5
  • 4
  • 2
  • +1
12 Comments
 
LVL 15

Expert Comment

by:Tommy Hui
Comment Utility
Go here for a library that saves images to .BMP files.

http://www.smalleranimals.com/jpegfile.htm

0
 

Expert Comment

by:bertp
Comment Utility
This what I think I would try... This is off-the-top-of-my-head so there may be bugs in my thought processes ;-)
 
 a)   I would temporarily resize the view so that it doesn't need scrolling

 b) copy the client area to a bitmap

  c) resize the window to normal and
     redraw



to resize:
----------------------------------

   you can use GetWindowPlacement() to get orginal position

perhaps you can compute the total size
by expoiting the scroll range of the scroll bar and current size of view?
 
you will probably also need use GetSystemMetrics() for the non-client values you will need when you resize the frame (in order to resize the view) with MoveWindow()

lastly turn off the scroll bar
with ShowScrollBar(FALSE)
--------------------------------------

Create a bitmap....

CreateCompabileDC.. CreateCompatibleBitmap..
BitBlt (ya know, the usual stuff
-----------------------------------

finally restore with SetWindowPlacement and redraw....


HTH

Bert

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Use off-screen drawing (ie draw into a bitmap) anyway and the output the bitmap to a file.

To do offscreen drawing, declare a bitmap member in your view.

Create / Recreate the bitmap in your OnSize call (so that it is always the same size as the view).

Make rename your OnDraw .. call it say OnDrawHelper.

Modify the OnDraw for your to create a DC for that bitmap, and call the OnDrawHelper passing it the DC you just created).  Then, use bitblt to copy it to the real dc.

You now have a bitmap with the view contents, which you can write to a file whenever you want.  With 24bit DIBs, the code to write to a file is not too tricky

NOTE: In your OnDraw, don't use the bitmap member and bitblt business if the DC if printing - just directly call OnDrawHelper passing through the original DC.

I (or other experts) can help with each of these steps.

0
 

Author Comment

by:nchenkin
Comment Utility
Hello all experts,

Thanks for the comments and proposed answer.

I was away from my desk yesterday afternoon and will be gone most of this morning. It looks like RONSLOW's answer will work out but I want to step through it when I have some time later today and then will be back to accept it (hopefully!)

Thanks again,
NC
0
 

Expert Comment

by:bertp
Comment Utility
Hey RONSLOW,
    to include the portion of the view that is scrolled off the screen wouldn't he need to resize the frame to the length of the "total" view?  or was I steering him wrong ;-) ?
0
 

Author Comment

by:nchenkin
Comment Utility
RONSLOW,

Not quite! There are two problems:

1) Goes back to bertp's comment, how do I get the stuff off screen? The cx and cy in OnSize() are only the visible portons of the view.

Here is what I am doing in OnSize()

      if( m_Bitmap.m_hObject != NULL )
         m_Bitmap.DeleteObject();        // get rid of old bitmap

      CClientDC dc(this);
      CDC dcMem;
      dcMem.CreateCompatibleDC(&dc);

      m_Bitmap.CreateCompatibleBitmap( &dc, cx, cy );
      CBitmap* pbmOld = dcMem.SelectObject( &m_Bitmap );
      dcMem.BitBlt( 0, 0, cx, cy, &dc, 0, 0, SRCCOPY );
      dcMem.SelectObject( pbmOld );
      dcMem.DeleteDC();

At this point I can successfully write the file and look at the resulting bitmap in Paint. But it is only the visible portion.

2) The other problem is that what I get is actually just what is onscreen at the time the above code is executed, it really has nothing to do with my view. So, for example, if I put a breakpoint in the above code, the resulting bit map is a lovely image if my development environment.

What am I doing wrong?

Thanks,
NC
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 10

Accepted Solution

by:
RONSLOW earned 200 total points
Comment Utility
nchenkin:

1) you are misunderstanding me.

In the OnSize you simply create a bitmap of the required size.  no bitblt or anything else.  Just make it.

Then in your OnDraw, you draw directly into the bitmap and not onto the screen.  Then blt from the bitmap to the screen.

2) I missed reading your comment about getting the offsecreen parts as well.

In that case, create the bitmap in (say) the oninitialupdate to be the size of your whole document (including offscree bits).  In your OnDraw, draw the whole document into the whole bitmap, then just bit the appropriate part into your view (the part that is visible).
0
 

Author Comment

by:nchenkin
Comment Utility
1) Yes, I misunderstood you. Now I get it (I think). And I see that maybe there is not a "simple" way to do this. I was hoping that Windows had stored an image of the entire view somewhere after it was drawn normally via OnDraw(). Then I could just blt that int a bitmap.

The 3rd party software I'm using makes it tough to just switch DC contexts without changing their source code, or so it seems at first glance.

Oh well...
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Does you code still have an OnDraw function (that calls Dundas code)?

If so, then an on-screen bitmap may well work ok. It should be similar to what happens when you do a print-preview.

If not, and it does all the drawing itself, then you are not in luck.

The only thing you can do is bitblt from the view window to a bitmap (ie. a screen capture).  This just gives you what you can see on the view, and is not really a 'nice' solution .. especially if you want
0
 

Author Comment

by:nchenkin
Comment Utility
RONSLOW,

Thanks much for your further comment.

> Does you code still have an OnDraw function (that calls Dundas code)?

Well, it does but indirectly. Their documentation recommended using a call to MoveWindow() in the OnSize() handler to update the screen. My app is getting data from remote embedded controllers and I am painting the screen periodically via a timer and the using pDoc->UpdateAllViews().

Dundas has a bunch of OnPaint() functions for each part of the screen grid (headins, margins, cells, etc) that get the resulting WM_PAINT messages. Inside these OnPaint() they always do:

     CPaintDC dc(this);

and pass this to all the functions that do the drawing, which is my problem, methinks.

Hmm... I've been going back and forth between the code as I write this and now I see they have a double buffer mode that is doing something with a m_bitmap. The bitmap is protected in the base class so my derived class should be able to get at it. Wonder if this is the entire grid or just the onscreen part. I'll dig deeper...

Thanks for now. I'll let you know what I find.

NC
0
 

Author Comment

by:nchenkin
Comment Utility
RONSLOW,

Nope, out of luck. The Dundas bitmap is just the visible portion of the screen, GetClientRect.

I'm trying to avoid creating another function which duplicates redrawing the entire grid into a bitmap, a function that will need maintenance anytime the screen design changes.

So far no luck.

NC
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Don't understand what you mean by "The Dundas bitmap is just the visible portion of the screen, GetClientRect."

What is 'the dundas bitmap' ???

Do you think you could post the OnDraw code for your view here?  And the OnPrepareDc?

These may be in the Dundas code somewhere, or just in your view class.  Either way, that might give me a clue as to what to suggest.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
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.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

744 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now