Ken_Bussell

Hello,

I have a custom forms designer. I've implemented a menu command service like so

MenuCommandServiceImpl mcsi = new MenuCommandServiceImpl();

host.AddService(typeof(IMenuCommandService), mcsi);

MenuCommandServiceImpl is derived from IMenuCommandService.

I "think" that the controls are supposed to move when the arrow keys are pressed via the

MenuCommands.KeyMoveUp etc. Commands. I've added those commands to my MenuCommand class, but nothing.

In all my searching around, I think that the DesignSurface.View is stealing the key press events for the Arrow keys, and should be the one to fire the correct events or preferably move the controls.

Have I added the wrong service or is it possibly added in the wrong order or is there somewhere else I need to look.

Ken



Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

Quirk

I implemented this by overriding ProcessCmdKey() in my main form (the one hosting the design surface). At that point it's just a matter of checking the KeyData argument (forgive the pseudo-ish code):

case Keys.Up:

if (mcsi != null)

mcsi.GlobalInvoke(MenuCommands.KeyMoveUp);

Msg.Result = IntPt.Zero; //we handled this message

break;

There's likely a more elegant way to do this (for instance I'm not taking Focus into account). I'd love to hear some suggestions :)





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

NateRickard

You can implement an IMessageFilter to listen for keypress events. This is what most custom forms designer implementations did before the DesignSurface control was introduced with 2.0. In the PreFilterMessage method, you check that the windows message being passed is the WM_KEYDOWN message and then check if your design surface is focused and handle the key message. Check out (warning - large PDF file):

http://www.ads4reed.com/specs/StevensSecondTest/Dissecting_A_CSharp_Application.pdf

for a good implementation in Chapter 16, p. 447. I wouldn't bother wrapping commands like they do. To check if the DesignSurface has the input focus, you can get the IRootDesigner through the IDesignerHost and call [rootdesigner].GetView(ViewTechnology.Default), which will return a Control that you can check for focus on.

Let me know if you need any more specifics





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

Ken_Bussell

Thanks Nate, this will be a good workaround if I need it. I'll let you know if I need any specifics if I need it. I'm using DesignSurface, and I'm thinking that it "Should" take care of it for me. The logic is easy to implement, but I prefer less code if I can. :) Hopefully someone will tell me that I missed something and tell me what to fix.



Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

NateRickard

Please let me know if you do find a "default" way. I looked for a while when I converted my designer to Whidbey, but then decided to rework my IMessageFilter because it works very well and I never found a built in way...





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

al12345

Hi,

Did anybody ever find the "default way" to implement the key presses in the forms designer in .Net 2.0 I too have just put the IMessageFilter in place but I am unsure how to handle multiple key presses like Ctrl+Right or Shift+Left (Those combinations align and resize controls.)

Thanks for any help,

Al





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

Ken_Bussell

The IMessageFilter is the answer. Below is what I implemented. It allows for the control keys that you asked about.

Also, the bool AllowDeleteKey is because you don't always want to send the global command delete. If you do you will find you have problems. Like when you have a property in the property grid selected and press delete, you delete the object and the property. It really sucked figuring that one out.

public class KeystrokMessageFilter : System.Windows.Forms.IMessageFilter

{

private IDesignerHost host;

private DesignSurface _DesignSurface;

public bool AllowDeleteKey = true;

public KeystrokMessageFilter()

{

}

public void SetHostAndMDIForm(IDesignerHost host, DesignSurface DesSurface)

{

this.host = host;

_DesignSurface = DesSurface;

}

#region Implementation of IMessageFilter

public bool PreFilterMessage(ref Message m)

{

if (_DesignSurface == null)

return false;

//return false;

// Catch WM_KEYCHAR if the designerView has focus

//System.Diagnostics.Trace.WriteLine(m.Msg.ToString());

//only send these messages out if the design surface has the focus

if ((m.Msg == 256 /*0x0100*/) && ((Control)_DesignSurface.View).Focused)

{

IMenuCommandService mcs = host.GetService(typeof(IMenuCommandService)) as IMenuCommandService;

// WM_KEYCHAR only tells us the last key pressed. Thus we check

// Control for modifier keys (Control, Shift, etc.)

//

switch (((int)m.WParam) | ((int)Control.ModifierKeys))

{

case (int)Keys.Up: mcs.GlobalInvoke(MenuCommands.KeyMoveUp);

break;

case (int)Keys.Down: mcs.GlobalInvoke(MenuCommands.KeyMoveDown);

break;

case (int)Keys.Right: mcs.GlobalInvoke(MenuCommands.KeyMoveRight);

break;

case (int)Keys.Left: mcs.GlobalInvoke(MenuCommands.KeyMoveLeft);

break;

case (int)(Keys.Control | Keys.Up): mcs.GlobalInvoke(MenuCommands.KeyNudgeUp);

break;

case (int)(Keys.Control | Keys.Down): mcs.GlobalInvoke(MenuCommands.KeyNudgeDown);

break;

case (int)(Keys.Control | Keys.Right): mcs.GlobalInvoke(MenuCommands.KeyNudgeRight);

break;

case (int)(Keys.Control | Keys.Left): mcs.GlobalInvoke(MenuCommands.KeyNudgeLeft);

break;

case (int)(Keys.Shift | Keys.Up): mcs.GlobalInvoke(MenuCommands.KeySizeHeightIncrease);

break;

case (int)(Keys.Shift | Keys.Down): mcs.GlobalInvoke(MenuCommands.KeySizeHeightDecrease);

break;

case (int)(Keys.Shift | Keys.Right): mcs.GlobalInvoke(MenuCommands.KeySizeWidthIncrease);

break;

case (int)(Keys.Shift | Keys.Left): mcs.GlobalInvoke(MenuCommands.KeySizeWidthDecrease);

break;

case (int)(Keys.Control | Keys.Shift | Keys.Up): mcs.GlobalInvoke(MenuCommands.KeyNudgeHeightIncrease);

break;

case (int)(Keys.Control | Keys.Shift | Keys.Down): mcs.GlobalInvoke(MenuCommands.KeyNudgeHeightDecrease);

break;

case (int)(Keys.Control | Keys.Shift | Keys.Right): mcs.GlobalInvoke(MenuCommands.KeyNudgeWidthIncrease);

break;

case (int)(Keys.ControlKey | Keys.Shift | Keys.Left): mcs.GlobalInvoke(MenuCommands.KeyNudgeWidthDecrease);

break;

case (int)(Keys.Escape): mcs.GlobalInvoke(MenuCommands.KeyCancel);

break;

case (int)(Keys.Shift | Keys.Escape): mcs.GlobalInvoke(MenuCommands.KeyReverseCancel);

break;

case (int)(Keys.Enter): mcs.GlobalInvoke(MenuCommands.KeyDefaultAction);

break;

case (int)(Keys.Delete):

if(AllowDeleteKey)

mcs.GlobalInvoke(MenuCommands.Delete);

break;

}

}

return false;

}

#endregion

}





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

danielreber

Ken,

How and where does the MessageFilter service get added or when does a variable of Type MessageFilter get instantiated

Thanks






Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

Ken_Bussell

Add an field of the KestrokMessageFilter type (your version obviously) to your application.

Then in the contructor (or whereever you want) put the following.

_KeyStrokeMessageFilter = new KeystrokMessageFilter();

Application.AddMessageFilter(_KeyStrokeMessageFilter);

Where KeystrokMessageFilter is your classes name. This is an application wiide message filter. Read the help on The Applicaiton.AddMessageFilter so you fully understand what happens when you add this.

Ken





Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

danielreber

Thanks Ken, that worked.




Re: Windows Forms Designer Arrow Keys don't move controls in custom forms designer

al12345

Hi Ken,

Thanks for your help. I really appreciate it.

Al