Gå til innhold

aadnk

Medlemmer
  • Innlegg

    2 990
  • Ble med

  • Besøkte siden sist

Innlegg skrevet av aadnk

  1. Det er nok lettest å ta screenshot av nettleseren, ettersom det såvidt jeg vet ikke er noen offisiel måte å laste ned bildene på. Men, om du du kan programmere (eller har god tid), er det jo mulig å bruke Street View-APIet direkte. En kort (og uoffisiel) gjennomgang er å finne her.

     

    Det er nokså enkelt å bruke dette APIet (foreløpig, i hvert fall), men du kan bare laste ned utsnitt på 512x512 piksler. For å pusle disse sammen til et stort panorama-bilde, må du enten gjøre det manuelt eller skrive et program.

     

    Si du vil laste ned hele dette bildet. Først trykker du på LINK oppe i høyre hjørne. Kopier så lenken inn i Notepad og finn frem til panoid-spørreparameteren (mellom panoid= og &), markert svart nedenfor:

     

    Du bruker følgende URL for å laste ned en av 512*512-kvadrantene:

    http://cbk0.google.com/cbk?output=tile&panoid=[PID]&zoom=[ZOOM]&x=[X]&y=[Y]

     

    Erstatt [PID] med panoid-verdien du fant ovenfor (i eksempelet XE6jJFqR4o4sAUscmyvWKg), sett [ZOOM] til 5, og sett inn [X]-verdier fra 0 til 25 og [Y] fra 0 til 12 (dvs. 26 * 13 = 338 kvadranter). Hvis du velger 14 i X og 6 i Y i eksempelet, får du et utsnitt av slottet:

    http://cbk0.google.com/cbk?output=tile&panoid=XE6jJFqR4o4sAUscmyvWKg&zoom=5&x=14&y=6

  2. Attributten VBFixedString, FileOpen, FileGet og FileClose ligger i Microsoft.VisualBasic og er først og fremst ment for å gjøre det mulig å automatisk oversette Visual Basic 6.0-programmer (du holder på med VB 7-10). Det er foretrukket at en bruker funksjoner i selve kjernen av .NET (System-navnerommet), men det er ikke i praksis et problem - VisualBasic-bakoverkompatibilitetslaget vil neppe bli fjernet fra .NET.

     

    Et slikt postsystem har sine fordeler, blant annet unngår du å måtte legge all informasjonen i RAM-en og det er mulig å endre størrelsen av felter uten å måtte skrive hele filen på nytt, men en er også begrenset av støttede datatyper og den øvre størrelsen i feltene. Disse innsparingene var muligens relevante i VB sin barndom, men i dag vil det være bedre og enklere å bare ha all informasjonen lagret i minne og skrive det ut til disken ved programslutt. I dag blir dette først et problem når man snakker om tusenvis/millioner av poster, og da burde en for lengst gått over til et skikkelig databasesystem med indeksering (Microsoft SQL Server, MySQL, Oracle, ect.).

     

    Men hvis antall poster er langt mindre enn dette, går det helt greit å åpne og lagre til en enkel filstruktur. I .NET er det lettest å oppnå dette med serialisering - nær automatisk konvertering fra objekter og til filer (gen. filstrømmer) og tilbake igjen. Dvs. at du kan lagre et objekt (eksempelvis en samling studenter) til en fil, og senere rekonstruerere dette objektet fra den samme filen.

     

    Først, gjør om strukturen din til en klasse uten attributtene:

    Public Class Student
       Public navn As String
       Public klasse As String
       Public epost As String
       Public født As Date
    End Class

     

    Deretter lager du et felt i formen (eller hovedklassen) som kan inneholde alle studentene. Det er også mulig å indeksere studentene slik at du f. eks. kan slå opp en student etter navn så som tallindeks:

     ' Dette er en array (som Dim s() As Students) som automatisk utvider seg '
    Private studenter As New List(Of Student)

     

    Merk at syntaksen ovenfor krever .NET 2.0 eller nyere. Hvis du bruker en eldre versjon, vil du få feilmelding og du må du erstatte List(Of Student) med ArrayList.

     

    For å legge til en ny post, bruker du Add-metoden:

    Dim nyStudent As New Student
    
    With nyStudent
       .Navn = "Test"
       .Klasse = "Klasse"
       .Epost = "[email protected]"
       .Født = New Date(1990, 1, 1)
    End With
    
    Studenter.Add(nyStudent)

     

    Hvis du bruker .NET 4.0 kan du gjøre dette i en linje (evt. med en konstruktør før 4.0):

    studenter.Add(New Student With {
               navn = "Test",
               klasse = "Klasse",
               epost = "[email protected]",
               født = New Date(1990, 1, 1)}

     

    For å endre en student, kan du modifisere feltene direkte med en indeks:

    With studenter(0) ' første student '
       .navn = "nytt navn"
       .klasse = "ny kasse"
       ' ect, '
    End With

     

    Du bør også sjekke at indeksen er korrekt. Studenter.Count gir deg antall studenter i listen, hvor tallindeks 0 er første student og tallindeks Studenter.Count - 1 er siste student.

     

    Du kan åpne å søke i listen på to måter - enten ved å indeksere studentene etter f.eks. navn (dette er raskere dersom du har veldig mange studenter), eller du kan gå gjennom hver enkelt student om gangen, som du har forsøkt å gjøre i koden ovenfor. Dette kan du eksempelvis gjøre med en For-løkke:

    For i = 0 To studenter.Count - 1
       ' Det vi er ute etter '
       If studenter(i).navn = "Test" Then
           ' Last inn student etter gitt indeks '
           LoadStudent(i)
       End If
    Next
    
    MessageBox.Show("Feil. Ingen student med det navnet")

     

    Hvis du har .NET 3.0 eller nyere, kan du bruke LINQ:

    ' Husk at LoadStudent-metoden må teste om indeksen er gyldig ' 
    LoadStudent(studenter.FindIndex(Function(s) s.navn = "Test"))

     

     

    Endelig, for å serialisere (lagre) en liste med studenter, gjør du følgende:

    Try
       Using output As New IO.FileStream("data.dat", IO.FileMode.Create)
           ' Legg gjerne til Imports Runtime.Serialization.Formatters.Binary '
           Dim Formater As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
           Formater.Serialize(output, studenter)
       End Using
    Catch ex As Exception
       ' Vis feil '
       MessageBox.Show(ex.ToString)
    End Try

     

    For å åpne, gjør du som så:

    If IO.File.Exists("data.dat") Then
       Try
           Using input As New IO.FileStream("data.dat", IO.FileMode.Open)
               ' Legg gjerne til Imports Runtime.Serialization.Formatters.Binary '
               Dim Formater As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
               studenter = Formater.Deserialize(input)
           End Using
       Catch ex As Exception
           ' Vis feil '
           MessageBox.Show(ex.ToString)
       End Try
    End If

  3. Du kan også skrive potenser med hjelp av TeX: mimetex.cgi?3^{2}. Syntaksen på forumet er som på Wikipedia, men må settes inn med kodetaggen tex (med klammeparanteser) istedenfor <math>.

     

    Ditt stykke kan løses ved forenkle teller med regelen chart?cht=tx&chl=a^{n} a^{m} = a^{n + m} samt multiplisere med inversen av nevner oppe og nede (dvs. gjøre negative potenser til positive og omvendt) og endelig forekle:

     

    chart?cht=tx&chl=\frac{3^{3}\,2^{-2}\,3^{-4}}{2^{-1}\,3^{-1}} = \frac{3^{3-4}\,2^{-2}\,\cdot\,2\,3}{2^{-1}\,3^{-1}\,\cdot\,2\,3} = \frac{3^{-1+1}\,2^{-2+1}}{2^{0}\,3^{0}} = 2^{-1} = \frac{1}{2}

     

    Edit: La til et ekstra steg i utregningen.

  4. Teoretisk sett er en plancklengde den minste mulige avstanden som, blant annet grunnet Heisenbergs usikkerhetsprinsipp i kvantemekanikken, vi kan i det hele tatt snakke om. Ettersom lyshastigheten er den øvrige hastighet, kan man utlede den øvrige tidsenheten - en plancktid (mimetex.cgi?t_{p}) - etter tiden det tar for lys å tilbakelegge en plancklengde, for å finne den minste tidsenhet det tilsvarende gir mening å resonnere med.

     

    Hvis man så anvender newtonisk mekanikk (som sikkert blir riv ruskende galt) og antar at en partikkel aksellererer fra 0 til c på en plancktid, burde aksellerasjonen være:

    chart?cht=tx&chl=l_{p} = \sqrt{\frac{\hbar G}{c^{3}}}

     

    chart?cht=tx&chl=t_{p} = \sqrt{\frac{\hbar G}{c^{5}}}

     

    chart?cht=tx&chl=s = \frac{1}{2}\,a\,t^{2}

     

    chart?cht=tx&chl=\sqrt{\frac{\hbar G}{c^{3}}} = \frac{1}{2}\,a\,\frac{\hbar G}{c^{5}}

     

    s^{2}

     

    Men dere må nok ta dette med en stor klype salt. Planckenhetene har kun blitt utledet matematisk, og det er nå heller tvilsomt en kan anvende newtonisk mekanikk på partikler. Likevel vil jeg tro det i prinsippet burde være mulig å finne en maksimal aksellerasjon.

  5. Det er noe av det samme:

    Public Class frmTest

     

       Private Sub frmTest_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

     

           ' Testdokumentets innhold:

           '  <html>

           '  <body>

           '      <form name="test">

           '          <input type="radio" name="sex" value="male"> Male <br>

           '          <input type="radio" name="sex" value="female"> Female

           '      </form>

           '  </body>

           '  </html>

     

           WebBrowser1.Navigate("file://C:\Test.html")

     

       End Sub

     

       Private Sub btnMark_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMark.Click

     

           ' ** Det kan være lurt å legge all denne koden i en egen prosedyre dersom du **

           ' ** skal avmerkere flere valgknapper.                                       **

     

           ' Parameter med tallet (n-1) brukes for å referere til den n'te formen

           ' (den første: (0), den andre: (1), ect.). Bruk dette når formen ikke har et navn.

           Dim TargetForm = WebBrowser1.Document.Forms("test")

     

           For Each Control As HtmlElement In TargetForm.GetElementsByTagName("input")

     

               ' Henter ut alle valgknapper

               If Control.GetAttribute("type").ToLower = "radio" Then

     

                   ' Generelt sett tar en alltid utgangspunkt i en egenskap som

                   ' elementene du vil lese/endre kun deler med hverandre.

     

                   ' I valgknappgrupper er denne egenskapen inndatakontrollenes navn.

                   ' Denne blir for øvrig sendt til serveren i URL'en (ved GET):

                   '     http://.../?...&[radiobuttonname]=[selected_button's_value]&...

                   If Control.Name.ToLower = "sex" Then

                       If Control.GetAttribute("value").ToLower = "male" Then

                           ' Velg èn av disse metodene!

                           Control.SetAttribute("checked", 1)

                           Control.InvokeMember("click")

                       End If

                   End If

     

               End If

           Next

     

       End Sub

    End Class

  6. Du får la aadnk gjøre som han vil da, selv ser jeg på det som en bjørnetjeneste å GIEF TEH CODEZ PLOX.
    Hvis han vet hva som er godt for ham selv, burde han kunne velge den løsningen han kan forstå, eventielt droppe det hele.

     

    Kanskje regex egentlig hadde vært den mest elegante løsningen her?
    Ikke hvis man har å gjøre med mange søkeord. Da må man jo manuelt passe på at de regulære uttrykkene tar hensyn til alle subsequence-ene, og da jeg antok nøkkelordene trådstarter oppgav var eksempler, tenkte jeg først og fremst på en mer generell løsning.
  7. Oi, litt mye til svar men jeg bruker VB 2008,

    og trenger bare kommando for det.

    + At jeg har prøvd elseif greia, og det funka ikke så lett.

    Du var nå såpass uklar i problembeskrivelsen at jeg umulig bare kunne gi deg "kommandoen" (koden), og i alle tilfeller vil jeg rent generelt at man faktisk lærer noe fra kodeeksemplene, og ikke bare kopiere kode og utnytte den tjenesten alle her yter gratis.

     

    I innlegget ovenfor nevnte jeg at ELSEIF-eksempelet KUN fungerer dersom koden kjøres èn gang. Legges koden inn i en knapp brukeren trykker på flere ganger, er dette såklart ikke tilstrekkelig, og en må dermed enten erstatte teksten etterhvert som den skrives i tekstboksen (mitt andre eksempel), eller ta høyde for indre sekvenser i resultatordene ved å rett og slett ignorere dem. Dette kunne man muligens ha gjort ved å lagre erstattede forekomster i en Array/liste, men da teksten kan endres radikalt av brukeren mellom hver knappetrykk, bør man i stedet bruke selve teksten som basis. Her kunne man godt brukt regulære uttrykk, men dette lar seg vanskelig automatisere for generelle søkeørd. Det beste er nok derfor å lage sin egen skreddesydde erstatningsfunksjon, så som følgende:

    Public Class Form1

       Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

           RichTextBox1.Text = ReplaceEx(RichTextBox1.Text, "k", "ør", "a", "kü")

       End Sub

     

       Public Function ReplaceEx(ByVal Text As String, ByVal ParamArray KeyValues() As String) As String

     

           ' Da vi behøver rask oppslag, konverterer vi til tabeller

           Dim Chars = Text.ToCharArray, Possible As Boolean, Longest As Integer

           Dim Values = KeyValues.Select(Function(x) x.ToCharArray).ToArray

           Dim Candidates As New List(Of Integer), Matches As New List(Of Integer)

           Dim Output As New System.Text.StringBuilder

     

           ' Gå gjennom alle karakterene (bokstaver, tall) èn etter èn

           For i = 0 To Chars.Length - 1

     

               ' Se om vi har kommet til et mulig nøkkelord

               For j = 0 To Values.Length - 1

                   If Chars.Length >= Values(j).Length + i AndAlso Values(j)(0) = Chars(i) Then

                       If Values(j).Length = 1 Then Matches.Add(j) Else Candidates.Add(j)

                       Longest = Math.Max(Values(j).Length - 1, Longest)

                       Possible = True

                   End If

               Next

     

               ' Test videre om mulig

               If Possible Then

     

                   Dim iBest As Integer = 0

     

                   For k = 1 To Math.Min(Chars.Length - 1 - i, Longest)

                       For j = 0 To Candidates.Count - 1

                           If j < Candidates.Count Then

                               ' Sjekk alle tegn

                               If Values(Candidates(j))(k) = Chars(i + k) Then

                                   If k = Values(Candidates(j)).Length - 1 Then

                                       Matches.Add(Candidates(j))

                                       Candidates.RemoveAt(j)

                                       j -= 1

                                   End If

                               Else

                                   Candidates.RemoveAt(j)

                                   j -= 1

                               End If

                           End If

                       Next

                   Next

     

                   If Matches.Count > 0 Then

     

                       ' Finn største gyldige forekomst

                       For Each Index In Matches

                           If Values(Index).Length > Values(iBest).Length Then

                               iBest = Index

                           End If

                           ' Om nødvendig, kan du favorisere søkeord over erstatningsord

                           ' (eller omvendt) i denne løkken

                       Next

     

                       '   i mod 2 =     0             1               0

                       ' KeyValues = {[søkeord], [å erstatte med], [søkeord], ...}

                       If iBest Mod 2 = 0 Then

                           If iBest < Values.Length - 1 Then

                               Output.Append(KeyValues(iBest + 1))

                           End If

                       Else

                           Output.Append(KeyValues(iBest))

                       End If

     

                       ' Ikke søk inn i selve søkeordet

                       i += Math.Max(Values(iBest).Length - 1, 0)

                   End If

     

                   ' Forberedelse til neste runde

                   Possible = False

                   Candidates = New List(Of Integer)

                   Matches = New List(Of Integer)

                   Longest = 0

               Else

                   Output.Append(Chars(i))

               End If

           Next

     

           Return Output.ToString

     

       End Function

    End Class

    Hvis du synes den er for lang, kan du jo prøve å forkorte den selv. Da vil du sannsynligvis lære en hel del, enten du lykkes eller ei.

  8. Dersom du ikke forventer å utføre erstatningsreglene om igjen, kan du forhindre at resultatene blir forandret ved å avslutte IF-setningene når en erstatning blir gjennomført; eksempelvis ved å lage èn lang IF-setning (via ElseIf):

    ' Du kan også bruke en løkke og en Dictionary

    If RichTextBox1.Text.Contains("k") Then

       RichTextBox1.Text = RichTextBox1.Text.Replace("k", "ør")

    ElseIf RichTextBox1.Text.Contains("a") Then

       RichTextBox1.Text = RichTextBox1.Text.Replace("a", "kü")

    End If

    Men, om denne koden kjøres flere ganger (eksempelvis i RichTextBox1_TextChanged) burde du heller utføre erstatningen i inndataen:

    Public Class Form1

       Private Sub RichTextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RichTextBox1.KeyDown

     

           ' Dersom du vil håndtere andre formater (HTML, RTF) må du hente ut tekstfelter slik at en unngår å erstatte

           ' karakterer i metafeltene (om ikke blir <a>ba</a> til <kü>bkü</kü> fremfor <a>bkü</a>)

           If e.Control AndAlso e.KeyCode = Keys.V Then

               If Clipboard.ContainsText(TextDataFormat.Text) OrElse Clipboard.ContainsText(TextDataFormat.UnicodeText) Then

                   RichTextBox1.SelectedText = ProcessText(Clipboard.GetText)

                   e.Handled = True

               End If

           End If

     

       End Sub

     

       Private Sub RichTextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles RichTextBox1.KeyPress

     

           ' Lar ENTER og BACKSPACE være i fred

           If Not Char.IsControl(e.KeyChar) Then

               RichTextBox1.SelectedText = ProcessText(e.KeyChar.ToString)

               e.Handled = True

           End If

     

       End Sub

     

       Public Function ProcessText(ByVal Value As String) As String

     

           ' Erstatt verdier

           If Value.Contains("k") Then

               Return Value.Replace("k", "ør")

           ElseIf Value.Contains("a") Then

               Return Value.Replace("a", "kü")

           Else

               Return Value

           End If

     

       End Function

    End Class

  9. Hack kalles det.
    Det er jo klart hva som er teknisk mulig på ingen måte overlapper med hva språkdesignerene hadde til hensikt eller hva som kanskje er forsvarlig/tilrådelig i en applikasjon, men på en annen side er svært mange av teknikkene i en VB6-programmerers verktøyboks av slik art at det faller innunder en eller begge av disse kategoriene.

     

    Å modifisere WndProc-funksjonen, hvilket er ytterst normalt i C og ikke noe særlig betydelig i .NET, krever en noe omfattende hack (å endre funksjonspekeren i vinduets informasjonsstruktur til å peke til en egendefinert funksjon som kaller den originale funksjonen før eller etter den utvidede funksjonaliteten har blitt håndtert) som ofte kunne føre til krasj i IDEen (alternative metoder har omgått dette dog). Når mange Windows-meldinger og funksjoner går VB-programmer hus forbi om man ikke subclasser WinProc var dette heller ingen uvanlig metode å finne i større VB-programmer. Selv noe så simpelt som å implementere IEnumerable krevde subclassing (erstatte funksjonspekere i COM-objektets vtable) og egendefinerte type-libraries.

     

    Personlig benyttet jeg svært ofte, gjerne i bilde- eller strengprosessering, en hack for å omgå fraværet av eksplisitte pointers (ByRef i parametere er vel det nærmeste en kommer) i VB der Array-implementasjonens SafeArray-struktur ble modifisert slik at den referte til minneområdet en ville lese/skrive til.

     

    Man kunne til en viss grad tillate seg slik dyp integrering med maskintypen og operativsystem, i motsetning til eksempelvis Java, ettersom VB6 kun skulle kjøres under èn enkel plattform - x86 Windows 95/98/NT. Når språket og den virtuelle maskinen var utilstrekelig, var det derfor nødvendig (og ikke langt fra uvanlig) å ty til denslags. Men i .NET skyr jeg dette som ilden.

     

    Poenget er at hva som i utgangspunktet ble ansett som hacks etterhvert utviklet seg til general practice, og at cFuncCall i lys av alt dette ikke er en så stor hack som maskinkode blir ansett i tilsvarende språk. Funksjonaliteten er dessuten ikke så snever som du antyder - majoriteren av funksjonskall i Win32 benytter kun DWORD (og pointers), og dessuten støtter teknikken, i motsetning til VB6 (som kun støtter stdcall), andre calling conventions (cdecl).

     

    For øvrig, funksjonspekere er faktisk implemenert i VB6 - AddressOf-operatøren returnerer en modulprosedyres/-funksjons minneadresse i en parameter (slik at Win32-enumerasjon lar seg gjennomføres), men dette er på langt nær komparabelt til Delegates i .NET-rammeverket.

  10. Det finnes mange måter. Her er et lite utvalg:

    Public Class Form1

     

       ' Den enkleste metoden er nok imidlertid å gruppere kontrollene manuelt (må initialiseres i Form_Load)

       Private YourGroup() As CheckBox

     

       Private Sub btnSet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSet.Click

     

           ' (1) Avkrysser alle sjekkbokser som starter med en gitt streng

           For Each Item As Control In Me.Controls

               If TypeOf Item Is CheckBox Then

                   With DirectCast(Item, CheckBox)

                       ' Man kan fint bruke andre identifikasjonsmetoder (Hint: Tag-egenskapen)

                       If .Name.StartsWith("CheckBox") Then

                           .Checked = True

                       End If

                   End With

               End If

           Next

     

           ' (2) Som ovenfor, men bruker her LINQ (inkludert i VB.NET 2008)

           For Each CheckBox In Me.Controls.OfType(Of CheckBox)()

               If CheckBox.Name.StartsWith("CheckBox") Then

                   CheckBox.Checked = True

               End If

           Next

     

           ' (3) Om disse sjekkboksene må refereres til ofte, kunne det vært en god idè å "refactor"-e

           '     utvelgelsen til en egen prosedyre (og evt. lagre resultatet i en variabel).

           For Each CheckBox In ControlGroup(Of CheckBox)("CheckBox")

               CheckBox.Checked = True

           Next

     

           ' (4) Manuel gruppe

           For Each CheckBox In YourGroup

               CheckBox.Checked = True

           Next

     

       End Sub

     

       Public Function ControlGroup(Of T As Control)(ByVal GroupName As String) As IEnumerable(Of T)

           ' Dersom man ikke har tilgang til LINQ må man bruke metode (1) internt

           Return Me.Controls.OfType(Of T)().Where(Function(x) x.Name.StartsWith(GroupName))

       End Function

     

       Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

           ' Kan ikke plasseres øverst da kontrollene ikke er initialisert på det tidspunktet

           YourGroup = New CheckBox() {CheckBox1, CheckBox2, CheckBox3, CheckBox4, CheckBox5}

       End Sub

    End Class

  11. Du kan også prøve å lage et plug-in system som laster Dll-er i VB6, det er ikke lett, hvis det engang er mulig. Dette er ganske enkelt å få til .NET, både med System.Reflection.Load eller ved å bruke LoadLibrary fra Kernel32.
    Det er mulig om man laster inn DLL-en med LoadLibrary, genererer assembly-koden for å kalle en gitt funksjon dynamisk og eksekverer denne kodeblokken med CallWindowProc (da, ulikt QBasic, VB6 ikke tillater tilfeldig kjøring av kode).

     

    Og nei, det krever ikke så mye kode som det kanskje gir inntrykk av - i det gamle APIByName-eksempelet på hjemmesiden min bruker teknikken kun 5 kB

  12. Man kan bruke Short.Parse eller Short.TryParse til dette (alt etter om man forventer mange Exceptions). Til nøds kan også Val() brukes (Val("&HFFS") eksempelvis), men da må deretter konvertere resultatet fra Double til Short. Det er òg noe unødvendig å anvende funksjoner i Microsoft.VisualBasic dersom det finnes fullgode alternativer i .NET-rammeverket.

    Dim Value As Short, Number As String

     

    Number = InputBox("Skriv inn et heksadesimalt tall.", "Hex", "FF")

     

    If Short.TryParse(Number, Globalization.NumberStyles.HexNumber, Nothing, Value) Then

       MessageBox.Show(Value)

    Else

       MessageBox.Show(String.Format("'{0}' er ikke et gyldig heksadesimalt tall.", Number))

    End If

  13. Det kommer litt an på arbeidsmengden - forventer du at bakgrunnstråden tilbringer svært liten tid på hver oppgave, er det nok mest optimalt å bruke et delt Queue-objekt, samt hente ut en synkronisert wrapper via Synchronized-metoden for trådsikkerhet (ArrayList og SyncLock i pre-2.0). La så hovedtråden starte bakgrunnstråden om køen er tom og for hver hendelseskjøring legge ut data. Bakgrunnstråden kan så simpelthen hente ut data, utføre prosesseringen, og dernest avslutte når køen er tom.

     

    Eventuelt, om arbeidsoppgavene er langvarige og egner seg til parallellkjøring, kan en godt bruke en ThreadPool.

  14. Det er dette som er så trist (eller for enkelte i VB6s tilfelle gledelig) med nåværende kopirettighetslover - åndsverk risikerer å gå fullstendig tapt for ettertiden dersom rettighetsholderen (av juridiske eller praktiske grunner) forkaster verket før tidsfrsten har utløpt og stanser all videre distribusjon. Dette er særlig et problem i softwareindustrien der det ikke tar lang tid før spill og programmer har utspilt sin rolle.

     

    Av den grunn har jeg valgt å gjøre VB6s lillebror, Visual Basic 5.0 Control Creation Edition, tilgjengelig på nett. I motsetning til Visual Studio/Basic 6, var dette programmet gratis, skjønt det kun tillot kompilering til ActiveX-kontroller (ikke programmer i form av EXE-filer). Dersom du kun har behov for å eksperimentere med VB6-språket, skulle det ikke by på altfor mange problemer å bruke VB5 da forskjellene er nokså minimale (overhodet ikke som transformasjonen mellom VB6 og VB .NET):

    http://home.lyse.net/aadnk/Filer/vb5ccein.exe

  15. Er ikke helt sikker på hva du mener, men dersom du tenker på egendefinerte kontroller er det jo ikke verre enn å overstyre OnPaint-prosedyren:

    http://msdn.microsoft.com/en-us/library/cksxshce.aspx

     

    For øvrig kan du alltids bruke AddHandler om du ønsker å registrere en event handler manuelt:

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

       AddHandler Control.Paint, AddressOf DinPaintMetode

    End Sub

     

    Private Sub DinPaintMetode(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)

       ' Ect.

    End Sub

  16. Her ville jeg nok anbefalt å legge fra deg Excel og heller benytte et RDBMS (Access, mySQL), men da datamengden ikke er så forskrekkelig uoverkommerlig, er det muligens ikke enda utenfor Excels arbeidsområde.

     

    I alle tilfeller kan du oppnå dette ved å bruke funksjonene innunder Lookup & Reference (Oppslagsfunksjoner), eksempelvis VLOOKUP (SLÅ.OPP):

    =VLOOKUP(A2;Sheet1!$A$2:$B$4;2)

    Dette legges i "Navn"-kolonnen i Ark2 hvor A-kolonnen er "Number"-kolonnen. Merk at Sheet1 (Ark1) MÅ ha "Numbers" i kolonne A og "Navn" i kolonne B (dvs. at "Numbers" kommer før "Navn", ikke motsatt). I tillegg må Ark1 være sortert etter kolonne A.

  17. Du kan nok tilnærme deg VB-programmer rent syntaksmessig, men jeg tviler på noen har tatt seg det bryet å utvikle et fullendt automatisk oversettelsesprogram (foruten fra VB6 til .NET) som tar seg av alle programmeringsmønstre, bibliotekskall og andre uforutsette omstendigheter. Du må med andre ord kunne programmere i VB for å bruke et slikt program.

     

    Eksempelvis måtte jeg gjøre følgende endringer når jeg benyttet denne netttjenesten for å konvertere fra C++ til VB.NET og endelig VB6:

    #include <cstdlib>
    #include <iostream>
    #include <math.h>
    using namespace std;
    
    const float Pi = 3.1415926535897932384626433832795;
    
    /* converts degree to radian */
    float toRadian(float degree)
    {
    return degree * (Pi / 180);	  
    }
    
    int main(int argc, char *argv[])
    {
    printf("sin(30) = %f\n", sin(toRadian(30)));
    
    system("PAUSE");
    return EXIT_SUCCESS;
    }

    Dette ble oversatt til følgende VB-NET-program:

    'Translation of code submitted from xx.xxx.x.xxx

    'Converted from C++ by xlat on 2008Sep28.1236

    'C++ parser version:2006Jan.A0

     

    Imports System

     

    Public Class Globals

       Public Shared Pi As float = 3.1415926535897932384626433832795

       Public Shared Function toRadian(degree As float) As float

           Return degree * Pi / 180

       End Function

       Public Shared Function Main(argv() As string) As Integer

           Console.Write("sin(30) = {0}\n",sin(toRadian(30)))

           system("PAUSE")

           Return EXIT_SUCCESS

       End Function

    End Class

    Dette lar seg imidlertid ikke kompileres. Til det må man modifisere koden kraftig:

    Option Explicit ' Påkrever variabeldeklarering

     

    'Imports System ' Navneområder eksisterer ikke i VB6/VBA

     

    'Public Class Globals ' Man må lage egne filer for klasser, og i dette tilfellet må koden legges

                         ' i en modul. Fjern evt. former om de kommer opp i standardprosjektet.

                         

    ' Man bruker Const fremfor variabler - i tillegg kan man ikke sette

    ' variabler samtidig som man deklarerer dem.

    Const Pi As Double = 3.14159265358979

       

    ' Datatypen er Single, ikke float. Videre må parametre settes som ByVal (kontra ByRef (default) - dvs.

    ' som referansetyper/pointers) dersom C-funksjonen ikke bruker OUT. Endelig er Shared-nøkkelordet

    ' meningsløst i en VB6-modul.

    Public Function toRadian(ByVal degree As Single) As Single

       ' Return-ekvivalenten er å sette en intern variabel med samme navn

       ' som funksjonen og hoppe ut av kjøringen med Exit-operasjonen

       toRadian = degree * Pi / 180

       Exit Function ' Nokså unødvendig her dog

    End Function

     

    ' Main er en tom prosedyre. For å avlese args må man bruke Command()

    Public Sub Main()

       ' Da VB6 (og VBA forørig) ikke kan kompilere til konsollapplikasjoner, må man implementere

       ' dette manuelt ved å bruke API-funksjoner/eksterne biblioteker samt endre på enkelte

       ' attributter i selve EXE-filen (fremgangsmåten/verktøyet kan graves frem med Google).

       

       ' Her har jeg valgt å bruke VBCorLib (velg Project - References og avmerker

       ' VB.EXT: VBCorLib 2.3 eller last det ned og bla deg frem til DLL-filen i overnevnte dialogboks)

       Console.WriteValue "sin(30) = {0}{1}", Sin(toRadian(30)), vbCrLf ' Man bruker ikke paranteser

       ' rundt prosedyrekall. I tillegg kan man ikke escape (/n) karakterer. Dette må legges ved

       ' manuelt (her: vbCrLf)

       

       ' Man kan også skrive en ny linje således:

       'Console.WriteLine "Ny linje"

       

       ' System ("PAUSE")

       Console.WriteValue "Press any key to continue."

       Console.Read

       

       ' Unødvendig da vi har med en prosedyre å gjøre

       'Return 0 'EXIT_SUCCESS

    End Sub

    'End Class

    Til sist står vi igjen med følgende VB6-program. Hva dette eksempelet angår ville det nok vært lettere å ha oversatt programmet direkte:

    Option Explicit

     

    Const Pi As Double = 3.14159265358979

       

    Public Function toRadian(ByVal degree As Single) As Single

       toRadian = degree * Pi / 180

    End Function

     

    Public Sub Main()

       Console.WriteValue "sin(30) = {0}{1}", Sin(toRadian(30)), vbCrLf

       Console.WriteValue "Press any key to continue."

       Console.Read

    End Sub

  18. Man kan, om man kun ønsker en måte å skjule informasjonen og ikke har noe særlig behov for kryptografisk beskyttelse, benytte en simpel Xor-kryptering. Det, i likhet med rot13, er svært enkelt å forstå og lar seg dekrypteres ved å kjøre algoritmen to ganger (rot13(rot13("hallo")) er derfor "hallo"):

    Public Function EncryptXor(ByVal Text As String, ByVal Key As String) As String

     

      With System.Text.Encoding.Unicode

     

          ' Konverterer strenger til byte-arrays

          Dim aData() As Byte = .GetBytes(Text)

          Dim aKey() As Byte = .GetBytes(Key)

     

          ' Utfører selve krypteringen

          EncryptXor(aData, aKey)

          Return .GetString(aData)

     

      End With

     

    End Function

     

    Public Sub EncryptXor(ByVal inputBuffer() As Byte, ByVal Key() As Byte)

     

      ' Xor virker på to binærstrenger (a og b) av samme lengde og returnerer en streng

      ' der en bit er èn dersom de to tilsvarende bittene i a og b er ulike (om ikke, 0).

     

      ' Eksempel:

      '   65 ("a" eller 0100.0001) Xor 109 ("d" eller 0110.1101) = 44 ("," eller 0010.1100)

      '   44 (",")                 Xor 109 ("d")                 = 65 ("a")

      For i = 0 To inputBuffer.Length - 1

          inputBuffer(i) = inputBuffer(i) Xor Key(i Mod Key.Length) ' Mod = rest etter divisjon t/n

      Next

     

    End Sub

    Ønsker du en smule mer sikrer/praktisk løsning, bør du ta en titt på System.Security.Cryptography-navneområdet.

×
×
  • Opprett ny...