Kirjoittaja: Antti Laaksonen
⚠ Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi. ⚠
Tämän VB-opassarjan päättävän osan oli alunperin tarkoitus käsitellä ainoastaan WinApia, mutta sitten muistinkin, etten ollut maininnut virheenkäsittelystä halaistua sanaa aiemmissa osissa. Tästä johtuen osa alkaakin virheenkäsittelyllä, jatkuen sitten WinApiin.
Miksi tarvitaan virheenkäsittelyä? Eikö ohjelmat pidä ensin tehdä virheettömiksi, ja sitten vasta julkaista? Kyllä, mutta on olemassa myös sellaisia virheitä joita ei ohjelmaa tehdessä voi ennakoida.
Otetaanpa esimerkiksi seuraava yksinkertainen koodinpätkä joka luo levykkeelle yksirivisen tekstitiedoston.
Private Sub Form_Click() Open "a:\testi.dat" For Output As #1 Print #1, "Testirivi" Close #1 End Sub
Mitäpä jos levykettä ei ole asemassa? Silloin VB ilmoittaa tylysti "Run-time error '71': Disk not ready" ja ohjelman suoritus loppuu välittömästi. Jos näin tapahtuu lopullisessa ohjelmassa, kaikki siihen asti tehty työ katoaa. Jos kyseessä oli parin tunnin työn tulos, saattaapa olla, että ohjelman käyttö katkeaa siihen.
Tällaiset tilanteet voi estää rakentamalla kaikkiin ohjelman virhealttiisiin osiin virheenkäsittelysysteemi. Tämä tehdään Visual Basicissa On Error Goto -lauseella ja nimiöillä. Opassarjan alussa vannotin, ettei Goto-käskyä ja nimiöitä saisi käyttää, mutta tässä erikoistapauksessa se on ainoa vaihtoehto.
Kun On Error Goto -lause ja nimiö on määritelty, nimiöön rakennetaan tavallisesti joku virheen tunnistava järjestelmä, virheen koodi löytyy Err-erikoismuuttujasta. Edellinen esimerkki voisi olla toimivalla virheenkäsittelyllä varustettuna seuraava:
Private Sub Form_Click() On Error GoTo virhe Open "a:\testi.dat" For Input As #1 Print #1, "Testirivi" Close #1 Exit Sub virhe: Select Case Err Case 71 'asemassa ei ole levykettä Dim a As Integer a = MsgBox("Asemassa ei ole levykettä!", vbAbortRetryIgnore) If a = vbRetry Then Resume Else Exit Sub End If Case Else 'joku muu virhe MsgBox "Tiedostovirhe: " & Error(Err) Exit Sub End Select Resume End Sub
Jos virhe on jokin muu kuin 71 (asemassa ei ole levykettä), esimerkiksi kirjoitussuojattu tiedosto, näytetään vakiomuotoinen virheilmoitus. Error(Err) palauttaa virheilmoituksen sellaisena kuin VB sen antaa (tässä "Disk not ready"). Resume yrittää suorittaa virherivin uudestaan (käyttäjä on laittanut levykkeen).
Joissain tapauksissa virhetilante on mahdollinen, mutta harmiton, esimerkiksi seuraavassa esimerkissä, jossa lasketaan 50 sattumanvaraisen kokonaislukuparin osamäärä:
Private Sub Form_Click() Dim i As Integer, x As Integer Randomize Timer For i = 1 To 50 x = Int(Rnd * 50) / Int(Rnd * 50) Next End Sub
Välillä, muttei aina, jakajaksi sattuu nolla, jolla jakaminen on tietenkin mahdotonta. Jos näin käy, VB tuottaa virheilmoituksen "Run-time error 11: Division by zero". Tämän ohjelman suorituksen kannalta ei kuitenkaan ole oleellista, että jokainen lasku saadaan päätökseen. Tällöin voidaan käyttää erilaista On Error -lausetta joka aina ohittaa mahdollisen virhetilanteen seuraavaan tapaan:
Private Sub Form_Click() On Error Resume Next Dim i As Integer, x As Integer Randomize Timer For i = 1 To 50 x = Int(Rnd * 50) / Int(Rnd * 50) If Err = 11 Then Err = 0 Next End Sub
Nyt virhetilanteen sattuessa siirrytään seuraavalle riville. Potentiaalista virhepaikkaa seuraavalla riville kannattaa laittaa Err-muuttujan tarkastus, ja tarvittaessa nollata se. Tällä tavoin ohjelma ei keskeydy vaikka toiseksi numeroksi tulisikin nolla - ja koodia tarvittiin paljon vähemmän kuin On Error Goto -tavalla.
Kuten edellisistä esimerkeistä näkyy, virhetilanteiden huomioon ottaminen lisää koodin määrää ja aiheuttaa aina lisämietittävää ohjelmoijalle. Monesti tekisikin mieli unohtaa tämä osuus ohjelman teossa, voiko näin tehdä?
Se riippuu aika paljon siitä, mihin ohjelma tulee. Jos ohjelman tekee itselleen apuohjelmaksi johonkin erikoistarkoitukseen, tällöin virhetilanteista ei kannata liikaa huolehtia, itse osaa kuitenkin pysyä erossa virhetilanteissa, kun tietää ohjelman rajoitukset. Tai jos ei osaa, sitten täytyy vain syyttää itseään.
Jos ohjelmaa rupeaa jakamaan muillekin esimerkiksi Internetissä, virhetilanteiden käsittelyn pitäisi kuitenkin olla kunnossa. Missään tilanteessa ei pitäisi olla mahdollisuutta ohjelman täydelliselle kaatumiselle. Yksikin hallitsematon virhetilanne voi antaa ohjelmasta epäluotettavan vaikutelman.
Vaikka Visual Basic aikoinaan kehitettiinkin vaikeakäyttöisen WinApi:n korvaajaksi, WinApi-funktiot ovat todella tarpeellisia kehittyneemmässä VB-ohjelmoinnissa. Funktioilla voi monesti tehdä sellaista, mikä pelkällä VB:llä olisi todella vaikeaa ellei mahdotonta.
WinApi:n kautta pääsee käsiksi moniin Windowsin ominaisuuksiin, jotka Visual Basicista puuttuvat tai ovat mukana yksinkertaistettuna. Lisäksi funktiot ovat poikkeuksetta nopeampia kuin VB:n omat - tämä on tärkeää etenkin grafiikkaohjelmien kanssa.
Funktiot määritellään formin/moduulin (Declarations)-osassa Declare-lauseella. Jos funktiota halutaan kutsua sen formin/moduulin alueella, jossa se on määritelty, lauseen eteen kirjoitetaan Private-avainsana. Jos funktio määritellään moduulissa, se voi myös olla voimassa ohjelman kaikissa osissa. Tällöin käytetään avainsanaa Public.
Tekstin tulostamiseen tarkoitetun TextOut-funktion määrittely näyttää esimerkiksi seuraavalta:
Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long"
Välillä funktion parametrit sisältävät erikoismuuttujatyyppejä, jotka on määriteltävä funktiomäärityksiä ennen Type-käskyllä. Funktio voi saada myös parametreikseen tai palauttaa vakioita, jotka määritetään niin ikään (Declarations)-osassa.
WinApi-funktioita kutsutaan ohjelmasta kuin mitä tahansa muita funktioita. Esimerkiksi seuraava koodinpätkä tulostaisi äsken määritellyllä TextOut-funktiolla tekstiä formille:
x = TextOut(Me.hdc, 0, 0, "Moikka!", 7)
Kahvat ('handles', parempaa suomennosta en tiedä) ovat suuressa roolissa WinApi:ssa. Ne ovat lukuja, jotka yksilöivät käyttöjärjestelmän oliot, esimerkiksi ikkunat, valikot ja kuvakkeet. Kahvojen nimet parametreina alkavat yleensä h-kirjaimella.
Kaksi tärkeintä kahvaa, joita monet funktiot vaativat parametreikseen, ovat hdc ja hwnd. Hdc esiintyy tavallisesti piirtokomennoissa, ja se kuvaa piirtoaluetta. VB:ssä formilla ja PictureBox-komponentilla on automaattisesti oma hdc.
Jokaisella ikkunalla taas on hwnd-kahva, joita tarvitaan useimmissa ikkunankäsittelyfunktioissa. Tämäkin löytyy VB:stä formin attribuuttina. Näiden lisäksi on lukuisia muita kahvoja, esimerkiksi hMenu, hIcon, hCursor ja hPalette, joita käytetään samalla periaatteella.
Yhdeksän osan ja neljän kuukauden jälkeen on aika lopettaa tämä opassarja. Paljon on tullut käsiteltyä, mutta paljon on jäänyt käsittelemättäkin. Visual Basicin hyviä puolia on sen loogisuus, monet asiat oppii kokeilemalla kun perusasiat on hoidossa.
Ongelmatilanteissa ja jatkokysymyksissä auttaa usein keskustelualue, minua voi myöskin lähestyä sähköpostilla - palaute on aina tervetullutta.
Kaikki ei kuitenkaan lopu tähän - tästä eteenpäin on Ohjelmointiputkassa tarkoitus ilmestyä pienempiä eri aiheita käsitteleviä oppaita VB:lle, mukaanlukien tietokannat, resurssitiedostot ja grafiikkaa WinApi:lla.
Olisi voinut olla enemmänkin esimerkkejä esim. kahvoista jne..
Mahtaisiko netistä löytyä mitään listaa WinAPI:n kaikista funktioista? Tässä kun oli mainittu vain yksi. Muuten hyvä opas, selittää hyvin, mikä WinAPI on ja miten sitä käytetään.
Mistä löytäis ton ohjelman???
(visual basic 5)
Hunajavohveli: http://www.mentalis.org/apilist/apilist.php
hunajavohveli: www.msdn.com
Ajattelin vain tässä viimeisessä osassa kiittää oppaan kirjoittajaa. Oppaasta on ollut tosi paljon hyötyä ja alkaa tuo VB olemaankin jo jotenkin päin hanskassa, tosin vielä on paljon opittavaa. ;)
voisko olla esimerkkejä enemmän
siis WinAPi;sta
Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.