從VB 6到VB.NET——窗體特殊應用 (轉)
從6到——窗體特殊應用:namespace prefix = o ns = "urn:schemas--com::office" />
李洪根
一、 摘要
VB做為的升級版本,具備了許多新的功能,它可以簡便快捷地建立 .NET 應用(包括 XML services 和 .NET Web 應用程式),還是一個功能強大的面向的語言(如繼承、介面和過載)。新的語言功能包括自由執行緒處理和結構化異常處理。VB.NET 還完全整合了.NET 和公共語言執行庫,.NET 框架和公共語言執行庫共同提供語言互操作性、垃圾回收、增強的性和改進的版本支援。可以說是一個劃時代的產品!
從VB6到VB.NET的開發過程中,窗體應用始終是一個永恆的話題。任何一個的應用程式,都與窗體密切相關,在許多場合,我們都需要對窗體進行一些特殊的設定或操作,本文用VB6和VB.NET相結合,來說明窗體應用的特殊問題及處理,以及VB.NET給我們帶來的新的功能!
二、正文
1、 建立特殊形狀的窗體
我們還是來看一下在VB6中的實現,VB6中實現(藉助)
做一個古怪的視窗必須要用的也是此程式中最重要的一個函式就是SetWindowRgn
它的功能就是對指定的視窗進行重畫,把這個視窗你選擇的部分留下其餘的部分抹掉
引數:hWnd:你所要重畫的視窗的控制程式碼,比如你想重畫form1則應該讓此引數為form1.hWnd
hRgn:你要保留的區域的控制程式碼,這個控制程式碼是關鍵,你需要透過別的渠道來獲得
在這裡的區域是由Combinergn合成的新區域
bRedram:是否要馬上重畫,一般設為true
函式CombineRgn將兩個區域組合為一個新區域
函式Createrectrgn為建立一個由點X1,Y1和X2,Y2描述的矩形區域
函式CreateEllipticRgn為建立一個X1,Y1和X2,Y2的橢圓區域
用Delete這個函式可刪除GDI物件,比如畫筆、刷子、字型、點陣圖、區域以及調色盤等等。物件使用的所有資源都會被釋放
以下是VB6的程式碼:
Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Const RGN_DIFF = 4
Private Sub Form_Load()
Dim rgn As Long
Dim rgnRect As Long
Dim rgnDest As Long
rgn = CreateEllipticRgn(0, 0, Me.Width / Screen.TwipsPerPixelX, Me.Height / Screen.TwipsPerPixelY)
rgnRect = CreateRectRgn((Me.Width / Screen.TwipsPerPixelX - 20) / 2, (Me.Height / Screen.TwipsPerPixelY - 20) / 2, (Me.Width / Screen.TwipsPerPixelX + 20) / 2, (Me.Height / Screen.TwipsPerPixelY + 20) / 2)
rgnDest = CreateRectRgn(0, 0, 1, 1)
CombineRgn rgnDest, rgn, rgnRect, RGN_DIFF
SetWindowRgn Me.hWnd, rgnDest, True
Call DeleteObject(rgnRect)
Call DeleteObject(rgnDest)
End Sub
Private Sub Command1_Click()
End
End Sub
在VB.NET中,我們可以使用.NET 框架類庫System.Drawing.Drawing2D的 類(應用程式使用路徑來繪製形狀的輪廓、填充形狀內部和建立剪輯區域),來繪製圖形,
然後透過窗體的Me.Region來設定視窗的可見區域。
以下是VB.NET的程式碼:
'宣告一個布林型變數,判斷窗體是否正常區域
Dim IsNormalRegion As Boolean = True
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
If (IsNormalRegion) Then
'構造一個GraphicsPath物件例項
Dim Graphics As New System.Drawing.Drawing2D.GraphicsPath()
Dim intHeight As Integer = Me.Size.Height
Dim intWidth As Integer = Me.Size.Width
'定義內矩形的左上角座標
Dim RectTop As Integer = 100
'在窗體上繪製一個大橢圓,左上角的座標取為(0,0)
Graphics.AddEllipse(0, 0, intWidth, intHeight)
'再繪製一個小矩形
Dim AddRect As New Rectangle(RectTop, RectTop, intHeight - (RectTop * 2), intHeight - (RectTop * 2))
Graphics.AddRectangle(AddRect)
'設定視窗的可見區域
Me.Region = New Region(Graphics)
Else
Me.Region = Nothing
End If
IsNormalRegion = Not IsNormalRegion
End Sub
程式執行的結果如下:
2、 使窗體在其他所有窗體之上(Allway On Top)
VB6中實現(藉助API函式SetWindowPos)
Private Declare Function SetWindowPLib "user32" (ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, _
ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
---- hWnd變元是視窗的控制程式碼;x,y是視窗的左上角的座標;cx、cy是視窗寬度和高度;hWndInsertAfter變元是視窗清單中hWnd視窗前面的視窗控制程式碼,有四個可選值:
序號 可 選 值 作 用
1 HWND_BOTTOM 把視窗放在視窗清單的底部
2 HWND_TOP 把視窗放在視窗清單的字元順序的頂部
3 HWND_TOPMOST 把視窗放在視窗清單的頂部
4 HWND_NOTOPMOST 把視窗放在視窗清單的頂部,最上層視窗之下
---- WFlags變元為整型值,有八個可選值:
序號 可 選 值 作用
1 SWP_DRAWFRAME 在視窗周圍畫一個方框
2 SWP_HWINDOW 隱藏視窗
3 SWP_NOACTIVATE 不啟用視窗
4 SWP_NOMOVE 保持視窗當前位置
5 SWP_NOREDRAW 視窗不自動重畫
6 SWP_NOSIZE 保持視窗當前尺寸
7 SWP_NOZORDER 保持視窗在視窗清單中的當前位置
8 SWP_SHOWWINDOW 顯示視窗
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, _
ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const SWP_NOMOVE = 2
Private Const SWP_NOSIZE = 1
Private Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Sub Command1_Click()
'把窗體放在最前面:
res% = SetWindowPos(Form1.hwnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS)
End Sub
Private Sub Command2_Click()
'使窗體恢復普通:
res% = SetWindowPos(Form1.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, FLAGS)
End Sub
在VB.NET中,太簡單了!系統為窗體提供了TopMost屬性,我們將TopMost屬性設定為True,就實現了Allways On Top 的功能,要取消此功能,設定為False即可。
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.TopMost = True
End Sub
3、 窗體透明度漸變效果
我們還是來看一下在VB6中的實現,VB6中實現(藉助API函式SetLayeredWindowAttributes)
使用這個函式,可以輕鬆的控制窗體的透明度。按照的要求,透明窗體在建立時應使用WS_EX_LAYERED引數(用CreateWindowEx),或者在建立後設定該引數(用SetWindowLong),我選用後者。
SetLayeredWindowAttributes函式,其中hwnd是透明窗體的控制程式碼,crKey為顏色值,bAlpha是透明度,取值範圍是[0,255],dwFlags是透明方式,可以取兩個值:當取值為LWA_ALPHA時,crKey引數無效,bAlpha引數有效;當取值為LWA_COLORKEY時,bAlpha引數有效而窗體中的所有顏色為crKey的地方將變為透明。
Const LWA_COLORKEY = &H1
Const LWA_ALPHA = &H2
Const GWL_EXSTYLE = (-20)
Const WS_EX_LAYERED = &H80000
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Sub Form_Load()
Dim Ret As Long
'Set the window style to 'Layered'
Ret = GetWindowLong(Me.hWnd, GWL_EXSTYLE)
Ret = Ret Or WS_EX_LAYERED
SetWindowLong Me.hWnd, GWL_EXSTYLE, Ret
'Set the opacity of the layered window to 128
'我們可以設定這個數值來控制透明程度
SetLayeredWindowAttributes Me.hWnd, 0, 128, LWA_ALPHA
End Sub
在VB.NET中,太簡單了!系統為窗體提供了Opacity屬性,來確定窗體的不透明和透明程度,0%為透明,100%為不透明。
以下程式透過迴圈顯示窗體的透明度過程,為了讓大家看清楚其變化,在迴圈過程中使用了System.Threading.Thread.Sleep來停頓。
Private Sub button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles button1.Click
'窗體的透明度漸變過程
button1.Enabled = False
Dim I As Double
For I = 0.01 To 1 Step 0.01
Me.Opacity = I
System.Windows.Forms.Application.DoEvents()
System.Threading.Thread.Sleep(5)
Next
Me.Opacity = 1
button1.Enabled = True
End Sub
4、 使窗體右上角的X無效,禁止Alt+F4關閉窗體
在特殊窗體的應用中,我們有時需要把窗體右上角標題欄上的關閉按鈕螢幕,當點選其它地方(比如說一個Button)退出,那我們怎麼做呢?。
我們還是來看一下在VB6中的實現,VB6中實現(藉助API函式)
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Const MF_BYPOSITION = &H400&
Const MF_REMOVE = &H1000&
Private Sub Form_Load()
Dim hSysMenu As Long, nCnt As Long
' Get handle to our form's system menu
' (Restore, Maximize, Move, close etc.)
hSysMenu = GetSystemMenu(Me.hwnd, False)
If hSysMenu Then
' Get System menu's menu count
nCnt = GetMenuItemCount(hSysMenu)
If nCnt Then
' Menu count is based on 0 (0, 1, 2, 3...)
RemoveMenu hSysMenu, nCnt - 1, MF_BYPOSITION Or MF_REMOVE
RemoveMenu hSysMenu, nCnt - 2, MF_BYPOSITION Or MF_REMOVE ' Remove the seperator
DrawMenuBar(Me.hwnd)
' Force caption bar's refresh. Disabling X button
Me.Caption = "Try to close me!"
End If
End If
End Sub
'如果還要遮蔽Alt+F4,加上
Private Sub Form_QueryUnload(ByVal Cancel As Integer, ByVal UnloadMode As Integer)
Cancel = 1
End Sub
在VB.NET中,這次需要藉助API了,因為系統沒有提供這樣的類,這個例子,同時給大家提供了一個API的使用範例。(因為系統類庫包裝了絕大部分API,所以不推薦使用)
以下是VB.NET的程式碼:
'API宣告
Private Declare Function GetSystemMenu Lib "User32" (ByVal hwnd As Integer, ByVal bRevert As Long) As Integer
Private Declare Function RemoveMenu Lib "User32" (ByVal hMenu As Integer, ByVal nPosition As Integer, ByVal wFlags As Integer) As Integer
Private Declare Function DrawMenuBar Lib "User32" (ByVal hwnd As Integer) As Integer
Private Declare Function GetMenuItemCount Lib "User32" (ByVal hMenu As Integer) As Integer
Private Const MF_BYPOSITION = &H400&
Private Const MF_DISABLED = &H2&
Private Sub disableX(ByVal wnd As Form)
Dim hMenu As Integer, nCount As Integer
'得到系統Menu
hMenu = GetSystemMenu(wnd.Handle.ToInt32, 0)
'得到系統Menu的個數
nCount = GetMenuItemCount(hMenu)
'去除系統Menu
Call RemoveMenu(hMenu, nCount - 1, MF_BYPOSITION Or MF_DISABLED)
'重畫MenuBar
DrawMenuBar(Me.Handle.ToInt32)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'使用X不能用
disableX(Me)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'關閉視窗
Me.Close()
End Sub
'如果還要遮蔽Alt+F4,加上
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Dim SC_CLOSE As Integer = 61536
Dim WM_SYMMAND As Integer = 274
'判斷是系統訊息,是不是關閉窗體,使Alt+F4無效
If m.Msg = WM_SYSCOMMAND AndAlso m.WParam.ToInt32 = SC_CLOSE Then
Exit Sub
End If
MyBase.WndProc(m)
End Sub
程式執行的結果如下:
5、 無標題欄的窗體的拖動問題
在特殊窗體的應用中,我們有時需要把窗體的標題欄遮蔽掉,以窗體換上自己的外殼。是,當去掉了窗體標題欄後,移動窗體就成了一個問題。
我們還是來看一下在VB6中的實現,VB6中實現(藉助API函式SendMessage)
在設計時將窗體的BorderStyle屬性設定為0-none
Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Private Declare Sub ReleaseCapture Lib "User32" ()
Const WM_NCLBUTTONDOWN = &HA1
Const HTCAPTION = 2
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim lngReturnValue As Long
If Button = 1 Then
'Release capture
Call ReleaseCapture()
'Send a 'left mouse button down on caption'-message to our form
lngReturnValue = SendMessage(Me.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End If
End Sub
Private Sub Form_Paint()
Me.Print("Click on the form, hold the mouse button and drag it")
End Sub
在VB.NET中,這次需要藉助API SendMessage 了
在設計時將Form.FormBorderStyle 屬性設定為None,然後新增以下程式碼:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Declare Sub ReleaseCapture Lib "User32" ()
Const WM_NCLBUTTONDOWN = &HA1
Const HTCAPTION = 2
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
ReleaseCapture()
SendMessage(Me.Handle.ToInt64, WM_NCLBUTTONDOWN, HTCAPTION, 0)
End Sub
三、結束語
以上例項在,VB6,VS.NET環境下執行透過。從以上例項,我們可以看到,以前VB6沒有的好多屬性和方法,在VB.NET中已經提供了出來,而且.NET提供了許多類庫,可以完成在VB6中需要藉助大量的API才能實現的操作。比如說構建一個多執行緒應用程式,用VB.NET就很容易了!更值得一提的就是,VB.NET是完全的物件導向,更加容易封裝我們的業務邏輯,構建N層應用程式等企業級應用。我愛VB6,更愛.NET!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-958387/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VB6升級到VB.NET(1) App的變化 (轉)APP
- VB.net中HOOK的應用(二) (轉)Hook
- VB.NET聊天程式 (轉)
- VB.Net中文教程(6) 母子物件關係 (轉)物件
- 在你的VB.NET應用程式中使用多執行緒 (轉)執行緒
- 精通ASP.NET(基於VB.NET)( 二)VB.NET類 (轉)ASP.NET
- 精通ASP.NET(基於VB.NET)(四)VB.NET繼承 (轉)ASP.NET繼承
- VB.NET中物件的克隆 (轉)物件
- 精通ASP.NET(基於VB.NET)( 三)VB.NET異常處理 (轉)ASP.NET
- 在VB.NET中尋找App (轉)APP
- VB.net 編碼規範(也適用於C#) (轉)C#
- 【從VB.NET視訊看學習態度】
- C#/VB.NET 將RTF轉為HTMLC#HTML
- C#/VB.NET 將Html轉為ExcelC#HTMLExcel
- VB中實現窗體自動隱藏 (轉)
- 用JScript實現VB.Net,C#的[委託Delegate]: (轉)JSC#
- Managed C++: Another VB, or VB.NET, or WhateverC++
- C#/VB.NET 將彩色PDF轉為灰度C#
- 走近VB.Net(二) 再談函式呼叫 (轉)函式
- VB.Net中文教程(11) Prototype樣式 (轉)
- VB.net 跟 C# 的程式碼轉換C#
- vb.net 讀取ExcelExcel
- VB.NET 總結一
- Managing Namespaces in VB.Netnamespace
- 在VB中實現窗體的動態效果 (轉)
- Henry的VB.NET之旅(十)—何時用介面
- 用VB實現“百葉窗”的圖形特效 (轉)特效
- C#/VB.NET 在Excel單元格中應用多種字型格式C#Excel
- VB.Net中文教程(2) Composite樣式 (轉)
- vb.net 存取資料庫中的圖片 (轉)資料庫
- 精通ASP.NET(基於VB.NET)(一)概述 (轉)ASP.NET
- VB.NET中監視資料夾的變化 (轉)
- VB.Net中文教程(7) Me參考值 (轉)
- VB.Net中文教程(5)程式多重定義 (轉)
- 在托盤上顯示Balloon Tooltip(VB.NET) (轉)
- VB中API的宣告特殊問題 (轉)API
- VB.net 與 C# 的對應邏輯運算子C#
- 手把手教會將 Windows 窗體桌面應用從.NET Framework遷移到 .NET SDK/.NET 6 格式WindowsFramework