C# 调用SetROP2实现橡皮线效果
郭胜涛 mailtogst@163.com
DotNet Framework的GDI+较GDI添加了新的功能并对现有的功能进行了优化,
但是Graphics类中没有提供实现类似GDI中SetROP2函数来更改绘图模式的功能。
在计算机图形应用程序开发过程中经常用到反色模式来实现用户交互活动线,
我们可以在.Net 开发环境调用非托管的Win32 API 来实现上述的功能。
先来看实例代码:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.InteropServices;

namespace
Win32APIDraw

...
{

/**//// <summary>
/// 封装交互线效果的类
/// </summary>
public class Win32XORPenDrawer : IDisposable

...{

声明Win32 api#region 声明Win32 api
struct POINTAPI

...{
public int x;
public int y;
}
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);

[DllImport("gdi32.dll")]
private static extern bool MoveToEx(IntPtr hDC,
IntPtr x,
IntPtr y,
ref POINTAPI lpPoint);

[DllImport("gdi32.dll")]
private static extern IntPtr LineTo(IntPtr hdc, IntPtr x, IntPtr y);
[DllImport("gdi32.dll")]
private static extern IntPtr SetROP2(IntPtr hdc, IntPtr fnDrawMode);

#endregion


构造函数#region 构造函数

/**//// <summary>
/// 传入创建DC的句柄和绘图模式
/// </summary>
/// <param name="hWnd"></param>
/// <param name="drawMode"></param>
public Win32XORPenDrawer(int hWnd, int drawMode)

...{
//GetDC by hwnd
this.hWnd = hWnd;
IntPtr res = GetDC(new IntPtr(hWnd));
hDc = res.ToInt32();
SetROP2(res, new IntPtr(drawMode));
}


~Win32XORPenDrawer()

...{
Dispose(false);
}

#endregion


私有成员#region 私有成员
private int hDc;

private int hWnd;

private bool disposed = false;

private void Dispose(bool disposing)

...{
if (!this.disposed)

...{
//ReleaseDC
ReleaseDC(new IntPtr(hWnd), new IntPtr(hDc));
}
disposed = true;
}
#endregion


公共接口#region 公共接口

IDisposable 成员#region IDisposable 成员

public void Dispose()

...{
Dispose(true);
}

#endregion


/**//// <summary>
/// 从x1, y1向x2, y2画线
/// </summary>
/// <param name="x1"></param>
/// <param name="y1"></param>
/// <param name="x2"></param>
/// <param name="y2"></param>
public void DrawLine(int x1, int y1, int x2, int y2)

...{
POINTAPI lpOld = new POINTAPI();
MoveToEx(new IntPtr(hDc), new IntPtr(x1), new IntPtr(y1), ref lpOld);
LineTo(new IntPtr(hDc), new IntPtr(x2), new IntPtr(y2));
}

public void MoveTo(int x, int y)

...{
POINTAPI lpOld = new POINTAPI();
MoveToEx(new IntPtr(hDc), new IntPtr(x), new IntPtr(y), ref lpOld);
}

public void LineTo(int x, int y)

...{
LineTo(new IntPtr(hDc), new IntPtr(x), new IntPtr(y));
}
#endregion
}
}
代码分析:
1 首先声明用到的Win32 API 函数.
主要用到GetDC, ReleaseDC, SetROP2, LineTo, MoveToEx几个函数,如果需要扩充其他交互效果
(如画弧)还要增加相应的API函数声明。
我们使用SetROP2函数来设置画笔的反色效果。
2 这个类的构造函数中传入图形设备的句柄和绘图模式,可以是窗体或打印机, 也可以是承载其他画图效果控件
的。当绘图模式参数传入值是6时,就是反色效果。因为在构造函数中我们调用了SetROP2函数。
这和在VC++中的实现方法是一致的。
3 声明相应的画线方法,调用Win32API画线。
最后要注意的是,在c#环境下必须注意释放通过win32API中创建的非托管资源,因此,我们使这个类实现
IDisposable接口。
运行效果:
