📄 shape.cs
字号:
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using OpenNETCF.Windows.Forms;
using OpenNETCF.Win32;
using OpenNETCF.Drawing;
namespace OpenNETCF.Windows.Graphics
{
/// <summary>
/// Used to create irregularly shaped regions from a bitmap.
/// Shape class loads a bitmap and eliminates all areas comprised with white pixels.
/// It can then apply the region to a given control.
/// </summary>
public class Shape: IDisposable
{
private IntPtr m_hRgn;
/// <summary>
/// Retuns a handle to the region
/// </summary>
public IntPtr Region { get { return m_hRgn; } }
/// <summary>
/// Constructs a Shape object out of a bitmap
/// </summary>
/// <param name="st">Stream containg a valid bitmap (BMP only)</param>
public Shape(Stream st)
{
RebuildRegion(st);
}
private void RebuildRegion(Stream st)
{
if ( m_hRgn != IntPtr.Zero )
Utils.DeleteObject(m_hRgn);
int cx = 0, cy = 0;
if ( st == null )
throw new NullReferenceException();
BitmapData b = Utils.GetBitmapData(st);
st.Seek(0, SeekOrigin.Begin);
for( int py = 0; py < b.Height; py ++ )
{
int px = 0;
int clrWhite = 0xffffff & ( ~(int)(0xffffffff << b.BitCount) );
while ( px < b.Width )
{
while( px < b.Width && b.GetPixel(px, py) == clrWhite )
px ++;
if ( px >= b.Width )
break;
int px0 = px;
while( px < b.Width && b.GetPixel(px, py) != clrWhite )
px ++;
if ( m_hRgn == IntPtr.Zero )
{
m_hRgn = Utils.CreateRectRgn(cx + px0 - 1, cy + py - 1, cx + px - 1, cy + py);
bool bRet = Utils.PtInRegion(m_hRgn, cx+px0, cy+py);
bRet = Utils.PtInRegion(m_hRgn, cx+px0, cy+py+1);
bRet = false;
}
else
{
IntPtr hRgn2 = Utils.CreateRectRgn(cx + px0 - 1, cy + py - 1, cx + px - 1, cy + py);
Utils.CombineRgn(m_hRgn, m_hRgn, hRgn2, RgnMode.RGN_OR);
Utils.DeleteObject(hRgn2);
}
}
}
}
/// <summary>
/// Retrieves control's HWND and sets its shape
/// </summary>
/// <param name="c">Control to set shape</param>
public void Apply(Control c)
{
if ( c == null )
throw new ArgumentException();
c.Capture = true;
IntPtr hWnd = Win32Window.GetCapture();
if ( hWnd == IntPtr.Zero )
throw new InvalidOperationException("Could not obtain HWND of the given control");
c.Capture = false;
Utils.SetWindowRgn(hWnd, this.Region, 1);
}
#region IDisposable Members
public void Dispose()
{
Utils.DeleteObject(m_hRgn);
}
#endregion
}
public class Utils
{
public const int HTCAPTION = 2;
public static BitmapData GetBitmapData(Stream st)
{
BitmapData data = new BitmapData();
BinaryReader rdr = new BinaryReader(st);
rdr.BaseStream.Seek(0, SeekOrigin.Begin);
// Check that the BMP file signatrure is present
if ( rdr.ReadByte() != 0x42 || rdr.ReadByte() != 0x4D )
throw new ArgumentException("Invalid bitmap. Only BMP files are accepted.");
rdr.BaseStream.Seek(10, SeekOrigin.Begin);
data.Start = rdr.ReadInt32();
rdr.ReadInt32();
data.Width = rdr.ReadInt32();
data.Height = rdr.ReadInt32();
rdr.ReadInt16();
data.BitCount = rdr.ReadInt16();
rdr.BaseStream.Seek(data.Start, SeekOrigin.Begin);
data.scLine = (data.Width * (data.BitCount >> 3) + 3 >> 2) << 2;
data.Data = rdr.ReadBytes(data.scLine * data.Height);
return data;
}
[DllImport("coredll")]
extern static public IntPtr DeleteObject(IntPtr hObj);
[DllImport("coredll")]
extern static public int SetWindowRgn(
IntPtr hWnd,
IntPtr hRgn,
int bRedraw
);
[DllImport("coredll")]
extern static public int CombineRgn(
IntPtr hrgnDest,
IntPtr hrgnSrc1,
IntPtr hrgnSrc2,
RgnMode fnCombineMode
);
[DllImport("coredll")]
extern static public IntPtr CreateRectRgn(
int nLeftRect,
int nTopRect,
int nRightRect,
int nBottomRect
);
[DllImport("coredll")]
extern static public IntPtr ExtCreateRegion(
IntPtr lpXform,
int nCount,
int[] lpRgnData );
[DllImport("coredll")]
extern static public int GetRgnBox(
IntPtr hrgn,
out RECT rc
);
[DllImport("coredll")]
extern static public bool PtInRegion(
IntPtr hrgn,
int X,
int Y
);
}
public struct RECT
{
public int l;
public int t;
public int r;
public int b;
}
public struct BitmapData
{
public int GetPixel(int x, int y)
{
switch( BitCount )
{
case 1:
case 2:
case 4:
case 16:
case 32:
throw new NotSupportedException("Bitmap must be 8, or 24 bpp");
case 8:
return Data[(Height - y - 1)*scLine+x];
case 24:
int p = ((Height - y - 1)*scLine+x * 3);
return (Data[p] << 16) + (Data[p+1] << 8) + (Data[p + 2]);
default:
throw new NotSupportedException("Bitmap must be 8, or 24 bpp");
}
}
public int Width;
public int scLine;
public int Height;
public int Start;
public int BitCount;
public byte [] Data;
}
public enum RgnMode
{
RGN_AND = 1,
RGN_OR = 2,
RGN_XOR = 3,
RGN_DIFF = 4,
RGN_COPY = 5,
RGN_MIN = RGN_AND,
RGN_MAX = RGN_COPY,
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -