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 ClassEntä 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 ClassKiitos 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 SubAika 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 ClassEdelleen 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 SubMultiline 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 SubHeippa 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 SubKiitos 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 Subneau33 kirjoitti:
...GetType.ToString.IndexOf("xtBo") > -1 ...
:D Aika ovelaa!
Aihe on jo aika vanha, joten et voi enää vastata siihen.