Simple BMP Viewer 

Environment: Developed with VC 5. 

This is a sample simple BMP viewer. It only shows the minimum code for loading a BMP from a file and showing it in a window. It does not do everything; I get frustrated trying to figure out how to do something simple using a sample that does everything. In particular, it does not do palettes, which is something that seems to be important, but also seems to be relatively complicated. I am not a graphics expert so I invite an expert to create another article documenting correspondingly simple palette processing and/or printing and print preview processing.

Consistent with the theme of keeping things simple, I will simply describe how to create a sample program and supply relevant code here. You can use this code as a sample for use in your project or use this code and instructions to create a complete working sample.

To create a complete working sample, start by generating an MDI application with a CScrollView view. You might want to de-select the option for printing and print preview. Then:

Use ClassWizard to add processing for ID_FILE_NEW in your application class, but do nothing more with it, since we do not support bitmap creation.

Use ClassWizard to add processing for DeleteContents in your document class and add the following to it:

if (m_Bitmap.m_hObject != NULL)

m_Bitmap.DeleteObject();

Use ClassWizard to add processing for OnOpenDocument in your document class and replace all the generated code with the following:

if (IsModified())

TRACE0("Warning: OnOpenDocument replaces an unsaved document\n");

DeleteContents();

BeginWaitCursor();

HBITMAP hImage = (HBITMAP)LoadImage(NULL, lpszPathName, IMAGE_BITMAP,

0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);

EndWaitCursor();

if (!hImage) {

DWORD LastError = GetLastError();

// Error message should be fomatted with LastError included

AfxMessageBox("LoadImage failed");

return FALSE;

}

if (!m_Bitmap.Attach(hImage)) {

AfxMessageBox("Bitmap could not be attached");

return FALSE;

}

SetModifiedFlag(FALSE);

UpdateAllViews(NULL);

return TRUE;

Add the following to the header for the document:

public:

HBITMAP GetHandle() const {return (HBITMAP)m_Bitmap.m_hObject;};

void SelectOldBitmap(CDC *pDCMem) {pDCMem->SelectObject(m_pOldBitmap);};

void SelectBitmap(CDC *pDCMem)

{m_pOldBitmap=pDCMem->SelectObject(&m_Bitmap);};

int GetBitmap(BITMAP* pBitMap) {return m_Bitmap.GetBitmap(pBitMap);};

protected:

CBitmap m_Bitmap;

CBitmap* m_pOldBitmap;

Use ClassWizard to remove processing for OnInitialUpdate in your view class and delete the function from the code

Add to the view constructor:

SetScrollSizes(MM_TEXT, CSize(0, 0));

Use ClassWizard to add processing for OnUpdate in your view class and add the following to it:

CBMPLookDoc* pDoc = GetDocument();

CFrameWnd* pParentFrame = GetParentFrame();

BITMAP BitMap;

if (!pDoc->GetHandle())

return;

pDoc->GetBitmap(&BitMap);

SetScrollSizes(MM_TEXT, CSize(BitMap.bmWidth, BitMap.bmHeight));

pParentFrame->RecalcLayout();

ResizeParentToFit();

Finally, replace the OnDraw processing with the following:

CBMPLookDoc* pDoc = GetDocument();

BITMAP BitMap;

CDC DCMem;

// Do not call CWnd::OnPaint() for painting messages

ASSERT_VALID(pDoc);

if (!pDoc->GetHandle())

return;

if (!DCMem.CreateCompatibleDC(pDC))

TRACE0("DCMem.CreateCompatibleDC failed\n");

pDoc->SelectBitmap(&DCMem);

pDoc->GetBitmap(&BitMap);

if (!pDC->BitBlt(0, 0, BitMap.bmWidth, BitMap.bmHeight, &DCMem, 0, 0, SRCCOPY))

TRACE0("BitBlt failed\n");

pDoc->SelectOldBitmap(&DCMem);

DCMem.DeleteDC();

You should also modify the "" and "" in the Document Template String to use appropriate file extensions and ".bmp" for the file extension. See CDocTemplate::GetDocString and Microsoft Knowledge Base article "INFO: Format of the Document Template String" (Article ID: Q129095) for information on Document Template Strings. The string resource id for the string is usually 129.