Home All Groups Group Topic Archive Search About

VBA stealing keys from ActiveX control?

Author
27 Jan 2006 9:08 PM
GBergeron
It appears that a UserForm displayed from VBA is stealing keystrokes from one
of our C++ ActiveX controls.  The keystrokes that are stolen are: backspace,
delete, and the arrow keys.  Normal alphanumeric keys work fine.  There may
be more keys that are stolen, but these are the important ones.

Setup:
We have a VB application that launches the VBA IDE (via a button click).  In
the VBA IDE, I create a UserForm that has a single TextBox in it.  The VB
code raises an event and the VBA code handles it by displaying the UserForm
with code like this: UserForm1.Show vbModeLess.  (BTW: The same problem
exists if you use vbModal as well)

Another button on the VB application launches an MFC C++ ActiveX control. 
This control comes up in it's own modeless dialog box and contains a few tabs
on it.  One of the tabs contains a few comboboxes: some editable (you can
type text into the field or choose an entry in the list) and some droplists. 
The editable combobox is where we have the problem.

So right now, we have 4 windows open: the VB application, the VBA IDE, the
UserForm and the C++ control. 
Here's the steps to reproduce the problem:
1) click in the UserForm and type some text into the TextBox
2) Now click in the C++ control and type some text into the combobox
3) hit the backspace key in the combobox in the C++ control
The text in the UserForm gets the backspace key and is shortened by one
character!  The text in the combobox is not touched and the cursor doesn't
move - even though it still has the focus!  So, this is very odd - hitting
the backspace key in one window deletes text in another window.  The delete
key works the same way.

If in step #1 above, you click in any other window, that's not the UserForm,
then click in the C++ control, the backspace key works fine - it deletes a
character in the combobox.  So, the problem only shows up if the UserForm is
the last window to have the focus, prior to clicking in the C++ control.

Spy++ Utility
I've run the Spy++ utility that comes with Visual Studio to track all the
messages that get sent to the windows in this VB application.  When it works
properly, here are the windows and the messages they get:
    - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
    - COMBOBOX: WM_CHAR: chCharCode ^H (0x08)
    - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.

When it fails, here are the windows and the messages they get:
    - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
    - USERFORM: WM_PAINT
    - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
So, the WM_CHAR message is not being sent.


Some more info:
- I put a TextBox1_Keydown event handler in the VBA code and it outputs the
key that was hit to the Immediate window.  The event handler is hit for every
keystroke that happens while the UserForm has the focus (as expected) as well
as while the C++ control has the focus (not expected)!  Even if I hit
alphanumeric keys in the combobox of the C++ control, the event handler is
triggered.  Weird.  The alphanumeric keys show up properly in the combobox
and they don't show up in the TextBox on the UserForm (which is good). 
However, VBA is getting all the keys to go through it's handling mechanism. 
For some reason, it allows alphanumeric keys to go through, but it steals the
backspace, delete, etc. keys for itself.
- The main form of the VB application has it's KeyPreview = True.  This
property determines whether keyboard events for forms are invoked before
keyboard events for controls. The keyboard events are KeyDown, KeyUp, and
KeyPress
- For some reason the control is forced to manage it's own tabbing behavior.
So, it captures the TAB key and sends focus to the next window depending on
which window currently has the focus.  It also manages it's own activation
state by capturing the WM_ACTIVATE message.  Based on this, there's some more
weird behavior.  I add another TextBox to the UserForm.  Then I do this:
1) click in the UserForm and type some text into the TextBox1, then type
some text into TextBox2
2) Now click in the C++ control and type some text into the combobox
3) hit the TAB key in the combobox in the C++ control
The focus jumps to TextBox1 in the UserForm!  Very weird.  Maybe this is
another problem, but it is very strange.  It's as if the UserForm had the
focus, I was in TextBox2 and I hit TAB and it jumps back to TextBox1.  If I
hit TAB a few more times while in the UserForm, it jumps back and forth
between the 2 TextBoxes (as expected).  However, it doesn't jump back to the
C++ control.

All this funky behavior hasn't caused any other problems for the last few
years so I don't really suspect it as the main culprit.  I just cannot
conclusively rule it out


So, this leads me to suspect one of two causes to the problem:
1) VBA is stealing the keys from the C++ control
2) the C++ control is actively (though unknowingly) giving up the keys to
someone higher up the food chain

#1 seems most likely considering the behavior.  However, I haven't ruled out
#2 yet because it does some funky things with tab-order.  If it's #1, then
it's Microsoft's bug.  If it's #2, then it's our own bug.

Author
31 Jan 2006 7:50 AM
Mark Yudkin
> - The main form of the VB application has it's KeyPreview = True.

You need to set the KeyPreview property to False (you state explicitly that
you DON'T want to process the key in the Form). Setting it to True requests
the behaviour you're seeing. In your control, pass any key you don't want to
process up to the form.

Show quoteHide quote
"GBergeron" <GBerge***@discussions.microsoft.com> wrote in message
news:B9446E2E-6D59-4DDF-91C3-73D11F0F54BB@microsoft.com...
> It appears that a UserForm displayed from VBA is stealing keystrokes from
> one
> of our C++ ActiveX controls.  The keystrokes that are stolen are:
> backspace,
> delete, and the arrow keys.  Normal alphanumeric keys work fine.  There
> may
> be more keys that are stolen, but these are the important ones.
>
> Setup:
> We have a VB application that launches the VBA IDE (via a button click).
> In
> the VBA IDE, I create a UserForm that has a single TextBox in it.  The VB
> code raises an event and the VBA code handles it by displaying the
> UserForm
> with code like this: UserForm1.Show vbModeLess.  (BTW: The same problem
> exists if you use vbModal as well)
>
> Another button on the VB application launches an MFC C++ ActiveX control.
> This control comes up in it's own modeless dialog box and contains a few
> tabs
> on it.  One of the tabs contains a few comboboxes: some editable (you can
> type text into the field or choose an entry in the list) and some
> droplists.
> The editable combobox is where we have the problem.
>
> So right now, we have 4 windows open: the VB application, the VBA IDE, the
> UserForm and the C++ control.
> Here's the steps to reproduce the problem:
> 1) click in the UserForm and type some text into the TextBox
> 2) Now click in the C++ control and type some text into the combobox
> 3) hit the backspace key in the combobox in the C++ control
> The text in the UserForm gets the backspace key and is shortened by one
> character!  The text in the combobox is not touched and the cursor doesn't
> move - even though it still has the focus!  So, this is very odd - hitting
> the backspace key in one window deletes text in another window.  The
> delete
> key works the same way.
>
> If in step #1 above, you click in any other window, that's not the
> UserForm,
> then click in the C++ control, the backspace key works fine - it deletes a
> character in the combobox.  So, the problem only shows up if the UserForm
> is
> the last window to have the focus, prior to clicking in the C++ control.
>
> Spy++ Utility
> I've run the Spy++ utility that comes with Visual Studio to track all the
> messages that get sent to the windows in this VB application.  When it
> works
> properly, here are the windows and the messages they get:
> - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
> - COMBOBOX: WM_CHAR: chCharCode ^H (0x08)
> - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
>
> When it fails, here are the windows and the messages they get:
> - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
> - USERFORM: WM_PAINT
> - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
> So, the WM_CHAR message is not being sent.
>
>
> Some more info:
> - I put a TextBox1_Keydown event handler in the VBA code and it outputs
> the
> key that was hit to the Immediate window.  The event handler is hit for
> every
> keystroke that happens while the UserForm has the focus (as expected) as
> well
> as while the C++ control has the focus (not expected)!  Even if I hit
> alphanumeric keys in the combobox of the C++ control, the event handler is
> triggered.  Weird.  The alphanumeric keys show up properly in the combobox
> and they don't show up in the TextBox on the UserForm (which is good).
> However, VBA is getting all the keys to go through it's handling
> mechanism.
> For some reason, it allows alphanumeric keys to go through, but it steals
> the
> backspace, delete, etc. keys for itself.
> - The main form of the VB application has it's KeyPreview = True.  This
> property determines whether keyboard events for forms are invoked before
> keyboard events for controls. The keyboard events are KeyDown, KeyUp, and
> KeyPress
> - For some reason the control is forced to manage it's own tabbing
> behavior.
> So, it captures the TAB key and sends focus to the next window depending
> on
> which window currently has the focus.  It also manages it's own activation
> state by capturing the WM_ACTIVATE message.  Based on this, there's some
> more
> weird behavior.  I add another TextBox to the UserForm.  Then I do this:
> 1) click in the UserForm and type some text into the TextBox1, then type
> some text into TextBox2
> 2) Now click in the C++ control and type some text into the combobox
> 3) hit the TAB key in the combobox in the C++ control
> The focus jumps to TextBox1 in the UserForm!  Very weird.  Maybe this is
> another problem, but it is very strange.  It's as if the UserForm had the
> focus, I was in TextBox2 and I hit TAB and it jumps back to TextBox1.  If
> I
> hit TAB a few more times while in the UserForm, it jumps back and forth
> between the 2 TextBoxes (as expected).  However, it doesn't jump back to
> the
> C++ control.
>
> All this funky behavior hasn't caused any other problems for the last few
> years so I don't really suspect it as the main culprit.  I just cannot
> conclusively rule it out
>
>
> So, this leads me to suspect one of two causes to the problem:
> 1) VBA is stealing the keys from the C++ control
> 2) the C++ control is actively (though unknowingly) giving up the keys to
> someone higher up the food chain
>
> #1 seems most likely considering the behavior.  However, I haven't ruled
> out
> #2 yet because it does some funky things with tab-order.  If it's #1, then
> it's Microsoft's bug.  If it's #2, then it's our own bug.
>
Author
31 Jan 2006 4:27 PM
GBergeron
Mark,

Thanks for the response.  I turned the KeyPreview off and I get the same
results.



Show quoteHide quote
"Mark Yudkin" wrote:

> > - The main form of the VB application has it's KeyPreview = True.
>
> You need to set the KeyPreview property to False (you state explicitly that
> you DON'T want to process the key in the Form). Setting it to True requests
> the behaviour you're seeing. In your control, pass any key you don't want to
> process up to the form.
>
> "GBergeron" <GBerge***@discussions.microsoft.com> wrote in message
> news:B9446E2E-6D59-4DDF-91C3-73D11F0F54BB@microsoft.com...
> > It appears that a UserForm displayed from VBA is stealing keystrokes from
> > one
> > of our C++ ActiveX controls.  The keystrokes that are stolen are:
> > backspace,
> > delete, and the arrow keys.  Normal alphanumeric keys work fine.  There
> > may
> > be more keys that are stolen, but these are the important ones.
> >
> > Setup:
> > We have a VB application that launches the VBA IDE (via a button click).
> > In
> > the VBA IDE, I create a UserForm that has a single TextBox in it.  The VB
> > code raises an event and the VBA code handles it by displaying the
> > UserForm
> > with code like this: UserForm1.Show vbModeLess.  (BTW: The same problem
> > exists if you use vbModal as well)
> >
> > Another button on the VB application launches an MFC C++ ActiveX control.
> > This control comes up in it's own modeless dialog box and contains a few
> > tabs
> > on it.  One of the tabs contains a few comboboxes: some editable (you can
> > type text into the field or choose an entry in the list) and some
> > droplists.
> > The editable combobox is where we have the problem.
> >
> > So right now, we have 4 windows open: the VB application, the VBA IDE, the
> > UserForm and the C++ control.
> > Here's the steps to reproduce the problem:
> > 1) click in the UserForm and type some text into the TextBox
> > 2) Now click in the C++ control and type some text into the combobox
> > 3) hit the backspace key in the combobox in the C++ control
> > The text in the UserForm gets the backspace key and is shortened by one
> > character!  The text in the combobox is not touched and the cursor doesn't
> > move - even though it still has the focus!  So, this is very odd - hitting
> > the backspace key in one window deletes text in another window.  The
> > delete
> > key works the same way.
> >
> > If in step #1 above, you click in any other window, that's not the
> > UserForm,
> > then click in the C++ control, the backspace key works fine - it deletes a
> > character in the combobox.  So, the problem only shows up if the UserForm
> > is
> > the last window to have the focus, prior to clicking in the C++ control.
> >
> > Spy++ Utility
> > I've run the Spy++ utility that comes with Visual Studio to track all the
> > messages that get sent to the windows in this VB application.  When it
> > works
> > properly, here are the windows and the messages they get:
> > - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
> > - COMBOBOX: WM_CHAR: chCharCode ^H (0x08)
> > - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
> >
> > When it fails, here are the windows and the messages they get:
> > - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
> > - USERFORM: WM_PAINT
> > - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
> > So, the WM_CHAR message is not being sent.
> >
> >
> > Some more info:
> > - I put a TextBox1_Keydown event handler in the VBA code and it outputs
> > the
> > key that was hit to the Immediate window.  The event handler is hit for
> > every
> > keystroke that happens while the UserForm has the focus (as expected) as
> > well
> > as while the C++ control has the focus (not expected)!  Even if I hit
> > alphanumeric keys in the combobox of the C++ control, the event handler is
> > triggered.  Weird.  The alphanumeric keys show up properly in the combobox
> > and they don't show up in the TextBox on the UserForm (which is good).
> > However, VBA is getting all the keys to go through it's handling
> > mechanism.
> > For some reason, it allows alphanumeric keys to go through, but it steals
> > the
> > backspace, delete, etc. keys for itself.
> > - The main form of the VB application has it's KeyPreview = True.  This
> > property determines whether keyboard events for forms are invoked before
> > keyboard events for controls. The keyboard events are KeyDown, KeyUp, and
> > KeyPress
> > - For some reason the control is forced to manage it's own tabbing
> > behavior.
> > So, it captures the TAB key and sends focus to the next window depending
> > on
> > which window currently has the focus.  It also manages it's own activation
> > state by capturing the WM_ACTIVATE message.  Based on this, there's some
> > more
> > weird behavior.  I add another TextBox to the UserForm.  Then I do this:
> > 1) click in the UserForm and type some text into the TextBox1, then type
> > some text into TextBox2
> > 2) Now click in the C++ control and type some text into the combobox
> > 3) hit the TAB key in the combobox in the C++ control
> > The focus jumps to TextBox1 in the UserForm!  Very weird.  Maybe this is
> > another problem, but it is very strange.  It's as if the UserForm had the
> > focus, I was in TextBox2 and I hit TAB and it jumps back to TextBox1.  If
> > I
> > hit TAB a few more times while in the UserForm, it jumps back and forth
> > between the 2 TextBoxes (as expected).  However, it doesn't jump back to
> > the
> > C++ control.
> >
> > All this funky behavior hasn't caused any other problems for the last few
> > years so I don't really suspect it as the main culprit.  I just cannot
> > conclusively rule it out
> >
> >
> > So, this leads me to suspect one of two causes to the problem:
> > 1) VBA is stealing the keys from the C++ control
> > 2) the C++ control is actively (though unknowingly) giving up the keys to
> > someone higher up the food chain
> >
> > #1 seems most likely considering the behavior.  However, I haven't ruled
> > out
> > #2 yet because it does some funky things with tab-order.  If it's #1, then
> > it's Microsoft's bug.  If it's #2, then it's our own bug.
> >
>
>
>
Author
1 Feb 2006 7:36 AM
Mark Yudkin
In that case, your C++ control is faulty. Unfortunately, it's quite common
as it's rather badly documented. I suggest you take the issue to a C++ (MFC)
/ OCX forum.

Show quoteHide quote
"GBergeron" <GBerge***@discussions.microsoft.com> wrote in message
news:53F9B02D-B26F-47C3-9118-85DBB792DCD5@microsoft.com...
> Mark,
>
> Thanks for the response.  I turned the KeyPreview off and I get the same
> results.
>
>
>
> "Mark Yudkin" wrote:
>
>> > - The main form of the VB application has it's KeyPreview = True.
>>
>> You need to set the KeyPreview property to False (you state explicitly
>> that
>> you DON'T want to process the key in the Form). Setting it to True
>> requests
>> the behaviour you're seeing. In your control, pass any key you don't want
>> to
>> process up to the form.
>>
>> "GBergeron" <GBerge***@discussions.microsoft.com> wrote in message
>> news:B9446E2E-6D59-4DDF-91C3-73D11F0F54BB@microsoft.com...
>> > It appears that a UserForm displayed from VBA is stealing keystrokes
>> > from
>> > one
>> > of our C++ ActiveX controls.  The keystrokes that are stolen are:
>> > backspace,
>> > delete, and the arrow keys.  Normal alphanumeric keys work fine.  There
>> > may
>> > be more keys that are stolen, but these are the important ones.
>> >
>> > Setup:
>> > We have a VB application that launches the VBA IDE (via a button
>> > click).
>> > In
>> > the VBA IDE, I create a UserForm that has a single TextBox in it.  The
>> > VB
>> > code raises an event and the VBA code handles it by displaying the
>> > UserForm
>> > with code like this: UserForm1.Show vbModeLess.  (BTW: The same problem
>> > exists if you use vbModal as well)
>> >
>> > Another button on the VB application launches an MFC C++ ActiveX
>> > control.
>> > This control comes up in it's own modeless dialog box and contains a
>> > few
>> > tabs
>> > on it.  One of the tabs contains a few comboboxes: some editable (you
>> > can
>> > type text into the field or choose an entry in the list) and some
>> > droplists.
>> > The editable combobox is where we have the problem.
>> >
>> > So right now, we have 4 windows open: the VB application, the VBA IDE,
>> > the
>> > UserForm and the C++ control.
>> > Here's the steps to reproduce the problem:
>> > 1) click in the UserForm and type some text into the TextBox
>> > 2) Now click in the C++ control and type some text into the combobox
>> > 3) hit the backspace key in the combobox in the C++ control
>> > The text in the UserForm gets the backspace key and is shortened by one
>> > character!  The text in the combobox is not touched and the cursor
>> > doesn't
>> > move - even though it still has the focus!  So, this is very odd -
>> > hitting
>> > the backspace key in one window deletes text in another window.  The
>> > delete
>> > key works the same way.
>> >
>> > If in step #1 above, you click in any other window, that's not the
>> > UserForm,
>> > then click in the C++ control, the backspace key works fine - it
>> > deletes a
>> > character in the combobox.  So, the problem only shows up if the
>> > UserForm
>> > is
>> > the last window to have the focus, prior to clicking in the C++
>> > control.
>> >
>> > Spy++ Utility
>> > I've run the Spy++ utility that comes with Visual Studio to track all
>> > the
>> > messages that get sent to the windows in this VB application.  When it
>> > works
>> > properly, here are the windows and the messages they get:
>> > - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
>> > - COMBOBOX: WM_CHAR: chCharCode ^H (0x08)
>> > - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
>> >
>> > When it fails, here are the windows and the messages they get:
>> > - COMBOBOX: WM_KEYDOWN nVirtKey:VK_BACK
>> > - USERFORM: WM_PAINT
>> > - COMBOBOX: WM_KEYUP nVirtKey:VK_BACK.
>> > So, the WM_CHAR message is not being sent.
>> >
>> >
>> > Some more info:
>> > - I put a TextBox1_Keydown event handler in the VBA code and it outputs
>> > the
>> > key that was hit to the Immediate window.  The event handler is hit for
>> > every
>> > keystroke that happens while the UserForm has the focus (as expected)
>> > as
>> > well
>> > as while the C++ control has the focus (not expected)!  Even if I hit
>> > alphanumeric keys in the combobox of the C++ control, the event handler
>> > is
>> > triggered.  Weird.  The alphanumeric keys show up properly in the
>> > combobox
>> > and they don't show up in the TextBox on the UserForm (which is good).
>> > However, VBA is getting all the keys to go through it's handling
>> > mechanism.
>> > For some reason, it allows alphanumeric keys to go through, but it
>> > steals
>> > the
>> > backspace, delete, etc. keys for itself.
>> > - The main form of the VB application has it's KeyPreview = True.  This
>> > property determines whether keyboard events for forms are invoked
>> > before
>> > keyboard events for controls. The keyboard events are KeyDown, KeyUp,
>> > and
>> > KeyPress
>> > - For some reason the control is forced to manage it's own tabbing
>> > behavior.
>> > So, it captures the TAB key and sends focus to the next window
>> > depending
>> > on
>> > which window currently has the focus.  It also manages it's own
>> > activation
>> > state by capturing the WM_ACTIVATE message.  Based on this, there's
>> > some
>> > more
>> > weird behavior.  I add another TextBox to the UserForm.  Then I do
>> > this:
>> > 1) click in the UserForm and type some text into the TextBox1, then
>> > type
>> > some text into TextBox2
>> > 2) Now click in the C++ control and type some text into the combobox
>> > 3) hit the TAB key in the combobox in the C++ control
>> > The focus jumps to TextBox1 in the UserForm!  Very weird.  Maybe this
>> > is
>> > another problem, but it is very strange.  It's as if the UserForm had
>> > the
>> > focus, I was in TextBox2 and I hit TAB and it jumps back to TextBox1.
>> > If
>> > I
>> > hit TAB a few more times while in the UserForm, it jumps back and forth
>> > between the 2 TextBoxes (as expected).  However, it doesn't jump back
>> > to
>> > the
>> > C++ control.
>> >
>> > All this funky behavior hasn't caused any other problems for the last
>> > few
>> > years so I don't really suspect it as the main culprit.  I just cannot
>> > conclusively rule it out
>> >
>> >
>> > So, this leads me to suspect one of two causes to the problem:
>> > 1) VBA is stealing the keys from the C++ control
>> > 2) the C++ control is actively (though unknowingly) giving up the keys
>> > to
>> > someone higher up the food chain
>> >
>> > #1 seems most likely considering the behavior.  However, I haven't
>> > ruled
>> > out
>> > #2 yet because it does some funky things with tab-order.  If it's #1,
>> > then
>> > it's Microsoft's bug.  If it's #2, then it's our own bug.
>> >
>>
>>
>>