Visual basic 6 events - vb6

How can i restrict an event to occur? Suppose i don't want textbox change event to occur when i press backspace.

Setting KeyAscii=0 in the KeyPress event will cause the keypress to be ignored.
Private Sub myTextBox_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeyBack Then KeyAscii = 0
End Sub

Since the Change event doesn't pass you the code of the last key pressed, you'll have to store that in the KeyPress event, then you can immediately exit the Change event whenever the backspace key is pressed.
Private keyCode As Integer
Private Sub Text1_Change()
If (keyCode = vbKeyBack) Then
Exit Sub
Else
// do whatever it is you want to do in this event
// P.S.: I know this is the wrong comment syntax,
// but this code prettifier has a problem with
// VB6 comments
End If
End Sub
Private Sub Text1_KeyPress(KeyAscii As Integer)
keyCode = KeyAscii
End Sub

Related

KeyDown map to GUI form button downstate

Hi I would like to ask if it's possible to map the KeyDown for keyboards in Visual Basic 6 to turn the state of a graphical Command Button on the form to the "Down State" while keyboard key is pressed then back to raised when released? Thanks
I am aware of the problem here, because I did somewhat similar in the past and ended up by using an array of PictureBoxes instead of graphical CommandButtons.
Anyway, a simple workaround with CommandButtons is to keep the focus away by adding to the Form another control which can act as focus target. Remember: when a Form goes activated, it will place the focus to the first focusable control inside itself.
As You haven't specified in Your question what kind of keyboard state You need, below is a simple example with the a s d f keys. You will need less than 5 minutes to get it up and running.
Step 0:
Copy and paste following declarations to Your VB Form:
Option Explicit
Option Base 0
Const BM_SETSTATE = &HF3
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim Target(254) As Long
Step 1:
Add to Your Form an array of CommandButtons called, for instance, Button(0), Button(1), Button(2), Button(3) and so on.
Set the properties which You need (Picture, DownPicture, etc.) and set also:
TabStop: False
Double-click one of this CommandButtons. You can see, You have just one entry point for the whole array of Controls. Choose GotFocus from the event drop-down and put this piece of code:
Private Sub Button_GotFocus(Index As Integer)
PicFocus.SetFocus
End Sub
Step 2:
On Your VB Form, set this property:
KeyPreview: True
Double-click the Form, choose Load from the event drop-down and set Your desired mapping between a KeyCode and the corresponding CommandButton:
Private Sub Form_Load()
Target(65) = Button(0).hwnd ' 65: KeyCode for "a"
Target(83) = Button(1).hwnd ' 83: KeyCode for "s"
Target(68) = Button(2).hwnd ' 68: KeyCode for "d"
Target(70) = Button(3).hwnd ' 70: KeyCode for "f"
End Sub
Choose KeyDown and KeyUp from the event drop-down and put inside the two global keyboard event handlers this piece of code - respectively -1 for the down-state and 0 for the up-state:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
' Debug.Print KeyCode
Call PostMessage(Target(KeyCode), BM_SETSTATE, -1&, 0&)
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
Call PostMessage(Target(KeyCode), BM_SETSTATE, 0&, 0&)
End Sub
Step 3:
Lastly, add to the same VB Form the PictureBox mentioned above and set following properties:
Name: PicFocus
Appearance: 0-Flat
BorderStyle: 0-None
HasDC: False
TabIndex: 0
TabStop: False
Width: 255
Left: -1000
Press Ctrl+F5 and test if this is what You need.
The CommandButton control has mouse and keyboard down and up events:
Private Sub Command1_Click()
Debug.Print "click"
End Sub
Private Sub Command1_KeyDown(KeyCode As Integer, Shift As Integer)
Debug.Print "keydown"
End Sub
Private Sub Command1_KeyUp(KeyCode As Integer, Shift As Integer)
Debug.Print "keyup"
End Sub
Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print "mousedown"
End Sub
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print "mouseup"
End Sub

TextBox Value Disappears after closing and reopening form

I have two forms: Form 1 and Form 2.
Form 1 has two Buttons and Form 2 has one textbox.
On Button 1 Click event I am writing "My Text" in my Form 2 TextBox and on button 2 I am showing Form 2.
What is happening is when I close my Form 2 using close [X] button and reopen it value in my Form 2 Textbox Disappears.
Please Help how can I resolve this
Form 1 Code:
Private Sub Command1_Click()
Form2.Text1.Text = "Parth"
End Sub
Private Sub Command2_Click()
Form2.Show
End Sub
Form 2 Code:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Me.Hide
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
'Cancel=true
Cancel=UnloadMode<>vbFormCode
Me.Hide
End Sub
Form1:
Option Explicit
Private Sub Command1_Click()
Form2.Text1.Text = "Parth"
End Sub
Private Sub Command2_Click()
Form2.Show vbModal, Me 'Since we are the owner, Form2 unloads when we do.
End Sub
If Form1 was not made the owner you'd need to explicitly unload Form2 within Form1's Unload event handler to avoid hanging the program.
You need to be careful not to test for the wrong UnloadMode value.
Form2:
Option Explicit
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Then
Cancel = True
Hide
End If
End Sub

VB6 When closing the Parent form do unload queryunload or terminate events fire in Child Forms

I've asked this question before but I must not have been clear because the answer turned out not to be correct as far as I can tell .. so here goes again.
I have a VB6 application .. it has main menu that opens up Forms and dialogs (not MDI I don't think)
I want to save the position of any open forms or dialogs when the application closes so the next time I open the application the positions will be restored.
I hoped that when I close down the application that ANY of queryUnload, unload, terminate would fire in the 'child' windows or dialogs and I could save their position .. but nothing seems to fire.
I've put break points on all the above events, but when I close down the application nothing gets hit.
VB6 is not my usual gig .. so I'm probably thinking too much .net ..
Is there a way this can be done in VB6 ..
Edit: So it seems if I click the close cross in the top right corner I 'end' the application. Is there a way in VB6 to edit this behavior so I could instigate a graceful close down ?
All 3 events fire, but the Terminate event might not be fired when you expect it.
Create a test project consisting of 1 MDI form, 1 MDI child form, 1 normal form and add the following code:
MDI form:
'MDI form : name=MDIForm1
Option Explicit
Private Sub MDIForm_Click()
End
End Sub
Private Sub MDIForm_Load()
Form1.Show
Form2.Show vbModeless, Me
WindowState = vbMaximized
End Sub
Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer)
MsgBox "MDI form QueryUnload event"
End Sub
Private Sub MDIForm_Terminate()
MsgBox "MDI form Terminate event"
End Sub
Private Sub MDIForm_Unload(Cancel As Integer)
MsgBox "MDI form Unload event"
End Sub
MDI child:
'1 form: name=Form1 MDIChild=true
Option Explicit
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
MsgBox "MDI child QueryUnload event"
End Sub
Private Sub Form_Terminate()
MsgBox "MDI child Terminate event"
End Sub
Private Sub Form_Unload(Cancel As Integer)
MsgBox "MDI child Unload event"
End Sub
Normal form:
'1 form: name=Form2
Option Explicit
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
MsgBox "Form2 QueryUnload event"
End Sub
Private Sub Form_Terminate()
MsgBox "Form2 Terminate event"
End Sub
Private Sub Form_Unload(Cancel As Integer)
MsgBox "Form2 Unload event"
End Sub
You will see the QueryUnload and Unload events are fired (in this order), but the Terminate event is fired when you close down the MDI form.
When you click the background of the MDI form, then End will be called and no event will be fired
"Child" forms do get the usual events. Notice that on Form_QueryUnload the UnloadMode parameter is vbFormOwner.
"Child" forms are shown with explcit owner form like this:
'--- using global references
Form2.Show vbModal, Form1
Form3.Show , Form1 '--- Form3 is modeless
'--- using instances
With New Form2
.Show vbModal, oOwnerForm
End With
With New Form3
.Show , oOwnerForm
End With

Allow computer keypad form be controlled from keyboard

I have created a dialer in VB6 to dial a phone number. It has the following buttons: the digits 0-9, backspace, "Call", and "Disconnect". Now I want enter numbers in the form using the keypad part of the keyboard. In the text box, any key can be typed in using the keypad. But I only want the number pad to operate.
For that I checked ASCII values using the KeyPress event - seeing if the pressed key value lies in between 47 and 58. But along with the key values its ASCII values are also getting displayed in the text box.
One more thing - I have one MS Flex Grid on the form along with the dialer. So when the cursor is on the form, or if the mouse is clicked anywhere other than the text box, values don't display in the text box. So how do I always keep focus on the text box?
Dim val As Integer
Private Sub append(val As Integer)
Text1.Text = Text1.Text & val
End Sub
Private Sub Backspace_Click()
With Text1
'FOCUS TO THE TEXTBOX
.SetFocus
'PUT THE CURSOR AT THE END OF THE TEXT
.SelStart = Len(.Text)
'SEND THE KEY
SendKeys ("{BACKSPACE}")
'AND THATS IT :D
End With
End Sub
Private Sub key_0_Click()
val = 0
append val
End Sub
Private Sub key_1_Click()
val = 1
append val
End Sub
Private Sub key_2_Click()
val = 2
append val
End Sub
Private Sub key_3_Click()
val = 3
append val
End Sub
Private Sub key_4_Click()
val = 4
append val
End Sub
Private Sub key_5_Click()
val = 5
append val
End Sub
Private Sub key_6_Click()
val = 6
append val
End Sub
Private Sub key_7_Click()
val = 7
append val
End Sub
Private Sub key_8_Click()
val = 8
append val
End Sub
Private Sub key_9_Click()
val = 9
append val
End Sub
Private Sub Text1_KeyPress(KeyAscii As Integer)
If (KeyAscii > 47 And KeyAscii < 58) Then
val = KeyAscii
append val
Else
KeyAscii = 0
' Text1.Text = KeyAscii
End If
End Sub
'Private Sub Text1_LostFocus()
' Text1.SetFocus
'End Sub
You could set the KeyPreview property on the form to true.
When you have done that, put your code in the KeyPress of the form that was in the KeyPress of the Textbox, and set the text value of the textbox, or better still move the code into a function and set it from there, that way you won't need to duplicate your code if you need it in other places.
Have a look at this and see if it helps it is the KeyPreview from MSDN
Hi,
Sorry for the delay. To use the KeyPreview for the form give this a try:
Double click on the form in the project to open it
In the properties for the form find the KeyPreview Property and set it to true
Double click on the form to bring up the code window
Select the keypress event for the form, and add the following code, or something similar.
Private Sub Form_KeyPress(KeyAscii As Integer)
Text1.Text = Text1.Text & Chr$(NrOnly(KeyAscii))
End Sub
Use the function NrOnly that Hqrls has posted as that will allow only numbers which could help you with the validation. You won't need any code in the Text1_KeyPress, the form will now handle that for you.
Give it a try and let me know if you need any other information and I'll see what I can do.
[EDIT 29/05/2014]
Hi,
I've had a bit of a play around with the code and added some bits in which I think might help. Have a look at this and see if it make sense. If you copy it into your code then make sure you back up your original code just in case you need to get back to it.
This is the code if you keep your textbox
Option Explicit
Dim val As String
Dim m_blnTextHasFocus As Boolean 'Added this, so it knows wether the the textbox
'has the focus or not
'it is so the sendkeys doesn't get stuck in a
'loop with the key presses
Private Sub append(strIn As String)
'Changed the parameter from an int to a string, so we can use it in the key press events
Text1.Text = Text1.Text & strIn
End Sub
Private Sub Backspace_Click()
'Moved the code into it's own sub
DeleteAChar
End Sub
Private Sub Form_KeyPress(KeyAscii As Integer)
'Handle a key press if the textbox doesn't have the focus but ignore the keypress if it does
If Not m_blnTextHasFocus Then
If IsNumeric(Chr$(KeyAscii)) Then
append Chr$(KeyAscii)
ElseIf KeyAscii = vbKeyBack Then
DeleteAChar
End If
End If
End Sub
Private Sub key_0_Click()
val = "0"
append val
End Sub
Private Sub key_1_Click()
val = "1"
append val
End Sub
Private Sub key_2_Click()
val = "2"
append val
End Sub
Private Sub key_3_Click()
val = "3"
append val
End Sub
Private Sub key_4_Click()
val = "4"
append val
End Sub
Private Sub key_5_Click()
val = "5"
append val
End Sub
Private Sub key_6_Click()
val = "6"
append val
End Sub
Private Sub key_7_Click()
val = "7"
append val
End Sub
Private Sub key_8_Click()
val = "8"
append val
End Sub
Private Sub key_9_Click()
val = "9"
append val
End Sub
Private Sub Text1_GotFocus()
m_blnTextHasFocus = True
End Sub
Private Sub Text1_KeyPress(KeyAscii As Integer)
'Check the keyascii value and ignore it if it isn't numeric or backspace
If Not IsNumeric(Chr$(KeyAscii)) And KeyAscii <> vbKeyBack Then
KeyAscii = 0
End If
End Sub
Private Sub DeleteAChar()
With Text1
'FOCUS TO THE TEXTBOX
.SetFocus
'PUT THE CURSOR AT THE END OF THE TEXT
.SelStart = Len(.Text)
'SEND THE KEY
SendKeys ("{BACKSPACE}")
'AND THATS IT :D
End With
End Sub
Private Sub Text1_LostFocus()
m_blnTextHasFocus = False
End Sub
If you don't need to keep the textbox then you could replace it with a label and have a try with that. It would remove the need to keep track of if the textbox has got the focus or not. Have a go with this and see if it helps any. The only other thing is to make sure KeyPreview is turned on for the form or the keypress code will only work for the form if it has the focus.
Is the textbox the only control you want to have the focus ?
In that case you can use the following code:
Private Sub Text1_LostFocus()
Text1.SetFocus
End Sub
If there are any other controls you want to be able to have the focus as well, then you can use Text1.SetFocus in the _GotFocus() event of the controls which you do not want to have the focus
Another possible solution would be to use the _KeyPress() event of the other controls as well, and convert your current Text1_KeyPress() event to a general function which can be called by the _KeyPress() event of the other controls .. make sure though that you send the output of this general function to the correct textbox
If you post the relevant parts of your code we might be able to give a more specific answer
[EDIT]
for the answer to your original question, go with the answer of lardymonkey using keypreview on the form
an example function for allowed only numeric keys and the backspace:
Private Sub Text1_KeyPress(KeyAscii As Integer)
KeyAscii = NrOnly(KeyAscii)
End Sub
Private Function NrOnly(intAscii As Integer) As Integer
Dim intReturn As Integer
intReturn = intAscii
Select Case intAscii
Case vbKeyBack
Case vbKey0 To vbKey9
Case Else
intReturn = 0
End Select
NrOnly = intReturn
End Function

How to deal with enter to tab in vb6?

Public Function EnterToTab(KeyAscii As Integer)
If KeyAscii = vbKeyReturn Then
SendKeys "{tab}"
KeyAscii = 0
End If
End Function
Private Sub txtUserCode_KeyPress(KeyAscii As Integer)
Call EnterToTab(KeyAscii)
End Sub
This code belongs to log-in form.
The txtUserCode contains code of specific user stored in database.
While running this form, when I enter any number in txtUserCode and press enter it doesn't go to next text box, it's keyascii became 49 which is not equal to 13.
The same thing is happening by pressing tab.
What about switching to the next text field using the setFocus method instead of simulating a TAB?
Private Sub txtUserCode_KeyPress(KeyAscii As Integer)
If (KeyAscii = vbKeyReturn) Then
txtNextTextField.setFocus
End If
End Sub
You could also use a controls array (array of all text fields contained in your form) and increment the index. So you could use this code for all text fields of your form without having to write redundant code.
So if the user presses return in text field index 0, you set the focus to index+1 (=1). To create a controls array, copy your first text field and paste it to the form. VB6 will ask you whether you want to create a controls array. If you click "yes", it will do automatically. Then you can use the following code:
Private Sub txtField_KeyPress(Index As Integer, KeyAscii As Integer)
If (KeyAscii = vbKeyReturn) Then
If ((Index + 1) < txtField.Count) Then
txtField(Index+1).setFocus
Else
MsgBox "Reached end of form!"
End If
End If
End Sub
There is a KB142816 How To Make ENTER Key Move Focus Like TAB Key for VB Controls with a reference implementation similar to yours. But. It's most important part, IMO, is disclaimer:
You can cause the ENTER key to move the focus to the control with the
next higher TabIndex property value, as the TAB key does.
However, using the ENTER key to move the focus does not follow
recommended Microsoft Windows-based application design guidelines. The
ENTER key should be used to process the default command or to process
entered information, not to move the focus.
Anyway, the reason your code doesn't work is a mystery. As neither Tab nor Enter moves focus from txtUserCode field, my only guess is that txtUserCode is the only field with TabStop property set to True. I.e. there's simply no other control to move focus to.
The example MrSnurb gives is a good start, but it's has a lot of problems, for instance, a control could be disabled or not visible (setfocus will crash), the next control in your controlarray doesn't mean it's also the next control which would get focus when using tab (you can set the tabindex whatever you want).
I've conjured 2 'simple' routines (and an extra function) which you can use to go to next or previous controls on a form (haven't actually checked if it works with a control on a container (Frame or something)), so it might need extra checks for that..
'##############################################################################
'##
'## Function fnControlCanHaveFocus
'##
'##############################################################################
'A separate routine, because On Error goto doesn't work with this type of
'error in the IDE within a For Each loop,
'even if you have set 'Only break on unhandled' errors
Private Function fnControlCanHaveFocus(ByRef ctrl As Control) As Boolean
On Error GoTo ErrorHandling
'--------------------------------------------------------------
'Check for properties which lets a control get a focus
'For now also Check TabStop even though the control CAN have focus if this is off
fnControlCanHaveFocus = (ctrl.TabStop And _
ctrl.Enabled And _
ctrl.Visible)
Exit Function
ErrorHandling:
fnControlCanHaveFocus = False
End Function
'##############################################################################
'##
'## Sub pSetFocusToNextControl
'##
'##############################################################################
Private Sub pSetFocusToNextControl(ByRef frm As Form)
Dim ctrl As Control
Dim ctrlFirst As Control
Dim ctrlNext As Control
'--------------------------------------------------------------
'Is there even an active control?
If Not frm.ActiveControl Is Nothing Then
'--------------------------------------------------------------
'Try and find the First and next control which can receive focus
Set ctrlFirst = Nothing
Set ctrlNext = Nothing
For Each ctrl In frm.Controls
'--------------------------------------------------------------
'Can this control have focus?
If fnControlCanHaveFocus(ctrl) And _
Not ctrl Is frm.ActiveControl Then
'--------------------------------------------------------------
'Check for Next control
If ctrl.TabIndex > frm.ActiveControl.TabIndex Then
If ctrlNext Is Nothing Then
Set ctrlNext = ctrl
ElseIf ctrlNext.TabIndex > ctrl.TabIndex Then
Set ctrlNext = ctrl
End If 'ElseIf ctrlNext.TabIndex>ctrl.TabIndex
End If 'If ctrl.TabIndex>frm.ActiveControl.TabIndex
'--------------------------------------------------------------
'Check for first control
If ctrlFirst Is Nothing Then
Set ctrlFirst = ctrl
ElseIf ctrlFirst.TabIndex < ctrl.TabIndex Then
Set ctrlFirst = ctrl
End If 'ElseIf ctrlFirst.TabIndex<ctrl.TabIndex
End If 'If fnControlCanHaveFocus(ctrl) And...
Next ctrl
'--------------------------------------------------------------
'Is there a next control to set focus to?
If Not ctrlNext Is Nothing Then
Call ctrlNext.SetFocus
'--------------------------------------------------------------
'No next control, but a first control to jump to?
ElseIf Not ctrlFirst Is Nothing Then
Call ctrlFirst.SetFocus
End If 'ElseIf Not ctrlFirst Is Nothing
End If 'If Not frm.ActiveControl Is Nothing
End Sub
'##############################################################################
'##
'## Sub pSetFocusToPreviousControl
'##
'##############################################################################
Private Sub pSetFocusToPreviousControl(ByRef frm As Form)
Dim ctrl As Control
Dim ctrlLast As Control
Dim ctrlPrevious As Control
'--------------------------------------------------------------
'Is there even an active control?
If Not frm.ActiveControl Is Nothing Then
'--------------------------------------------------------------
'Try and find the Last and previous control which can receive focus
Set ctrlLast = Nothing
Set ctrlPrevious = Nothing
For Each ctrl In frm.Controls
'--------------------------------------------------------------
'Can this control have focus?
If fnControlCanHaveFocus(ctrl) And _
Not ctrl Is frm.ActiveControl Then
'--------------------------------------------------------------
'Check for Previous control
If ctrl.TabIndex < frm.ActiveControl.TabIndex Then
If ctrlPrevious Is Nothing Then
Set ctrlPrevious = ctrl
ElseIf ctrlPrevious.TabIndex < ctrl.TabIndex Then
Set ctrlPrevious = ctrl
End If 'ElseIf ctrlPrevious.TabIndex<ctrl.TabIndex
End If 'If ctrl.TabIndex<frm.ActiveControl.TabIndex
'--------------------------------------------------------------
'Check for Last control
If ctrlLast Is Nothing Then
Set ctrlLast = ctrl
ElseIf ctrlLast.TabIndex > ctrl.TabIndex Then
Set ctrlLast = ctrl
End If 'ElseIf ctrlLast.TabIndex>ctrl.TabIndex
End If 'If fnControlCanHaveFocus(ctrl) And...
Next ctrl
'--------------------------------------------------------------
'Is there a previous control to set focus to?
If Not ctrlPrevious Is Nothing Then
Call ctrlPrevious.SetFocus
'--------------------------------------------------------------
'No previous control but a Last control to jump to?
ElseIf Not ctrlLast Is Nothing Then
Call ctrlLast.SetFocus
End If 'ElseIf Not ctrlLast Is Nothing
End If 'If Not frm.ActiveControl Is Nothing
End Sub
And you use it like this for instance:
Private Sub txt_KeyDown(Index As Integer, KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyDown, _
vbKeyReturn
Call pSetFocusToNextControl(Me)
KeyCode = 0
Case vbKeyUp
Call pSetFocusToPreviousControl(Me)
KeyCode = 0
End Select
End Sub

Resources