C#使用GDI绘制格尺
2013-01-13 02:22
786 查看
使用C#绘制一个标尺,其实是在学习Gdi绘图的一些知识,也在试验出好多人平时总问的一个问题,一个毫米等于多少像素,同时自己也了解了在图形中尺寸是怎么计算的。
1.尺寸的确定
在使用标尺测试控件的宽度时,一个像素是指起始点开始后一个像素点才为一个像素,我总是认为一个像素就是屏幕上的一个格子。
2.如何使用重绘时不闪烁
在网上找到许多人的文章,代码如下,收藏之:
3.Onpaint的参数中ClipRectangle为需重绘矩形区域,不要误认为是ClientRectangle。
4.毫米与像素的换算,其实是依赖于显示设备的和分辨率以及DPI的,需要使用API确定这些值后,经过换算就可以得到。
这里收藏一下GetDeviceCaps方法的调用,其声明为如下:
调用时hdc为设备句柄,要以使用这种方式获取:
其中的亦为API函数,需要声明引用。
最后源代码文件:
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);
}
}
}
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#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#使用GDI绘制格尺
- C#学习笔记之使用GDI绘制简单的图形
- c# 使用GDI绘制验证码实例
- C#中使用GDI绘制验证码
- C#使用GDI绘制直线的方法
- C#使用GDI绘制矩形的方法
- OpenGL In C# 02 使用FBO的方式绘制OpenGL窗体 并在XP下实现全透明
- C#:使用双缓冲让界面绘制图形时避免闪烁
- C#使用GDI中的API函数
- C#中使用GDI+绘制一把漂亮的直尺(带透明度)
- Asp.Net使用GDI绘制3D饼图入门篇源码
- C#GDI绘制渐变线条,可用于添加阴…
- 如何使用GDI绘制半透明矩形