⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mimage.cpp

📁 这是一个简单的使用WinAPI基于WinSock的ICP/IP程序
💻 CPP
字号:
// MImage.cpp: implementation of the CMImage class.
//
// Written by Marat Bedretdinov (maratb@hotmail.com)
// Copyright (c) 2000.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// If the source code in  this file is used in any commercial application 
// then acknowledgement must be made to the author of this file 
// and permissions to use this file are requested from the author
//
// (in whatever form you wish).// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// It's free - so you get what you pay for.//

#include "stdafx.h"
#include <atlconv.h>

#include "MImage.h"
#include "MDC.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

int _convert = 0; UINT _acp = GetACP(); LPCWSTR _lpw = NULL; LPCSTR _lpa = NULL;

#define A2W(lpa) (\
	((_lpa = lpa) == NULL) ? NULL : (\
		_convert = (lstrlenA(_lpa)+1),\
		ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert)))

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMImage::CMImage():
m_pbmSource(0),
m_pbmMask(0),
m_pIPic(0),
m_hWnd(0),
m_bVisible(true)
{
  Cleanup();

// create the font
  VERIFY(m_font.CreateFont( 12,                        // nHeight
							0,                         // nWidth
							0,                         // nEscapement
							0,                         // nOrientation
							FW_NORMAL,                 // nWeight
							FALSE,                     // bItalic
							FALSE,                     // bUnderline
							0,                         // cStrikeOut
							ANSI_CHARSET,              // nCharSet
							OUT_DEFAULT_PRECIS,        // nOutPrecision
							CLIP_DEFAULT_PRECIS,       // nClipPrecision
							DEFAULT_QUALITY,           // nQuality
							DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
							"Arial"));                 // lpszFacename// create it invisible

}

CMImage::~CMImage()
{
  Cleanup();
}

void CMImage::Cleanup(bool bDelBm/* = true*/)
{
// cleanup
  m_ptNew.x  = 0;
  m_ptNew.y  = 0;
  m_ptOld.x  = 0;
  m_ptOld.y  = 0;

  memset(&m_bmHdr, 0, sizeof(m_bmHdr));

// the mask bitmap gets deleted anytime 
// new bitmap is being Loaded/Attached to 'this'
  if (m_pbmMask)
	delete m_pbmMask;
  m_pbmMask = 0;

// delete palette
  m_palette.DeleteObject();
// empty visible rect
  m_rtVisible.SetRectEmpty();

  if (!bDelBm) return;

  if (m_pbmSource) 
    delete m_pbmSource;
  m_pbmSource = 0;

  if (m_pIPic)
    m_pIPic->Release();
}

void CMImage::CreateLogicalPalette()
{
  ASSERT(m_pbmSource);

// precaution
  m_palette.DeleteObject();

// create a logical palette for the bitmap
  DIBSECTION ds;
  BITMAPINFOHEADER &bmInfo = ds.dsBmih;
  m_pbmSource->GetObject(sizeof(ds), &ds);

  int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount;

// create a halftone palette if colors > 256. 
  CClientDC dc(NULL);			// Desktop DC

  if( nColors > 256 )
	m_palette.CreateHalftonePalette(&dc);
  else {
// Create the palette
	RGBQUAD *pRGB = new RGBQUAD[nColors];
	CDC mdc;
	mdc.CreateCompatibleDC(&dc);
	mdc.SelectObject(m_pbmSource);

	::GetDIBColorTable(mdc, 0, nColors, pRGB );

	UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
	LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

	pLP->palVersion = 0x300;
	pLP->palNumEntries = nColors;

	for( int i=0; i < nColors; i++)	{
	  pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
	  pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
	  pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
	  pLP->palPalEntry[i].peFlags = 0;
	}

	m_palette.CreatePalette(pLP);

	delete[] pLP;
	delete[] pRGB;
  }
}

BOOL CMImage::Load(UINT nBm)
{
  Cleanup();

  LPCTSTR lpszBm = (LPCTSTR)nBm;
// still need to understand LR_CREATEDIBSECTION
  HBITMAP hBm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), lpszBm, 
								     IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR/*LR_CREATEDIBSECTION*/);
  if(!hBm) return FALSE;

  m_pbmSource = new CBitmap;
  m_pbmSource->Attach(hBm);
  m_pbmSource->GetBitmap(&m_bmHdr);

  CreateLogicalPalette();

  return TRUE;
}

BOOL CMImage::Load(const char* path)
{
  Cleanup();

  LPOLESTR lposPath = A2W(path);
  if (OleLoadPicturePath(lposPath, 0, 0, 0, IID_IPicture, (void**)&m_pIPic) != S_OK)
    return FALSE;

  OLE_HANDLE hBm = 0;
  m_pIPic->get_Handle(&hBm);
  if (!hBm) {
	Cleanup();
	return FALSE;
  }
  m_pbmSource = new CBitmap;
  m_pbmSource->Attach((HBITMAP)hBm);
  m_pbmSource->GetBitmap(&m_bmHdr);

  CreateLogicalPalette();
  return TRUE;
}

BOOL CMImage::Save(const char* path)
{
  if (!m_pIPic) return FALSE;

  LPOLESTR lposPath = A2W(path);

  IPictureDisp* pDispatch = 0;
  if (m_pIPic->QueryInterface(IID_IPictureDisp, (void**)&pDispatch) != S_OK)
	return FALSE;

  if (OleSavePictureFile(pDispatch, lposPath) != S_OK) {
	pDispatch->Release();
    return FALSE;
  }

  pDispatch->Release();
  return TRUE;
}

CBitmap* CMImage::Attach(CBitmap* pBm)
{
// save in a temp pointer the source bitmap
  CBitmap* pSource = m_pbmSource;
// pass 'false' to preserve the source bitmap
  Cleanup(false);

  m_pbmSource = pBm;
  m_pbmSource->GetBitmap(&m_bmHdr);

  CreateLogicalPalette();

  return pSource;
}

CBitmap* CMImage::Detach()
{
// save in a temp pointer the source bitmap
  CBitmap* pSource = m_pbmSource;
// pass false to preserve the source bitmap
  Cleanup(false);
// members points to nil
  m_pbmSource = 0;

  return pSource;
}

void CMImage::DrawAt(HWND hWnd, CDC& dc, const CPoint& pt)
{
  if (!m_bVisible) return;

  ASSERT(hWnd);
// save the CWnd pointer
  m_hWnd = hWnd;
// save new position
  m_ptNew = pt;

// get the union of old and new rect
  CRect rtUnion;
  GetRectUnionVisible(rtUnion);
// invalidate that rect in the window this image is drawn
// but leave the background alone
  InvalidateRect(m_hWnd, rtUnion, TRUE);

// draw it
  Draw(&dc);

// validate that rect in the window back in
  ValidateRect(m_hWnd, rtUnion);
}

void CMImage::Draw(CDC* pDC)
{
// simply draw the whole image without nay blending
  DrawBlended(pDC, 0xFF);
}

void CMImage::DrawBlended(CDC* pDC, BYTE nAlpha)
{
  DrawBlendedRect(pDC, CRect(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight), nAlpha);
}

// draw a part of image defined by rect with nAlpha blend factor
void CMImage::DrawBlendedRect(CDC* pDC, CRect& rect, BYTE nAlpha)
{
  if (!m_bVisible) return;
// precaution
  ASSERT(pDC);
  ASSERT(m_hWnd);
  ASSERT(m_pbmSource);

// get new rect
  CRect rtNew;
  GetRectNew(rtNew);  

  CRect rtClip;
  pDC->GetClipBox(rtClip);
// draw only if any part of the image is visible
  if (!pDC->RectVisible(rtNew) || !rtClip.IntersectRect(rtNew, rtClip))
	return;

  CPalette* pOldPalette = 0;
// realize pallete if supported and I built it for this image successfully
  BOOL bPalette = pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE;
  if(bPalette && m_palette.m_hObject) {
    pOldPalette = pDC->SelectPalette(&m_palette, FALSE);
    pDC->RealizePalette();
  }

// this DC will hold the restored background and the new image
  CMDC dcAll(pDC, rtNew);

// now copy current source pDC image
// so the invisible areas of this image will show correct background
  dcAll.CopyFromBase();

// blend it if asked
  if (nAlpha < 0xFF)
	dcAll.CopyBlendFrom(*m_pbmSource, CPoint(rect.left, rect.top), m_ptNew, rtNew.Width(), rtNew.Height(), nAlpha);
  else
// draw the bitmap itself, only visible part of it
    dcAll.CopyFrom(*m_pbmSource, CPoint(rect.left, rect.top), m_ptNew, rtNew.Width(), rtNew.Height());

// now when drawing is over new point is old
  m_ptOld = m_ptNew;

// unrealize my pallete and realize privious one
  if (pOldPalette) {
	pDC->SelectPalette(pOldPalette, FALSE);
    pDC->RealizePalette();
  }
}


void CMImage::DrawMasked(CDC* pDC, COLORREF crMask)
{
  DrawMaskedRect(pDC, CRect(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight), crMask);
}

void CMImage::DrawMaskedRect(CDC* pDC, CRect& rect, COLORREF crMask)
{
  if (!m_bVisible) return;

// precaution
  ASSERT(pDC);
  ASSERT(m_hWnd);
  ASSERT(m_pbmSource);

// get new rect
  CRect rtNew;
  GetRectNew(rtNew);  

  CRect rtClip;
  pDC->GetClipBox(rtClip);

// draw only if any part of the image is visible
  if (!pDC->RectVisible(rtNew) || !rtClip.IntersectRect(rtNew, rtClip))
	return;

  CPalette* pOldPalette = 0;
// realize pallete if supported and I built it for this image successfully
  BOOL bPalette = pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE;
  if(bPalette && m_palette.m_hObject) {
    pOldPalette = pDC->SelectPalette(&m_palette, FALSE);
    pDC->RealizePalette();
  }

  if (!m_pbmMask)
	InitMask(crMask);

// this DC will hold the restored background and the new image
  CMDC dcAll(pDC, rtNew);
// now copy current source pDC image
// so the invisible areas of this image will show correct background
  dcAll.CopyFromBase();

// draw the mask of the source bitmap, only visible part of it
  dcAll.CopyFrom(*m_pbmMask, CPoint(rect.left, rect.top), m_ptNew, rect.Width(), rect.Height(), SRCAND);
// now draw the source bitmap itself, only visible part of it
  dcAll.CopyFrom(*m_pbmSource, CPoint(rect.left, rect.top), m_ptNew, rect.Width(), rect.Height(), SRCPAINT);

// now when drawing is over new point is old
  m_ptOld = m_ptNew;

// unrealize my pallete and realize privious one
  if (pOldPalette) {
	pDC->SelectPalette(pOldPalette, FALSE);
    pDC->RealizePalette();
  }
}

void CMImage::DrawMaskedBlended(CDC* pDC, COLORREF crMask, BYTE nAlpha)
{
  DrawMaskedBlendedRect(pDC, CRect(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight), crMask, nAlpha);
}

void CMImage::DrawMaskedBlendedRect(CDC* pDC, CRect& rect, COLORREF crMask, BYTE nAlpha)
{
  if (!m_bVisible) return;

// precaution
  ASSERT(pDC);
  ASSERT(m_hWnd);
  ASSERT(m_pbmSource);

// get new rect
  CRect rtNew;
  GetRectNew(rtNew);  

  CRect rtClip;
  pDC->GetClipBox(rtClip);

// draw only if any part of the image is visible
  if (!pDC->RectVisible(rtNew) || !rtClip.IntersectRect(rtNew, rtClip))
	return;

  CPalette* pOldPalette = 0;
// realize pallete if supported and I built it for this image successfully
  BOOL bPalette = pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE;
  if(bPalette && m_palette.m_hObject) {
    pOldPalette = pDC->SelectPalette(&m_palette, FALSE);
    pDC->RealizePalette();
  }

// this DC will hold the restored background and the new image
  CMDC dcAll(pDC, rtNew);
// now copy current source pDC image
// so the invisible areas of this image will show correct background
  dcAll.CopyFromBase();

// blend it
  dcAll.CopyBlendMaskedFrom(*m_pbmSource, CPoint(rect.left, rect.top), m_ptNew, crMask, rect.Width(), rect.Height(), nAlpha);

// now when drawing is over new point is old
  m_ptOld = m_ptNew;

// unrealize my pallete and realize privious one
  if (pOldPalette) {
	pDC->SelectPalette(pOldPalette, FALSE);
    pDC->RealizePalette();
  }
}

void CMImage::SetParent(HWND hWnd)
{
  ASSERT(hWnd);
// save the CWnd pointer
  m_hWnd = hWnd;
}

void CMImage::Move(const CPoint& pt)
{
  ASSERT(m_hWnd);
// save new position
  m_ptNew = pt;
// get the union of old and new rect
  CRect rtUnion;
  GetRectUnionVisible(rtUnion);
// invalidate that rect in the window this image is drawn
  InvalidateRect(m_hWnd, rtUnion, FALSE);
}

void CMImage::InitMask(COLORREF crTrans)
{
  if (m_pbmMask) {
	delete m_pbmMask;
	m_pbmMask = 0;
  }

  m_pbmMask = new CBitmap;

// create monochrome bitmap
  m_pbmMask->CreateBitmap(m_bmHdr.bmWidth, m_bmHdr.bmHeight, 1, 1, NULL);

// create two dc(s) 
  CDC dcS;
  dcS.CreateCompatibleDC(NULL);
  CDC dcD;
  dcD.CreateCompatibleDC(NULL);

// select bitmaps
  CBitmap* pbmOldS = dcS.SelectObject(m_pbmSource);
  CBitmap* pbmOldD = dcD.SelectObject(m_pbmMask);

// set backgound color as crTrans for the source dc
  COLORREF crOldBk = dcS.SetBkColor(crTrans);

// copy the source bitmap into the mask bitmap
  dcD.BitBlt(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight, &dcS, 0, 0, SRCCOPY);

  COLORREF crOldText = dcS.SetTextColor(RGB(255,255,255));
  dcS.SetBkColor(RGB(0,0,0));
  
  dcS.BitBlt(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight, &dcD, 0, 0, SRCAND);

  dcS.SetTextColor(crOldText);
  dcS.SetBkColor(crOldBk);
  dcS.SelectObject(pbmOldS);
  dcD.SelectObject(pbmOldD);
}

void CMImage::GetDiffRgn(CRgn& rgnDiff)
{
}

CRect CMImage::GetSize() const
{
  return CRect(0, 0, m_bmHdr.bmWidth, m_bmHdr.bmHeight);
}

void CMImage::GetRectNew(CRect& rt) const
{
  rt.SetRect(m_ptNew.x, m_ptNew.y, 
	         m_ptNew.x + m_bmHdr.bmWidth, m_ptNew.y + m_bmHdr.bmHeight); 
}

void CMImage::GetRectNewVisible(CRect& rtVisible) const
{
  ASSERT(m_hWnd);

  CRect rtWnd;
  GetClientRect(m_hWnd, &rtWnd);
  CRect rtNew;
  GetRectNew(rtNew);

  rtVisible.IntersectRect(rtWnd, rtNew);
}

void CMImage::GetRectOld(CRect& rt) const
{
  rt.SetRect(m_ptOld.x, m_ptOld.y, 
	         m_ptOld.x + m_bmHdr.bmWidth, m_ptOld.y + m_bmHdr.bmHeight); 
}

void CMImage::GetRectOldVisible(CRect& rtVisible) const
{
  ASSERT(m_hWnd);

  CRect rtWnd;
  GetClientRect(m_hWnd, &rtWnd);
  CRect rtOld;
  GetRectOld(rtOld);

  rtVisible.IntersectRect(rtWnd, rtOld);
}

void CMImage::GetRectUnion(CRect& rtUnion) const
{
// union old img rect with its new one
  CRect rtOld;
  GetRectNew(rtUnion);
  GetRectOld(rtOld);
  rtUnion.UnionRect(rtUnion, rtOld);
}

void CMImage::GetRectUnionVisible(CRect& rtVisible) const
{
  ASSERT(m_hWnd);

  CRect rtWnd;
  GetClientRect(m_hWnd, &rtWnd);
  CRect rtUnion;
  GetRectUnion(rtUnion);

  rtVisible.IntersectRect(rtWnd, rtUnion);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -