bitbucket: C++ MFC ATL WTL Win32 COM ActiveX Samples Tutorials Source Code Controls

WndImage

Download Sample Project

Abstract

CWndImage implements the minimal steps required to display a bitmap. The class is "plug-and-play" for MFC, most of the magic happens in the OnPaint function which should be easy to port to Win32 or ATL. Some features like scaling, cutting and tiling were added on the way, when they were a spinoff of the required implementation (or existing snippets). 

 

Overview

Version 1.2
wndimg256.gif (25394 bytes)

Sample application screenshot

Easy to use:
  1. add a CWndImage m_img member variable to your window class (dialog or whatever)
  2. for dialogs, place a static or a picture control on your dialog resource, and call m_img.CreateFromStatic. For other windows, simply call the m_img.Create
  3. use m_img.SetImg(IDB_BITMAPxxx) or m_img.SetImgFile("C:\\images\\cool.bmp")  anytime.

Features:

  • various stretch modes, tile, custom zoom
  • align left/center/right, top/center/bottom
  • window of source bitmap
  • support for palettized display modes
Download Source 12 K Source + Documentation
Download Sample Project 122 K Sample Project, Documentation, Executable, Sample Images
Download Version 1.1 70 K old version Sample Project + Documentation

Note on the demo: The flicker when resizing is caused by the dialog itself, not by the CWndImage. Avoiding this requires quite some work, so I didn't include it here.

Will not be done: image processing, rotating, shearing. Loading other file formats than BMP. For the latter you can use one of the many libraries to load images into an HBITMAP, and then continue. The class is neither optimized nor intended to handle large images. Using large images on weak hardware will hog the system.

Try it!

  1. add the WndImage.h and wndImage.cpp to your project, #include wndimage.h where you need it
  2. add a static or "picture" control to one of your dialogs. Give it an IDC_ST_IMG control ID.
  3. Add a CWndImage m_img member variable to your dialog class
  4. Add the following lines to OnInitDialog:
    m_img.CreateFromStatic( GetDlgItem(IDC_ST_IMG) );
    Hint: if you use a FormView, put this code into OnInitialUpdate. Thanks to V. Pontes for pointing out.
  5. To select an image, and make it fit,add
    m_img.SetImg(IDB_MYBITMAP);  // specify a valid bitmap resource here
    m_img.SetBltMode(CWndImage::bltFitXY);
  6. Enjoy

 

Documentation

Create BOOL Create(RECT const & r, CWnd * parent, UINT id, DWORD dwStyle = WS_CHILD | WS_VISIBLE)
BOOL CreateFromStatic(CWnd * static)

CreateFromStatic will use a static control's style, position, and ID, and replace it with the wndImage control. If a bitmap was specified for the static control (you nedd to choose 'picture control' in the resource editor for this), this bitmap is displayed in FitXY mode (stretched proportional to fit without clipping).
Not that only window-specific styles (like WS_BORDER) will be visible with the control. Window styles specific to static controls have no effect
Select Image void SetImg(HBITMAP bmp, bool shared = false)
void SetImg(CBitmap * bmp)
bool SetImg(LPCTSTR resID, HINSTANCE instance = 0, bool useDIB = true)  // Load from resource
bool SetImg(UINT resID, HINSTANCE instance = 0, bool useDIB = true)     // Load from resource
bool SetImgFile(LPCTSTR fileName, bool useDIB = true)                   // Load from File

shared: if true, the WndImage control will not DeleteObject() the HBITMAP provided upon destruction. The prototypes 2..5 do not share the bitmap.
instance: if not NULL, specifies the module handle from which to load the bitmap.
useDIB: if true (default), the bitmap is loaded as DIB section. This is necessary for correct palette managment. see the "Palette Issues" for more.
Standard Blit Modes void SetBltMode(int mode)
bltNormal the image is drawn in it's original size a/r
bltStretch the image is stretched to fit the entire window
bltFitX the image is scaled proportional, to horizontally fit the window a/r
bltFitY the image is scaled proportional, to vertically fit the window a/r
bltFitXY the image is scaled proportional to the largest possible size that does not clip the image a/r
bltFitSm the image is scaled proportional so that one coordinate fits the window and the other is clipped
(this mode is good for small views whose aspect ratio differs strongly from the image's a/r)
a/r
bltTile the image is repeated in it's original size to fit the window a/r

Note: the constants must be prefixed with "CWndImage::"
Note: a/r: These modes preserve the image's aspect ratio

Standard Alignment void SetAlign(int alignX, int alignY)
void SetAlignX(int alignX)
void SetAlignY(int alignY)

Valid alignments are: bltLeft, bltTop, bltCenter, bltRight, bltBottom (I hope you can figure out their meaning)

Custom Zoom void SetZoom(double zoomX, double zoomY)
void SetZoom(double zoom)

Sets a zoom factor (1.0 == original size, <1 smaller, >1 larger).
The second prototype sets a proportional zoom with zoomX == zoomY.
Custom Zoom cannot be used together with bltTile mode.
Custom Alignment void SetOrigin(int origX, int origY)
void SetOriginX(int origX)
void SetOriginY(int origY)

Sets the position of the images left upper corner in the window. positive values move the image to the center, negative values move it out of sight.
Custom alignment can be used with tiling, too.
Source Clipping void SetSourceRect(RECT const & r)
void SetSourceRect()

by using  SetSourceRect, you can specify a clipping rectangle for the bitmap. This can be used with all modes. The coordinates are in bitmap pixels. The second prototype restores the setting to the entire bitmap.
When the image is changed (SetImg, SetImgFile), all settings except the Source window are preserved. Source window is reset to the entire image.
Background void SetBackgroundBrush(HBRUSH)
void SetBackgroundBrush(int sysColorIndex)
void SetBackgroundBrush(CBrush & brush)

Sets the brush used to fill background not occupied by the image. For valid sysColorindex values, see GetSysColor Win32 API documentation (e.g. COLOR_WINDOW for default window background color, or COLOR_3DFACE for default dialog background)
Initial color is COLOR_3DFACE
Get Info
int    GetImgSizeX() const int    GetImgSizeY() const
int    GetBltMode() const
double GetZoomX() const double GetZoomY() const
int    GetAlignX() const int    GetAlignY() const
int    GetOriginX() const int    GetOriginY() const

These functions return what they promise. The values are valid in custom and in standard blit or alignment modes.

HBITMAP GetBitmap(bool detach = false)
Returns a handle the bitmap in use. If detach is true, the control will no longer use it.

CRect GetVisibleRect()
Returns the part of the source image that is currently visible. If the Blit Mode is bltTile, an empty rectangle is returned

 

Palette Issues (implemented in Version 1.2)

Correct display at 256 colors turned out to be more than a "quick fix". Well, I learnt a lot about bitmaps, palettes & GDI... Thanks to the codeproject & codeguru site. (I don't quite remember which actual article I used)

Load Bitmap:

For correct display on 256 color, the bitmap must be loaded as DIB section. This is the default (V1.2) for SetImg(resID), SetImg(resName), and SetImgFile.
Otherwise, Windows will map the bitmaps colors already when loading the bitmap, and this can look quite ugly. You can control this by the useDIB parameter in SetImg(File). In the sample, you can play around with the "use DIBSECTION" checkbox.

Capture Palette changes:

The image needs to redisplay after system palette changes. The corresponding message (WM_PALETTECHANGED) is only sent to top level windows, so here's what you have to do:

a) Add a WM_PALETTECHANGED handler to your top level window, and call the m_wndImg.OnAppPaletteChanged() function. This technique is used in the sample.

b) alternatively, you can place the following code in your handler:

// WM_PALETTECHANGED message handler (top level window)
void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd ) 
{
  SendMessageToDescendants(WM_PALETTECHANGED, (WPARAM) pFocusWnd->GetSafeHwnd(), 0);
  CDialog::OnPaletteChanged(pFocusWnd);
}

This will forward the message to all child windows. CWndImage has a handler for this, and other windows should be unharmed.

The following sample images are included:

 


Revision History:

Version 1.2 Correct display in 256 color modes
The signature of some members has changed (SetImg, SetImgFile). An argument with default value was added, so existing code should compile ok. However, the default value changes behaviour 8to the better) - see "Palette issues"
added "GetVisibleRect"
Version 1.1 CreateFromStatic now uses the initial bitmap (if any).



bitbucket c++ site © Peter Hauptmann. Questions & Comments to  cherea@cherea.de
page updated 29/02/04