自制数字时钟项目

在本教程中,将探讨如何从零开始创建一个项目,该项目不仅关注如何旋转图像,而且关注完全用代码实现。正在寻找的是“从头开始”、“自制”的应用程序。准备好接受挑战了吗?

概念

旋转图像的概念很简单。首先,需要找到放置图片角落的位置,然后映射像素,就可以创建出旋转后的图像了。但这听起来像是一项艰巨的工作。幸运的是,有一种更好的方法。在这个问题上,非常重视Graphics类。不仅因为它能实现想要的功能,还因为它存在于窗体的PaintEventArgs中,这对于在运行时显示图像、图表和其他东西至关重要。这个“神奇类”将是代码的焦点。但在开始编码之前...

需要一个体面的图形用户界面(GUI)

创建一个新的VB项目(注意这个应用程序可以在Visual Studio的Express版本中实现):将其命名为PocketWatchVB并点击OK。当一个空白窗体出现时,改变FormBorderStyleFixedSingle。这样做是为了防止用户调整窗体大小,从而避免将来可能出现的错误。为了实现平滑的动画效果,将DoubleBuffered设置为True。这将确保不会看到任何动画闪烁或质量下降。再次确保样式设置为FixedSingle

图像

在进行下一步之前,建议已经准备好了将要用作背景和手表指针的文件。可以从下面下载,自己制作,或者可以使用源代码来检索图像(SRC.zip\Watch\Resources)。如果要自己制作图像,这篇文章是为了256x256的图片尺寸制作的。它们都应该有透明的背景,指针应该比手表略小(但图像尺寸仍然是256x256)。

导入资源

通过更改Form1BackgroundImage并导入所有四个图像来导入应该保存的四个图像。将所有四个图像导入.resx文件。选择(none)。选择none的目的是导入资源后不需要担心代码中的外部路径,程序更便携,引用资源的代码也更清晰。所以不要设置任何BackgroundImage,这只是为了导入资源。将窗体的大小设置为370,370。这将使图像位于窗体的正中心。只是为了外观。

检查点1

如果窗体看起来像这样,做得很好!;)关键是这是一个空白窗体。为了帮助“自制”方面,一切都是在运行时完成的(实际上这种方式更快,更适合叠加图片)。是的,叠加了一个图标。喜欢吗?

编码一切

为了在开始编码之前了解需要做什么,让使用一个表格。

计时器滴答

重新绘制窗体

绘制背景

找到小时

格式化小时为12小时制

找到分钟

找到所有旋转角度

旋转秒针 - 叠加它

旋转分钟针 - 叠加它

旋转小时针 - 叠加它

很容易看出,大部分代码将用于旋转和叠加时钟的指针,而前半部分的程序则用于达到这一点。

声明!

在一切正常工作之前,需要一些声明。这些是项目成功所必需的。

在声明区域导入这些:

Imports System.Windows.Forms Imports System.Drawing Imports System.Drawing.Drawing2D

然后声明以下变量:

Dim clockHour As Double Dim clockmin As Integer Dim hourAng As Integer Dim minAng As Integer Dim secAng As Integer Dim secBMP As Image = (My.Resources.secondHand) Dim minBMP As Image = (My.Resources.minuteHand) Dim hourBMP As Image = (My.Resources.hourHand1) Dim watchBMP As Image = (My.Resources.PocketWatchProj)

在代码运行之前声明BMPs有助于顺利运行。另一方面,需要在关闭窗体之前释放它们。为此,添加一个Form1_FormClosed()事件处理程序。

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed secBMP.Dispose() minBMP.Dispose() hourBMP.Dispose() watchBMP.Dispose() End Sub

绘画

好了,开始工作。代码的主要部分将位于Form1_Paint()事件处理程序中。这就是将真正“绘制”窗体的地方。画家将是继承PaintEventArgs的Graphics类,这样就可以“绘制”窗体。也可以绘制控件、面板等,但代码可能需要调整。

e.Graphics.DrawImage(WatchBMP, 0, 0)

首先,让将怀表绘制到窗体的背面。由于这在Form1_paint()事件处理程序中,e指的是PaintEventArgs。这个类允许访问将绘制窗体的Graphics画家。这里只是告诉“画家”在点(0,0)绘制图片(在资源中)。

clockHour = Now.TimeOfDay.Hours If clockHour > 12 Then clockHour -= 12 ElseIf clockHour = 0 Then clockHour = 12 End If

将24小时制转换为12小时制的普通模拟格式,然后根据每个相应的公式计算角度,这并不难理解,只要计算出需要12小时,将360除以12,然后告诉应用程序相应地乘以,等等。

Dim sec As New Matrix() sec.Translate(1, 1) sec.RotateAt(secAng, New PointF(170, 170)) e.Graphics.Transform = sec e.Graphics.DrawImage(secBMP, 0, 0) sec.Dispose()

这个代码片段创建了一个矩阵,在将更改应用到“画家”之前,可以比普通的Graphics类更成功地操纵矩阵。首先,矩阵被定位,旋转在必要的点以确保时钟的指针不会移出中心,甚至移出屏幕。然后使用e.Graphics.Transform = sec将更改应用到“画家”。在此之后,图像被绘制到窗体上,矩阵被释放以正确地释放资源。

Dim min As New Matrix() min.Translate(1, 1) min.RotateAt(minAng, New PointF(170, 170)) e.Graphics.Transform = min e.Graphics.DrawImage(minBMP, 0, 0) min.Dispose()

请注意,代码与上一个代码片段相同,只是图像、角度和名称等有所不同。这里不需要太多解释。只是上一个代码片段的重复,这里和那里的变化。

Dim hour As New Matrix() hour.Translate(0, 0) hour.RotateAt(hourAng, New PointF(170, 170)) e.Graphics.Transform = hour e.Graphics.DrawImage(hourBMP, 44, 44) hour.Dispose()

这里是变化的地方。做同样的事情,除了图像绘制的位置。出于某种原因,如果在正常点绘制图像,它会使它偏离中心,最好的点是(44,44)。

几乎完成了!

现在工作程序已经完成,需要一种方法来启动它们。添加计时器滴答处理程序来启动这一切。

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick Me.Refresh() End Sub

好的,只是刷新窗体?刷新窗体会使它重新绘制自己。这会调用OnPaint处理程序,它处理所有的职责。那么,让看看这是否有效。运行窗体,时钟应该在一瞬间是空白的,然后看到一张图片。更像是一张自制的图片。=)

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485