这里介绍BitBlt的应用。我把书上的代码重新写了一边,在该加注释的地方加了一些注释。这样大家读起来就会更加方便一些。这是第十四章的代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;

namespace AlphaDragExample


{
public partial class Form1 : Form

{

构造函数#region 构造函数
public Form1()

{
InitializeComponent();
dragString = "Dragging Me";
DragMePosition = new Point(100, 100);
dragStringFont = new Font("Times New Roman", 14, FontStyle.Bold);
}
#endregion


Windows API#region Windows API

[DllImport("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to desination DC (device context)
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-corrd of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);

[DllImport("gdi32.dll")]
private static extern IntPtr CreateDC(
String driverName,
String deviceName,
String outPut,
IntPtr lpInitData
);

[DllImportAttribute("gdi32.dll")]
private static extern bool DeleteDC(
IntPtr dc
);

/**//// <summary>
/// 该方法用来取得鼠标在屏幕中的坐标
/// </summary>
/// <param name="hWnd">handle to window</param>
/// <param name="lpPoint">screen coordinates</param>
/// <returns></returns>
[DllImportAttribute("user32.dll")]
private static extern unsafe bool ClientToScreen(
IntPtr hWnd, //handle to window
Point* lpPoint //screen coordinates
);
#endregion


私有变量#region 私有变量
const int SRCCOPY = 0x00CC0020;
private Point DragMePosition;
private bool mouseDown = false;
private Point mouseDelta;
private Bitmap backingStore;
private Point backingStorePos;
private string dragString;
private Graphics backingStoreGraphics;
private IntPtr backingStoreDC;
private Graphics displayGraphics;
private IntPtr displayDC;
private Size dragImageSize;
private Font dragStringFont;
#endregion


私有方法#region 私有方法
//加载页面时,初始化dragImageSize
private void Form1_Load(object sender, EventArgs e)

{
Graphics g = this.CreateGraphics();
SizeF temp = g.MeasureString(dragString, dragStringFont);
dragImageSize = new Size((int)temp.Width, (int)temp.Height);
g.Dispose();
}

private void getDisplayDC()

{
// 创建显卡的DC
displayDC = CreateDC("DISPLAY", null, null, (System.IntPtr)null);
// 获得显卡的设备上下文的句柄
displayGraphics = Graphics.FromHdc(displayDC);
}

private void disposeDisplayDC()

{
displayGraphics.Dispose();
DeleteDC(displayDC);
}

private unsafe Point controlToScreen(int x, int y)

{
Point p = new Point(x, y);
Point* pp = &p;
ClientToScreen(Handle, pp);
return p;
}

private void Form1_Paint(object sender, PaintEventArgs e)

{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.Bisque, ClientRectangle);
Font bf = new Font("Times New Roman", 32);
g.DrawString("Bonjour Le Monde", bf, Brushes.Blue, 10, 10);
bf.Dispose();
drawDragImage(g, false, DragMePosition.X, DragMePosition.Y, dragString);
}

private void drawDragImage(Graphics g, bool alphablend, int x, int y, string s)

{
Rectangle r = new Rectangle(x, y, dragImageSize.Width, dragImageSize.Height);

//draw background
if (alphablend)

{
Color c1 = Color.FromArgb(0, Color.Red);
Color c2 = Color.FromArgb(80, Color.Red);
Rectangle r1 = new Rectangle(r.Left, r.Top, r.Width / 2, r.Height);
Rectangle r2 = new Rectangle(r.Left + r.Width / 2, r.Top, r.Width / 2, r.Height);

// 定义一个渐变的笔刷,利用该笔刷可以实现渐变
LinearGradientBrush lgb1 = new LinearGradientBrush(r1, c1, c2, 0f);
LinearGradientBrush lgb2 = new LinearGradientBrush(r2, c2, c1, 0f);

// 用渐变的笔刷来填充矩形
g.FillRectangle(lgb1, r1.Left + 1, r1.Top, r1.Width + 1, r1.Height);
g.FillRectangle(lgb2, r2);

lgb1.Dispose();
lgb2.Dispose();
}
else
g.FillRectangle(Brushes.Red, r);

//Draw the text
Color c;
if (alphablend)
c = Color.FromArgb(80, Color.Black);
else
c = Color.Black;
Brush blackBrush = new SolidBrush(c);
g.DrawString(s, this.dragStringFont, blackBrush, r);
}

private void Form1_MouseDown(object sender, MouseEventArgs e)

{
//Rectangle
Rectangle dragMeRectangle = new Rectangle(DragMePosition, new Size(dragImageSize.Width, dragImageSize.Height));
//Point screenPoint2 = controlToScreen(e.X, e.Y);
if (dragMeRectangle.Contains(e.X, e.Y))

{
mouseDown = true;
mouseDelta = new Point(e.X - DragMePosition.X, e.Y - DragMePosition.Y);

// 得到在显示器中的位置
Point screenPoint = controlToScreen(e.X, e.Y);

// 算出所绘的图片顶点在屏幕中的坐标
screenPoint.X -= mouseDelta.X;
screenPoint.Y -= mouseDelta.Y;

// 取得屏幕的DC
getDisplayDC();

backingStore = new Bitmap(dragImageSize.Width, dragImageSize.Height);
backingStoreGraphics = Graphics.FromImage(backingStore);
//backingStoreGraphics.FillRectangle(Brushes.Red, 0, 0, backingStore.Width, backingStore.Height);
backingStoreDC = backingStoreGraphics.GetHdc();

// 把屏幕上的图片考到位图上
BitBlt(backingStoreDC, 0, 0, backingStore.Width, backingStore.Height, displayDC, screenPoint.X, screenPoint.Y, SRCCOPY);
// 利用BitBlt方法,可以直接往显示器上绘图,这个和DrawString方法都是差不多的。
BitBlt(displayDC, screenPoint.X, screenPoint.Y, backingStore.Width, backingStore.Height, backingStoreDC, 0, 0, SRCCOPY);
//BitBlt(displayDC, screenPoint.X+30, screenPoint.Y+30, backingStore.Width, backingStore.Height, backingStoreDC, 0, 0, SRCCOPY);
backingStorePos = new Point(screenPoint.X, screenPoint.Y);

drawDragImage(displayGraphics, true, screenPoint.X, screenPoint.Y, dragString);
}
}

private void Form1_MouseMove(object sender, MouseEventArgs e)

{
if (mouseDown)

{
Point screenPoint = controlToScreen(e.X, e.Y);

screenPoint.X -= mouseDelta.X;
screenPoint.Y -= mouseDelta.Y;

// 通过循环,重新覆盖背景图片
// 先覆盖
BitBlt(displayDC, backingStorePos.X, backingStorePos.Y, backingStore.Width, backingStore.Height, backingStoreDC, 0, 0, SRCCOPY);
// 后取,把screenPoint范围内的全部存下来
BitBlt(backingStoreDC, 0, 0, backingStore.Width, backingStore.Height, displayDC, screenPoint.X, screenPoint.Y, SRCCOPY);
backingStorePos = new Point(screenPoint.X, screenPoint.Y);

// 利用DrawString方法绘出字符串
drawDragImage(displayGraphics, true, screenPoint.X, screenPoint.Y, dragString);
}
}

private void Form1_MouseUp(object sender, MouseEventArgs e)

{
if (mouseDown)

{
mouseDown = false;
BitBlt(displayDC, backingStorePos.X, backingStorePos.Y, backingStore.Width, backingStore.Height, backingStoreDC, 0, 0, SRCCOPY);

disposeDisplayDC();

backingStoreGraphics.ReleaseHdc(backingStoreDC);
backingStoreGraphics.Dispose();

backingStore.Dispose();
backingStore = null;
}
}
#endregion
}
}

BitBlt是GDI中的方法,它通过各个对象的句柄来直接实现绘图操作,是一个十分重要的方法。