#if !defined(AFX_BITMAPDIALOG_H__A76F9E74_DF43_11D4_AE27_4854E828E6FD__INCLUDED_)
#define AFX_BITMAPDIALOG_H__A76F9E74_DF43_11D4_AE27_4854E828E6FD__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// BitmapDialog.h : header file
//
/
// CBitmapDialog dialog
class CBitmapDialog : public CDialog
{
// Construction
public:
// Common constructor
void Constructor (LPCTSTR lpszResourceName, UINT nIDResource,
LPCTSTR lpszFilename, CBitmap *pBitmap);
CBitmapDialog (LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL,
LPCTSTR lpszResourceName = NULL, UINT nIDResource = 0,
LPCTSTR lpszFilename = NULL, CBitmap *pBitmap = NULL);
CBitmapDialog (UINT nIDTemplate, CWnd* pParentWnd = NULL,
LPCTSTR lpszResourceName = NULL, UINT nIDResource = 0,
LPCTSTR lpszFilename = NULL, CBitmap *pBitmap = NULL);
CBitmapDialog (LPCTSTR lpszResourceName = NULL, UINT nIDResource = 0,
LPCTSTR lpszFilename = NULL, CBitmap *pBitmap = NULL);
// Destructor (just release the bitmap)
~CBitmapDialog () { ReleaseBitmap (); }
// Bitmap
BOOL LoadBitmap (LPCTSTR lpszResourceName,
LPCTSTR lpszFilename); // Load from resource or file
BOOL LoadBitmap (UINT nIDResource); // Load from resource
BOOL CopyBitmapFrom (CBitmap *pBitmap); // Copy of user defined
void SetBitmap (CBitmap *pBitmap); // User defined
void ReleaseBitmap ();
CBitmap *GetBitmap () { return m_bmBitmap; }
// Transparency
void SetTransparent (BOOL bTransparent);
BOOL GetTransparent () { return m_bTransparent; }
void SetTransColor (COLORREF col);
COLORREF GetTransColor () { return m_colTrans; }
// Static control transparency
void SetStaticTransparent (BOOL bTransparent) { m_bStaticTransparent = bTransparent; }
BOOL GetStaticTransparent () { return m_bStaticTransparent; }
// Clicking anywhere moves
void SetClickAnywhereMove (BOOL bMove) { m_bClickAnywhereMove = bMove; }
BOOL GetClickAnywhereMove () { return m_bClickAnywhereMove; }
// Dialog Data
//{{AFX_DATA(CBitmapDialog)
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBitmapDialog)
protected:
//}}AFX_VIRTUAL
// Implementation
protected:
void MakeWindowRgn ();
// Transparency
BOOL m_bTransparent;
BOOL m_bStaticTransparent;
HBRUSH m_brushHollow;
COLORREF m_colTrans;
// Clicking anywhere moves
BOOL m_bClickAnywhereMove;
// Bitmap and its DC
BOOL m_bBitmapCreated, m_bBitmapExists;
CBitmap *m_bmBitmap;
// Generated message map functions
//{{AFX_MSG(CBitmapDialog)
afx_msg BOOL OnEraseBkgnd (CDC *pDC);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BITMAPDIALOG_H__A76F9E74_DF43_11D4_AE27_4854E828E6FD__INCLUDED_)
/*
*************************************************************************************
. cpp
*************************************************************************************
*/
// BitmapDialog.cpp : implementation file
//
// Created by David Forrester, January 1, 2001
// Feel free to use this code in any way you want.
#include "stdafx.h"
#include "BmpDlg.h"
#include "BitmapDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CBitmapDialog dialog
//----------------------------------------------------------------
// CBitmapDialog :: CBitmapDialog - constructor for CBitmapDialog
//
// Parameters:
// lpszTemplateName - the name of the dialog template resource
// nIDTemplate - the ID of the dialog template resource
// pParentWnd - the parent window
//
// You can leave any or all of the below NULL or 0 to not use it
// lpszResourceName - the name of the bitmap resource to load
// nIDResource - the ID of the bitmap resource to load
// lpszFilename - the filename of the bitmap file to load
// pBitmap - the bitmap to use (user is responsible for handling the bitmap)
// The common constructor for CBitmapDialog
void CBitmapDialog :: Constructor (LPCTSTR lpszResourceName, UINT nIDResource,
LPCTSTR lpszFilename, CBitmap *pBitmap)
{
m_bTransparent = FALSE; // No transparency
m_bStaticTransparent = TRUE; // Static controls are transparent
m_bBitmapCreated = FALSE; // Don't automatically release the bitmap
m_bBitmapExists = FALSE; // IS there a bitmap?
m_bClickAnywhereMove = FALSE; // Clicking anywhere moves
// Create a hollow brush used in making static controls transparent
m_brushHollow = (HBRUSH) GetStockObject (HOLLOW_BRUSH);
// Load a bitmap from a resource name
if (lpszResourceName != NULL)
{
LoadBitmap (lpszResourceName, NULL);
}
// Load a bitmap from a resource ID
else if (nIDResource != 0)
{
LoadBitmap (nIDResource);
}
// Use the passed bitmap
else if (pBitmap != 0)
{
// NOTE: The user is responsible for handling the bitmap
SetBitmap (pBitmap);
}
// else: No bitmap has been created yet
}
CBitmapDialog::CBitmapDialog (LPCTSTR lpszTemplateName, CWnd* pParentWnd,
LPCTSTR lpszResourceName, UINT nIDResource,
LPCTSTR lpszFilename, CBitmap *pBitmap)
: CDialog (lpszTemplateName, pParentWnd)
{
Constructor (lpszResourceName, nIDResource, lpszFilename, pBitmap);
}
CBitmapDialog::CBitmapDialog (UINT nIDTemplate, CWnd* pParentWnd,
LPCTSTR lpszResourceName, UINT nIDResource,
LPCTSTR lpszFilename, CBitmap *pBitmap)
: CDialog (nIDTemplate, pParentWnd)
{
Constructor (lpszResourceName, nIDResource, lpszFilename, pBitmap);
}
CBitmapDialog::CBitmapDialog (LPCTSTR lpszResourceName, UINT nIDResource,
LPCTSTR lpszFilename, CBitmap *pBitmap)
: CDialog ()
{
Constructor (lpszResourceName, nIDResource, lpszFilename, pBitmap);
}
//----------------------------------------------------------------
// CBitmapDialog :: LoadBitmap - load a bitmap from a resource or file
//
// Parameters:
// lpszResourceName - the name of the bitmap resource to load.
// Set this to NULL if you use lpszFilename.
// lpszFilename - the filename of the bitmap file to load.
// Set this to NULL if you use lpszResourceName.
// nIDResource - the ID of the bitmap resource to load
BOOL CBitmapDialog :: LoadBitmap (LPCTSTR lpszResourceName, LPCTSTR lpszFilename)
{
// Release the bitmap if it was created
ReleaseBitmap ();
if (lpszResourceName != NULL)
{
// Load the bitmap from a resource
m_bmBitmap = new CBitmap;
if (!m_bmBitmap->LoadBitmap (lpszResourceName))
return FALSE;
// Automatically delete the object
m_bBitmapCreated = TRUE;
m_bBitmapExists = TRUE;
// Make the window transparent if needed
MakeWindowRgn ();
}
else
{
// Load the bitmap from a file
HBITMAP hbm = (HBITMAP) LoadImage (NULL, lpszFilename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if (hbm == NULL) return FALSE;
// Get the CBitmap object
CopyBitmapFrom (CBitmap::FromHandle(hbm));
//m_bmBitmap = CBitmap::FromHandle (hbm);
}
return TRUE;
}
BOOL CBitmapDialog :: LoadBitmap (UINT nIDResource)
{
// Release the bitmap if it was created
ReleaseBitmap ();
// Load the bitmap
m_bmBitmap = new CBitmap;
if (!m_bmBitmap->LoadBitmap (nIDResource))
return FALSE;
// Automatically delete the object
m_bBitmapCreated = TRUE;
m_bBitmapExists = TRUE;
// Make the window transparent if needed
MakeWindowRgn ();
return TRUE;
}
//----------------------------------------------------------------
// CBitmapDialog :: CopyBitmapFrom - sets the bitmap to a copy
// of a CBitmap.
//
// Parameters:
// pBitmap - a pointer to the bitmap to make a copy of and use.
BOOL CBitmapDialog :: CopyBitmapFrom (CBitmap *pBitmap)
{
// Release the bitmap if it was created
ReleaseBitmap ();
// Get the bitmap information
BITMAP bmSrc;
pBitmap->GetBitmap (&bmSrc);
// Get a DC to the source bitmap
CDC dcSrc;
dcSrc.CreateCompatibleDC (NULL);
CBitmap *bmSrcOld = dcSrc.SelectObject (pBitmap);
// Create a new bitmap
m_bmBitmap = new CBitmap;
if (!m_bmBitmap->CreateCompatibleBitmap (&dcSrc, bmSrc.bmWidth, bmSrc.bmHeight))
return FALSE;
// Get a DC to the destination bitmap
CDC dcDst;
dcDst.CreateCompatibleDC (NULL);
CBitmap *bmDstOld = dcDst.SelectObject (m_bmBitmap);
// Copy the bitmap
dcDst.BitBlt (0, 0, bmSrc.bmWidth, bmSrc.bmHeight, &dcSrc, 0, 0, SRCCOPY);
// Release
dcSrc.SelectObject (bmSrcOld);
dcDst.SelectObject (bmDstOld);
dcSrc.DeleteDC ();
dcDst.DeleteDC ();
// Automatically delete the object
m_bBitmapCreated = TRUE;
m_bBitmapExists = TRUE;
// Make the window transparent if needed
MakeWindowRgn ();
return TRUE;
}
//----------------------------------------------------------------
// CBitmapDialog :: SetBitmap - sets the bitmap
//
// Parameters:
// pBitmap - a pointer to the bitmap to use.
//
// NOTE: This function does not copy the bitmap. You are responsible
// for handling the bitmap. Use CopyBitmapFrom() to copy a bitmap.
void CBitmapDialog :: SetBitmap (CBitmap *pBitmap)
{
// Release the bitmap if it was created
ReleaseBitmap ();
// Set the bitmap
m_bmBitmap = pBitmap;
// The bitmap exists, but was not created
m_bBitmapExists = TRUE;
// Make the window transparent if needed
MakeWindowRgn ();
}
//----------------------------------------------------------------
// CBitmapDialog :: ReleaseBitmap - releases a bitmap if it was
// created using LoadBitmap or CopyBitmapFrom.
void CBitmapDialog :: ReleaseBitmap ()
{
// Make sure that the bitmap was created using LoadBitmap or CopyBitmapFrom
if (m_bBitmapCreated)
{
// Delete the bitmap
m_bmBitmap->DeleteObject ();
delete m_bmBitmap;
// The bitmap has not been created yet
m_bBitmapCreated = FALSE;
}
m_bBitmapExists = FALSE;
}
//----------------------------------------------------------------
// CBitmapDialog :: SetTransparent - sets the dialog's transparent
// state.
void CBitmapDialog :: SetTransparent (BOOL bTransparent)
{
m_bTransparent = bTransparent;
MakeWindowRgn ();
}
void CBitmapDialog :: SetTransColor (COLORREF col)
{
m_colTrans = col;
MakeWindowRgn ();
}
//----------------------------------------------------------------
// CBitmapDialog :: MakeWindowRgn - makes a window region from
// the bitmap and uses it if on transparent mode.
void CBitmapDialog :: MakeWindowRgn ()
{
if (!m_bTransparent)
{
// Set the window region to the full window
CRect rc;
GetWindowRect (rc);
CRgn rgn;
rgn.CreateRectRgn (0, 0, rc.Width(), rc.Height());
SetWindowRgn (rgn, TRUE);
}
else
{
// Set the region to the window rect minus the client rect
CRect rcWnd;
GetWindowRect (rcWnd);
CRgn rgn;
rgn.CreateRectRgn (rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom);
CRect rcClient;
GetClientRect (rcClient);
ClientToScreen (rcClient);
CRgn rgnClient;
rgnClient.CreateRectRgn (rcClient.left, rcClient.top, rcClient.right,
rcClient.bottom);
// Subtract rgnClient from rgn
rgn.CombineRgn (&rgn, &rgnClient, RGN_XOR);
// Get a DC for the bitmap
CDC dcImage;
dcImage.CreateCompatibleDC (NULL);
CBitmap *pOldBitmap = dcImage.SelectObject (m_bmBitmap);
// Get the bitmap for width and height information
BITMAP bm;
m_bmBitmap->GetBitmap (&bm);
// Get window width and height
CRect rc;
GetClientRect (rc);
// Use the minimum width and height
int width = min (bm.bmWidth, rc.Width());
int height = min (bm.bmHeight, rc.Height());
// Use RLE (run-length) style because it goes faster.
// Row start is where the first opaque pixel is found. Once
// a transparent pixel is found, a line region is created.
// Then row_start becomes the next opaque pixel.
int row_start;
// Go through all rows
for (int y=0; y<height; y++)
{
// Start looking at the beginning
row_start = 0;
// Go through all columns
for (int x=0; x<width; x++)
{
// If this pixel is transparent
if (dcImage.GetPixel(x, y) == m_colTrans)
{
// If we haven't found an opaque pixel yet, keep searching
if (row_start == x) row_start ++;
else
{
// We have found the start (row_start) and end (x) of
// an opaque line. Add it to the region.
CRgn rgnAdd;
rgnAdd.CreateRectRgn (rcClient.left+row_start,
rcClient.top+y, rcClient.left+x, rcClient.top+y+1);
rgn.CombineRgn (&rgn, &rgnAdd, RGN_OR);
row_start = x+1;
}
}
}
// If the last pixel is still opaque, make a region.
if (row_start != x)
{
CRgn rgnAdd;
rgnAdd.CreateRectRgn (rcClient.left+row_start, rcClient.top+y,
rcClient.left+x, rcClient.top+y+1);
rgn.CombineRgn (&rgn, &rgnAdd, RGN_OR);
}
}
SetWindowRgn (rgn, TRUE);
}
}
BEGIN_MESSAGE_MAP(CBitmapDialog, CDialog)
//{{AFX_MSG_MAP(CBitmapDialog)
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_CTLCOLOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CBitmapDialog message handlers
//----------------------------------------------------------------
// CBitmapDialog :: OnEraseBkgnd - normally erases the background.
// We override this function to replace it with window drawing
// code.
BOOL CBitmapDialog :: OnEraseBkgnd (CDC *pDC)
{
// If no bitmap is loaded, behave like a normal dialog box
if (!m_bBitmapExists)
return CDialog :: OnEraseBkgnd (pDC);
// Get the client rectangle of the window
CRect rc;
GetClientRect (rc);
// Get a DC for the bitmap
CDC dcImage;
dcImage.CreateCompatibleDC (pDC);
CBitmap *pOldBitmap = dcImage.SelectObject (m_bmBitmap);
// Get bitmap width and height
BITMAP bm;
m_bmBitmap->GetBitmap (&bm);
// Use the minimum width and height
int width = min (bm.bmWidth, rc.Width());
int height = min (bm.bmHeight, rc.Height());
// Draw the bitmap as the window background
pDC->BitBlt (0, 0, rc.Width(), rc.Height(), &dcImage, 0, 0, SRCCOPY);
// Release
dcImage.SelectObject (pOldBitmap);
dcImage.DeleteDC ();
// Return value: Nonzero if it erases the background.
return TRUE;
}
//----------------------------------------------------------------
// CBitmapDialog :: OnLButtonDown - left mouse button is clicked
// on the window
void CBitmapDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnLButtonDown(nFlags, point);
// Fool windows into thinking that we clicked on the caption
if (m_bClickAnywhereMove)
PostMessage (WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y));
}
//----------------------------------------------------------------
// CBitmapDialog :: OnCtlColor - set the colors for controls
HBRUSH CBitmapDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// Make static controls transparent
if (m_bStaticTransparent && nCtlColor == CTLCOLOR_STATIC)
{
// Make sure that it's not a slider control
char lpszClassName[256];
GetClassName (pWnd->m_hWnd, lpszClassName, 255);
if (strcmp (lpszClassName, TRACKBAR_CLASS) == 0)
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkMode (TRANSPARENT);
return m_brushHollow;
}
// TODO: Return a different brush if the default is not desired
return hbr;
}