Visual Studio 2022 VB.Net如何制作带标尺和页面边框的窗体应用
VB.Net WinForm 实现标尺+页面边框效果
问题背景
开发环境:Visual Studio 2022 + VB.Net Windows 窗体应用框架
需求:实现类似Office文档编辑区的标尺、带阴影的页面边框效果,效果参考下图:
实现思路
完全基于原生GDI+自定义绘图实现,不需要引入第三方控件,核心是在容器控件的Paint事件里分层绘制标尺、页面、阴影、刻度元素,开启双缓冲避免绘图闪烁即可。
具体实现步骤
- 第一步:搭建基础画布
从工具箱拖一个Panel控件到窗体,命名为printCanvas,作为绘图的容器。在窗体构造函数里通过反射开启Panel的双缓冲,避免拖动、缩放时的闪烁问题,代码如下:Public Sub New() InitializeComponent() ' 开启Panel双缓冲,默认属性面板不暴露该配置 Dim doubleBufferProp = GetType(Panel).GetProperty( "DoubleBuffered", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic ) doubleBufferProp.SetValue(printCanvas, True, Nothing) End Sub - 第二步:编写Paint事件绘图逻辑
给printCanvas绑定Paint事件,按「页面阴影→页面白底+边框→标尺背景→标尺刻度」的顺序绘制,避免图层覆盖。核心代码如下:Private Sub printCanvas_Paint(sender As Object, e As PaintEventArgs) Handles printCanvas.Paint Dim g As Graphics = e.Graphics g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias g.Clear(Color.FromArgb(240, 240, 240)) ' 画布背景设为浅灰 ' 固定配置项 可根据自己的需求调整 Const RulerSize As Integer = 32 ' 水平/垂直标尺的宽/高 Const PageGap As Integer = 25 ' 标尺和页面之间的间距 Const PageShadowOffset As Integer = 4 ' 页面阴影偏移量 Dim pageSize As New Size(850, 1202) ' 页面尺寸 按A4比例(1:√2)设置即可 ' 计算页面所在的矩形区域 Dim pageRect As New Rectangle( RulerSize + PageGap, RulerSize + PageGap, pageSize.Width, pageSize.Height ) ' 1. 绘制页面阴影 g.FillRectangle(Brushes.Gainsboro, pageRect.X + PageShadowOffset, pageRect.Y + PageShadowOffset, pageRect.Width, pageRect.Height) ' 2. 绘制页面白底+黑色边框 g.FillRectangle(Brushes.White, pageRect) g.DrawRectangle(Pens.Black, pageRect) ' 3. 绘制水平标尺 Dim hRulerRect As New Rectangle(RulerSize, 0, pageSize.Width, RulerSize) g.FillRectangle(Brushes.WhiteSmoke, hRulerRect) g.DrawLine(Pens.Gray, hRulerRect.Left, hRulerRect.Bottom - 1, hRulerRect.Right, hRulerRect.Bottom - 1) ' 毫米转像素 按当前系统DPI计算,96DPI下1毫米≈3.78像素 Dim mm2Px As Single = g.DpiX / 25.4F For mm = 0 To CInt(pageSize.Width / mm2Px) Dim drawX As Single = hRulerRect.X + mm * mm2Px Select Case mm Mod 10 Case 0 ' 1厘米长刻度+数值标注 g.DrawLine(Pens.Black, drawX, hRulerRect.Bottom, drawX, hRulerRect.Bottom - 12) g.DrawString((mm / 10).ToString(), New Font("微软雅黑", 8F), Brushes.Black, drawX - 9, 2) Case 5 ' 5毫米中刻度 g.DrawLine(Pens.Black, drawX, hRulerRect.Bottom, drawX, hRulerRect.Bottom - 7) Case Else ' 1毫米短刻度 g.DrawLine(Pens.Black, drawX, hRulerRect.Bottom, drawX, hRulerRect.Bottom - 3) End Select Next ' 4. 绘制垂直标尺 Dim vRulerRect As New Rectangle(0, RulerSize, RulerSize, pageSize.Height) g.FillRectangle(Brushes.WhiteSmoke, vRulerRect) g.DrawLine(Pens.Gray, vRulerRect.Right - 1, vRulerRect.Top, vRulerRect.Right - 1, vRulerRect.Bottom) For mm = 0 To CInt(pageSize.Height / mm2Px) Dim drawY As Single = vRulerRect.Y + mm * mm2Px Select Case mm Mod 10 Case 0 ' 1厘米长刻度+竖排数值标注 g.DrawLine(Pens.Black, vRulerRect.Right, drawY, vRulerRect.Right - 12, drawY) g.TranslateTransform(vRulerRect.X + 12, drawY + 9) g.RotateTransform(-90) g.DrawString((mm / 10).ToString(), New Font("微软雅黑", 8F), Brushes.Black, 0, 0) g.ResetTransform() Case 5 ' 5毫米中刻度 g.DrawLine(Pens.Black, vRulerRect.Right, drawY, vRulerRect.Right - 7, drawY) Case Else ' 1毫米短刻度 g.DrawLine(Pens.Black, vRulerRect.Right, drawY, vRulerRect.Right - 3, drawY) End Select Next End Sub - 第三步:可选交互优化
- 需要鼠标定位辅助线:处理Panel的
MouseMove事件,记录当前鼠标坐标,在Paint事件里额外在水平/垂直标尺对应位置绘制红色指示线即可 - 需要支持页面缩放:所有绘图坐标、尺寸统一乘上缩放比例因子,标尺刻度值同步按比例换算
- 需要可拖动页边距标记:在标尺对应边距位置绘制可拖动的小滑块,处理鼠标按下、移动、抬起事件,实时更新边距数值并重绘即可
- 需要鼠标定位辅助线:处理Panel的
内容的提问来源于stack exchange,提问作者Bluerose
相关产品推荐
相关产品推荐

