您的位置:首页 > 编程语言 > C#

C#使用GDI绘制格尺

2013-01-13 02:22 786 查看
使用C#绘制一个标尺,其实是在学习Gdi绘图的一些知识,也在试验出好多人平时总问的一个问题,一个毫米等于多少像素,同时自己也了解了在图形中尺寸是怎么计算的。



1.尺寸的确定
在使用标尺测试控件的宽度时,一个像素是指起始点开始后一个像素点才为一个像素,我总是认为一个像素就是屏幕上的一个格子。



2.如何使用重绘时不闪烁
在网上找到许多人的文章,代码如下,收藏之:

private void InitControl()
{
InitializeComponent();

//减少闪烁
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
}


3.Onpaint的参数中ClipRectangle为需重绘矩形区域,不要误认为是ClientRectangle。
4.毫米与像素的换算,其实是依赖于显示设备的和分辨率以及DPI的,需要使用API确定这些值后,经过换算就可以得到。

public static double MillimetersToPixelsWidth(IntPtr hDc, double length)
{
//以毫米为单位的显示器宽度
int width = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZSIZE); // 4
//像素数量
int pixels = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZRES); //8
return (((double)pixels / (double)width) * (double)length);
}
public static double PixelsToMillimetersWidth(IntPtr hDc, double length)
{
int width = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZSIZE);
int pixels = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZRES);
return (double)width / (double)pixels * (double)length;
}


这里收藏一下GetDeviceCaps方法的调用,其声明为如下:

[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int Index);


调用时hdc为设备句柄,要以使用这种方式获取:

var hDc = Util.NativeMethods.GetDC(this.Handle);


其中的亦为API函数,需要声明引用。
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);


最后源代码文件:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace DrawLine
{
public partial class PixRular : Control
{
public PixRular()
{
InitControl();
}

private void InitControl()
{
InitializeComponent();

//减少闪烁
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
}

public PixRular(IContainer container)
{
container.Add(this);

InitControl();
}

protected override void OnSizeChanged(EventArgs e)
{
this.Invalidate();

base.OnSizeChanged(e);
}

/// <summary>
/// 注意,e.ClipRectangle为需要重绘的矩形区域(失效区域),并不是ClientRectangle,
/// 如果不能确定重绘区域内的内容,则按ClientRectangle全部重绘一遍
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
var clientRect = this.ClientRectangle;

//backgroup
var br = new SolidBrush(Color.LightGoldenrodYellow);
e.Graphics.FillRectangle(br, clientRect);
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(clientRect.Location, new Size(clientRect.Width - 1, clientRect.Height - 1)));

//draw rular
var pen = Pens.Black;
var width = clientRect.Width;
var height = clientRect.Height;
var unitHeight = 10;
var halfUnitHeght = 5;
var packUnitHeight = 15;
var hDc = Util.NativeMethods.GetDC(this.Handle);

for (int i = 0; i < width; i++)
{
if (i % 50 == 0)
{
e.Graphics.DrawLine(pen, i, 0, i, packUnitHeight);
e.Graphics.DrawString(i.ToString(), this.Font, Brushes.Black, i, packUnitHeight + 1);
e.Graphics.DrawString(Util.PixelsToMillimetersWidth(hDc,(double)i).ToString("f1") + "mm", this.Font, Brushes.Black, i, packUnitHeight + 15);
}
else
{
if (i % 10 == 0)
{
e.Graphics.DrawLine(pen, i, 0, i, unitHeight);
}
else if (i % 5 == 0)
{
e.Graphics.DrawLine(pen, i, 0, i, halfUnitHeght);
}
}
}

base.OnPaint(e);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using DrawLine.Enums;
using System.Drawing.Drawing2D;

namespace DrawLine
{
class Util
{

public static double MillimetersToPixelsWidth(IntPtr hDc, double length) {
int width = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZSIZE);
int pixels = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZRES);
return (((double)pixels / (double)width) * (double)length);
}

public static double PixelsToMillimetersWidth(IntPtr hDc, double length)
{
int width = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZSIZE);
int pixels = NativeMethods.GetDeviceCaps(hDc, NativeMethods.CapIndex.HORZRES);
return (double)width / (double)pixels * (double)length;
}

public class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int Index);

public class CapIndex
{
public static readonly int DRIVERVERSION = 0;
public static readonly int TECHNOLOGY = 2;
public static readonly int HORZSIZE = 4;
public static readonly int VERTSIZE = 6;
public static readonly int HORZRES = 8;
public static readonly int VERTRES = 10;

4000
public static readonly int BITSPIXEL = 12;
public static readonly int PLANES = 14;
public static readonly int NUMBRUSHES = 16;
public static readonly int NUMPENS = 18;
public static readonly int NUMMARKERS = 20;
public static readonly int NUMFONTS = 22;
public static readonly int NUMCOLORS = 24;
public static readonly int PDEVICESIZE = 26;
public static readonly int CURVECAPS = 28;
public static readonly int LINECAPS = 30;
public static readonly int POLYGONALCAPS = 32;
public static readonly int TEXTCAPS = 34;
public static readonly int CLIPCAPS = 36;
public static readonly int RASTERCAPS = 38;
public static readonly int ASPECTX = 40;
public static readonly int ASPECTY = 42;
public static readonly int ASPECTXY = 44;
public static readonly int SHADEBLENDCAPS = 45;
public static readonly int LOGPIXELSX = 88;
public static readonly int LOGPIXELSY = 90;
public static readonly int SIZEPALETTE = 104;
public static readonly int NUMRESERVED = 106;
public static readonly int COLORRES = 108;
public static readonly int PHYSICALWIDTH = 110;
public static readonly int PHYSICALHEIGHT = 111;
public static readonly int PHYSICALOFFSETX = 112;
public static readonly int PHYSICALOFFSETY = 113;
public static readonly int SCALINGFACTORX = 114;
public static readonly int SCALINGFACTORY = 115;
public static readonly int VREFRESH = 116;
public static readonly int DESKTOPVERTRES = 117;
public static readonly int DESKTOPHORZRES = 118;
public static readonly int BLTALIGNMENT = 119;

}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C# 像素转换毫米