Jednou z velmi užitečných vlastností platformy .NET je, že se neomezuje jenom na jeden typ aplikací. Ve stejném jazyce, vývojovém prostředí a stejnými technologiemi lze psát aplikace webové (Web Forms), desktopové (Windows Forms) i pro kapesní počítače (Compact Framework).
Ač to na první pohled nemusí být zřejmé, tato vlastnost je velice výhodná i pro čistokrevného webového programátora. Webové rozhraní prostě má svoje omezení a není vhodné pro všechny typy úkolů. Lze-li očekávat, že klient bude vybaven .NET Frameworkem, je možné řadu těchto omezení vyřešit napsáním jednoduché aplikace, která požadované operace provede. Se svým webovým protějškem pak může komunikovat například přes web service rozhraní.
Microsoft .NET 2.0 (Whidbey), toho času dostupný jako Beta 2, přináší řadu novinek, a to i pro vývoj desktopových aplikací. Rozhodl jsem se napsat v něm aplikaci, která bude schopna zobrazit aktuální teplotu, přičemž informace o ní bude čerpat jednak z veřejně dostupné webové služby, jednak z teplotního čidla připojeného na sériový port.
Jako lokální teplotní čidlo jsem použil modul "TM" od Papouch Electronics (viz papouch.com). Stejný výrobce nabízí i celou řadu dalších čidel (nejen teplotních), včetně připojení na USB nebo Ethernet, ale pro naše účely bohatě postačí toto nejjednodušší a nejlacinější.
Zapojuje se na sériový port a funguje tak, že po připojení (s parametry 9600-8-N-1)
a nahození
signálu DTR změří teplotu a pošle ji na výstup jako jednoduchý ASCII řetězec (např.
+025.5C
). Proof-of-concept kód pro načtení aktuální teploty do numerické
proměnné vypadá takto:
' Connect to serial port Dim Port As New System.IO.Ports.SerialPort() Port.PortName = "COM1" Port.BaudRate = 9600 Port.DataBits = 8 Port.StopBits = IO.Ports.StopBits.One Port.Parity = IO.Ports.Parity.None Port.ReadTimeout = 1000 Port.DtrEnable = True Port.Open() ' Get current value Dim S As String = Port.ReadTo("C") Dim T As Single = Single.Parse(S.Substring(0, 6), _ New System.Globalization.CultureInfo("en-US")) MsgBox(String.Format("Current temperature is: {0:N2} °C", T)) Port.Close() Port.Dispose()
Vzhledem k významu počasí pro leteckou dopravu jsou ideálním zdrojem informací o počasí letecké systémy. Přístup do nich lze získat příkladně pomocí webové slyžby GlobalWeather, jejíž popis najdete na http://live.capescience.com/GlobalWeather/. Tato služba je zároveň důkazem interoperability technologie Web Services, protože neběží na platformě .NET, ale lze ji bez problémů z .NETu využívat.
Informace o počasí (nejen teplotě) je k dispozici pro každé mezinárodní letiště. Pro ČR lze využít následující:
LKPR
)LKKV
)LKTB
)LKHO
)LKMT
)Chcete-li tuto službu využívat, přidejte si Web reference na adresu http://live.capescience.com/wsdl/GlobalWeather.wsdl
a nazvěte ji GlobalWeather
. Tato webová služba vystavuje dvě třídy,
které nás budou zajímat, a to StationInfo
a GlobalWeather
.
Ke zjištění informací o lokaci jest možno využít metodu getStation
třídy
StationInfo
. Tato třída obsahuje ještě další zajímavé metody, jimiž
jest možno prohledávat seznam stanic. Budete-li chtít, můžete s jejich použitím
rozšířit aplikaci tak, aby umožňovala např. výběr ze seznamu či prohledávání.
V této fázi se spokojím s tím, že pomocí webové služby získám pro danou lokaci její
název a zemi, kde je umístěna. V okně nastavení (FormServiceOptions
)
tak identifikuji, zda byl zadán platný kód letiště:
Dim StationWS As New GlobalWeather.StationInfo() Dim Station As GlobalWeather.Station = StationWS.getStation(Me.TextBoxWebLocationCode.Text) If Station Is Nothing Then MsgBox("Location not found - check code", MsgBoxStyle.Exclamation) Else MsgBox(String.Format("{0} is {1}, {2}", Me.TextBoxWebLocationCode.Text, Station.name, Station.country), MsgBoxStyle.Information) End If StationWS.Dispose()
Chceme-li na dané lokaci zjistit aktuální meteorologickou situaci, jejíž součástí
je i teplota, použijete k tomu metodu getWeatherReport
třídy GlobalWeather
.
Ta vrátí informace o lokaci a její meteorologické situaci:
Dim WeatherWS As New GlobalWeather.GlobalWeather() Dim Report As GlobalWeather.WeatherReport = WeatherWS.getWeatherReport(My.Settings.ServiceLocationCode) If Not Report Is Nothing Then Me.LabelService.Text = String.Format("{0:N1}°C", Report.temperature.ambient) Me.GroupBoxService.Text = String.Format("{0} ({1})", Report.station.name, Report.station.country) Me.LabelUpdateService.Text = Report.timestamp.Value.ToShortDateString() & " " & Report.timestamp.Value.ToShortTimeString() End If WeatherWS.Dispose()
Okno vlastností projektu (ukáže se po dvojkliknutí na "My Project" v Solution Exploreru) je ve Whidbey mnohem zajímavější, než tomu bylo v předchozích verzích. Zastavme se pro tento ukamžik u záložky "Application":
Po povolení Enable Application Framework máte možnost pro svou aplikaci
jednoduše nastavit způsob, jakým se celkově má chovat. Po klepnutí na View Application
Events se vám otevře soubor ApplicationEvents.vb
(standardně
skrytý ve složce My Project
), ve kterém můžete definovat event handlery
pro události týkající se celé aplikace. Připomíná to mechanismus Global Application
Class (alias global.asax
) známý z webových ASP.NET aplikací.
Můžete například reagovat na neošetřenou výjimku a pokud ve vaší aplikaci nastane, nějak ji vyřešit - například zobrazit chybové hlášení a vygenerovat log:
Namespace My Class MyApplication Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException If MsgBox("The follofing exception occured:" & vbCrLf & e.Exception.Message & vbCrLf & "Do you want to create log file?", MsgBoxStyle.Critical Or MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then Dim LogFileName As String = My.Computer.FileSystem.GetTempFileName() My.Computer.FileSystem.WriteAllText(LogFileName, e.Exception.ToString(), False) System.Diagnostics.Process.Start("notepad.exe", LogFileName) End If e.ExitApplication = True End Sub End Class End Namespace
Téměř každá aplikace má nějaká nastavení, která jest třeba někde ukládat. Obvykle
v nějakém konfiguračním souboru, případně v registrech. Což s sebou nese nutnost
se o tyto údaje starat a validovat je. Whidbey disponuje technologií, která tyto
operace provádí transparentně a vystavuje je pro programátora ve formě strongly-typed
třídy, dostupné jako My.Settings
.
Předtím, než začneme experimentovat s nastaveními, doporučuji ještě na záložce
Application klepnout na tlačítko Assembly Information a nastavit metadata
týkající se aplikace. V předchozí verzi se zapisovaly do souboru AssemblyInfo.vb
(ten je přítomen stále, ale je generován automaticky a skryt v adresář My Project
),
nyní je na to i GUI.
Konfigurace totiž rozeznává dva druhy parametrů: per user a per application. Ty aplikační
jsou uloženy klasicky v souboru jménoassembly.config
, ale uživatelské
jsou uloženy do souboru v uživatelově profilu. Přesná cesta k němu se generuje právě
na základě shora uvedených metadat.
Po dokončení nezbytných příprav jest nám vrhnouti se na genervání vlastních nastavení. Za tímto účelem se v okně My Project přepneme na záložku Settings, kdežtě můžeme určovat konfigurační proměnné, jejich typy a defaultní hodnoty:
Milé je, že jako typ konfigurační proměnné je možno použít cokoliv, nejenom primitivní
typy jako String
nebo Integer
. Příkladem budiž Enum
typy použité pro uložení nastavení sériového portu (např. System.IO.Ports.StopBits
a další). Načítání se pak v kódu děje způsobem, jež je až urážlivě jednoduchý:
Dim Port As New System.IO.Ports.SerialPort() Port.PortName = My.Settings.SensorPortName Port.BaudRate = My.Settings.SensorBaudRate Port.DataBits = My.Settings.SensorDataBits Port.StopBits = My.Settings.SensorStopBits Port.Parity = My.Settings.SensorParity Port.ReadTimeout = My.Settings.SensorTimeout Port.DtrEnable = True Port.Open()
Pokud se jedná o nastavení s user scope, je možno stejným způsobem hodnoty
nejenom číst, ale i nastavovat (po dokončení nastavování zavolejte My.Settings.Save()
).
Nastavení s application scope nelze za běhu aplikace měnit.
Komponenta NotifyIcon
, reprezentující ikonu v system tray (lokace známá
též jako "vedle hodin") byla k dispozici již v předchozích verzích .NET Frameworku.
Její Whidbey verze obsahuje též podporu pro "Baloon tip" - notifikaci nově používanou
ve Windows XP.
V souvislosti s NotifyIcon umí aplikace tři věci:
Stará se o to následující kód:
Private Sub FormMain_Resize(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Resize If Me.WindowState = FormWindowState.Minimized Then Me.Visible = False Me.TrayIcon.Visible = True End If End Sub Private Sub TrayIcon_MouseClick(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles TrayIcon.MouseClick If e.Button = Windows.Forms.MouseButtons.Right Then Me.Visible = True Me.TrayIcon.Visible = False Me.WindowState = FormWindowState.Normal Else Dim Message As String = String.Format("{0}: {1}\n{2}: {3}", _ Me.GroupBoxSensor.Text, Me.LabelSensor.Text, _ Me.GroupBoxService.Text, Me.LabelService.Text) Me.TrayIcon.ShowBalloonTip(5, "Current temperature", _ Message.Replace("\n", vbCrLf), ToolTipIcon.Info) End If End Sub
Toto je funkční aplikace, která využívá některé nové možnosti, dostupné v Microsoft .NET Beta 2. K jejímu spuštění potřebujete Whidbey beta 2, projekt je pro VS.NET, ale měl by být kompatibilní i s Visual Basic Expressem.
Pracuji na obsáhlejším projektu, který bude umět centralizovaně monitorovat teplotu ve více bodech, včetně síťové komunikace a využití pokročilejších papouščích čidel. Dočkáte se ho během několika týdnů.