Hei!
Mites VB 2008:ssa asetetaan nappulalle (Button) Default- ja Cancel-ominaisuudet? Eli Default Button on esimerkiksi "Laske" jonkin tekstiruudun vieressä; tällöin enterin painallus tekstiruudussa olisi sama kuin Laske-napin klikkaus.
VB6:ssahan tämä tehtiin vain asettamalla ominaisuusikkunassa CommandButtonin Default-ominaisuus arvoon True (jolloin kaikkien muiden CommandButtonien Default-ominaisuus muuttui automaattisesti arvoon False).
MS Visual Studio 2008 Documentation kertoo Button-luokalla olevan ominaisuus IsDefault: "Gets or sets a value indicating whether the button control is the default button." Eli kyseessä kai on hakemani ominaisuus. Nyt tulee tyhmä kysymys. Koska kyseinen ominaisuus on Protected, niin miten ihmeessä sen saa asetettua?!? Lomakkeen koodista se ei onnistu koska se katselee Button-objektia "ulkopuolelta". Tässä yritys:
Public Class frmTestiLomake Private Sub frmTestiLomake_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load btnKerro.isdefault() = True ' aiheuttaa tietysti virheen End Sub Private Sub btnKerro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnKerro.Click lblTulos.Text = Val(txtSyöttöLuku.Text) * 2 End Sub End Class
Entä miten Cancel-button tehdään? (Itse tehdyssä dialogi-ikkunassa on usein kätevä laittaa Sulje-napille Cancel-ominaisuus, jolloin Esc-napin painaminen missä tahansa tilanteessa sulkee ikkunan.)
Ps. Hieman nimeämiskäytännöistä VB .Netissä: Ohjausobjekteille kannattanee edelleen käyttää etuliitteitä "txt", "btn", "lbl" jne., mutta entä lomakkeille?
Moikka vesimies!
olettaisin, että DefaultButton-ominaisuus voidaan asetella lennossa tyyliin...
Imports Microsoft.VisualBasic Imports System.Windows.Forms Public Class frmTestiLomake: Inherits Form Protected WithEvents MyDefaultButton As New Button Private Sub frmTestiLomake_Shown(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Shown Me.CancelButton = Me.btnPeruuta MyDefaultButton = Me.btnKerro MyDefaultButton.Focus 'Ja voilà nyt kun painat Enter'iä niin... End Sub Private Sub btnKerro_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnKerro.Click Me.CancelButton.PerformClick End Sub Private Sub btnPeruuta_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPeruuta.Click MsgBox("Enkä kerro...") MyDefaultButton.Focus End Sub End Class
Kiitos vastauksesta, Nea!
Cancel Button toimii täysin. :) Default Button sen sijaan ei... :( MyDefaultButtonin tekeminen ei muuta sitä asiaa, että oletusnappi saa fokuksen vain ikkunaa avattaessa. Eli kun fokus on tekstiruudussa, niin enterin painaminen ei vaikuta mitään.
Okei, nyt kai olisi pari tapaa hoitaa homma:
- Tehdään jokaiselle tarvittavalle kontrollille näppäinpainalluksen tapahtumankäsittely, ja tutkitaan painettiinko enteriä, ja jos niin klikataan oletusnappia koodista (voiko olla kömpelömpää, tätä en kyllä tee)
- Tehdään lomakkeelle samanlainen näppäinpainalluksen tapahtumankäsittely, ja lisäksi kerrotaan lomakkeelle että se nappaa kaikki näppäimet ennen tekstiruutua:
Me.KeyPreview = True ' tai ominaisuusikkunassa
Hetkonen tätähän pitää testata, miten tekstiruutu silloin käyttäytyy...
Nyt en kyllä saa millään selville miten se enter tunnistetaan. Näin olen yrittänyt:
Private Sub frmTestiLomake_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles Me.KeyPress ' Miksei tämä vertailu onnistu: If e.KeyChar = System.Windows.Forms.Keys.Enter Then btnKerro.PerformClick() Else ' ei tarvi tehdä mitään, merkki menee teksikenttään ' (jos fokus on siellä) End If ' Error: Operator '=' is not defined for types 'Char' and 'System.Windows.Forms.Keys'. ' No mikä tyyppi se sitten on? End Sub
Aika monimutkainen viritys, vaikka sen varmaan saakin toimimaan. Siihen verrattuna että asettaisi vain Default Buttonin. Mikähän nyt olisi paras tapa? Tokihan ohjelman saa toimimaan ilmankin tätä ominaisuutta mutta kyllä se lisää käyttömukavuutta todella paljon.
Muutenkin on näin aluksi VB6:n jälkeen sellainen olo kuin olisi ennen ajellut ladalla ja nyt löytää itsensä avaruusraketin ohjaamosta... Tietää että tämä on paljon tehokkaampi mutta ei osaa käyttää sen vertaa että pääsisi edes hieman rämistelemään eteenpäin. Mutta jospa se tästä.
OT: Mikä idea muuten on tuossa "Inherits Form"-kohdassa? Kokeilin ottaa sen pois, ja toimi ihan samalla lailla. Tiedän siis suunnilleen mitä perintä on, mutten ymmärrä miksi sitä tässä tarvii käyttää.
No nyt sain sen toimimaan:
Public Class frmTestiLomake ' Muistipaikka sille oliko painettu näppäin enter vai jokin muu: Private oliEnter As Boolean Private Sub frmTestiLomake_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.KeyPreview = True ' varmistetaan että lomake ottaa näppäinpainallukset Me.CancelButton = Me.btnSulje End Sub ' Kun näppäintä painetaan, niin katsotaan mikä nappi se oli: Private Sub frmTestiLomake_KeyDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyEventArgs) _ Handles Me.KeyDown oliEnter = (e.KeyCode = Keys.Enter) ' no niin se on sitten muistissa End Sub ' Tämä tapahtuma tulee KeyDownin jälkeen: Private Sub frmTestiLomake_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles Me.KeyPress If oliEnter Then btnKerro.PerformClick() End Sub ' Sitten varsinaiset nappulatapahtumat: Private Sub btnKerro_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnKerro.Click lblTulos.Text = (Val(txtSyöttöLuku.Text) * 10).ToString End Sub Private Sub btnPeruuta_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSulje.Click Me.Close() End Sub End Class
Edelleen otetaan vastaan helpompi tapa tehdä tämä.
Heippa taas vesimies!
Ideana tuossa "Inherits Form"-kohdassa oli sellainen, että säätelin hieman SharpDevelop'n templaatteja ja editori pukkaa sen oletuksena suoraan formille uuden projektin avaamisen yhteydessä, enkä huomannut sitä erikseen poistaa...
..ja sitten takaisin TekstiBoxi-ongelmaan, eli siis...
'... Sub TextBox1_KeyDown(sender As Object, _ e As KeyEventArgs) Handles TextBox1.KeyDown TsekaaTila(sender, e) End Sub Public Sub TsekkaaTila(ByVal ctl As TextBox, ByVal args As KeyEventArgs) If Not ctl.Multiline And _ args.KeyCode = Keys.Enter Then MyDefaultButton.PerformClick End If End Sub
Multiline oli hyvä huomio. Ja tosiaan, KeyPress on tässä turha, jäljittelin vain liiaksi ohjeiden esimerkkiä (ks. ohjeista aihe Control.KeyPress Event). Nyt on tällainen toimiva versio:
Private Sub frmTestiLomake_KeyDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown Dim nappiin As Boolean = False Dim tekstiruutu As TextBox If e.KeyCode = Keys.Enter Then nappiin = True ' Katsotaan mikä on aktiivinen kontrolli, ' ja jos tekstiruutu niin ' tutkitaan Multiline: If Me.ActiveControl.GetType Is txtSyöttöLuku.GetType Then ' Miten tyyppi katsotaan tyylikkäämmin? tekstiruutu = Me.ActiveControl nappiin = Not tekstiruutu.Multiline End If End If If nappiin Then btnKerro.PerformClick() End Sub
Heippa taas vesimies!
vielä ehkä hitunen lisää dynaamisuuttaa...
Private Sub frmTestiLomake_KeyDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown If e.KeyCode = Keys.Enter Then If Me.ActiveControl.GetType.ToString _ = "System.Windows.Forms.TextBox" Then Dim ctl As TextBox = Me.ActiveControl If Not ctl.Multiline Then _ MyDefaultButton.PerformClick Else MyDefaultButton.PerformClick End If End If End Sub
Kiitos taas. Jotenkin tuntuu hassulta tehdä valintarakenne vertaamalla pitkää tyyppinimi-Stringiä, mutta kaipa siihen tottuu.
Hei mutta nytpä löysin sen ohjeista! Himputti! Turhaan väkersin! Nimittäin:
"On any Windows Form, you can designate a Button control to be the accept button, also known as the default button." ::)
Eli lomakkeen accept buttoniksi vaan se haluttu.
No tulipahan ihan hyviä ohjelmointiharjoituksia näppäinkäsittelyistä.
Heippa taas vesimies!
AcceptButton on näppärä paitsi...Jos haluaa rivinvaihdon toimivan Enter-näppäimellä fromin multiline-boxeissa niin MyDefaultButton toimii edelleen..."MultilineBoxin" yhteydessä voi asettaa ehdon vaikkapa Control-näppäimelle sallimaan MyDefaultButton_Click-tapahtuman painettaessa Enter-näppäintä...
Private Sub frmTestiLomake_KeyDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown If e.KeyCode = Keys.Enter Then If Me.ActiveControl.GetType. _ ToString.IndexOf("xtBo") > -1 Then Dim ctl As TextBox = Me.ActiveControl If Not ctl.Multiline MyDefaultButton.PerformClick ElseIf ctl.Multiline And e.Control Then ctl.Tag = ctl.Text MyDefaultButton.PerformClick ctl.Text = ctl.Tag ctl.SelectionStart = ctl.Text.Length ctl.SelectionLength = 0 End If Else MyDefaultButton.PerformClick End If End If End Sub
neau33 kirjoitti:
...GetType.ToString.IndexOf("xtBo") > -1 ...
:D Aika ovelaa!
Aihe on jo aika vanha, joten et voi enää vastata siihen.