郭勝濤
[email protected]
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接口。
運行效果:
