ActiveX programmering och properties
Förord
Hej igen, den uppmärksamme läsare finner att rubriken ”Vad är ActiveX-komponenter” även återfinns i den första delen av kursen. Varför är den här igen då? Jo, när artikeln lades upp så fick jag genom chatten på Pellesoft indikationer på att något saknades i min första artikel. Något som jag hade tänkt ta upp men bestämde mig för att spara tills nu, nämligen vem man kodar för när man skriver sin komponent. När man utvecklar en komponent så är det inte för slutanvändaren (kunden, personen som utnyttjar ditt program) utan för dig själv som utvecklare eller någon annan som utvecklare. Detta är en mycket viktig sak att tänka på när man skriver sina komponenter, framför allt när man namnger de egenskaper och metoder komponenten skall ha. Ingen vill ha en komponent där man delar ut egenskapen ”Efternamn” om komponenten inte är designad just för att hantera efternamn, så tänk på detta. Jag vill också passa på att nämna att flera av de principer jag tar upp i denna och min förra artikel också gäller programmering av DLL´r så om du är ovan / nybörjare så är dessa artiklar rekommenderad läsning.
Nåja, vad skall vi sysselsätta de små grå med idag då?
Jag tänkte att vi skall börja med gå igenom innehållet i den här kursen. Till att börja med så vill jag säga att tempot kommer att öka, jag har inte ork att detaljförklara allt utan måste ta upp ett ämne visa hur det går till förklara vad det används till och sedan hoppa på nästa ämne. Det bör inte vara några problem de flesta då man som programmerare vill tänka själv och inte låta andra tänka för en. Propertybags är en grej som jag kommer att ta upp som kan vara lite diffus och svår att greppa, jag kommer även och tala om allmän VB-programmering, tangentbordsgenvägar och felsökning. De sista områdena är till för att hjälpa er som programmerare och visa er ett sätt att arbeta effektivare i VB.
Min första OCX, a step further than last time!
Först tänkte jag visa vad en propertybag är och vad den används till. Öppna projektgruppen från den förra artikeln och kommenterar ut kodraden under Form_Load() på formuläret. Öppna sedan formuläret och markera kontrollen. Därefter skriver du abc i AllowedCharacters-propertien, detta ska i en normala fall resultera i att kontrollen bara tar emot tangenterna a, b, och c (testkör nu så fortsätter jag att prata). Det blev inte så bra eller hur? Detta beror på att kontrollen saknar någon möjlighet att behålla sina inställningar (properties) och det är där propertybagen kommer in i bilden. Den är som lite resväska där lägga sina inställningar så att kontrollen kommer ihåg dessa.Men hur gör man då? Jo till att börja med så går vi igenom vilka händelser och metoder som omger en kontrolls egenskaper. Den första vi skall ta upp är en händelse som heter InitProperties:
Den händelsen sker när en ny instans av ett objekt skapas (till exempel när du lägger ut en kontroll på ett formulär eller när du startar ett program). Här är det stället man lägger in de defaultvärden man vill att sina egenskaper skall ha. Koden för denna händelse ser i mitt exempel ut så här:
'Initialisera egenskaperna för MinTextKontroll
Private Sub UserControl_InitProperties()
sAllowedCharacters = "abcdefghijklmnopqrstuvwxyzåäö"
End Sub
Detta resulterar att kontrollen kommer att tillåta inmatningar av tecknena A-Ö som default när du har lagt ut den på ditt formulär. Nästa grej vi skall ta upp är en metod som heter PropertyChanged. Det är en metod som tar emot ett strängargument och strängen är namnet på egenskapen som har ett förändrat värde. Den metoden är viktig på grund av två saker, dels så berättar den designmiljön vilken egenskap som har fått ett nytt värde (så att du kan se det när du tittar på din kontrolls egenskaper) och dels så triggar den igång nästa händelse som heter WriteProperties. PropertyChanged anropar man i den rutinen där man sätter värdet på en egenskap (normalt sett Property Let), så koden för våran kontroll skulle bli följande:
' Hit kommer vi när vi LÄMNAR information om vilka giltiga tecken vi skall ha i kontrollen
Public Property Let AllowedCharacters(vValue As Variant)
If IsNumeric(vValue) Then
Select Case vValue
Case AllowOnlyAlpha
sAllowedCharacters = "abcdefghijklmnopqrstuvwxyzåäö"
Case AllowOnlyNumerical
sAllowedCharacters = "0123456789"
End Select
Else
sAllowedCharacters = vValue
' Berätta för användargränsnittet att AllowedCharacters har fått ett nytt värde samt se till att WriteProperties utförs
Call UserControl.PropertyChanged("AllowedCharacters")
' Raden ovan kan också skrivas så här:
' PropertyChanged "AllowedCharacters"
End If
End Property
Okej, nu ska vi ta upp händelsen WriteProperties, när den sker så är det en notifikation till ditt objekt om att nu har det hänt något som vi måste spara undan för att använda vid ett senare tillfälle. När WriteProperties händer så skickas en PropertyBag med, denna är objektets egna egenskapsbehållare och återspeglar de egenskaper som objektet har. Det är också i den man skall lagra förändringarna. Lite kod som jag förklarar nedan:
' Nu vill kontrollen spara sin inställningar
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
' Spara inställningen
Call PropBag.WriteProperty("AllowedCharacters", sAllowedCharacters, "abcdefghijklmnopqrstuvwxyzåäö")
End Sub
WriteProperty är en metod hos propertybagen som tar emot tre argument, första argumentet är namnet på egenskapen vi skall spara undan, det andra argumentet är värdet vi skall spara och det tredje argumentet är det defaultvärde som egenskapen skall ha. Anledningen till att man skickar med defaultvärden är att hanteringen av objekten faktiskt blir snabbare i utvecklingsmiljön och filstorleken på formulären kontrollen ligger i blir mindre så ta det till en vana att skicka in defaultvärden till propertybagen.
Den sista händelsen vi ska gå in på är ReadProperties som händer när kontrollen har sparade egenskaper som skall användas. Det är till exempel här det är tänkt att man skall hamna när du följer exemplet jag började det här stycket med. I den här händelsen skall man alltid felhantera allting därför att om någon editerar inställningarna på fil-nivå så kan allting gå käpprätt åt h-vete och det är inte så bra. Koden vi skall använda ser ut så här:
' Här läser vi redan sparade egenskaper
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
' Om något går fel så skall vi bara ignorera felet och gå vidare
On Error Resume Next
' Läs in de sparade värdena för egenskapen AllowedCharacters
sAllowedCharacters = PropBag.ReadProperty("AllowedCharacters", "abcdefghijklmnopqrstuvwxyzåäö")
End Sub
ReadProperty är en metod som tar emot två argument, det första är en sträng som beskriver vilken egenskap vi vill läsa ut värdet från, det andra är precis som i WriteProperty ett defaultvärde för egenskapen. ReadProperty returnerar även ett värde, det värde som är sparat under egenskapen vi valde att läsa från.
Nu kan du testa att återupprepa det som vi gjorde i början av artikeln. Det fungerade, eller hur? Det här var en ganska mastig del att skriva så här långt så jag tänkte spara databindningarna till nästa kapitel.
VB i allmänhet
Vad jag tänkte ta upp här är de tekniker jag och många med mig använder oss av för att felsöka och navigera oss i våran kod. Först vill jag visa en liten lathund av kortkommandon som kan vara bekväma att känna till. Några av dessa kommandon är faktiskt väldigt okända även bland proffsen så passa på och lär er. Om ni tycker att min förklaring är otydlig så pröva er fram, det finns inget bättre sätt än att pröva saker.Knappar | Exempel nr. | Funktion |
---|---|---|
<SHIFT> + <F2> | 1 | Hoppar till definitionen av det objekt du står på. |
<CTRL> + <SHIFT> + <F2> | 2 | Backa tillbaka markören till dit du kom från (upp till fem steg tror jag fungerar). |
<CTRL> + <SPACE> | 3 | Öppna en lista till halvifyllt kommando. |
<F2> | 4 | Öppna objectbrowsern |
<CTRL> + F | - | Sök |
<CTRL> + H | - | Ersätt |
<F3> | - | Sök nästa |
<F9> | 5 | Sätt en breakpoint. |
<CTRL> + <F8> | - | Kör fram till markören (i debug läge). |
<SHIFT> + <F8> | - | Kör en sub men gå inte in i den (i debug läge). |
<SHIFT> + <F9> | - | I debug läge, titta på en variabel vad den har värde. |
<CTRL> + <L> | - | I debug läge, öppna callstacken (se var du kommer ifrån). |
- 1. Gå in i MinTextKontroll och ställ markören på sAllowedCharacters i UserControl_ReadProperties, tryck på <SHIFT><F2> och se var du hamnar.
- 2. Klicka sedan in dig någon annanstans i formuläret och tryck på <CTRL><SHIFT><F2> så kommer du tillbaka till där du var, upprepa en gång till så har du backat ytterligare ett steg.
- 3. Skriv ”sAllow” någonstans i koden och tryck <CTRL><SPACE>.
- 4. Tryck på F2 och lek lite med objectbrowsern som är till för att se vilka egenskaper objekt har och vilka konstanter som som finns till ett objekt. Den är mycket bra att känna till hur den fungerar.
- 5. Sätter en breakpoint som gör att programmet stannar och du kan titta på värden.
Debugga sitt program
Gör så här:Leta rätt på raden Private Sub txt_KeyPress(KeyAscii As Integer) och sätt en breakpoint där. Kör igång ditt program och skriv något i din kontroll.
Programmet stannar vid breakpointen eller hur? Nu kan du testa massor av saker till exempel tryck på CTRL+L för att se hur anropen har skett, gå ner i immediate-fönstret och skriva följande för att se vad som händer:
sAllowedCharacters="EFG" + ENTER
Det här med debugging är ett stort område och en konst att utöva på ett bra sätt. Det är dessvärre också ytterst svårt att skriva om men jag ville få igång era hjärnor lite så jag tog i alla fall upp ämnet. Enda sättet att bli duktig är att göra fel och när du har gjort fel så leta rätt på felet själv, då lär man sig mest.
VB-programmering i allmänhet.
När man skriver ett program är det mycket viktigt att vara tydlig i koden och gärna konsekvent. Jag använder mig till exempel av prefix på alla variabelnamn för att beskriva vad variabeln innehåller. Nu har jag gjort det lite enklare för mig genom att bara använda en bokstav till skillnad från de flesta andra som använder Ungersk Notation (UN) som det heter. Samma sak gäller när man namnger sina variabler; sNamn är kanske inte riktigt lika tydligt som sForNamn eller enligt UN strForNamn. Tänk på att det viktiga inte är vad ni skriver i eran kod utan hur ni skriver det.
Ett lite rörigare kapitel är slut.
Den här delen kanske inte blev lika bra som den första men om den föll er i smaken så kommer snart nästa artikel. Då skall vi börja på ett nytt projekt och det skall bli en DLL. För de som undrar, jag har inga planer just nu på att ta upp mer avancerade koncept i ActiveX-programmering i de första kapitlena, jag vill att de som läser mina kurser skall få lära sig grunderna innan någon rör ihop det för dom. Däremot så får ni skicka imail med frågor som rör svårare grejor så skall jag besvara dom när jag hinner. Önskemål angående innehåll i framtida delar av min artikelserie är också sådant som tacksamt tas emot via imail eller email.Så här på slutet vill också tacka min korrekturläserska Anna-Karin Söderberg (aka Cougarina) för utan hennes hjälp skulle delar av min grammatik vara utom all hjälp.
Fil att tanka
Fil: ActiveX_Del2.zip
Avslutningsvis
För att jag skall veta om kursen är bra eller om den måste skrivas om så rösta gärna här uppe till höger. Skicka gärna ett iMail om du vill kommentera något som är felaktigt eller du tycker borde förtydligas./Pontus Wång
0 Kommentarer