Application-Spanning Shortcuts

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,
I have an application consisting of a parent form and several child-forms.
The parent form has a menu and uses the default shortcut CTRL+O to open
files. I would like to have the shortcut available in the sub-forms (which
are owned by the main window) as well. If I remember correctly this used to
work once upon a time, but I do not know what I have changed -- now it does
not work any more. Is there a simple way to establish this?

I run the main form using Application::Run (MainForm), sub-windows are
created like this:

SubWindow ^w = gcnew SubWindow ();
SubWindow->Show (MainForm);

(using .NET 2.0 Framework here, but the question is also valid for other
versions of the framework, of course)

Thanks in advance
Felix Arends
 
Hi Felix,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you cannot use the shortcut key on MDI
parent form when child form is active. If there is any misunderstanding,
please feel free to let me know.

Based on the code you have provided, I think it has to be

SubWindow ^w = gcnew SubWindow ();
w->Show (MainForm);

since we're trying to display an instance of the SubWindow.

If that still doens't work, could you please try to post the code with
problem in .NET framework 1.1? Because .NET framework 2.0 is a beta product
which hasn't been released yet. Thank you!

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi,
thanks for you response.
First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you cannot use the shortcut key on MDI
parent form when child form is active. If there is any misunderstanding,
please feel free to let me know.

I am not using MDI forms. All my windows are derived from the
System.Windows.Forms.Form class, but I use SecondForm->Show (MainForm) to
display the "sub-form" (= the second form, which is still an independant
window, but owned by the main form).
So I create two (actually more, but that doesn't matter ;))
System.Windows.Forms.Form's and one is owned by the other one. Now if the
user has focused the owned form, I still want the owner form to catch the
Menu Shortcuts which I specified in its main menu.

Thanks
Felix Arends
 
Hi

We have reviewed this issue and are currently researching on it. We will
update you ASAP. Thanks for your patience!

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi Felix,

Sorry for letting you wait for so long.

.Net winform just encapsulates the Win32 window and messaging mechanism.
The menu is actually invoked through WM_COMMAND message, so we may just
intercept the Ctrl+O accelerate key in the child form and just send a
WM_COMMAND message to the parent form.

To intercept the WM_COMMAND message, we may override child form's WndProc.
In WndProc method, we may listen for WM_CHAR message, which WParam is
'0x0F'(Stand for Ctrl+O). Then use P/invoke to send WM_COMMAND message to
the parent form. Sample code like this:


private Form1 parentForm=null;
public Form2(Form1 f)
{
InitializeComponent();
parentForm=f;
}

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
IntPtr lParam);

private const int WM_CHAR=0x102;
private const int WM_COMMAND=0x111;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_CHAR)
{
if((int)m.WParam==0x0F)
{
MessageBox.Show("Ctrl+O");
SendMessage(this.parentForm.Handle, WM_COMMAND, (IntPtr)0x101,
IntPtr.Zero); //In parentform, we may use SPY++ to see that the menu item's
command id is 0x101
}
}
base.WndProc (ref m);
}

//In Form1

private void menuItem2_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Test");
}

private void button1_Click(object sender, System.EventArgs e)
{
Form2 f=new Form2(this);
f.Show();
}

The code snippet above works well when there are no child controls on
parent form. But if there are more than one child controls on the form, the
key messages will be intercepted by the child controls, the form can not
get any key stroke message, so the code does not work again. For this
issue, I think there is not a good way to get it done, below are 2 choices:
1. Use NativeWindow class to subclass the child controls, then we can
intercept the key stroke in subclass window procedure. But if there are too
many controls on the form, subclass is not a good idea for this.
2. Using local KeyBoard hook to intercept the current main thread's
keyboard messages. This should work, but it is not a recommanded way, which
is somewhat too complex for this issue.

Actually, the standard way of sharing menu between several forms is MDI
form architecture. So I suggest you use MDI form for this issue.

Hope this helps.
=============================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Hi, thanks for your response. Unfortunately I didn't notice it at once. I am
pretty sure this used to work, but maybe I'm simply mistaken. I'll try to do
the hook thing, which should work if I use Application::AddMessageFilter. The
only messy thing about this is that I need to hard-code the shortcut keys
(unless I make quite a bit of effort...) -- or is there a function which
checks a window message for all the shortcuts which might be occupied by a
single form?

Thanks again,
Felix Arends

"Jeffrey Tan[MSFT]" said:
Hi Felix,

Sorry for letting you wait for so long.

.Net winform just encapsulates the Win32 window and messaging mechanism.
The menu is actually invoked through WM_COMMAND message, so we may just
intercept the Ctrl+O accelerate key in the child form and just send a
WM_COMMAND message to the parent form.

To intercept the WM_COMMAND message, we may override child form's WndProc.
In WndProc method, we may listen for WM_CHAR message, which WParam is
'0x0F'(Stand for Ctrl+O). Then use P/invoke to send WM_COMMAND message to
the parent form. Sample code like this:


private Form1 parentForm=null;
public Form2(Form1 f)
{
InitializeComponent();
parentForm=f;
}

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
IntPtr lParam);

private const int WM_CHAR=0x102;
private const int WM_COMMAND=0x111;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_CHAR)
{
if((int)m.WParam==0x0F)
{
MessageBox.Show("Ctrl+O");
SendMessage(this.parentForm.Handle, WM_COMMAND, (IntPtr)0x101,
IntPtr.Zero); //In parentform, we may use SPY++ to see that the menu item's
command id is 0x101
}
}
base.WndProc (ref m);
}

//In Form1

private void menuItem2_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Test");
}

private void button1_Click(object sender, System.EventArgs e)
{
Form2 f=new Form2(this);
f.Show();
}

The code snippet above works well when there are no child controls on
parent form. But if there are more than one child controls on the form, the
key messages will be intercepted by the child controls, the form can not
get any key stroke message, so the code does not work again. For this
issue, I think there is not a good way to get it done, below are 2 choices:
1. Use NativeWindow class to subclass the child controls, then we can
intercept the key stroke in subclass window procedure. But if there are too
many controls on the form, subclass is not a good idea for this.
2. Using local KeyBoard hook to intercept the current main thread's
keyboard messages. This should work, but it is not a recommanded way, which
is somewhat too complex for this issue.

Actually, the standard way of sharing menu between several forms is MDI
form architecture. So I suggest you use MDI form for this issue.

Hope this helps.
=============================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Hi Felix,

Thanks for your feedback!

Yes, because we just need to intercept the posted messages of our
applicaiton, we may use Application::AddMessageFilter to get the Ctrl+O
short cut key. Furthermore, if we open the KeyPreview property to true in
the child form, we may also intercept the WM_CHAR of the child controls on
the form, like this:

private void Form1_Load(object sender, System.EventArgs e)
{
this.KeyPreview=true;
}

private void Form1_KeyPress(object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar==0x0F)
{
MessageBox.Show("Ctrl+O");
}
}
I think this should be the simplest way of intercepting the shortcut key
press.
======================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Back
Top