.NET Forum / Languages / C# / January 2008
Passing events from the menu to a control
|
|
Thread rating:  |
michael sorens - 09 Jan 2008 23:49 GMT I created a user control that handles certain keystrokes, e.g. Ctrl-C for cut, Ctrl-V for paste, plus other more specialized keystrokes. I want to list these in the menubar like any other menu items. Once I assign a Shortcut Key to the menu item, that menu sees the event before the control, as one would expect. The question is, then, inside the menu item handler what code do I need to pass on the keystroke to a control? This is slightly complicated by the fact that the keystroke could go to any one of several controls, depending on which is active. I have not been successfully in web searches on this topic so far. Environment: .Net 3.0, VS2005, C#.
Linda Liu[MSFT] - 10 Jan 2008 06:38 GMT Hi Michael,
Based on my understanding, you have a UserControl that handles certain short keys and you'd like to set these keys as the shortcut keys of some menu items. The problem is that you don't know what code you should write in the menu item Click event handler because the key stroke could go to any one of several controls, depending on which is ative. If I'm off base, please feel free to let me know.
Firstly, I don't think it makes any difference after you assign the shortcut keys of the menu items. You can still use the ActiveControl propetry of the form to determine which control in the form is active currently.
I will illustrate this with an example. It requires you to add a MenuStrip with a menu item to a form. The menu item has a shortcut key of Ctrl+W. It also requires you to add two TextBoxes onto the form. In the menu item's Click event handler, write down the following code:
private void toolStripMenuItem1_Click(object sender, EventArgs e) { TextBox txtbox = this.ActiveControl as TextBox; if (txtbox != null) { txtbox.Copy(); } }
Build the project and run the application. Type some text into one of the two TextBoxes and select some text in it. Whether you click the menu item on the form or press Ctrl+W, the selected text is copied to the Clipboard.
Hope this helps. If you have any question, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
michael sorens - 10 Jan 2008 17:54 GMT Thanks for the suggestions, but that is not quite what I need. Your code sample uses the approach of explicitly calling methods to do specific actions. What I need to do is different--I just want the menu item handler to "get out of the way". By that, I mean I want it to pass on the keystroke event so that whatever would have happened to the keystroke (if the menu handler did not intercept it) happens. To put this another way, if the menu item event provided a KeyPressEventArgs argument instead of an EventArgs argument, the menu item handler would simply set the Handled property to false, allowing the KeyPress event to "pass through".
Linda Liu[MSFT] - 14 Jan 2008 06:23 GMT Hi Michael,
Thank you for your reply!
We can call the SendKeys.Send method to send keystrokes to the active application. In your scenario, you can call the SendKeys.Send method to send the shortcut key of the menu item to the application so as to "pass" on the key stroke event.
For example, we use Ctrl+O as the shortcut key of a menu item. In the Click event handler of this menu item, add the following line of code to send Ctrl+O to the application.
private void toolStripMenuItem1_Click(object sender, EventArgs e) { SendKeys.Send("^o"); }
For more information on the SendKeys.Send method, you may refer to the following MSDN document:
http://msdn2.microsoft.com/en-us/library/system.windows.forms.sendkeys.send. aspx
Hope this helps. If you have any question, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
michael sorens - 14 Jan 2008 23:31 GMT What you suggest will simply cause an infinite loop--it will return to the exact same handler, unless you have some trick to do otherwise that you do not mention. (And besides that, I do not believe that invoking what is essentially a debugging aid for routine code would really be considered a "best practice" for this scenario.)
Peter Duniho - 15 Jan 2008 01:22 GMT > What you suggest will simply cause an infinite loop--it will return to > the [quoted text clipped - 3 lines] > essentially a debugging aid for routine code would really be considered a > "best practice" for this scenario.) Here's the thing: there is no public method in Control that will allow you to just pass along the data from a key event.
You mentioned in a previous post that you'd like to be able to just set a "Handled" property to false, but this only works when you're in the same chain of event handlers for an event. You're trying to translate an event that occurs in one object to be handled by event handling in a different object. At least, that's how your posts read.
Given what you've written so far, I think Linda's replies are quite appropriate. Her first suggestion is in fact what I would have suggested given your question, and her second suggestion seems like the most obvious alternative given your refusal to just use the simple solution of calling methods directly.
It's difficult for me, reading your question, to know _exactly_ what it is you're trying to do. It's possible that you're not getting answers that you find useful because you haven't really described your question very well.
As an example of the vagueness of your question: we do not even know which menu class you're using. I mean, I suppose we can assume you're dealing with a ToolStrip menu, with ToolStripMenuItem instances. But you haven't said that explicitly.
As another example: you've provided no simple code sample to illustrate how your code works now, nor to illustrate what sort of architectural design you'd like to implement. In the latter case, you wouldn't necessarily need to provide working code (obviously :) ). Just code that _looks_ like what you think the final solution should look like.
It's _possible_ that your question could be answered by suggesting that you subclass ToolStripMenuItem and override a method like ProcessCmdKey() or ProcessDialogKey(), or by suggesting that you set up some sort of "keystroke received" event that the active control can subscribe to and which you raise in response to receiving a keystroke in your menu.
But with such a vague question, it's going to be very hard to say for sure.
Pete
michael sorens - 15 Jan 2008 03:40 GMT I want to say first, Pete, that I appreciate you taking the time to put down your thoughts so thoroughly. My comments:
(1) My rejection of the "simple" solution was not on a whim; I do not have exposed methods to call needed by that solution (which I should have stated).
(2) I maintain that the SendKey suggestion is an infinite loop--yet you say this is "appropriate"; please explain how.
(3) Regarding your comment "You're trying to translate an event that occurs in one object to be handled by event handling in a different object." That was present, in fact, for precisely the reason of disambiguating what I wanted. I was giving a related example--note that I said "IF it provided ...". (Sounds like I am damned if I do, damned if I don't :-)
(4) Yes, I am referring to ToolStripMenuItems. I was not aware there were other types, a fact reinforced by Linda's use of it in both examples.
(5) As for example code I cannot offer much beyond what Linda has already provided twice: private void toolStripMenuItem1_Click(object sender, EventArgs e) { // This menu command needs to pass the event--or perhaps // generate a different event--so that the approrpriate // event handler in a custom user control will act on the user's cmd. } For another example, consider the ordinary TextBox. It supports a variety of keystrokes: cut, copy, paste, home, end, select-all, etc. I just want to add those types of keys to a menu in the menu bar so that they are enumerated along with all the menu commands that I am providing explicit implementation for. It sounds like the only simple way to do this is from Linda's first suggestion, i.e. call the specific methods.
Anyway, thanks for keeping me on my toes.
Peter Duniho - 15 Jan 2008 05:13 GMT > I want to say first, Pete, that I appreciate you taking the time to put > down [quoted text clipped - 4 lines] > exposed methods to call needed by that solution (which I should have > stated). Whim or not, you did reject it. It may be for good reason, but that doesn't change the desirability of using that solution. Just the feasibility.
> (2) I maintain that the SendKey suggestion is an infinite loop--yet you > say > this is "appropriate"; please explain how. I don't see an infinite loop. Presumably the Click handler that Linda posted resides in the Control that should receive the keyboard input, not the ToolStripMenuItem. So, unless the Control upon receiving the keyboard input then turns around and somehow raises a Click event in the ToolStripMenuItem, where's the infinite loop?
Does your Control do that?
> (3) Regarding your comment "You're trying to translate an event > that occurs in one object to be handled by event handling in a different > object." That was present, in fact, for precisely the reason of > disambiguating what I wanted. I was giving a related example--note that I > said "IF it provided ...". (Sounds like I am damned if I do, damned if I > don't :-) Well, that's fine. It's not how I read that post though. It's not just a matter of having the event use a different EventArgs class. There's just not even that event mechanism. It wasn't clear from your post that was understood.
> (4) Yes, I am referring to ToolStripMenuItems. I was not aware there were > other types, a fact reinforced by Linda's use of it in both examples. ToolsStripMenuItem is the most common, but there are legacy classes that you could have been using instead. In any case, you should always be specific, even if in theory there are no other alternatives.
> (5) As for example code I cannot offer much beyond what Linda has already > provided twice: [quoted text clipped - 4 lines] > // event handler in a custom user control will act on the user's cmd. > } Well, first...those are Linda's examples, both of which you said were inappropriate. How are we supposed to know that those actually do serve as examples of what you're trying to do?
Secondly, those are hardly complete enough to really understand the issue. They don't tell us anything about the Control classes you're trying to interface with, or about how you'd prefer them to work.
Based on the code you posted above, either of Linda's suggestions would work fine. Since you say they don't work fine, obviously the above example is not nearly specific enough to provide useful advice to you. You need to provide an example that is at least complete enough for people to understand why the simple example's Linda's offered don't work.
> For another example, consider the ordinary TextBox. It supports a > variety of [quoted text clipped - 5 lines] > for. It sounds like the only simple way to do this is from Linda's first > suggestion, i.e. call the specific methods. Well, the TextBox class has all of those specific methods (well, cut, copy, paste, home, end, and select-all...I don't know what's left in "etc." so I can't comment on that). But you wrote "I do not have exposed methods to call needed by that solution".
So what's really the problem?
> Anyway, thanks for keeping me on my toes. You're welcome. :)
Pete
michael sorens - 15 Jan 2008 21:46 GMT Regarding the infinite loop debate, you state "Presumably the Click handler that Linda posted resides in the Control that should receive the keyboard input, not the ToolStripMenuItem." But no, Linda's handler is in the menu item. Furthermore: (a) If the handler is in the control, how is it supposed to get the event, since the menu got it first? (b) But say the control does get the event--then why would I need the click handler? That is the whole point, to get the event to the control.
One of us, I think, is missing some assumption here since this issue is in dispute; but I am not sure if it is you or me :-)
In any case, it is not terribly crucial, as I think I have gained what I am able from this thread.
Thanks for all the input.
Peter Duniho - 15 Jan 2008 22:13 GMT > Regarding the infinite loop debate, you state "Presumably the Click > handler > that Linda posted resides in the Control that should receive the > keyboard input, not > the ToolStripMenuItem." But no, Linda's handler is in the menu item. Why do you say that? Nothing in Linda's post says that the handler "is in the menu item", and it flies in the face of logic that it would be.
If for no other reason than that if it were, there's the possibility of an infinite loop whereas if it's in the control, such a problem is avoided. Also note that you specifically said you wanted to send the key to the control...since her code does not qualify a specific control in the call to the SendKeys() method, it stands to reason that the method is contained within the control class that should receive the key input.
Why do you insist on believing that she posted useless code, rather than accepting the possibility that maybe you misunderstand the code?
> Furthermore: > (a) If the handler is in the control, how is it supposed to get the > event, > since the menu got it first? Huh? A handler for any event can be anywhere in any class. It "gets the event" by subscribing to the event. When the event is raised, it gets the event.
Whether the menu "got it first" or not is irrelevant. There's not even any reason to believe that the menu has a handler subscribed to the event. The ToolStripMenuItem class itself is unlikely to have subscribed to the event, so unless you've sub-classed the class and written your own event handler which you've subscribed to the event, the menu would not in fact have a handler subscribed to the event.
> (b) But say the control does get the event--then why would I need the > click > handler? That is the whole point, to get the event to the control. Well, it is in fact hard to understand what your problem is. I don't in fact understand why you wouldn't just subscribe an event handler in the control to the menu's event. But since you prefer to complain about the answers given rather than elaborate on what the actual problem is, you continue to apparently not receive the help you desire.
> One of us, I think, is missing some assumption here since this issue is > in > dispute; but I am not sure if it is you or me :-) I am sure it is you.
> In any case, it is not terribly crucial, as I think I have gained what I > am > able from this thread. Does that mean that your problem is solved? If so, how is it solved?
Pete
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|