Is it possible to have a checkbox' keydown event fire when one of the arrow keys is pressed? Or at least is there any way around this?
Printable View
Is it possible to have a checkbox' keydown event fire when one of the arrow keys is pressed? Or at least is there any way around this?
I just thought I could use the validate event... Would that make any difference?
No I can't, there's no way to know the code of the pressed key. I've tried to enable keypreview for the form and trap the arrow keys in the form's keydown event but it doesn't work.Quote:
Originally Posted by krtxmrtz
So how what can I do so that the arrow keys trigger some event when a checkbox has the focus?
I believe you'll need some API code for that. I'll post back when I find something
EDIT: http://www.vbforums.com/showthread.p...t=key+trap+api
Try:
VB Code:
Private Sub CheckBox1_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = vbKeyUP or vbKeyDown or vbKeyLeft or vbKeyRight Then 'call your save function here End If End Sub
Just edited Shuja Ali's post for what I've gathered from your post. It might not exactly work, but it should be something similar to that i hope... :sick:
Could you do a msgbox and find out the ascii value for those keys and then use the keypress event to test for them?
VB Code:
Private Sub Form_Load() Me.KeyPreview = True End Sub Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyLeft MsgBox "left arrow" Case vbKeyRight MsgBox "right arror" End Select End Sub
vbKeyLeft = 37
vbKeyUp = 38
vbKeyRight = 39
vbKeyDown = 40
I am not sure what the problem you are having is, you were given code to test for key events and the corresponding codes for those keys. Is there something that we are overlooking??
Thanks,
D
I understand the problem, but I'm not sure I know the solution.
You could create a usercontrol that encapsulates a checkbox - I think you could make this work for you.
Alternatively you can use the LostFocus event of the checkbox (but this doesn't let you know which key was pressed).
All right, I'll try to explain what I want to do. It's related to my previous thread (this one)
Please, take a moment to read my first post there and then try out the code attached to this post. If you click on the grid or use the enter or arrow keys, you'll see that the text in the target cell is selected (this I've done by means of a textbox), but in row 8 a checkbox appears. Click on any cell of row 8 and then try to navigate from there by means of the keyboard. The ener key works ok, but not so the arow keys. I'm trying to figure out the logic of it all... :confused:
The first thing I did was to add a form-level Watch on ActiveControl.Name, set to break when the value changed. I then made the following change
And I was happy when it worked. I then got rid of the watch and it no longer worked! I'm guessing that since the only thing that really happened was that the code was no longer pausing between the changing of the active control that a DoEvents (or two) will fix the problem, but I haven't been able to get it right yet.VB Code:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) kee = KeyCode [HL="#FFFF80"] If KeyCode = vbKeyRight Then chk1_KeyDown KeyCode, 0 End If[/HL] End Sub
Okay forget about the previous code. Just do
VB Code:
Private Sub setupcheckbox() With grid grid.CellBackColor = vbYellow chk1.Visible = True chk1.Move .Left + .CellLeft + 0.5 * (.CellWidth - chk1.Width), .Top + .CellTop chk1.Value = grid.TextMatrix(grid.Row, grid.Col) ' chk1.SetFocus [HL="#FFFF80"]Commented[/HL] chk1.ZOrder oldcol = .Col oldrow = .Row End With End Sub
I'm not sure what this code's supposed to do... The idea is when the checkbox has the focus (i.e. when we are in row 8) then if I hit any of the arrow keys I want:Quote:
Originally Posted by MartinLiss
1. The checkbox to become invisible
2. The cell's text to be updated to 0 or 1 according to the checkbox value
3. To select the text of the corresponding neighbour cell (therefore to update the textbox and make it visible)
In testing this I found another problem. If you use the right arrow to "tab" in the checkbox row and you go from column 8 to column 9, that triggers the grid_Scroll sub which calls the setuptextbox sub which shows the original value of the grid cell in row 8, column 9.
Please describe what you mean by that.Quote:
Originally Posted by krtxmrtz
Yes, I thought I would deal with the scroll event after the current problem had been fixed.Quote:
Originally Posted by MartinLiss
See the attached image.Quote:
Originally Posted by MartinLiss
as the arrow keys ( and tab) are system level keys, they are not returned in the keydow, keyup or keypress events of a form or any control on the form, so i am guessing you would have to use a system wide hook to catch them
only other option i can see is to catch the event they cause, like the getfocus of whatever is next
I agree about the tab key but the arrow keys do trigger the keydown/keyup events. You can test this: just place a few common contols on a form, set breakpoints in the respective keydown events and then hit the arrow keys.Quote:
Originally Posted by westconn1
However they just don't respond in the demo project I'm working on, maybe because the checkbox is sitting on a grid or maybe because the code has some flaws.
I think the attached does what you want. I had to hook the windows messages for the chekbox to do it so while the msghook dll that I used to do that claims that there aren't the "normal" problems with subclassing, always make sure when testing to end the app normally otherwise VB might crash.
Thanks Marty, I have yet to study the code and the readme file about the dll. One thing that doesn't work though is the right and left arrow keys when I'm in the checkbox. Could it be some minor fine tuning that I'm not aware of?Quote:
Originally Posted by MartinLiss
I don't understand. If, for example, I go to a cell in the check box row that is currently zero, and check it and then use either the left or right arrow, the previously zero cell will show one. Isn't that what you want?Quote:
Originally Posted by krtxmrtz
OK but when I leave the cell with the checkbox, I want to go up/down if I hit the up/down arrow keys, but the right/left arrow keys should take me to the right/left neighbouring cells, which don't: left & right arrow keys work exactly as the up & down arrows.Quote:
Originally Posted by MartinLiss
Here is an example of what happens when I run the program. Please try and tell me exactly what is not correct.
Row 7: 387 190 631
Row 8: _1_ _0_ _1_
Row 9: 190 267 316
I click the zero in column 2 and check the checkbox. I then use the up arrow and the 0 changes to a one and 190 is highlighted.
I go back and click the same checkbox cell and now uncheck it. I then use the down arrow and the 1 changes to a 0 and the 267 is highlighted
I go back to the same cell and check it. I the use the left arrow and the 0 changes to a 1 and the 1 in col 1 row 8 is highlighted.
I go back to the same cell and uncheck it. I use the right arrow and the 1 changes to a 0 and the 1 in col 3 row 8 is highlighted.
Don't click on row 8: click for example on '190' in row 7, now arrow down to take you to the 0 (non-checked checkbox) of row 8 and now type left or right arrow. It goes down or up rather than left or right.Quote:
Originally Posted by MartinLiss
I don't understand why the other doesn't work but try this.
VB Code:
Private Sub IMsgHookEvents_BeforeMessage(ByVal obj As MsgHookSvr.MsgHook, uMsg As Long, wParam As Long, lParam As Long, ReturnValue As Long, Cancel As Boolean) ' in this particular case, it isn't really necessary to test for ' hWnd, because we are subclassing only the chk1 If obj.hWnd = chk1.hWnd Then Select Case uMsg Case WM_KILLFOCUS chk1.Visible = False If GetAsyncKeyState(vbKeyLeft) Then chk1_KeyDown vbKeyLeft, 0 ElseIf GetAsyncKeyState(vbKeyRight) Then chk1_KeyDown vbKeyRight, 0 ElseIf GetAsyncKeyState(vbKeyUp) Then chk1_KeyDown vbKeyUp, 0 ElseIf GetAsyncKeyState(vbKeyDown) Then chk1_KeyDown vbKeyDown, 0 End If End Select End If End Sub
No, this one isn't working either. It behaves somewhat erratically. The right and left arrow keys now work correctly for the checkbox row, they move you to the next cell to the right or left, but the checkbox should now be visible on the current cell and isn't.Quote:
Originally Posted by MartinLiss
Also, if you navigate by means of the up or down arrow keys or the retunr key, sometimes you see strange things like moving one column to the left after typing return, moving one cell up after typing arrow down, etc. Also the background colour is not always updated.
Well, I have printed the dll guide and your code and will try to study it and see what can do about this. :)
Try this - the magic row is #4 and space will check the checkboxEdit: it also needs this Sub (attachment updated):VB Code:
Private Sub Check1_Click() MSFlexGrid1.SetFocus End Sub Private Sub Form_Load() Check1.Visible = False End Sub Private Sub MSFlexGrid1_EnterCell() With MSFlexGrid1 If .Row = 4 Then Check1.Left = .Left + .ColPos(.Col) + (.ColWidth(.Col) - Check1.Width) \ 2 Check1.Top = .Top + .RowPos(.Row) + (.RowHeight(.Row) - Check1.Height) \ 2 Check1.Value = Val(.TextMatrix(.Row, .Col)) Check1.Visible = True End If End With End Sub Private Sub MSFlexGrid1_KeyPress(KeyAscii As Integer) If MSFlexGrid1.Row = 4 Then If KeyAscii = 32 Then Check1.Value = Abs(Not CBool(Check1.Value)) End If End Sub Private Sub MSFlexGrid1_LeaveCell() With MSFlexGrid1 If .Row = 4 Then .TextMatrix(.Row, .Col) = Check1.Value Check1.Visible = False End If End With End SubEdit2: another slight change to code (in bold above) - attachment not updatedVB Code:
Private Sub MSFlexGrid1_Scroll() With MSFlexGrid1 If Not (.RowIsVisible(.Row) And .ColIsVisible(.Col)) Then Check1.Visible = False Else[B]If .Row = 4 Then[/B] Check1.Left = .Left + .ColPos(.Col) + (.ColWidth(.Col) - Check1.Width) \ 2 Check1.Top = .Top + .RowPos(.Row) + (.RowHeight(.Row) - Check1.Height) \ 2 Check1.Visible = True End If End With End Sub
It works, but the original project included a textbox to provide the selstart and sellength properties not available for the grid's cells. This makes it more difficult to fine tune it.Quote:
Originally Posted by bushmobile
At the moment I have so much feedback from you guys that I've got to put on the thinking cap and sit for a while in front of the printed code.
Hey Presto! Textbox and Checkbox combined
Hey, that's great! :thumb: Just one more detail's left to deal with, At the risk of messing around somewhat, I'd like the checkbox (and/or the cell it's on) to display a yellow background as well. Is that possible?Quote:
Originally Posted by bushmobile
umm, addingshould do itVB Code:
' In SetUpCheckBox() .CellBackColor = vbYellow ' In MSFlexGrid1_LeaveCell (under first If condition) .CellBackColor = vbWhite
Yes it does...Quote:
Originally Posted by bushmobile
I've just noticed what still's not working: when you hit return on the checkbox.
ok, change this subplus you'll want to add in this one, which i forgot:VB Code:
Private Sub MSFlexGrid1_KeyPress(KeyAscii As Integer) If MSFlexGrid1.Row = CBRow Then If KeyAscii = 32 Then Check1.Value = Abs(Not CBool(Check1.Value)) ElseIf KeyAscii = 13 Then MSFlexGrid1.Row = MSFlexGrid1.Row + 1 KeyAscii = 0 End If End If End SubVB Code:
Private Sub Text1_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then KeyAscii = 0 End Sub
Very good job, bushmobile, that is it! This evening's beer is on me... can you digitize that??? :DQuote:
Originally Posted by bushmobile
:lol: no probs :thumb:
Here's my current (final?) version. I've made a few minor changes (value of row 4) and fixed scrolling problems. I have set the grid width as:
Depending on the total grid width (play around with the number of extra pixels) some problems appear with scrolling. It appears that you need 2 extra pixels so that the rightmost visible column is considered totally visible, but then another pixel may be necessary to prevent unwanted scrolling effects (try and see).VB Code:
tx = Screen.TwipsPerPixelX With Grid 'Sum of the widths of all the columns (all have the same ' width) plus the widths of the left and 'right borders '(times 2, found by trial and error) .Width = .ColWidth(0) * nVisibleCols + 4 * .BorderStyle * tx 'And I have added 3 extra pixels (see below) .Width = .Width + 3 * tx End With
All in all I have the feeling that I'm on shaky ground and that the whole thing is a mess.