Winform keyboard doesn't work when called modeless from VB6

G

Guest

I have a .NET DLL containing a Winform that is being called from a VB6 application. When the VB6 application calls ShowDialog, the keyboard works correctly with the form that is loaded from the DLL. When the Show method is used, however, the keyboard (with the exception of the spacebar) is inoperative.

The form is a simple one with two command buttons and each of them defines a hot key ("Button &1" for example). When the form is displayed with the "Show" method, the "Alt" key will not display the hotkeys, the "Tab" key will not move focus between the command buttons, in short, most of the keyboard is inoperative. The space bar does activate the first button in the tab order but nothing else seems to work. When the "ShowDialog" method is called, however, the form works as desired. Unfortunately, we don't want this form to be modal

Is there a way to fix this problem?
 
Y

Ying-Shen Yu[MSFT]

Hi Ken,

This is an known issue when displaying a modeless dialogbox in a DLL, you
may read this KB:

Q233263 - PRB: Modeless Dialog Box in a DLL Does Not Process TAB Key
<http://support.microsoft.com/default.aspx?scid=kb;en-us;233263>

To resolve this problem in managed code, you need hook the message queue
use P/Invoke,
I pasted a sample code in the end of this post.

If you still have problem on this issue please feel free to reply this
thread.
Thanks!

<code>
//Note, this code uses the Hook sample code in Technical Article <Windows
Hooks in the .NET Framework >
//http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/
//You need add the "windowshooks.cs" file into your project or write your
own hook implementation to make it work properly.
class TestForm : Form
{
private MsdnMag.LocalWindowsHook lwh;
public TestForm()
:base()
{
lwh = new MsdnMag.LocalWindowsHook(MsdnMag.HookType.WH_GETMESSAGE);
lwh.HookInvoked +=new
MsdnMag.LocalWindowsHook.HookEventHandler(lwh_HookInvoked);
}

protected override void WndProc(ref Message m)
{
Debug.WriteLine(m.Msg);
const int WM_CREATE = 0x0001;
const int WM_DESTROY = 0x0002;
if (m.Msg == WM_CREATE)
{
lwh.Install();
Debug.WriteLine ("Hook Installed");
}
if (m.Msg == WM_DESTROY)
{
lwh.Uninstall();
Debug.WriteLine ("Hook Uninstalled");
}
base.WndProc (ref m);
}

private void lwh_HookInvoked(object sender, MsdnMag.HookEventArgs e)
{
const int WM_NULL = 0;
const int PM_REMOVE = 0x0001;
const int WM_KEYFIRST = 0x0100;
const int WM_KEYLAST = 0x0109;
if (e.HookCode >= 0 && new IntPtr(PM_REMOVE) == e.wParam)
{
#if DEBUG
Debug.WriteLine("offsetof(message) = {0}",
Marshal.OffsetOf(typeof(MSG),"Msg").ToInt32().ToString());
#endif

uint msg = (uint)Marshal.ReadInt32(e.lParam,
Marshal.OffsetOf(typeof(MSG),"Msg").ToInt32());
if ( msg >= WM_KEYFIRST && msg <= WM_KEYLAST)
{
if (IsDialogMessage(this.Handle,e.lParam) != 0)
{

Marshal.WriteInt32(e.lParam,Marshal.OffsetOf(typeof(MSG),"Msg").ToInt32(),WM
_NULL);

Marshal.WriteInt32(e.lParam,Marshal.OffsetOf(typeof(MSG),"wParam").ToInt32()
,0);

Marshal.WriteInt32(e.lParam,Marshal.OffsetOf(typeof(MSG),"lParam").ToInt32()
,0);
}
}
}
}

[
StructLayout(LayoutKind.Sequential)
]
struct MSG
{
IntPtr hwnd;
uint Msg;
IntPtr wParam;
IntPtr lParam;
int time;
//POINT pt
int x;
int y;
}

[DllImport("user32.dll")]
private static extern int IsDialogMessage(IntPtr hDlg, IntPtr lpMsg);
}
</code>




Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Y

Ying-Shen Yu[MSFT]

Hi Ken,

The API Declaration of IsDialogMessage is not correct, in this scenario
the e.lParam is already the pointer to the MSG structure, we needn't pass
it by reference, change it to ByVal should fix this problem.

Cheers!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Y

Ying-Shen Yu[MSFT]

This is the definition used in my test program:

Declare Function IsDialogMessage Lib "user32" Alias
"IsDialogMessageA" _
(ByVal hDlg As IntPtr, ByVal lpMsg As IntPtr) As Integer

Thanks!
Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
K

Ken Beccard

Thanks for your response. After changing the ByRef to ByVal, I now have
your solution working. I have also tested the solution proposed by Brent
Clark and it works as well.

I consider this problem resolved and give thanks to the people who
responded.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top