不规则窗体的实现

#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  {
   // Start looking at the beginning
   row_start = 0;

   // Go through all columns
   for (int x=0; 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;
}

你可能感兴趣的:(经典设计(类)永久保存)