Softassa, jossa on kontrolleja ohjaustaulukossa, ei varmaan kannata käyttää Select Case tai If selvittämään mitä kunkin kontrollin kohdalla pitäisi tehdä ? Puhumattakaan jos kaikille samassa CAI:ssa oleville kontrolleille pitäisi tehdä täsmälleen sama koodi, hirveää toistoa, eikö ? Mitä tehdä ?
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) lblButton(Index).BorderStyle = 0 End Sub Private Sub frame_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) lblButton(Index).BorderStyle = 0 End Sub Private Sub lblButton_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) lblButton(Index).BorderStyle = 1 End Sub
Ylläoleva koodi toimii lblButton(0) kohdalla, mutta ei seuraavien kohdalla, siis ensiksi mainittu käyttäytyy kuin kuuluu mutta muut ei. Lisäksi lblButton(1) pitää BorderStyle:n samana vaikka mitä tekisi. Mitä kannattaisi tehdä ?
Kannattaa pitää päällä VB:n kanssa Option Explicit... Index-muuttujalla on oikea arvo vain tuolla lblButton_MouseMove-aliohjelmassa, frame_MouseMove-aliohjelmassa sen arvo on aina 0. Tuollaisessa systeemissä kannattaisi käyttää ylimääräistä muuttujaa jossa pidät muistissa viimeisintä indeksiä.
' Jossain tämä: Public Viimeisin As Integer Private Sub frame_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) lblButton(Viimeisin).BorderStyle = 0 End Sub Private Sub lblButton_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) lblButton(Index).BorderStyle = 1 Viimeisin = Index End Sub
Siitä on kauan kun VB:n päälle viimeksi mulkaisin, saatan olla väärässäkin.
Pitää myös huomata, että myös lblButton_MouseMovessa pitää tehdä viimeisimmälle nollaus, mikäli Viimeisin ei ole sama kuin Index.
Private Sub lblButton_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) If (Index <> Viimeisin) Or (lblButton(Index).BorderStyle = 0) Then lblButton(Viimeisin).BorderStyle = 0 lblButton(Index).BorderStyle = 1 Viimeisin = Index End If End Sub
Eli nyt jos indeksi on eri tai jos BorderStyle ei ole tämänhetkisellä päällä, niin sitten nollataan edellinen kytketään päälle nykyinen.
Sqwiikin ja Merrin koodit toimivat kun käyttää molempia :)
Ihmettelen vain, miten alussa BorderStyle:n vaihto voi yleensäkään toimia frame_- ja Form_MouseMovessa kun se kerran on nolla ?
Kun sinulla ei ole Option Explicit käytössä, niin Index-muuttuja luodaan automaattisesti ja sen arvo on nolla, koska sitä ei muuallakaan ole asetettu. Tällöin framen ja Formin MouseMovet pelittävät aina vain nollaindeksille.
Nyt on Option Explicit käytössä. Miten koodi pitäisi muuttua nyt ?
(Mod. huom: turhien viestien lähettäminen ei auta asiaa.)
Ei se koodi mitenkään siitä muutu, mutta kääntäjä antaa virheilmoituksen, jos yrität käyttää muuttujaa jota ei ole määritelty (kuten tuo index tuossa alkuerpäisessä frame_MouseMove:ssasi). Eli et turhaan ihmettele miksi saat johonkin arvon 0 kun kehitysympäristö kertoo sinulle suoraan että "hei, et oo määritellyt tällaista muuttujaa, mitä oikein luulet tekeväsi?"
Varsinaiset muutoksethan jos tuossa kerrottiinkin, tuo Option Explicit oli lähinnä kommentti tuohon ihmettelyysi 20.10. 19:17
Ja se Option Explicit kannattaa tosiaan aina olla käytössä. Itse asiassa idioottimaista Microsoftilta, että se on oletuksena pois päältä. (muistaakseni)
Eli Optionsiin vaan Editor välilehdelle ruksi siihen kohtaan "Require Variable Declaration" niin se läpsii aina uusiin tiedostoihin automaagisesti sen Option Explicit:n alkuun.
Option Explicit ei vaikuta siihen, miten tuo toiminto pitää toteuttaa, vaan vain siihen, että määrittelemättömän muuttujan käyttö aiheuttaa virheen. Kokeilepa sen kanssa esimerkiksi alkuperäistä koodiasi, niin huomaat, miksei se toiminut. Syy on tuo, jonka Merri juuri selitti.
Grez kirjoitti:
Itse asiassa idioottimaista Microsoftilta, että se on oletuksena pois päältä.
Käsittääkseni VB.Net on kuitenkin tehnyt parannuksen.
Vain sillä, että kaikki käytettävät muuttujat täytyy määrittää — käytännössä siis Dim jokaista muuttujaa kohden. Muuta muutosta ei tapahdu. Jos muuttujaa ei ole määritetty, niin ilman Option Explicitiä se luodaan lennosta Variant-tyyppisenä; Option Explicitin kanssa tulee virhe. Yleensä on järkevä määrittää sopivin mahdollinen muuttujatyyppi: jos teet merkkijonoa, määritä merkkijonoksi, jos käsittelet valuuttoja, käytä Currencyä, jos vaan tarvitsee laskea isoja lukuja tai tarvitse desimaaleja, eikä tietyn tason pyöristäminen haittaa, käytä Doublea ja niin edelleen. Yksi huomattava muuttujien määrittämisen hyöty on se, että se paljastaa monta helposti huomaamattomaksi jäävää bugia, kuten kirjoitusvirheen tai muuttujan käyttämisen sellaisessa paikassa, jossa sitä ei ole.
Sitten yksi asia, jota et varmaan vieläkään ole täysin tajunnut, jolla ei ole mitään tekemistä Option Explicitin kanssa:
' Form1.frm Option Explicit ' Tämä muuttuja on käytettävissä kaikkialla Form1:ssä, mutta ei ole käytettävissä sen ulkopuolella. Dim YksityinenMuuttuja As String ' Sama kuin edellinen, mutta selvemmin tarkoitusperän esille tuoden (suosittelen tätä tapaa, parantaa koodin luettavuutta). Private YksityinenMuuttuja2 As String ' Tämä muuttuja on käytettävissä myös Form1:n ulkopuolella, kutsuminen onnistuu muodossa Form1.JulkinenMuuttuja Public JulkinenMuuttuja As String ' Tämä Index on käytettävissä vain Command1_Click:ssä! Se on tarjottu parametrinä proseduuriin, joten muualla siitä ei ole tietoa. Private Sub Command1_Click(Index As Integer) ' Ongelma: meillä on jo YksityinenMuuttuja Form1:ssä! Miten käy? Dim YksityinenMuuttuja As String ' Vastaus: tämä on eri YksityinenMuuttuja, joka on paikallinen vain Command1_Click:lle. Muutokset siinä eivät tallennu muualle tai seuraavaan kutsuun. End Sub Private Sub Command2_Click() ' Proseduuriin määritetty static-muuttuja muistaa arvonsa kutsusta toiseen. Paikallinen vain Command2_Click:lle. Static PysyväMuuttuja As String PysyväMuuttuja = PysyväMuuttuja & "." MsgBox PysyväMuuttuja End Sub
' Module1.bas Option Explicit ' Mitä mitä mitä? Tämä muuttuja onkin julkinen? Kyllä vain, tätä muuttujaa voi käyttää missä tahansa päin projektia. ' Paikallisemmat muuttujat kuitenkin ovat tärkeämpiä. Tähän muuttujaan voi kuitenkin viitata suoraan myös käyttäen Module1.JulkinenMuuttuja Dim JulkinenMuuttuja As String ' Kuten äskeinen Dim, mutta selvemmin ymmärrettävissä. Public JulkinenMuuttuja2 As String ' Tämä muuttuja onkin sitten paikallinen, eli käytettävissä vain Module1:ssä. Private YksityinenMuuttuja As String
Tämä toivottavasti selventää tilannetta.
Merri on mukavan pitkäpinnainen kun jaksaa selventää pilkun viilaamista tälläiselle aloittelijantapaiselle :)
[Oma edit]
Miten tässä tredissä sovellettua koodia voi soveltaa myös samassa softassa, jossa on tarkoitus saada klikattaessa kyseisen klikatun painikkeen tekstin menemään ISOILLE kirjaimille ? Kun on klikattu ja teksti muuttunut isoksi, pitäisi erikseen formille tehty erillinen Frame liusua esiin, paljastaen klikatun painikkeen alivalinnat.
Aihe on jo aika vanha, joten et voi enää vastata siihen.