一闪一闪小星星






3.20/5 (12投票s)
如何在 VB.NET 中创建不规则形状的窗体。
引言
曾经,我需要给我的老板留下深刻印象。我们必须进行年度薪资讨论。所以我写了一个应用程序来展示我“非常高级的编程技能”。
背景
现在我已将这个精彩的应用程序翻译成 VB.NET。
使用代码
只需运行代码,您就会看到代码产生的所有壮丽结果。
关注点
基本 API
Structure RECT
Public Left As Int32
Public Top As Int32
Public Right As Int32
Public Bottom As Int32
End Structure
Public Structure POINTAPI
Dim X As Int32
Dim Y As Int32
End Structure
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As Boolean
Declare Function GetStockObject Lib "gdi32.dll" (ByVal nIndex As Int32) As IntPtr
Declare Function GetWindowRgn Lib "user32" (ByVal hwnd As IntPtr,
ByVal hRgn As IntPtr) As IntPtr
Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As IntPtr,
ByVal hRgn As IntPtr, ByVal bRedraw As Boolean) As Int32
'for round form
Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Int32, ByVal Y1 As Int32,
ByVal X2 As Int32, ByVal Y2 As Int32, ByVal X3 As Int32, ByVal Y3 As Int32) As IntPtr
'for star form
Declare Function CreatePolygonRgn Lib "gdi32" (ByRef lpPoint As POINTAPI,
ByVal nCount As Int32, ByVal nPolyFillMode As Int32) As IntPtr
'for elliptic form
Declare Function CreateEllipticRgn Lib "gdi32.dll" (ByVal X1 As Int32,
ByVal Y1 As Int32, ByVal X2 As Int32, ByVal Y2 As Int32) As IntPtr
Declare Function CreateRectRgn Lib "gdi32.dll" (ByVal X1 As Int32, ByVal Y1 As Int32,
ByVal X2 As Int32, ByVal Y2 As Int32) As IntPtr
Declare Function GetWindowDC Lib "user32" (ByVal hWnd As IntPtr) As IntPtr
Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr,
ByVal hdc As IntPtr) As Int32
'for frame of form
Declare Function FrameRgn Lib "gdi32" (ByVal hdc As IntPtr, ByVal hRgn As IntPtr,
ByVal hBrush As IntPtr, ByVal nWidth As Int32, ByVal nHeight As Int32) As IntPtr
Private Const BLACK_BRUSH As Int32 = 4
(注意:POINTAPI
不在框架中。)
星星的制作
Private Sub MakePolygonForm(ByVal InForm As Form, ByVal Offset As Single)
Const WINDING As Int32 = 2
Const RADIEKONVERT As Double = 3.1416 / 180
Const GRADER As Int32 = 360
Const MAXRADER As Int32 = 200
'change this to 6 for a David star, try alsso 5,7,8,9,10
Const SPETSAR As Int32 = 7
Dim x, y As Int32
Dim xCenter, yCenter, Radie, Punkter, I As Int32
Dim Vinkel As Double
Dim Rotation As Int32
Dim arPoints(MAXRADER) As POINTAPI
Dim RECT As RECT
Dim rgn As IntPtr
RECT.Right = 300
RECT.Left = 0
RECT.Top = 0
RECT.Bottom = 300
xCenter = CInt((RECT.Right - RECT.Left) / 2)
yCenter = CInt((RECT.Bottom - RECT.Top) / 2)
Rotation = CInt(GRADER / (2 * SPETSAR))
Punkter = 2 * SPETSAR
Radie = yCenter
For I = 0 To Punkter - 1
If (I Mod 2) = 0 Then
Radie = CInt((Radie / 2))
Else
Radie = yCenter
End If
'remove Offset to make it stay put: Vinkel = I * Rotation * RADIEKONVERT
Vinkel = I * Rotation * RADIEKONVERT + Offset
x = CInt(xCenter + (System.Math.Cos(Vinkel) * Radie))
y = CInt(yCenter + (System.Math.Sin(Vinkel) * Radie))
arPoints(I).X = x
arPoints(I).Y = y
Next
rgn = CreatePolygonRgn(arPoints(0), Punkter, WINDING)
Call SetWindowRgn(Me.Handle, rgn, True)
If CInt(rgn) <> 0 Then DeleteObject(rgn)
End Sub
如果您想要另一种窗体形式,请使用
MakeRoundForm(Me)
或
MakeEllipticForm(Me)
您可以在 FrameRgn 中调整框架的粗细
Private Function FrameWindowRgn(ByVal hwnd As IntPtr) As IntPtr
Dim hRgn,hDC As IntPtr
hDC = GetWindowDC(hwnd) ' Get a DC for non-client area
If CInt(hDC) <> 0 Then
hRgn = CreateRectRgn(0, 0, 0, 0) ' Create empty region
If CInt(hRgn) <> 0 Then
If CInt(GetWindowRgn(hwnd, hRgn)) <> 0 Then
' to make border thicker, adjust the 2:s to something else
FrameWindowRgn = FrameRgn(hDC,hRgn, GetStockObject(BLACK_BRUSH), 2, 2) ' Draw the frame
End If
End If
End If
If CInt(hRgn) <> 0 Then DeleteObject(hRgn) 'release resources
If CInt(hDC) <> 0 Then ReleaseDC(hwnd, hDC) 'release resources
End Function