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

📄 mdc.cpp

📁 这是一个简单的使用WinAPI基于WinSock的ICP/IP程序
💻 CPP
字号:
// MDC.cpp: implementation of the CMDC 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 "MDC.h"

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

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

CMDC::CMDC():
m_pSDC(0),
m_pOldCanvas(0),
m_pCanvasBits(0)
{
  m_crt.SetRectEmpty();
}

// CDC* - the source DC, which this DC will be compatible with
// rect - is the rectangular area of the source DC in which this DC can draw
CMDC::CMDC(CDC* pSDC, CRect& rect):
m_pSDC(0),
m_pOldCanvas(0),
m_pCanvasBits(0)
{
  Create(pSDC, rect);
}

void CMDC::Create(CDC* pSDC, CRect& rect)
{
// cleanup
  DeleteObject();
// initialize
  m_pSDC = pSDC;
  m_crt = rect;
// create compatible DC
  CreateCompatibleDC(pSDC);
// and bitmap
  m_canvas.CreateCompatibleBitmap(pSDC, rect.Width(), rect.Height());
// select the created bitmap into 'this' DC and save the old one
  m_pOldCanvas = SelectObject(&m_canvas);
// now reposition origin of this DC, so when one will draw in it the coordinates
// can be relative to the origin of the source DC
  SetWindowOrg(rect.left, rect.top);
// copy the clipping rect
  CRect rtClip;
  pSDC->GetClipBox(rtClip);
  IntersectClipRect(rtClip);
}

// destroyes the canvas, and DC
void CMDC::DeleteObject()
{
  if (!m_pSDC) return;

  SelectObject(m_pOldCanvas);
  m_canvas.DeleteObject();
  m_crt.SetRectEmpty();
  m_pOldCanvas = 0;
  m_pSDC = 0;
  CDC::DeleteDC();
}

CMDC::~CMDC()
{
// if m_pSDC is 0 then caller used empty constructor
// and never called Create(...), or prior do destroying
// this instance called DestroyObject()
  if (!m_pSDC) return;

  CopyToBase();
  SelectObject(m_pOldCanvas);
}

void CMDC::CopyFromBase()
{
// now copy the image from the source buffer into 'this' buffer 
  BitBlt(m_crt.left, m_crt.top, m_crt.Width(), m_crt.Height(), 
         m_pSDC, m_crt.left, m_crt.top, SRCCOPY);
}

void CMDC::CopyToBase()
{
// now copy the image from the 'this' memory buffer into the source 
  m_pSDC->BitBlt(m_crt.left, m_crt.top, m_crt.Width(), m_crt.Height(), 
	             this, m_crt.left, m_crt.top, SRCCOPY);
}

// copies the context of 'this' 
// at position pt with size of [dx,dy] 
// into bmTarget
void CMDC::CopyTo(CBitmap& bmTarget, CPoint& pt, int dx, int dy)
{
// precaution
  ASSERT(m_pSDC);

// if the bitmap has to be created for the first time
  if (!bmTarget.m_hObject) {
// recreate
    bmTarget.DeleteObject();
    bmTarget.CreateCompatibleBitmap(m_pSDC, dx, dy);
  } else {
	// the bitmap has been created but will not fit the requested [dx, dy]
    BITMAP bm;
    bmTarget.GetBitmap(&bm);
    if (dx > bm.bmWidth || dy > bm.bmHeight) {
    // recreate
      bmTarget.DeleteObject();
   	  bmTarget.CreateCompatibleBitmap(m_pSDC, dx, dy);
	}
  }

// create compatible with m_pSDC dc and bitmap
  CDC dc;
  dc.CreateCompatibleDC(m_pSDC);
// copy the context
  CBitmap* pOldBitmap = dc.SelectObject(&bmTarget);
  dc.BitBlt(0, 0, dx, dy, 
	        this, pt.x, pt.y, SRCCOPY);
// restore the old bitmap
  dc.SelectObject(pOldBitmap);
}

// copies the context of bmSource into m_pSDC
// at position pt with size of [dx,dy] 
void CMDC::CopyFrom(CBitmap& bmSource, CPoint& ptSrc, CPoint& pt, 
					int dx /*= -1*/, int dy /*= -1*/, DWORD nOp/* = SRCCOPY*/)
{
// precaution
  ASSERT(m_pSDC);

  BITMAP bm;
  bmSource.GetBitmap(&bm);
  if (dx == -1 && dy == -1) {
	dx = bm.bmWidth;
	dy = bm.bmHeight;
  } else
	  if (ptSrc.x + dx > bm.bmWidth || ptSrc.y + dy > bm.bmHeight) {
	    dx = bm.bmWidth  - ptSrc.x;
		dy = bm.bmHeight - ptSrc.y;
	  }

  int infx = (pt.x + dx) - m_crt.right;
  int infy = (pt.y + dy) - m_crt.bottom;
// if the m_canvas will not be able to fit bmSource - error out
  if (infx > 0 || infy > 0 )
	ASSERT(FALSE);

// create compatible with m_pSDC dc and bitmap
  CDC dc;
  dc.CreateCompatibleDC(m_pSDC);
// copy the context of the source bitmap
  CBitmap* pOldBitmap = dc.SelectObject(&bmSource);
  BitBlt(pt.x, pt.y, dx, dy, 
		 &dc, ptSrc.x, ptSrc.y, nOp);
// restore the old bitmap
  dc.SelectObject(pOldBitmap);
}

void CMDC::GetColorRef(BYTE& r, BYTE& g, BYTE& b, BITMAP& bm, BYTE* pBits, unsigned int x, unsigned int y)
{
  unsigned int nOffset;
  unsigned short nBytesPerPixel = (bm.bmBitsPixel / 8);
  nOffset = (y > 0) ? bm.bmWidthBytes * (y - 1) + nBytesPerPixel * x :  nBytesPerPixel * x;
  b = (*(pBits + nOffset));
  g = (*(pBits + nOffset + 1));
  r = (*(pBits + nOffset + 2));
}

bool CMDC::SetColorRef(BYTE r, BYTE g, BYTE b, BITMAP& bm, BYTE* pBits, unsigned int x, unsigned int y)
{
  unsigned int nOffset;
  unsigned short nBytesPerPixel = (bm.bmBitsPixel / 8);
  nOffset = (y > 0) ? bm.bmWidthBytes * (y - 1) + nBytesPerPixel * x :  nBytesPerPixel * x;
  *(pBits + nOffset) = b;
  *(pBits + nOffset + 1) = g;
  *(pBits + nOffset + 2) = r;
  return true;
}

// copy and blend the first param bitmap into 'this' dc bitmap 
// at the position indicated by the second param, 
// and with the Width and the Height as the third  and fourth the  params specify
// with the alpha as the fifth param tells
// with the "transparent" color as the six parameter
void CMDC::CopyBlendFrom(CBitmap& bmSource, CPoint& ptSrc, CPoint& pt, int dx /* = -1*/, int dy /* = -1*/, int nA /* = 127*/)
{
// get bitmap bits of the source bitmap
  BITMAP bitmap;
  bmSource.GetBitmap(&bitmap);
  DWORD nSrsSz = bitmap.bmWidthBytes * bitmap.bmHeight;
  BYTE* pSrcBits = new BYTE[nSrsSz];

  DWORD nRet = bmSource.GetBitmapBits(nSrsSz, pSrcBits);

  if (nRet != nSrsSz) {
	delete [] pSrcBits;
	return;
  }

// get bitmap bits of the canvas bitmap
  BITMAP canvas;
  m_canvas.GetBitmap(&canvas);

  DWORD nCanSz = canvas.bmWidthBytes * canvas.bmHeight;
  BYTE* pCanBits = new BYTE[nCanSz];

  nRet = m_canvas.GetBitmapBits(nCanSz, pCanBits);

  if (nRet != nCanSz){
	delete [] pSrcBits;
	delete [] pCanBits;
	return;
  }

  BYTE rS, gS, bS, rD, gD, bD;
  CRect rect;
// the rect to be copied and blended
  rect.SetRect(0, 0, dx, dy);

  CPoint ptOrg = GetWindowOrg();

  for (int x=0; x<rect.Width() - ptSrc.x; x++)
	 for (int y=0; y<rect.Height() - ptSrc.y; y++) {
// start from x = ptSrc.x + x; y = ptSrc.y + y
	   GetColorRef(rS, gS, bS, bitmap, pSrcBits, ptSrc.x + x, ptSrc.y + y);
// start from pt.x + x; pt.x + y
	   GetColorRef(rD, gD, bD, canvas, pCanBits, pt.x + x - ptOrg.x, pt.y + y - ptOrg.y);
       
	   SetColorRef((BYTE)((((rS - rD) * nA) + (rD << 8)) >> 8), 
		           (BYTE)((((gS - gD) * nA) + (gD << 8)) >> 8), 
				   (BYTE)((((bS - bD) * nA) + (bD << 8)) >> 8), 
				   canvas, pCanBits, pt.x + x - ptOrg.x, pt.y + y - ptOrg.y);
	 }

// set belended bits into the destination bitmap
  nRet = m_canvas.SetBitmapBits(nCanSz, pCanBits);

  delete [] pSrcBits;
  delete [] pCanBits;
}

// param 1 - copy and blend the source bitmap into 'this' dc bitmap 
// param 2 - the origin point for 'this' dc bitmap
// param 3 - dx of the source bitmap
// param 4 - dy of the source bitmap
// param 5 - blend strength (alpha value)
// param 6 - "transparent" color (the source's bitmap color that is excluded and only destination's bitmap color is preserved)

void CMDC::CopyBlendMaskedFrom(CBitmap& bmSource, CPoint& ptSrc, CPoint& pt, COLORREF crTrans, int dx /*= -1*/, int dy /*= -1*/, int nA /* = 127*/)
{
// get bitmap bits of the source bitmap
  BITMAP bitmap;
  bmSource.GetBitmap(&bitmap);
  DWORD nSrsSz = bitmap.bmWidthBytes * bitmap.bmHeight;
  BYTE* pSrcBits = new BYTE[nSrsSz];


  DWORD nRet = bmSource.GetBitmapBits(nSrsSz, pSrcBits);

  if (nRet != nSrsSz) {
	delete [] pSrcBits;
	return;
  }

// get bitmap bits of the canvas bitmap
  BITMAP canvas;
  m_canvas.GetBitmap(&canvas);

  DWORD nCanSz = canvas.bmWidthBytes * canvas.bmHeight;
  BYTE* pCanBits = new BYTE[nCanSz];

  nRet = m_canvas.GetBitmapBits(nCanSz, pCanBits);

  if (nRet != nCanSz){
	delete [] pSrcBits;
	delete [] pCanBits;
	return;
  }

  BYTE rS, gS, bS, rD, gD, bD;
  CRect rect;
// the rect to be copied and blended
  rect.SetRect(0, 0, dx, dy);

  CPoint ptOrg = GetWindowOrg();

  for (int x=0; x<rect.Width() - ptSrc.x; x++)
	 for (int y=0; y<rect.Height() - ptSrc.y; y++) {
// start from x = ptSrc.x + x; y = ptSrc.y + y
	   GetColorRef(rS, gS, bS, bitmap, pSrcBits, ptSrc.x + x, ptSrc.y + y);
// start from pt.x + x; pt.x + y
	   GetColorRef(rD, gD, bD, canvas, pCanBits, pt.x + x - ptOrg.x, pt.y + y - ptOrg.y);

// if this is the "transparent" color, ignore it 
	   if (rS == rD && gS == gD && bS == bD)
		 continue;

	   BYTE r =  (BYTE)(rS * nA + (1 - nA) * rD);
	   BYTE g =  (BYTE)(gS * nA + (1 - nA) * gD);
	   BYTE b =  (BYTE)(bS * nA + (1 - nA) * bD);

	   SetColorRef((BYTE)((((rS - rD) * nA) + (rD << 8)) >> 8),
		           (BYTE)((((gS - gD) * nA) + (gD << 8)) >> 8),
				   (BYTE)((((bS - bD) * nA) + (bD << 8)) >> 8), 
				    canvas, pCanBits, pt.x + x - ptOrg.x, pt.y + y - ptOrg.y);
	 }

// set belended bits into the destination bitmap
  nRet = m_canvas.SetBitmapBits(nCanSz, pCanBits);

  delete [] pSrcBits;
  delete [] pCanBits;
  return;


// !! test !!
//  float nA = 0.5;
/*
 //the source image is being blended out of the range of the destination DC
  if ((pt.x + dx) - m_crt.right > 0 ||
	  (pt.y + dy) - m_crt.bottom > 0)
	ASSERT(FALSE);

  BYTE r, g, b;
  BYTE rS, gS, bS, rD, gD, bD;
  COLORREF crS;
  COLORREF crD;
  CRect rect;
// the rect to be copied and blended
  rect.SetRect(0, 0, dx, dy);
// create compatible with m_pSDC dc and bitmap
  CDC dc;
  dc.CreateCompatibleDC(m_pSDC);
// copy the context of the source bitmap
  CBitmap* pOldBitmap = dc.SelectObject(&bmSource);

  for (int x=0; x<rect.Width() - ptSrc.x; x++)
	 for (int y=0; y<rect.Height() - ptSrc.y; y++) {
// start from x = ptSrc.x + x; y = ptSrc.y + y
//	   crS = dc.GetPixel(ptSrc.x + x, ptSrc.y + y);
// start from pt.x + x; pt.x + y
//	   crD = GetPixel(pt.x + x, pt.y + y);

// if this is the "transparent" color, ignore it 
	   if (crS == crTrans)
		 continue;

	   rS = GetRValue(crS);
	   gS = GetGValue(crS);
	   bS = GetBValue(crS);

	   rD = GetRValue(crD);
	   gD = GetGValue(crD);
	   bD = GetBValue(crD);

//	   r =  (BYTE)(rS * nA + (1 - nA) * rD);
//	   g =  (BYTE)(gS * nA + (1 - nA) * gD);
//	   b =  (BYTE)(bS * nA + (1 - nA) * bD);

       r =  (BYTE)((((rS - rD) * nA) + (rD << 8)) >> 8);
	   g =  (BYTE)((((gS - gD) * nA) + (gD << 8)) >> 8);
	   b =  (BYTE)((((bS - bD) * nA) + (bD << 8)) >> 8);
       
//	   SetPixel(pt.x + x, pt.y + y, RGB(r,g,b));
	 }
*/
}

⌨️ 快捷键说明

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