Hopp til innhold

Visual Basic

Fra Wikibøker – frie læremidler
Uoppdelt: Denne boken har alt innholdet på forsiden, og bør deles opp i passende kapitler.

Utviklingsfase: 50% (ved 1. februar 2007) (1. februar 2007)



Introduksjon

[rediger]

Dette er programmeringsspråket for deg uten erfaring fra andre dataspråk. Visual Basic er enkelt, samtidig som det har svært få begrensninger i språket. Kort sagt er Visual Basic (heretter referert som VB) et kraftig utviklerverktøy som kan skape komplekse programmer uten at man har noen særlig stor kunnskap om data. Men, skal man lage komplekse programmer, er det helt uvanlig å velge VB, og det krever dessuten tilsvarende kunnskap.

VB er et egnet programmeringsspråk for nybegynnere, fordi det er så enkelt å lære seg. Senere kan man gå over til andre mer avanserte programmeringsspråk, som C++, hvis det i hele tatt skulle være nødvendig. Visual Basic var i starten ganske tregt i forhold til andre språk, men har i senere tid forbedret seg kraftig, og man kan i dag faktisk lage store ressurskrevende 3D-spill direkte i VB. Det er i alle fall teoretisk mulig.

I disse flyktige tider, har det allerede kommet en ny VB-versjon som ikke vil bli dekket i denne guiden. VB.NET, som den kalles, er så fundamental annerledes enn forgjengerne at mye i denne guiden ikke vil kunne fungere skikkelig. Derfor bør du helst ha VB versjon 6, eller lavere, før du starter. VB skal dermed heretter leses som "Visual Basic versjon 6", et helt konkret program fra Microsoft, og ikke språket Visual Basic, som omfatter den langt mer aktuelle VB.NET som har kommet i ettertid.

En bør for øvrig merke seg at VB er et proprietært programmeringsspråk - det støttes hovedsaklig kun av Microsoft Windows, hvilket betyr at en kan møte svært store problemer med å få VB-programmer til å fungere på andre operativsystemer. Microsoft avsluttet også støtten for dette språket 31 Mars, 2005. VB-programmer pleier å fungere greit i Wine/Linux, dog. Nå har Novell/Mono kommet med en VB.net kompilator som er åpen kildekode.

Hva du trenger

[rediger]

For å skrive VB-kode trenger man kun en helt vanlig teksteditor. For å gjøre om VB-koden til en exe-fil (et kjørbart program), trenger man en kompilator. Kompilatoren er et program som oversetter VB-koden til maskinkode som CPU-en i datamaskinen kan forstå. Du kan kjøpe et slikt program, eller laste ned en gratis "demo", VB CCE, her Du kan ikke lage exe-filer VB CCE, men skal du bare teste ut VB er dette heller ikke nødvendig.

Hvis du heller vil lære et relevant programmeringsspråk, som hverken er dødt eller proprietært, så går det an å ta en titt på VisualBasic.NET under Mono. Det er fri programvare, kryssplattformkompatibelt, har god medvind, kan lett bruke kode skrevet i andre språk og kan fint produsere exe-filer.

VB-programmet

[rediger]
Fil:VB6-sesjon.png
Programmet burde være seende ut som sådan til nå.

Etter du har åpnet VB-miljøet spretter en dialogboks fram med spørsmål om hva du vil lage. Ikke bry deg om alt det andre, men velg "Standard EXE" og trykk på OK. Helt automatisk vil en "form" (et slags program-tegnebrett) bli laget hvor du kan legge inn hva det skal være. Til venstre ser du en hel del knapper og bokser som indikerer forksjellige "kontroller" (tekstboks, listeboks osv) som du kan legge inn i formen. Trykk f.eks. på boksen med A, og trykk så på en vilkårlig plass i formen og dra. Du vil nå ha lagt inn en Label, et tekstfelt der du kan vise frem fram tekst i programmet ditt til brukeren.

La oss nå komme i gang. Legg inn en CommandButton ved å velge knappen med bildet av en liten boks og legg den inn på et tilfeldig sted i formen. Dobbeltklikk på knappen du nettopp laget, og teksteditoren til VB-miljøet vil dukke opp.



Koding med VB

[rediger]

Du vil nå kunne se denne teksten i innskrivningsvinduet:

   Private Sub Command1_Click()
   
   End Sub

La oss se nærmere på dette. Den første linjen markerer begynnelsen på hva VB skal gjøre når noen trykker på knappen. Command1 er navnet på knappen og Click er hendelsen som gjør at akkurat denne delen av koden kjøres. (I dette tilfellet at noen trykker på knappen.) Private betyr bare at koden er lokal og kan ikke nås fra andre moduler. End Sub markerer slutten på koden.

Eksempelkoden over kalles en prosedyre. Mesteparten av den koden du skriver vil være i prosedyrer, som egentlig bare er en måte å segmentere koden på. Det finnes forskjellig typer prosedyrer, og Sub er en type. Koden vi nettopp så, kalles også en Event fordi den startes når noe skjer. I dette tilfellet er det når en bruker trykker på en knapp. La oss skrive inn noe kode:

Imellom Private Sub Command1_Click() og End Sub skriver du:

   MsgBox "Hallo verden!"

La oss så teste dette ved å trykke på F5, eller på play-knappen i verktøylinjen. Formen vi laget dukker så opp, sammen med den knappen vi la inn. Trykk på knappen og en meldingsboks med teksten Hallo verden kommer opp. Stilig, ikke sant?

Du kan skrive inn hva det skal være istedenfor Hallo verden, men det må være mellom de to gåseøynene for at det skal virke.

Kontroller

[rediger]

Tekstboks

[rediger]

Gå ut av kodedelen og tilbake til formen. Dette gjør du ved å avslutte kode-vindet med X-knappen nedenfor den helt øverst til høyre. Så skal du se etter en knapp på verktøylinjen helt til venstre der du helt tydelig ser en liten boks med skriften ab| i. Trykk på den, og legg den inn slik du gjorde med Command1-knappen. Så må du endre navnet på tekstboksen. Dette gjør du ved å markere tekstboksen og så lete etter en verktøyboks kalt "Properties - Text1". Dersom du ikke finner den, må du kanskje framheve den med F4. I denne verktøyboksen skal det være to kolonner med forskjellige verdier i. Det er her alle egenskapene til et objekt befinner seg i. Se etter (Name) i den venstre kolonnen. Når du har funnet den endrer du cellen i den høyre kolonnen fra Text1 til txtTekst. Dette er for å gjøre alt mer oversiktelig og lettere å lese uten å teste koden. Vi trenger ikke skifte navnet på Command1, men for din egen del bør du navngi alt du legger inn, også formen.

Når den er trygt lagt inn i formen går du tilbake til Command1-koden ved å trykke på knappen du allerede har i formen. Så bytter du ut MsgBox koden du la inn med dette:

   MsgBox txtTekst.Text

Start koden med F5 og skriv noe inn i tekstboksen. Trykk så på knappen og voila, teksten du skrev inn vil befinne seg i meldingsboksen. Så, hva skjedde her? Jo, tekstboksen du kalte for txtTekst kan nås ved å skrive dens navn. Teksten inne i en tekstboks hentes ved å skrive .Text etter navnet. Hvis du ser nærmere på Properties vinduet vil du finne cellen merket med Text. Syntaksen er derfor:

   [objekt].[egenskap]

Prøv nå å legge inn denne koden istedenfor:

   txtTekst.Text = "Hallo verden!"

Tekstboksen vil nå inneholde teksten Hallo verden etter du har trykket på knappen. Dette kalles Property, eller en Egenskap til en kontroll. Dette er helt grunnleggende i programmering, og er følgelig lurt å lære seg.

Knapp

[rediger]

Man endrer teksten i knappen med egenskapen Caption. Gå inn i Properties vinduet, finn egenskapen, og endre cellen ved siden av.

Sjekkboks

[rediger]

Du legger den inn ved å markere den fjerde boksen fra toppen i første rad i verktøyboksen med de ymse kontrollene; den ser ut som en teksboks med en V. Egenskapen Caption er teksten som skal settes inn ved siden av boksen. Den mer interessante egenskapen er Value som befinner seg nesten helt nederst i Properties vinduet. Den kan ha tre mulige verdier:

   0 = Unchecked
   1 = Checked
   2 = Grayed

Det betyr at når du skal teste om en checkbox er markert må du bruke noe lignende denne koden:

   If Check1.Value = 1 Then
       MsgBox "Checkboksen er markert!"
   End If

Skal du ha betingelser for flere checkbokser bruker du binariske operatører (forklares senere i detalj)

Valgboks

[rediger]

Denne kontrollen finner du til høyre for sjekkboksen i verktøyboksen. Den er i forhold til sjekkboksen ganske lik, men med to vesentlige forskjeller:

  • Value-egenskapen kan bare inneholde to verdier: True eller False
  • Bare én option-boks kan være markert om gangen.

Så for å teste om en valgboks er markert gjør du slik:

   If Option1.Value = True Then
       MsgBox "Valgboksen er markert!"
   End If

Label

[rediger]

Er markert i verktøyboksen med en stor A. Teksten endres med Caption-egenskapen.

Kombiboks

[rediger]

Er en nyttig liten kontroll som brukes ofte i programmeringen. Du finner den rett under sjekkboksen. For å legge til "Items", eller tekst må du enten bruke List egenskapen eller ’’AddItem’’ prosedyren:

   Combo1.List(0) = "Hallo"
   Combo1.List(1) = "Hallo verden!"
   Combo1.AddItem "Hallo alle sammen!"

Du kan ikke bruke ’’AddItem’’ for å legge til tekst før du har startet programmet, men du må da bruke List egenskapen. Trykk på den i ’’Properties’’ vinduet og trykk på knappen som dukker opp i høyre kolonne. I tekstboksen som dukker opp kan du skrive inn de forskjellige tingene brukeren kan velge mellom.

For å se hva som er valgt kan du bruke Text egenskapen:

   If Combo1.Text = "Hallo" Then
       MsgBox "Hallo til deg også!"
   End if

Normalt sett kan brukeren skrive inn sin egen tekst i kombiboksen, men dette er ikke alltid ønskelig. For å gjøre den til "Drop-down only" setter du egenskapen Style til 2.

Du har kanskje lagt merke til at når du starter programmet er kombiboksene helt tomme. Brukeren må selv velge et alternativ før de har innhold, og dette kan i mange tilfeller være svært plagsomt. For å løse dette må du bli introdusert med en ny hendelse kalt Form_Load.

Denne hendelsen kalles når formen lastes inn. Legg følgende kode inn i formen, men du må legge den utenfor Command1_Click sub-en. Du kan ikke legge en prosedyre direkte inn i en annen prosedyre.

   Private Sub Form_Load()
       Combo1.ListIndex = 0
   End Sub

Merk at kombiboksen må inneholde noe, ellers vil programmet ditt bli avsluttet og du sendes tilbake til VB. Når kombibokser er tomme har de ListIndex -1, som ikke refererer til noen tekst i Listen. Derfor må du sette indeksen til 0, som er det første elementet i kombiboksen.

Det er på dette området VB kan virke litt underlig for nybegynnere. Hvorfor begynner VB å telle på 0, når alle andre her i verden begynner på 1? Dette gjelder for så vidt også mange andre programmeringsspråk, som ikke gjør forvirringen bedre. Det er blant annet fordi matematikere begynner å telle på null, og derfor er Windows basert på dette. VB prøver faktisk også å rette opp på dette med at ved mange teknikker begynner tellingen på 1.

Listboks

[rediger]

Du finner den rett ved siden av kombiboksen. Den eneste forskjellen er at du må ikke trykke på noen knapp for å se alle elementene, men de er allerede synlig. Du forstår nok hva jeg mener når du prøver den ut.

Timer

[rediger]

Denne kontrollen finner du i verktøyboksen som en klokke. Den viser ikke klokken men kan brukes istedenfor en loop. Legg inn en timer i formen og kall den for tmrKlokke. Så legger du denne koden inn:

   Private Sub tmrKlokke_Timer()
       Form1.Caption = Time
   End Sub

Set Interval-egenskapen til 10 og start programmet. Det vil nå være en klokke i formens tittelbar (caption).

Interval er hvor mange millisekund det tar før Timer hendelsen kjøres igjen. Skal du stoppe Timeren må du enten sette Interval til 0 eller Enabled til False. Begge funker utmerket.

Skal du f.eks. få en timer til å kjøre 15 ganger kan du gjøre slik:

   Private Sub tmrKlokke_Timer()
       tmrKlokke.Tag = Val(tmrKlokke.Tag) + 1
               
       If tmrKlokke.Tag >= 15 Then 
           tmrKlokke.Enabled = False
       End If
       
       Form1.Backcolor = QBColor(tmrKlokke.Tag)
   End Sub

Sett Interval til 1000 slik at du ser hva som skjer. Val oversetter tekst om til tall. Dette er for å hindre at VB genererer en feil fordi du plusser en tom streng (tekst) med et tall.

Felles egenskaper

[rediger]

Ved alle de gjennomgåtte kontrollene, eksisterer det en del egenskaper som kan benyttes noenlunde likt på alle kontroller:

Egenskap: Beskrivelse:
Backcolor Bakgrunnsfargen til kontrollen
Forecolor Skriftfargen til kontrollen
Left X-koordinatene til kontrollen
Top Y-koordinatene til kontrollen
Width Bredden i Twips
Height Høyden i Twips
Font Skrifttype, -størrelse og -navn.
Tag Variabel som kan benyttes til hva som helst.

Mange av disse egenskapene er selvforklarende, mens noen har sine underligheter. Top er plasseringen på Y-aksen, men denne aksen er annerledes enn den vi lærte i matematikktimene. Den er snudd opp ned slik at 0 blir høyere på skjermen enn 400. Hvorfor er ikke så viktig, men du må vite dette.

For å endre skriften må du markere den i Properties vinduet og så trykke på knappen som dukker opp. Deretter kan du velge skrifttypen slik du f.eks. gjør i Notepad.

Twips er målet satt til standard av VB. På min skjerm er 1 piksel lik 15 twip. Vi skal ikke gå innpå det å endre målet i VB ennå (egenskapen heter for øvrig ScaleMode), men du kan ha dette i bakhodet.

Tag har ingen innvirkning på kontrollen og du kan sette den til hva det skal være. Bruk den når du vil lagre ekstra informasjon.

Variabler

[rediger]

Deklarering

[rediger]

Variabler er en sentral del av programmeringsspråket. Til forskjell fra mange andre språk trenger man ikke deklarere en variabel før man kan bruke den, men det er absolutt å anbefale. For å deklarere en variabel bruker man kommandoen Dim. Vi kan teste dette ved å legge denne koden inn i en kommandoknapps Click-hendelse:

   Dim Test
   Test = "Hallo verden!"
   MsgBox Test

Når vi skal deklarere flere variabler kan det av og til være nyttig å ha alt på samme linje. Dette kan vi gjøre ved å dele opp variablene med komma slik:

   Dim Tall, Sum
   Tall = 5
   Sum = Tall + 5
   MsgBox Sum

Du kan deklarere så mange variabler du vil på samme linje, men ikke overdriv. Lag en ny dim linje når det hele begynner å bli uoversiktlig. Eventuelt deklarer etter kategorier slik at du Dim-er alle strengvariablene først, og så tar tall variablene på en ny linje. Det er helt opp til deg hvordan du vil skrive koden, men det er nyttig å holde alt ryddig å pent. Det kan hindre deg fra å bruke mange timer med debugging.

Anvendelse

[rediger]

Man kan fint sette en variabel lik en egenskap i en kontroll. Start med en tom form og legg til to tekstbokser med henholdsvis navnet txtNavn ok txtAlder, samt en kommandoknapp. Finn fram kodevinduet og lim inn følgende i kommandoknappes hendelse:

   Dim TekstUt
   TekstUt = "Mitt navn er " & txtNavn.Text
   TekstUt = TekstUt & ". Jeg er " & txtAlder.Text & " år gammel"
   MsgBox TekstUt

Kjør koden og skriv navnet ditt inn i txtNavn, mens du skriver inn alderen din i txtAlder. Trykk på knappen. Nå vil en meldingsboks komme opp hvor navnet og alderen din står. Som du ser gjør variabler det mye enklere å skrive kode. Du la muligens merke til et for nå ukjent tegn i programmeringen, nemlig & .Denne brukes ganske enkelt for å sette sammen tekst slik som vist i eksempelet.

Du trenger ikke bare benytte tekst i variablene dine. Tall kan også brukes, og naturligvis utregning av mattematiske uttrykk. Se på dette eksempelet.

   Dim Tall
   Tall = 2 + 2
   MsgBox Tall

Dette vil gi tallet 4. Alle fire regnearter kan benyttes, og alle varibaler som er tilgjengelige der koden kjøres kan flettes inn i uttrykket:

   Dim Ledd
   Dim Ledd2
   Dim Sum
   
   Ledd = 12
   Ledd2 = 8
   Sum = Ledd + Ledd2
   MsgBox Ledd & " + " & Ledd2 & " = " & Sum

Artimetiske operatorer

[rediger]

Innledning

[rediger]

Disse operatørene inneholder blant annet finner de fire hovedregneartene. For å illustrere dette, kan vi lage et lite regneprogram. Lag først et nytt prosjekt med en tom form og legg til en kommandoknapp og to tekstbokser. Kall den ene teksboksen for txtTall, og den andre for txtTall2. Legg dernest følgende inn i Command1 sub-en:

   MsgBox txtTall.Text & " * " & txtTall2.Text & " = " & txtTall.Text * txtTall2.Text

Vær oppmerksom på at tekstboksene må inneholde tall, ikke bokstaver. Følger man ikke denne regelen får man en feilmelding (Type mismatch) og programmet stanser. Kommer dette fram har man valget å debuge (debug), eller å avslutte programmet og returnere til VB (end).

Oversikt over aritmetiske operatører

[rediger]
Operator: Anvendelse: Eksempel:
^ Eksponentiering 2^4 = 16
- Negasjon -X
* Multiplikasjon 5 * 6 = 30
/ Divisjon 7 / 4 = 1.75
\ Heltallsdivisjon 7 \ 4 = 1
Mod ’’Modulus’’ (rest) 7 Mod 4 = 3
+ Addisjon 2 + 2 = 4
- Subtraksjon 12 - 4 = 8

Funksjoner

[rediger]

Innledning

[rediger]

Funksjoner er prosedyrer akkurat som sub-er, men hvor de i tillegg returnerer en variabel. Vi kan først se på funksjonen UCase, som gjør all tekst om til STORE bokstaver. Kall den ene tekstboksen for txtTekst og legg inn dette eksempelet:

   Dim Tekst
   Tekst = UCase(txtTekst.Text)
   MsgBox Tekst

Prosedyrer kan inneholde såkalte parametere. I det foregående tilfellet hadde UCase én parameter. For å forklare dette kan vi se på denne koden:

   Form1.Backcolor = RGB(255, 0, 0)

RGB har tre parametere, alle atskilt fra hverandre med komma. Formens bakgrunnsfarge vil i dette tilfellet bli rødt, idet den første parameteren henviser til hvor mye rødt det skal være i fargen (i en skala fra 0 til 255). Den andre viser til hvor mye grønt det skal være i fargen, og den siste forteller hvor mye blått fargen skal inneholde.

MsgBox

[rediger]

Til nå har du ikke sett halvparten av hva msgbox egentlig er i stand til å gjøre. Skriv inn MsgBox "test", i kodevinduet. Du vil nå se en liste over forskjellige konstanter. Velg vbInformation og kjør programmet. Opp kommer en meldingsboks med et ikon til venstre. Lek deg litt med de andre konstantene. Du kan bruke flere på en gang ved å addere dem sammen slik:

   MsgBox "test", vbInformation + vbYesNo

Legg så til et komma og skriv inn dette: "title". Kjør programmet og meldingsboksen får Title øverst i vinduet istedenfor Project1

MsgBox er i virkeligheten også en funksjon, således kan du også finne ut hvilken tast brukeren har trykket på. Prøv ut dette eksempelet:

   If MsgBox("Vil du avslutte",vbQuestion + vbYesNo, "Avslutte?") = vbYes Then
       End ' Du kan også benytte Unload Me
   End If

Som du ser avsluttes programmet når brukeren trykker på Yes. End er en kommando som avslutter programmet, og vbYes er konstanten for knappen Yes i MsgBox-en.

InputBox

[rediger]

En veldig nyttig kommando som muliggjør inntasting av tekst i en meldingsboks. Se på dette eksempelet:

   Dim Out
   Out = InputBox("Skriv inn noe", "Title", "Standard tekst")
   MsgBox "InputBox returnerte " & Out, vbInformation, "InputBox test"

Liste over nyttige funksjoner

[rediger]
Navn: Parameter: Returnerer:
RGB Rød, Grønn, Blå Blå - En farge sammensatt av rød (0-255), grønn (0-255) og blå (0-255). Merk: rgb(0,0,0) = Svart og rgb(255,255,255) = Hvitt.
UCase Tekst Parameteren tekst omgjort til store bokstaver.
LCase Tekst Parameteren tekst omgjort til små bokstaver.
QBColor Tall En farge fra en forhåndsdefinert liste med 16 forskjellige farger; 0 er svart, mens 15 er hvit.
Sin Tall Sinus til tallet (i radianer)
Cos Tall Cosinus til tallet (i radianer)
Tan Tall Tangens til tallet (i radianer)
Log Tall Logaritmen til tallet.
Rnd (Tall) Tilfeldig tall mellom 0 og 1

Disse er langt ifra de eneste i VB, men det er ikke nødvendig å liste opp alle. Ikke alle parameter er nødvendig, som dette eksempelet viser:

   Dim Tilfeldig as random
   MsgBox Tilfeldig.next (1, 999)

Meldingen vil nå generer et tall fra 1 - 999, denne kan endres etter eget behov. Når du ser etter i listen skulle Rnd ha en parameter. Men ettersom denne er skrevet med ( ), er det ikke nødvendig å skrive denne. Dette kalles for en Optional (valgfri) parameter.

Betingelsesprogrammering

[rediger]

IF-THEN syntaks

[rediger]

Dette er den mest grunnleggende formen av betingelsesprogrammering i VB. Den brukes slik:

   If txtTekst.Text = "hallo" Then
       MsgBox "Hallo igjen!"
   End If

Skriv inn hallo i tekstboksen. Meldingsboksen kommer opp. Skriver du ikke hallo vil heller ikke meldingsboksen vises. Vi kan oversette VB koden til norsk således:

   HVIS txtTekst.Text ER LIK "hallo" DA SKAL
       MsgBox "Hallo igjen"
   SLUTT PÅ HVIS

Man kan også legge til en Else-del av IF-syntaksen:

   If txtTekst.Text = "hallo" Then
       MsgBox "Hallo igjen!"
   Else
       MsgBox "Ikke det? Nei vel."
   End If

Hvis tekstboksen ikke inneholder hallo vil en meldingsboks med teksten Ikke det? Nei vel. komme fram. Else kan på norsk oversettes til HVIS IKKE. Hvis du vil ha flere betingelser kan du enten legge inn flere IF-er, eller bruke ELSEIF:

   If txtTekst.Text = "hallo" Then
       MsgBox "Hallo igjen!"
   ElseIf txtTekst.Text = "farvel" Then
       MsgBox "Farvel"
   Else
       MsgBox "Hva sa du?"
   End If

Du trenger ikke bruke tekstbokser, og du trenger heller ikke sjekke for tekst:

   Dim Tall
   Tall = 5
If Tall = 5 Then MsgBox "Tall er lik 5" Else MsgBox "Tall er ikke lik 5" End If

Select-Case

[rediger]

Select Case er en nyttig del av VB som forenkler visse aspekter av betingelsesprogrammeringen. La oss se på et eksempel:

   Select Case txtTekst.Text
   Case "hallo"
       MsgBox "Hallo igjen!"
   Case "verden"
       MsgBox "Hallo verden!"
   Case "farvel"
       MsgBox "Farvel!"
   Case Else
       MsgBox "Hva skrev du?"
   End Select

Som du ser er den lett i bruk og krever egentlig ikke noen ytterligere forklaring. Den ligner veldig på IF-THEN-syntaksen, men er mye lettere å skrive.

Dersom du skal ha flere betingelser i samme case, bruker du komma for å skille dem fra hverandre:

   Select Case txtTekst.Text
   Case "hallo", "verden", "hallo verden"
       MsgBox "Hallo verden!"
   Case Else
       MsgBox "Hva skrev du?"
   End Select

Det er imidlertid et par ting å notere seg. Skal du eksempelvis teste om et tall er imellom to andre, må du gjøre som følger:

   Dim i
   
   i = 36
   
   Select Case i
   Case 0 To 40
       MsgBox "Tallet er mellom 0 og 40"
   Case Else
       MsgBox "Tallet er utenom 0 og 40"
   End Select

Løkker

[rediger]

Løkker (en. looping) er en viktig del av all programmering og er fundamentalt i spillprogrammering. Et greit eksempel på hvor slikt er påkrevd, kan være følgende oppgave:

   Lag et program hvor brukeren får 10 meldinger med samme tekst.

Lett, tenker du kanskje, og skriver inn følgende kode:

   Private Sub Form_Load()
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
       MsgBox "hallo"
   End Sub

Vel, jo, oppgaven kan selvfølgelig løses på den måten; men det er meget bedre å bruke løkker:

   Private Sub Form_Load()
   
       Dim i
   
       For i = 1 To 10
           MsgBox "hello"
       Next
           
   End Sub

Dette gjør koden mer dynamisk og i stand til å eksekvere de samme linjene en gitt antall ganger.

Eksempelet oversatt fra VB til norsk blir som sådan:

   -Når formen laster:
   
   Lag en variabel med navn "i"
   
   Sett variabel "i" til 1 og kjør løkken helt til i er større enn 10
   Vis melding "hello"
   Inkrementer i med 1 og gå tilbake
   
   -Slutt

Du trenger sågar ikke gi den samme meldingen:

   Private Sub Form_Load()
   
       Dim i
   
       For i = 1 To 10
           MsgBox "Melding nummer " & i
       Next
   
   End Sub

Mulighetene er uendelige. Du kan f.eks. endre bakgrunnsfargen til en form 65 536 ganger slik:

   Private Sub Form_Load()
   
       Dim Red, Green
   
       ' På dette tidspunktet er ikke formen synlig, slik at dette må gjøres manuelt
       Show 
       
       For Red = 0 To 255
           For Green = 0 To 255
               Form1.BackColor = RGB(Red, Green, 0)
               DoEvents
           Next
       Next
   
   End Sub

Det finnes også andre typer løkker, hvorav en heter en DO-LOOP. Den er forholdsvis simpel og fungerer slik:

   Dim i, g
   
   Do Until i > 255
       Form1.Backcolor = RGB(i, g, 0)
       DoEvents
       i = i + 1
       g = g + 1
   Loop

Du trenger ikke å skrive et boolsk uttrykk etter Do, men da risikerer du å få en uendelig loop.

Binære operatører

[rediger]

Anvendelse

[rediger]

Hvis du vil sjekke for flere uttrykk samtidig med eksempelvis IF, slik at en meldingsboks kommer fram når du skriver inn helt bestemte verdier i flere teksbokser, kunne du gjort slik:

   If txtTekst.Text = "hallo" Then
       If txtTall2.Text = "verden" Then
           MsgBox "Hallo verden!"
       End If
   End If

Boolske operatorer kan forkorte dette ved å sammenligne to uttrykk i samme setning:

   If txtTekst.Text = "hallo" AND txtTall2.Text = "verden" Then
       MsgBox "Hallo verden!"
   End If

Den siste er å foretrekke på grunn av bedre oversiktlighet og lesbarhet. Dersom du ønsker å kun vise den spesifiserte koden når en eller begge av uttrykkene gir sant, er følgende vanlig å anvende:

   If txtTekst.Text = "hallo" OR txtTall2.Text = "verden" Then
       MsgBox "Hallo verden!"
   End If

Teori

[rediger]

Ved oppbygging av logiske uttrykk bruker en seks hovedoperatører; Not, And, Or, Xor, Eqv og Imp, hvorav de fire første er de mest brukte. Betydning av disse operatørene er vist i tabellen til venstre, og en fullstendig tabell over logiske uttrykk hvor en bruker disse operatørene er vist til høyre. I tabellen til høyre vises resultatet for den boolske operasjonen avhengig av inn-verdiene til variablene A og B (som kan ha verdiene True eller False).

Operatør: Anvendelse:
Not Negasjon
And Konjunksjon
Or Atskillelse (logisk addisjon)
Xor Eksklusiv atskillelse
Eqv Ekvivalent
Imp Indirekte


A B A And B A Or B A Xor B A Eqv B A Imp B
T T T T F T T
T F F T T F F
F T F T T F T
F F F F F T T

Kommentarer

[rediger]

For å skrive inn en kommentar i VB-koden setter du inn en apostrof etterfulgt av hva du vil skrive. Kommentaren avsluttes ved linjeskift.

   MsgBox "Hallo" ' Denne koden viser en meldingsboks med teksten hallo

Det er å anbefale at du dokumenterer koden din med kommentarer, om ikke for din egen del, så for andres. Dette betyr nødvendigvis ikke at du må tillegge en forklaring på hver eneste minste kodelinje - det forverrer heller lesbarheten. Nei, en bør snarere kommentere der det ikke helt kommer frem (med målgruppen for øye) hva koden har til hensikt å utføre (spesielt dersom koden anvender seg av en ukonvensjonell fremgangsmåte). I andre tilfeller kan det å eksempelvis vedlegge en sammendrag av hva de ulike prosedyrene gjør og krever (inndata og utdata) betraktelig forbedre lesbarheten. Det kan nok også være nyttig å kunne legge ved informasjon som kopirett og forfatter i selve kildekoden.


Sammenligningsoperatorer

[rediger]

Innledning

[rediger]

Disse operatørene, sammensatt av <, > og =, benyttes til for å teste om ett tall er mindre, større eller lik ett annet. Du kjenner kanskje prinsippet igjen fra barneskolen. Uansett bruker du de slik:

   Dim i
   
   i = 50
   
   If i < 0 Then
       MsgBox "i er mindre enn 0" 
   ElseIf i <= 100 And i >= 0 Then
       MsgBox "i er mindre eller lik hundre og større eller lik 0"
   ElseIf i > 100 And i < 200 Then
       MsgBox "i er større enn hundre og mindre enn 200"
   Else
       MsgBox "i er større en eller lik 200"
   End if

Oversikt

[rediger]
Operatør: Anvendelse:
= Likhet
<> Ulikhet
< Mindre enn
> Større enn
>= Større enn eller lik
<= Mindre enn eller lik

Datatyper

[rediger]

Flere innebygde datatyper

[rediger]

Til nå har vi utelukkende tatt i bruk én datatype når vi har deklarert variabler, nemlig Variant. Denne datatypen kan inneholde all data, og er satt til standard på alle udefinerte variabler.

Når du skal definere en datatype bruker du ’’As’’ nøkkelordet. En typisk deklarering blir da:

   Dim Tell As Long

Long er sammen med Single den vanligste datatypen for tall. Bruk dem så ofte som mulig istedenfor Variant, da de tar mye mindre plass og er meget raskere. Se bare på følgende tabell:

Datatype: Prefiks: Minnebruk i byte: Tidsbruk ved 10000 adderinger:
Byte . 1 1,9141 ms
Long & 2 1,1917 ms
Single ! 4 1,0491 ms
Double # 8 1,2922 ms
Currency @ 8 1,4112 ms
Variant 16 1,4373 ms
String $ 2 pr. tegn 3,2100 ms

Prefiks er den karakteren du kan sette etter variabelen for å definere datatypen uten bruk av As. Det er kun for å støtte bakoverkompatibelhet med eldre BASIC-versjoner. Mange kyndige VB-programmerere kaller bruken av disse prefikser for "street basic", og fnyser av de som bruker dem. Som et eksempel, kunne følgende ...

   Dim Tell As Long

... vært skrevet sådan:

   Dim Tell&

En variant tar ALLTID minst 16 byte, uansett innholdet. Dermed kan du spare svært mye tid og ressurser med å holde deg til den egnede datatypen.

I tabellen betyr 10000 adderinger hvor lang tid det tar å addere tallet 1 med en annen variabel 10 000 ganger. Den er bare tilstede for å underbygge grunnen til at du helst ikke bør benytte variant.


Brukerdefinerte datatyper

[rediger]

Brukerdefinerte datatyper (en. User defined types, forkortet UDT) benyttes for å koble sammen ulike datatyper - både forhåndsdefinerte og brukerdefinerte - til én logisk struktur (klasse) som kan benyttes i en eller flere variabler. Dette tilsvarer Pascal records og C structs. I VB kan en nå denne funksjonaliteten ved å anvende Type-nøkkelordet, innledet av enten Private eller Public i henholdsvis former/klassemoduler og moduler. Et eksempel på en UDT kan være følgende definisjon på en adresse:

   Private Type Address
       Street As String * 50            ' Gateadresse - begrenset til 50 tegn
       City As String * 50              ' By
       StateOrProvince As String * 50   ' Stat eller fylke
       PostalCode As Long               ' Postnummer (heltall)
       Country As String * 25           ' Land - her begrenset til 25 tegn
   End Type

En brukerdefinert datatype kan bestå av alle former for datatyper, sågar datatyper av samme sort som den selv, dersom de er definert ovenfor. Plasser følgende datatypedefinisjon nedenfor Adresse-definisjonen:

   Private Type Profile
       Address As Address          ' Brukerdefinisjon på en addresse
       Email As String * 64        ' E-postadresse (begrenset til 64 tegn)
       WebPageURL As String * 128  ' URL til en webside
       FullName As String * 64     ' Denne personens navn
       Age As Long
       HomeNumber As Long
       BuisinessNumber As Long
       MobileNumber As Long
       ' ... osv. Mange flere variabler kan legges til.
   End Type

Etter disse to definisjonene er plassert øverst i en form (etter Option Explicit vel å merke) kan en begynne å ta i bruk disse to nye datatypene som helt vanlige variabler:

   Dim Test As Profile
   
   ' Sett informasjon (bruk punktum til å få tilgang til de ulike variablene innunder)
   Test.Address.Street = "Gatevei 42"
   Test.Address.City = "Oslo"
   Test.Address.PostalCode = "0116"
   Test.Address.StateOrProvince = "Oslo"
   Test.Address.Country = "Norway"
   Test.Age = 30
   Test.Email = "epost@epost.com"
   Test.FullName = "Ola Normann"
   Test.HomeNumber = 12345678
   Test.WebPageURL = "http://www.google.com/"
   ' Osv.
   
   ' En kan hente verdiene på samme måte: (Trim fjerner unødvendige
   ' mellomrom som skapes med fikserte strenger)
   MsgBox "Epostadressen til " & Trim(Test.FullName) & " er " & Trim(Test.Email) & ".", vbInformation

Brukerdefinerte datatyper kan være en meget nyttig metode for å struktuere data raskt og effektivt, især når en opererer med filer. Dette skal vi se nærmere på i de kommende kapitlene.

Indekserte Variabler

[rediger]

Indekserte variabler kan være veldig nyttig i et utall av sammenhenger. Se f.eks. på denne koden:

   Dim Tall(0 To 10), i As Long
   
   For i = 0 To 10
       Tall(i) = Rnd * 100
   Next
   
   i = Rnd * 10
   
   MsgBox "Tall nummer " & i & " er lik " & Tall(i)

Som du ser lager du indekserte variabler med å sette paranteser etter variabelen. Du bruker To nøkkelordet for å definere kvantiteten.

Man kan også anvende brukerdefinerte datatyper:

   Dim Profiles(1 To 2) As Profile
   
   ' Sett verdiene i de ulike profilene
   Profiles(1).FullName = "Ola Normann"
   Profiles(2).FullName = "Kari Normann"

Det er også mulig å endre på kvantiteten til den indekserte variabelen i sanntid:

   Dim aNumbers()
   
   ' Endre kvantitet til ett element (fjerner all data)
   ReDim aNumbers(0)
   
   ' Sett verdi
   aNumbers(0) = 42
   
   ' Endrer kvantitet igjen (beholder tidligere data)
   ReDim Preserve aNumbers(1)
   
   ' Sett ny data
   aNumbers(1) = 43
   
   ' Vis data
   MsgBox "Den indekserte variabelen inneholder følgende verdier: " & Join(aNumbers, ", ") & "."


Åpne/lagre filer

[rediger]

Et essensielt aspekt av VB er hvordan filer lagres og leses, slik at man på et tidspunkt kan tilgjengeliggjøre data for senere bruk. Syntaksen for dette er som følger:

   Dim Free As Long
   
   Free = FreeFile
   
   Open "C:\testfil.txt" For Output As #Free
   Close #Free

Oversatt til norsk blir det:

   Finn et filnummer som ikke er i bruk.
   Åpne fil C:\testfil.txt og slett alt innhold. Åpne filen med filnummeret vi fant i foregående linje.
   Lukk filen vi nettopp åpnet

For å skrive til filen bruker vi Print-kommandoen. Den brukes slik:

   Print #Free, "hallo"

Du må naturlivis sette kommandoen etter OPEN syntaksen men før CLOSE syntaksen.

For å åpne setter vi inn For Input istedenfor For Output

   Dim Tekst As String, Free As Long
   
   Free = FreeFile
       
   Open "C:\testfil.txt" For Input As #Free
       Line Input #Free, Tekst
   Close #Free
   
   MsgBox Tekst


Skal du hente flere linjer på en gang må du bruke en DO-LOOP:

   Dim Buff As String, Tekst As String, Free As Long
   
   Free = FreeFile
   
   Open "C:\testfil.txt" For Input As #Free
       Do Until EOF(Free) ' EOF er TRUE når VB har nådd enden av fila
           Line Input #Free, Buff
           Tekst = Tekst & Buff & vbNewLine ' vbNewLine er konstanten for linjeslutt
       Loop
   Close #Free
   
   MsgBox Tekst


Eller du kan hente inn hele filen på en gang:

   Dim Buff As String, Free As Long
   
   Free = FreeFile
   
   Open "C:\Testfil.txt" For Input As #Free
       Buff = Input(Free, LOF(Free))
   Close #Free
   
   MsgBox Buff


Skal du åpne en fil i samme mappe som programmet gjør du slik:

   Dim Tekst As String, Free As Long
   
   Free = FreeFile
   
   Open App.Path & "\testfil.txt" For Input As #Free
       Line Input #Free, Tekst
   Close #Free
   
   MsgBox Tekst


En annen metode er å åpne filen binarisk - dvs. uten unødigheter som konverterer data, eller som er ineffektive når store filer skal lastes inn. Ytelsesmessig er dette den mest gagnlige fremgangsmåten, idet vi laster inn hele filen i ett stort jafs.

   Dim Tekst As String, Free As Long
   
   Free = FreeFile
   
   Open App.Path & "\testfil.txt" For Binary As #Free
       
       ' Denne metoden krever at vi allokerer bufferen før vi laster inn data.
       Tekst = Space(LOF(Free))
       
       ' Last inn data
       Get #Free, , Tekst
       
   Close #Free
   
   MsgBox Tekst


Man kan også lagre filer på en likeledes måte:

   Dim Tekst As String, sFile As String, Free As Long
   
   Free = FreeFile
   
   ' Filen vi skal åpne
   sFile = App.Path & "\testfil.txt"
   
   ' Dersom du skal begynne med en tom fil når data skal skrives, må du fjerne kommentartegnet på følgende linjer:
   ' If Dir(sFile) <> Then ' Sjekker om filen eksisterer
   '     Kill sFile
   ' End if
   
   ' Data som skal lagres (kan være av andre datatyper)
   Tekst = "Hallo verden!"
   
   Open sFile For Binary As #Free
   
       ' Skriv data
       Put #Free, , Tekst
       
   Close #Free


En fordel ved å benytte teknikken ovenfor, er muligens at en ikke er begrenset til å kun lese og skrive med strenger. Dersom man lagrer store tallnummer, er det naturligvis fordelaktig at tallene lagres binarisk og ikke som en streng - det krever mindre ressurser og går langt kjappere. Jamfør følgende med streng-metoden (For Output):

   Dim Talldata As Long, Free As Long
   
   Free = FreeFile
   
   Talldata = 123456789
   
   Open App.Path & "\testfil.txt" For Binary As #Free
       ' Skriv variabelen til filen
       Put #Free, , Talldata
   Close #Free

Utdata blir som følger:

   &#21;Í[&#7;  

Noe som er helt annerledes (og mindre) enn den tilsvarende metoden med Output. Bemerk at en ikke behøver å allokere slike variabeler når en skal lese filen - dette kreves kun med strenger og arrayer.

Lagre/åpne UDT-variabler

[rediger]

La oss benytte Profile-datatypen i dette eksempelet. Dersom du har kontaktinformasjon om brukere knyttet til en array av denne datatypen, kan du lagre dette noe som følger:

   Private Sub SaveData(sFile As String, Contacts() As Profile)
       
       Dim Free As Long
       
       ' Hent ledig filnummer
       Free = FreeFile
       
       ' Åpne fil
       Open sFile For Binary As #Free
           
           ' Lagre først antall kontakter, dernest selve kontaktinformasjonen
           Put #Free, , CLng(LBound(Contacts))
           Put #Free, , CLng(UBound(Contacts))
           Put #Free, , Contacts
           
       ' Lukk fil
       Close #Free
       
   End Sub

For å laste inn en fil med denne filstrukturen, kan en benytte følgende:

   Private Sub LoadData(sFile As String, Contacts() As Profile)
       
       Dim Free As Long, Low As Long, Upper As Long
       
       ' Hent ledig filnummer
       Free = FreeFile
       
       ' Åpne fil
       Open sFile For Binary As #Free
       
           ' Først, hent inn array-grenseverdiene til kontaktinformasjonen
           Get #Free, , Low
           Get #Free, , Upper
           
           ' Realloker array
           ReDim Contacts(Low To Upper)
           
           ' Last inn verdier
           Get #Free, , Contacts
           
       ' Lukk fil
       Close #Free
       
   End Sub

Man kan også laste inn kontakter som poster ved å benytte Len = LenB(Contact) i endelsen av Open-kommandoen, og deretter sette Get/Put #Free, [indeks til post], Contact([Index]) for å hente/lagre en post.

Åpne programmer

[rediger]

Noen ganger vil det kanskje være ønskelig å åpne andre programmer ifra ditt program. Dette kan du gjøre med Shell-kommandoen:

   Shell "notepad.exe"
   Shell "calculator.exe"
   Shell "control userpasswords2"
   Shell "cmd /K echo dette er en test"

Overstyring

[rediger]

Overstyring (en. subclassing) kan være svært nyttig når man vil legge til funksjonalitet som i utgangspunktet ikke støttes av VB. For å klarlegge hvordan dette foregår, må vi først gjennomgå litt bakgrunnsteori. Det har seg nemlig slik at alle vinduer (f.eks. en form, en knapp, en listeboks osv.) i Windows har spesifisert en funksjon som operativsystemet eller andre programmer kan kalle for å kommunisere med programmet. Windows kan f.eks. sende hendelser som når musepekeren kommer over vinduet, en tast sendes til vinduet og mye mer. Programmer kan på sin side sende forespørsel om spesielle opplysninger angående vinduet; eksempelvis vil EM_GETLINECOUNT få en tekstboks til å sende tilbake antall linjer i teksten. Man kan også definere sine egne "funksjoner".

For å kalle disse spesielle funksjonene, kan man bruke enten PostMessage, SendMessage eller CallWindowProc (forutsetter at man kjenner adressen til prosedyren).

Vanligvis ser en slik funksjon ut som sådan:

  Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, _ 
   ByVal lParam As Long) As Long
   	
  		 ' Din kode her
  	Select Case uMsg
  	Case 0
       	' Noe her
   	Case 1
       	' Noe her
   	End Select
   		
   	WindowProc = 0 ' Returner en verdi til avsender
   	
  End Function

I denne funksjonen er hwnd adressen eller pekeren til vinduet avsenderen har prøvd å nå; uMsg er ID-en til funksjonen/hendelsen eller hva enn anropet gjalt; wParam er en valgfri variabel som benyttes til flere forskjellige hensikter, avhengig av ID-en - likeså er det med lParam.

Dersom jeg for eksempel ønsker å sette tittelbaren på en form, kunne jeg uten problemer gjort som følger:

   Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _ 
    ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long
   
   Private Const WM_SETTEXT = &HC
   
   Private Sub Form_Load()
   
   	SendMessage Me.hwnd, WM_SETTEXT, 0&, "Dette er en test"
   
   End Sub

Mottakeren ville så fått en melding til sin vindu-funksjon, omtrent som dette:

  Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, _ 
   ByVal lParam As Long) As Long
   	
   	' hwnd er nå lik Me.hwnd, uMsg er WM_SETTEXT, wParam er 0 og lParam er 
   	' "Dette er en test"
   	
   	' Det ser neppe slik ut i virkeligheten, men det gir et nokså godt bilde av hva som skjer under overflaten
   	Select Case uMsg
   	Case WM_SETTEXT
   	
       	Me.Caption = lParam
       
   	'Case  ... (mange flere her)
   	End Select
   
   End Function

Hva er så poenget med subclassing? Jo, i denne teknikken overstyrer vi rett og slett et programs egentlige vindu-funksjon ved å legge inn vår egen, og dernest sende eller la være å sende meldingen videre - alt etter hva vi ønsker. For å spesifisere vår egen vindu-funksjon, bruker vi API-kallet SetWindowLong. Studer og legg følgende eksempel inn i en modul:

   Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, _  
    ByVal dwNewLong As Long) As Long
   Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _  
    ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   Declare Function SetClipboardViewer Lib "user32" (ByVal hwnd As Long) As Long
   Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _ 
    ByVal wParam As Integer, ByVal lParam As Any) As Long
   
   Public Const WM_SETTEXT = &HC
   Public Const GWL_WNDPROC = (-4)
   
   Private PrevProc As Long ' Den originale funksjonen
   
   Public Sub SubclassForm(F As Form)
   
       ' AddressOf WindowProc = gir adressen til funksjonen
       PrevProc = SetWindowLong(F.hwnd, GWL_WNDPROC, AddressOf WindowProc)
       
   End Sub
   
   Public Sub SubclassForm(F As Form)
   
       ' Det er SVÆRT viktig at vi tilbakestiller subclassingen. Dersom dette ikke blir gjort, kræsjer hele VB
       SetWindowLong F.hwnd, GWL_WNDPROC, PrevProc
       
   End Sub
   
   Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, _ 
    ByVal lParam As Long) As Long
       
       Dim sTemp As String
       
       If uMsg = WM_SETTEXT Then
           ' Ikke la den egentlige teksten komme frem, erstatt den med vår egen
           sTemp = StrConv("Overstyring" & Chr(0), vbFromUnicode)
           lParam = StrPtr(sTemp)
       End If
       
       ' Kall den originiale funksjonen
       WindowProc = CallWindowProc(PrevProc, hwnd, uMsg, wParam, lParam)
           
   End Function

Legg så inn en form med knappen cmdTest, og legg til følgende kode i formen:

   Private Sub cmdTest_Click()
   
       SendMessage Me.hwnd, WM_SETTEXT, 0&, "Dette er en test"
   
   End Sub
   
   Private Sub Form_Load()
   
       ' Starter subclassingen
       SubclassForm Me
   
   End Sub
   
   Private Sub Form_Unload(Cancel As Integer)
   
       ' Dersom du stopper prosjekter (med eksempelvis stoppknappen) uten at denne blir kalt, kan det gå ille
       SubclassForm Me
   
   End Sub

Når du så trykker på knappen cmdTest, vil du se at teksten som kommer opp i tittelvinduet er ikke "Dette er en test", men "Overstyring".

Eksterne linker

[rediger]
Lenk Kommentar
XtremeVBTalk Et svært aktivt engelskspråklig forum.
Hw.no-VB Et aktivt norskspråklig forum.
WinsockVB Har absolutt alt relatert til Winsock-programmering i VB.
VBSpeed Optimaliserte VB-prosedyrer.
GPWiki Inneholder spillrelaterte VB-artikler.
AllAPI Eksempler for Windows APIs
DirectX4VB Tilbyr læreprogrammer for DirectX 7,8,9 til VB- programmerer
PlanetSourceCode Et utall med eksempler og fullverdige programmer skrevet i VB.
Hardcore Visual Basic Bruce McKinneys mesterverk; beviser at en kan skrive sågodt som alt som tenkes kan i VB.
VBCode.com Fri kildekode for VB


Visual Basic