移植VB維護程序到mobile下
Windows CE現(xiàn)在在嵌入式系統(tǒng)應(yīng)用已經(jīng)很多了,以前使用EVC的開發(fā)多些,開發(fā)難度大周期長。VS2005退出后,CF.net2.0對于VB.NET支持很好,使將原來的基于windows平臺的Visual Basic維護程序移植到CE上面提供呢可能,本文將就Visual Basic維護程序移植到CE上面做一個試驗性質(zhì)的開發(fā)。
Visual Basic因為其界面開發(fā)快速,掌握難度低,在嵌入式系統(tǒng)的程序員中應(yīng)用很廣,比如說本人,以前經(jīng)常做些單片機的開發(fā),那么一些系統(tǒng)參數(shù)或規(guī)約的驗證,就會隨手寫個Visual Basic程序驗證下,以前是VB6.0,后來VB.net多些,VB的開發(fā)擴展性好,做界面簡單快速,而且方便在調(diào)試中修改程序,在驗證單片機的程序時是再方便不過了。
最早的人機界面、維護參數(shù)基本是通過串口通訊,在計算機或便攜筆記本上面顯示,設(shè)置。隨著嵌入式系統(tǒng)發(fā)展,用戶要求越來越高,現(xiàn)在好多的設(shè)備上面要有顯示參數(shù)和狀態(tài)的液晶,對于一些高檔設(shè)備,更是需要復(fù)雜的用戶界面,如果能將設(shè)備的維護和狀態(tài)顯示程序移植到基于Windows CE的系統(tǒng)平臺上面去,就會提供快速的軟件開發(fā),用戶界面會更加美觀,開發(fā)速度大幅提供,方便嵌入式系統(tǒng)工程師的開發(fā)工作,同時基于windows CE的PDA掌上電腦,方便攜帶,待機時間更加長,方便現(xiàn)場維護人員和分布式系統(tǒng)的設(shè)置和分析工作。
講原有的VB.net移植到winCE,比較簡單,如果沒有使用第三方的windows平臺的控件,可以很簡單的移植過去,窗體可以很簡單的復(fù)制過去,代碼基本是可以復(fù)用的,如果是VB6的程序,移植的難度會大些,窗體部分設(shè)計需要重新設(shè)置,VB.net的窗體界面和VB的區(qū)別很大,可以先按照老的程序的界面設(shè)置,在新的程序里面設(shè)置,代碼方面的移植難度不大,基本的語句還是一樣的,VB.NET支持界面上的元素可以全新創(chuàng)建,不用想VB那樣,從窗口的控件數(shù)組里面派生了,而且vb.net可以在運行中定義事件的處理函數(shù),這個對VB是很大的改進,是自動根據(jù)規(guī)約或界面設(shè)置進行處理變得方便快捷。
對于嵌入式系統(tǒng)來說和外界的通訊主要有幾個方面,串口(RS485、RS232),網(wǎng)絡(luò)。網(wǎng)絡(luò)方面的程序區(qū)別不是很大,串口方面,windows下面VB程序員一般是使用MSCOMM來進行通訊,微軟在CF.NET2.0里面提供了新的串口開發(fā)支持SerialPort,比1.0和EVC更加快速。另外VB.NET支持多線程,使串口開發(fā)變得容易。
下面提供一個我自己實現(xiàn)的串口多線程類。
Imports System.IO.Ports
Imports System.Threading
‘232串口操作類
‘2006 6 20 V1.0 by 趙力釗
‘使用說明
‘使用前調(diào)用 Init 退出程序或關(guān)閉串口使用 Close
‘SendDate 發(fā)送數(shù)據(jù)到串口 返回發(fā)送成功與否
‘判斷ComStatus 是否為2 數(shù)據(jù)是否準(zhǔn)備好 準(zhǔn)備好 調(diào)用 ReadData 傳空的BYTE數(shù)組(可以Redim的),返回數(shù)據(jù)長度
Public Class RS232TXClass
Shared m_SerialPort As New SerialPort
Shared readThread As Thread = New Thread(AddressOf Read)
Public ComSetting As String ‘"9600,n,8,1"
Public ComPort As Integer
Public ComType As Integer ‘硬件設(shè)置
Dim strBaudRate As String
Dim Parity As String
Dim Handshake As Integer
Dim DataBits As Integer
Dim PortName As String
Dim StopBits As Integer
Shared _continue As Boolean
Shared bRxLock As Boolean
Shared iRxLen As Integer
Shared iRxTime As Integer
Shared bRxStatus As Byte
Const READOK = 2
Const READOUTTIME = 4
Const READLOCK = 8
Const COMOK = 1
Const COMERROR = 0
Const COMFREE = 16
‘輸入函數(shù) setting 串口設(shè)置如 9600,n,8,1 Type 握手協(xié)議 0 沒有握手協(xié)議 Port 串口號
Public Sub Init(ByVal Setting As String, ByVal Type As Integer, ByVal Port As Integer)
ComSetting = Setting
ComPort = Port
ComType = Type
ComInit()
End Sub
Sub ComInit()
Dim iStart As Integer
Dim iTemp As Integer
Dim bDate() As Byte
m_SerialPort = New System.IO.Ports.SerialPort()
iStart = InStr(1, ComSetting, ",")
strBaudRate = Mid(ComSetting, 1, iStart - 1)
iTemp = InStr(iStart + 1, ComSetting, ",")
Parity = Mid(ComSetting, iStart + 1, iTemp - iStart - 1)
iStart = iTemp + 1
iTemp = InStr(iStart, ComSetting, ",")
DataBits = CInt(Mid(ComSetting, iStart, iTemp - iStart))
iStart = iTemp + 1
StopBits = CInt(Mid(ComSetting, iStart, Len(ComSetting) - iStart + 1))
m_SerialPort.BaudRate = strBaudRate
Select Case Parity
Case "n"
m_SerialPort.Parity = IO.Ports.Parity.None
Case "N"
m_SerialPort.Parity = IO.Ports.Parity.None
Case "e"
m_SerialPort.Parity = IO.Ports.Parity.Even
Case "E"
m_SerialPort.Parity = IO.Ports.Parity.Even
Case "o"
m_SerialPort.Parity = IO.Ports.Parity.Odd
Case "O"
m_SerialPort.Parity = IO.Ports.Parity.Odd
End Select
m_SerialPort.DataBits = DataBits
Select Case StopBits
Case 0
m_SerialPort.StopBits = IO.Ports.StopBits.None
Case 1
m_SerialPort.StopBits = IO.Ports.StopBits.One
Case 2
m_SerialPort.StopBits = IO.Ports.StopBits.Two
End Select
Select Case ComType
Case 0
m_SerialPort.Handshake = IO.Ports.Handshake.None
[!--empirenews.page--]Case 1
m_SerialPort.Handshake = IO.Ports.Handshake.RequestToSend
Case 2
m_SerialPort.Handshake = IO.Ports.Handshake.RequestToSendXOnXOff
Case 3
m_SerialPort.Handshake = IO.Ports.Handshake.XOnXOff
End Select
m_SerialPort.PortName = "COM" + CStr(ComPort)
m_SerialPort.ReadTimeout = 500
m_SerialPort.WriteTimeout = 500
If m_SerialPort.IsOpen = True Then
m_SerialPort.Close()
End If
m_SerialPort.Open()
If m_SerialPort.IsOpen = True Then
bRxStatus = COMOK
ReDim bDate(2)
ReadData(bDate)
bRxLock = False
readThread.Start()
Else
bRxStatus = COMERROR
End If
‘ readThread.Join()
End Sub
Public Function ComStatus() As Byte
ComStatus = bRxStatus
End Function
Function ReadData(ByRef bDate() As Byte) As Integer
Dim bLen As Integer
bLen = m_SerialPort.BytesToRead
If bLen > 0 Then
ReDim bDate(bLen)
m_SerialPort.Read(bDate, 0, bLen)
ReadData = bLen
Else
ReadData = 0
End If
bRxStatus = COMFREE
End Function
Public Function SendDate(ByVal bDateBuff() As Byte, ByVal iLen As Integer) As Boolean
If bRxLock = False Then
m_SerialPort.Write(bDateBuff, 0, iLen)
bRxLock = True
bRxStatus = READLOCK
SendDate = True
Else
SendDate = False
End If
End Function
Public Shared Sub Read()
While (1)
Thread.Sleep(50)
Try
If m_SerialPort.BytesToRead <> iRxLen Then
iRxLen = m_SerialPort.BytesToRead
iRxTime = 0
bRxStatus = READLOCK
Else
If iRxLen > 0 Then
‘收到數(shù)據(jù)
bRxStatus = READOK
bRxLock = False
Else
iRxTime = iRxTime + 1
If iRxTime > 10 Then
bRxStatus = READOUTTIME
End If
bRxLock = False
End If
End If
Catch ex As TimeoutException
‘ Do nothing
End Try
End While
End Sub
Public Sub Close()
readThread.Abort()
m_SerialPort.Close()
End Sub
End Class
定義窗口變量
Dim ComPort As New RS232TXClass
啟動后調(diào)用
ComPort.Init("9600,n,8,1", 0, 1)
在主窗口中,通過一個定時器事件,查看串口情況
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim bDate() As Byte
Dim iLen As Integer
ReDim bDate(2)
If ComPort.ComStatus = 2 Then
iLen = ComPort.ReadData(bDate)
If iLen > 2 Then
ShowRevDate(bDate, iLen)
End If
End If
End Sub
下面實現(xiàn)一個windows的路燈維護程序移植到windows CE上面去的一些簡單示例。
這是原來VB上面的一個界面。
這個是我移植到VB.net for Mobile的版本,因為在Mobile上面多窗口切換很麻煩,就作成分頁的顯示了。
需要注意的是,因為Mobile上面的輸入法啟動后會遮蓋一部分窗口,為了輸入方面最后把需要輸入的地方放到上面去,以免影響輸入。這里我把兩個顯示性Label放到了后面。
VB.NET的繪圖和VB不是很一樣,更加接近C++的繪圖方式,但是只要不一些概念弄清楚,你會發(fā)現(xiàn)這種繪圖方式使用更加方便,更加方便你對于GDI+的理解。
VB.NET中可以使用 Dim bm As New Bitmap(238, 214) 直接建立一個位圖,然后把繪制好的位圖覆蓋回去。
繪制文字的時候,需要字體和畫刷,象下面這樣:
ShowTextBrush = New SolidBrush(Color.Blue)
mFont = New Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular)
g.DrawString("HELLO", mFont, ShowTextBrush, 12, 82)
繪制線的時候,需要畫筆。
Pen1 = New Pen(Color.Red)
g.DrawLine(Pen1, OldX, OldY, NewX, NewY)
填充圖形的時候,需要畫刷
tempbrush = New SolidBrush(Color.FromArgb(192, 192, 255))
g.FillRectangle(tempbrush, 0, 0, 238, 214)
繪制扇形和弧形,VB.NET沒有提供,但是我從網(wǎng)上找到了實現(xiàn)方法,用聯(lián)系線和連續(xù)填充實現(xiàn)弧形和棒圖的繪制。函數(shù)如下
‘=====================================================
‘繪制弧形
‘
‘ graphicsObject - Graphics 對象
‘ pen - 畫筆
‘ x,y - 弧的圓心
‘ width - 寬度 (X直徑)
‘ height - 高度 (Y直徑)
‘ startAngle - 起始角度
‘ sweepAngle - 結(jié)束角度
‘
Private Sub drawPie(ByVal graphicsObject As Graphics, ByVal pen As Pen, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal startAngle As Single, ByVal sweepAngle As Single)
Dim xAngle(12) As Single
Dim yAngle(12) As Single[!--empirenews.page--]
Dim angleIncrement As Single
angleIncrement = (sweepAngle - startAngle) / 10
Dim angle As Single
angle = startAngle
Dim i As Integer
For i = 0 To 10
xAngle(i) = x + (Math.Cos(angle * (Math.PI / 180)) * (width / 2))
yAngle(i) = y + (Math.Sin(angle * (Math.PI / 180)) * (height / 2))
angle += angleIncrement
Next i
xAngle(11) = x + (Math.Cos(sweepAngle * (Math.PI / 180)) * (width / 2))
yAngle(11) = y + (Math.Sin(sweepAngle * (Math.PI / 180)) * (height / 2))
Dim anglePoints(12) As Point
anglePoints(0) = New Point(x, y)
For i = 0 To 11
anglePoints(i + 1) = New Point(CInt(xAngle(i)), CInt(yAngle(i)))
Next
graphicsObject.DrawPolygon(pen, anglePoints)
End Sub
‘=====================================================
‘填充弧形
‘ graphicsObject - Graphics 對象
‘ solidBrush - 畫刷
‘ x,y - 弧的圓心
‘ width - 寬度 (X直徑)
‘ height - 高度 (Y直徑)
‘ startAngle - 起始角度
‘ sweepAngle - 結(jié)束角度
‘
Sub fillPie(ByVal graphicsObject As Graphics, ByVal solidBrush As SolidBrush, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal startAngle As Single, ByVal sweepAngle As Single)
Dim xAngle(12) As Single
Dim yAngle(12) As Single
Dim angleIncrement As Single
angleIncrement = (sweepAngle - startAngle) / 10
Dim angle As Single
angle = startAngle
Dim i As Integer
For i = 0 To 10
xAngle(i) = x + (Math.Cos(angle * (Math.PI / 180)) * (width / 2))
yAngle(i) = y + (Math.Sin(angle * (Math.PI / 180)) * (height / 2))
angle += angleIncrement
Next i
xAngle(11) = x + (Math.Cos(sweepAngle * (Math.PI / 180)) * (width / 2))
yAngle(11) = y + (Math.Sin(sweepAngle * (Math.PI / 180)) * (height / 2))
Dim anglePoints(12) As Point
anglePoints(0) = New Point(x, y)
For i = 0 To 11
anglePoints(i + 1) = New Point(CInt(xAngle(i)), CInt(yAngle(i)))
Next
graphicsObject.FillPolygon(solidBrush, anglePoints)
End Sub