If I want to detect multiple alphabet keys ( like DI for example) in my WPF app. How can I do it? Note that I only care to fire my events when I have detected multiple alphabet keys ( no CTRL, no SHIFT, no 1, 2 or 3..., just a, b, c, d and so on).
I tried something like
if (Keyboard.IsKeyDown(Key.D) && Keyboard.IsKeyDown(Key.I))
But it didn't work at all.
The solution I find mostly has to do with one of the keys is a modifier. So it doesn't really fit my needs.
Once I encountered a very same situation in which I could not detect several keys when pressed at the same time. The thing I was missing (which you may also be) was that I did not declare the code in the window's function itself. After writing that code inside the main window's KeyDown() function, it worked. After declaring the function for the window, you may try the code below to see if it actually works on your side.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.A) && Keyboard.IsKeyDown(Key.B) && Keyboard.IsKeyDown(Key.S))
{
// Whatever you would like to do
MessageBox.Show("Pressed!");
}
}
Related
I have some C++ code that performs calculations and I would like to visualize it.
I'm using windows forms (.NET).
The idea is to perform calculations in C++ and to include .h with chart.
As I need fast update, I use timer. As my data is in C++ I should use some tricks to draw it from .h. I was advised to use BeginInvoke() method, here's my proto code from header:
System::Void ActionD ()
{
for (pts = 0; pts < arrlength; pts++) {
chart1->series1->Points->AddXY(test_array_x[pts], test_array_y[pts]);
}
}
private:
System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) {
MethodInvoker^ mi = gcnew MethodInvoker(this,&ActionD);
chart1->Invoke(mi);
//check if timer works:
Beep(300,500);
}
I have some errors: "...MethodInvoker: a delegate constructor expects 1 argument"
Question is if the general concept of code correct and how can I fix that error?
The C++/CLI compiler in older versions of VS don't produce a very good diagnostic for bad delegate constructor calls. The issue is with &ActionD, it needs to be a fully qualified method name, like this:
MethodInvoker^ mi = gcnew MethodInvoker(this, &Form1::ActionD);
Replace "Form1" with the name of your form class if necessary.
And no, the general concept is not correct. You are using a regular Winforms timer, there's no need at all to use BeginInvoke since the code already runs on the main thread. Nor would you be ahead at all by using an asynchronous timer class, it doesn't make the code any faster.
You make your chart fast by filtering the data, only keeping the Points in the series that you actually need to get an accurate chart drawn. Which doesn't take a lot of points, a few hundred up to a thousand is more than enough. Monitors don't have a lot of pixels so using multiple thousands just keeps the Chart control busy for no benefit. Doing that filtering in a worker thread is the way to get ahead.
I've found a little bit similar topic:
How can I update data in a chart in execution time (in C++ builder)?
So I'm doing this inside my timer:
System::Windows::Forms::DataVisualization::Charting::Series^ seriezz1 = chart1->Series[0];
seriezz1->Points->AddXY(test_array_x[pts], test_array_y[pts]);
It compiles, but crashes at start :(
I'm trying to make a simple text editor with winapi, its working for simple letter, but its not with capital letter or shift key.
char keys[256];
int x = 0;
while (1)
{
for (x = 0; x <= 256; x++)
{
if (GetAsyncKeyState(x) == -32767)
{
char c[5];
GetKeyboardState(keys);
ToAscii(x, MapVirtualKey(x, 0), keys, c, 0);
putchar(c[0]);
}
}
}
The behaviors of keyboard input are far more complex than what you think. Your method doesn't work because:
GetAsyncKeyState can miss keys. What happens when the user hits a key between calls?
What happens when you hold down a key? What about keyboard repeat?
Most critically, your code assumes a 1:1 relationship between key and character. You don't have any mechanism to deal with combinations like shift / caps lock state, or dead keys.
It would be better if you tried to explain what you're trying to do, and you can get advice on the right way to approach it. Trying to re-invent the behaviors of such a fundamental input device is not likely to be the best approach.
GetAsyncKeyState is likely not the way to go here: the real way to make a text editor type control is to instead handle the WM_KEYDOWN and WM_CHAR messages. Windows will send these to your WndProc when your HWND has focus. This is the technique used by the Windows EDIT and RichEdit controls.
Use WM_KEYDOWN to handle the non-character keys - like arrows (VK_LEFT, VK_RIGHT), page up and so on; and use WM_CHAR for text characters. WM_KEYDOWN tells you the key pressed using a VK_ value, and doesn't take shift state into account; while WM_CHAR does take shift state, so gives you 'A' vs 'a' or '1' vs '!' as appropriate. (Note that you have to have TranslateMessage in your messsage loop for this to happen.)
Having said all that, an even easier/better thing to do is just use the existing Windows EDIT or RichEdit controls and let them do the work for you - there's rarely a good reason to reinvent the wheel - unless you're playing around for fun and learning Win32 perhaps. Writing a proper text editor is pretty complex; there's a lot of non-obvious stuff to consider, especially when you get into non-English text: you'd need to ensure it works correctly with right-to-left text (Arabic, Hebrew), works with IMEs which are used to enter Japanese and Chinese characters. And you have to ensure that your control is accessible to screenreaders so that users with visual impairments can still use the control. EDIT and RichEdit do all this for you.
The actual Notepad app, for example, is just a wrapper for an EDIT control; while WordPad just wraps a RichEdit control; both let the control do all the hard work, and just add the extra UI and file save/load functionality on top.
Try to call
GetKeyState(VK_CAPITAL);
before
GetKeyboardState(keys);
The Silverlight version of NotifyCollectionChangedEventArgs differs from the full framework version, in that it does not accept multiple (added, changed, removed) items. The constructors that take lists are in fact missing, so it appears Microsoft intended to block this usage. Indeed, if you pass in a collection of items, they're just nested as the first item of an internal collection.
However! Since the NewItems and OldItems members are of type IList, they are not immutable and can be grown. I made the following helper to test this idea:
private NotifyCollectionChangedEventArgs CreateEventArgsWithMultiple(NotifyCollectionChangedAction action, IEnumerable items, int newStartingIndex)
{
NotifyCollectionChangedEventArgs eventArgs = null;
foreach (var item in items)
{
if (eventArgs == null)
{
eventArgs = new NotifyCollectionChangedEventArgs(action, item, newStartingIndex);
}
else
{
eventArgs.NewItems.Add(item);
}
}
return eventArgs;
}
I haven't seen any problems yet, but I'm looking for experience and input with this particular corner of Silverlight. Should I bother to batch Adds like this, or just use a Reset?
This is on Windows Phone 7.1 (Mango), by the way.
Edit: To follow up on the comment by Erno. Microsoft says in this (poorly worded) Silverlight documentation page on MSDN that it can be "generally" assumed that NewItems only has one element, and even suggests the shortcut of using NewItems[0] to access it. So they retain the IList signature for "compatibility", but then go on butcher the meaning of the type. Disappointing.
I haven't run into any issues, but the answer is "Don't do it!" (unless you're only passing the args to code that you've written).
The reason (as has been said in the comments) is that there may be code in Silverlight which assumes there's only one item. Even if there isn't today, there may be tomorrow, and you definitely don't want your app to break when some new version of Silverlight comes out that relies more heavily on this assumption.
I'm currently coding a version of breakout as a quick learning experience of C and OpenGL.
Im having some issues with moving the paddle. I've set a keyboard callback so that when the left arrow is pressed, it subtracts 1 from the x value on the paddle, and adds 1 to the x value when pressing the right arrow.
With this in mind, the paddle moves incredibly slow when I hold either key. I can change this by increasing the amount the x value is changed to 10 for example. When I do this the paddle seems to stutter across the screen because it's jumping 10 at a time. It does of course move faster along the screen now but doesn't look smooth.
I'm using GLUT for windowing on OSX.
Is there a way of speeding this up and keeping it looking smooth?
A common thing in games is a keyboard array. Therefore you will be also able to press several buttons at a time.
You have an array where you keep state of keys (you put 1 when you get pressed, set 0 when released). And you process game in each frame by taking information just from array, not directly from input.
Here is some code from one of my projects:
bool keyDown[256];
...
//Called when a key is pressed
void handleKeypress(unsigned char key, int x, int y) {
keyDown[key] = true;
}
void handleKeyUp(unsigned char key, int x, int y){
keyDown[key] = false;
}
This essentially keeps an array of the states of each key, so you can just check them each time. Then you don't have to depend on the callbacks coming in that frequently.
I have a requirement to be able to auto-tab from one control to the "next control" in a SL3 app. For example, a TextBox is limited to 3 characters - on typing the 3rd character the focus should automatically move to the next control on the form (my actual usage is slightly different but that example suffices).
However, as SL automatically determines the tab sequence there doesn't seem to be a way of doing this apart from reverse engineering/duplicating Silverlight's logic to figure out which control in the visual tree should be the next control to gain focus.
Has anybody implemented this already?
I was looking for a fairly generalised solution - but I've been able to make do with something fairly specific - basically it uses the VisualTreeHelper to find children with the same parent as the control that I want to tab next to, and sets focus to that.
It's a more palatable solution than having to go through all my controls (and this is for a fairly large LOB application) and configure the "next" control for each of them.
Here's my code, in case it helps somebody else. (VisualTreeeHelperUtil is a class of my own that adds some utility functions to VisualTreeHelper)
public static void TabNext(DependencyObject parentElement, Control fromControl)
{
var children = VisualTreeHelperUtil.FindChildren<Control>(parentElement).
Where(c => c.IsEnabled && c.IsTabStop && c.Visibility == Visibility.Visible).
ToList();
if (children.Contains(fromControl))
{
var thisIndex = children.IndexOf(fromControl);
var targetIndex = thisIndex + 1;
if (children.Count > targetIndex)
{
var targetChild = children[targetIndex];
fromControl.Dispatcher.BeginInvoke(() =>
{
targetChild.Focus();
var txt = targetChild as TextBox;
if (txt != null)
{
txt.SelectAll();
}
});
}
}
}
If you're looking for a generalized solution, and are OK basing it on the visual tree ordering (as opposed to arranged layout), I imagine it would not be so bad. Haven't heard of it being done, though.
Most of the phone number or credit card entry forms I've seen with this behavior honestly just hard-code the next field in the proper change handler when the right # of characters have been entered.
Since it sounds like your auto-focusing solution (for 3 chars) is going to already require some sort of event hookup, monitoring the TextChanged event, couldn't you just go ahead and either 1) hard-code a Focus() to the next form element that you know, 2) use the Tag property to store the name of the control that you'd like to focus next, then do a FindName + Focus on that, or 3) do some sort of VisualTreeHelper (or logical tree search through peers)?