473,581 Members | 2,497 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Using KeyDown from inside OnPaint

KeyDown won't work KeyPress fails KeyDown not seen

inspired by a poster here:http://tinyurl.com/62d97l I found some
interesting stuff, which I reproduce below for newbies like me.

The main reason you would want to do this is for example to trigger
something from an OnPaint event without resorting to boolean switches--
say if a user presses the "M" key while the program is Painting, the
user gets the PaintHandler to do something else. Arguably it's
quicker than waiting for Paint to finish, though I'm not sure of
that. BTW I think for KeyPress the form needs to have focus, but I'm
not sure. But KeyDown I think will work regardless of focus.

RL
public partial class Form1 : Form
{

Keys myGlobalKey;

char myGlobalChar; //declare your 'global' (not really)
variables here--important!

// stuff deleted

public Form1()
{

myGlobalKey = new Keys(); //instantiate here. For safety
do this before InitializeCompo nent();
myGlobalKey2 = new Keys();
myGlobalChar = new char();

//stuff deleted

// !!! IMPORTANT – make sure “key preview” property is set to true in
Form!! Default is False (!)

// InitializeCompo nent(); should have this line (if key preview
property set to true): this.KeyPreview = true

// for Debug. to work below (optional) set debugger windows to operate
(F5 key) and declare “using System.Diagnost ics;”

///////// set up “key down” event (lightning bolt)

private void Form1_KeyDown(o bject sender, KeyEventArgs e)
{

myGlobalKey = e.KeyCode;

if (myGlobalKey == Keys.D)
{
Debug.WriteLine ("D/d pressed");
MessageBox.Show ("D!");
} //works fine from here, for example, but also works from
OnPaint, see below
Invalidate(true ); //refresh the form immeadiately after a
key pressed
}

// for less bounce (debatable) this is an older way of getting
information from the key, use “KeyPress” event (works with char not
KeyCode). Not as easy to use most say.

private void Form1_KeyPress( object sender, KeyPressEventAr gs
e)
{
//more stable, since key down and up both req'd, but need
control to have focus
myGlobalChar = e.KeyChar; //not e.KeyCode, but returns
character
if (myGlobalChar== 'x')
{
Debug.WriteLine ("small X pressed");
MessageBox.Show ("x!"); //works fine from here
}
Invalidate(true );
}

////////// now, to show keypresses work even from OnPaint, which is
overridden onto the base PaintEventHandl er

protected override void OnPaint(PaintEv entArgs e)
{
base.OnPaint(e) ; //!!! manditory or nothing from Paint Event
handler done. Putting it at beginning rather than end of OnPaint
executes Paint event handler first rather than last (before rather
than after OnPaint). Note: Frazier p. 450 to p453 has a discussion on
OnPaint versus PaintEventHandl er base. base.OnPaint(e) will trigger
the PaintEventHandl er
if (MouseButtons == MouseButtons.Le ft)
{
Debug.WriteLine ("LMB clicked");
}
//shows you can get mouse info from inside OnPaint

if (myGlobalKey == Keys.O)
{
Debug.WriteLine ("Oh! O pressed inside paint");
MessageBox.Show ("O! from Paint");
} //works fine, but note: since OnPaint refreshes so fast, you’ll
get a dozen or so messageboxes even if you press quickly. Use escape
key to get out of them

if (myGlobalChar == 'w')
{
Debug.WriteLine ("small w pressed Paint");
MessageBox.Show ("w! from Paint"); //works fine, but you get lots
of messageboxes, as before
}

// another way of triggering keyboard using ModifierKeys

if ((ModifierKeys == Keys.Shift))
{
Debug.WriteLine ("Shift pressed");
if (Cursor.Positio n.X 50)
{ MessageBox.Show (“shift pressed and cursor 50”);}
} //shows you can get/use mouse cursor from inside OnPaint

// works fine, but I could not get documentation on how ModifierKeys
is declared, so I prefer to use Keys as above.


Aug 5 '08 #1
14 2951
On 5 août, 19:25, raylopez99 <raylope...@yah oo.comwrote:
KeyDown won't work KeyPress fails KeyDown not seen

inspired by a poster here:http://tinyurl.com/62d97lI found some
interesting stuff, which I reproduce below for newbies like me.

The main reason you would want to do this is for example to trigger
something from an OnPaint event without resorting to boolean switches--
say if a user presses the "M" key while the program is Painting, the
user gets the PaintHandler to do something else. *Arguably it's
quicker than waiting for Paint to finish, though I'm not sure of
that. *BTW I think for KeyPress the form needs to have focus, but I'm
not sure. *But KeyDown I think will work regardless of focus.

RL

public partial class Form1 : Form
* * {

* * * * Keys myGlobalKey;

* * * * char myGlobalChar; *//declare your 'global' (not really)
variables here--important!

// stuff deleted

* * * public Form1()
* * * * {

* * * * * * myGlobalKey = new Keys(); //instantiate here. *For safety
do this before InitializeCompo nent();
* * * * * * myGlobalKey2 = new Keys();
* * * * * * myGlobalChar = new char();

//stuff deleted

// *!!! IMPORTANT – make sure “key preview” property is set to true in
Form!! *Default is False (!)

// InitializeCompo nent(); should have this line (if key preview
property set to true): *this.KeyPrevie w = true

// for Debug. to work below (optional) set debugger windows to operate
(F5 key) and declare “using System.Diagnost ics;”

///////// set up “key down” event (lightning bolt)

* * * * private void Form1_KeyDown(o bject sender, KeyEventArgs e)
* * * * {

* * * * * * myGlobalKey = e.KeyCode;

* * * * * * if (myGlobalKey == Keys.D)
* * * * * * {
* * * * * * * * Debug.WriteLine ("D/d pressed");
* * * * * * * * MessageBox.Show ("D!");
* * * * * * } //works fine from here, for example, but also works from
OnPaint, see below

* * * * * * Invalidate(true ); //refresh the form immeadiatelyaft er a
key pressed
* * * * }

// for less bounce (debatable) this is an older way of getting
information from the key, use “KeyPress” event (works with char not
KeyCode). *Not as easy to use most say.

* * * * private void Form1_KeyPress( object sender, KeyPressEventAr gs
e)
* * * * {
* * * * * * //more stable, since key down and up both req'd, but need
control to have focus
* * * * * * myGlobalChar = e.KeyChar; //not e.KeyCode, but returns
character
* * * * * * if (myGlobalChar== 'x')
* * * * * * {
* * * * * * * * Debug.WriteLine ("small X pressed");
* * * * * * * * MessageBox.Show ("x!"); //works fine from here
* * * * * * }
* * * * * * Invalidate(true );
* * * * }

////////// *now, to show keypresses work even from OnPaint, which is
overridden onto the base PaintEventHandl er

protected override void OnPaint(PaintEv entArgs e)
*{

* * *base.OnPaint(e ); //!!! manditory or nothing from Paint Event
handler done. *Putting it at beginning rather than end of OnPaint
executes Paint event handler first rather than last (before rather
than after OnPaint). *Note: Frazier p. 450 to p453 has a discussion on
OnPaint versus PaintEventHandl er base. base.OnPaint(e) will trigger
the PaintEventHandl er

* if (MouseButtons == MouseButtons.Le ft)
* * {
* * * * Debug.WriteLine ("LMB clicked");
* * }
//shows you can get mouse info from inside OnPaint

* if (myGlobalKey == Keys.O)
* {
* * * Debug.WriteLine ("Oh! O pressed inside paint");
* * * MessageBox.Show ("O! from Paint");
* } //works fine, but note: *since OnPaint refreshes so fast, you’ll
get a dozen or so messageboxes even if you press quickly. *Use escape
key to get out of them

* if (myGlobalChar == 'w')
* {
* * * Debug.WriteLine ("small w pressed Paint");
* * * MessageBox.Show ("w! from Paint"); //works fine, but you get lots
of messageboxes, as before
* }

// another way of triggering keyboard using ModifierKeys

* * * *if ((ModifierKeys == Keys.Shift))
* * * *{
* * * * * *Debug.WriteLin e("Shift pressed");
* * * * * *if (Cursor.Positio n.X 50)
* * * * * *{ MessageBox.Show (“shift pressed and cursor 50”);}
* * * * } //shows you can get/use mouse cursor from inside OnPaint

// works fine, but I could not get documentation on how ModifierKeys
is declared, so I prefer to use Keys as above.
Hey Ray,

Just one thing : you shouldn't use MessageBox inside a Paint handler,
because of the problems you mention (typically, closing the MessageBox
will cause another repaint, which will cause another MessageBox to
appear, and so on). Just use "Debug.WriteLin e("blh blah");" and when
you type Ctrl-F5, make sure the "Output" window is showing (View/
Output). Pin it down if necessary. That way, all your debug messages
are shown in this window and don't interrupt the main program, or
cause stacks of alert boxes (there's nothing wrong with your program,
it's just a convenience). Thanks for the tutorial !

Michel
Aug 5 '08 #2
On Tue, 05 Aug 2008 11:38:56 -0700, <mi************ **@gmail.comwro te:
Just one thing : you shouldn't use MessageBox inside a Paint handler,
[...]
Ideally, you shouldn't do _anything_ in a Paint handler (or in OnPaint())
that is not directly related to drawing the current state of the control.

There are a few reasonable exceptions, like debug output (as you
mentioned) and calculations that don't affect the state of the control
(e.g. frame rate calculations). Doing other stuff creates a "spaghetti
design" at best, and could lead to serious bugs at the worst.

The Paint handler is for _drawing_ (or "painting" if you like :) ). It's
not a place for other things.

Pete
Aug 5 '08 #3
On Aug 5, 11:38*am, michel.desang.. .@gmail.com wrote:
On 5 août, 19:25, raylopez99 <raylope...@yah oo.comwrote:
KeyDown won't work KeyPress fails KeyDown not seen
inspired by a poster here:http://tinyurl.com/62d97lIfound some
interesting stuff, which I reproduce below for newbies like me.
The main reason you would want to do this is for example to trigger
something from an OnPaint event without resorting to boolean switches--
say if a user presses the "M" key while the program is Painting, the
user gets the PaintHandler to do something else. *Arguably it's
quicker than waiting for Paint to finish, though I'm not sure of
that. *BTW I think for KeyPress the form needs to have focus, but I'm
not sure. *But KeyDown I think will work regardless of focus.
RL
public partial class Form1 : Form
* * {
* * * * Keys myGlobalKey;
* * * * char myGlobalChar; *//declare your 'global' (not really)
variables here--important!
// stuff deleted
* * * public Form1()
* * * * {
* * * * * * myGlobalKey = new Keys(); //instantiate here.*For safety
do this before InitializeCompo nent();
* * * * * * myGlobalKey2 = new Keys();
* * * * * * myGlobalChar = new char();
//stuff deleted
// *!!! IMPORTANT – make sure “key preview” property is set to true in
Form!! *Default is False (!)
// InitializeCompo nent(); should have this line (if key preview
property set to true): *this.KeyPrevie w = true
// for Debug. to work below (optional) set debugger windows to operate
(F5 key) and declare “using System.Diagnost ics;”
///////// set up “key down” event (lightning bolt)
* * * * private void Form1_KeyDown(o bject sender, KeyEventArgs e)
* * * * {
* * * * * * myGlobalKey = e.KeyCode;
* * * * * * if (myGlobalKey == Keys.D)
* * * * * * {
* * * * * * * * Debug.WriteLine ("D/d pressed");
* * * * * * * * MessageBox.Show ("D!");
* * * * * * } //works fine from here, for example, but alsoworks from
OnPaint, see below
* * * * * * Invalidate(true ); //refresh the form immeadiately after a
key pressed
* * * * }
// for less bounce (debatable) this is an older way of getting
information from the key, use “KeyPress” event (works with char not
KeyCode). *Not as easy to use most say.
* * * * private void Form1_KeyPress( object sender, KeyPressEventAr gs
e)
* * * * {
* * * * * * //more stable, since key down and up both req'd, but need
control to have focus
* * * * * * myGlobalChar = e.KeyChar; //not e.KeyCode, but returns
character
* * * * * * if (myGlobalChar== 'x')
* * * * * * {
* * * * * * * * Debug.WriteLine ("small X pressed");
* * * * * * * * MessageBox.Show ("x!"); //works fine from here
* * * * * * }
* * * * * * Invalidate(true );
* * * * }
////////// *now, to show keypresses work even from OnPaint, which is
overridden onto the base PaintEventHandl er
protected override void OnPaint(PaintEv entArgs e)
*{
* * *base.OnPaint(e ); //!!! manditory or nothing from Paint Event
handler done. *Putting it at beginning rather than end of OnPaint
executes Paint event handler first rather than last (before rather
than after OnPaint). *Note: Frazier p. 450 to p453 has a discussion on
OnPaint versus PaintEventHandl er base. base.OnPaint(e) will trigger
the PaintEventHandl er
* if (MouseButtons == MouseButtons.Le ft)
* * {
* * * * Debug.WriteLine ("LMB clicked");
* * }
//shows you can get mouse info from inside OnPaint
* if (myGlobalKey == Keys.O)
* {
* * * Debug.WriteLine ("Oh! O pressed inside paint");
* * * MessageBox.Show ("O! from Paint");
* } //works fine, but note: *since OnPaint refreshes so fast, you’ll
get a dozen or so messageboxes even if you press quickly. *Use escape
key to get out of them
* if (myGlobalChar == 'w')
* {
* * * Debug.WriteLine ("small w pressed Paint");
* * * MessageBox.Show ("w! from Paint"); //works fine, but you getlots
of messageboxes, as before
* }
// another way of triggering keyboard using ModifierKeys
* * * *if ((ModifierKeys == Keys.Shift))
* * * *{
* * * * * *Debug.WriteLin e("Shift pressed");
* * * * * *if (Cursor.Positio n.X 50)
* * * * * *{ MessageBox.Show (“shift pressed and cursor >50”);}
* * * * } //shows you can get/use mouse cursor from inside OnPaint
// works fine, but I could not get documentation on how ModifierKeys
is declared, so I prefer to use Keys as above.

Hey Ray,

Just one thing : you shouldn't use MessageBox inside a Paint handler,
because of the problems you mention (typically, closing the MessageBox
will cause another repaint, which will cause another MessageBox to
appear, and so on). Just use "Debug.WriteLin e("blh blah");" and when
you type Ctrl-F5, make sure the "Output" window is showing (View/
Output). Pin it down if necessary. That way, all your debug messages
are shown in this window and don't interrupt the main program, or
cause stacks of alert boxes (there's nothing wrong with your program,
it's just a convenience). Thanks for the tutorial !

Michel
Thanks Michel. If you have a favorite book on C# let me know (I've
ordered a bunch, including Jon Skeet's!)

Tx Peter D., for pointing out Paint should only be for painting. I
was actually trying to show here how you don't have to use bools to
trigger events in other eventhandlers, but, looking over this code, I
notice essentially the use of 'global' (form wide, namespace wide)
variables does the same thing as a bool. So, aside from the static
member functions you pointed out, I'm at a loss on how you can
transfer 'e' across different event handlers (not inherited but
totally different), other than of course using a 'global' state-
holding class, which is what i do anyway. So I know I'm on the right
track..

RL
Aug 6 '08 #4
On Aug 6, 1:46*pm, raylopez99 <raylope...@yah oo.comwrote:
variables does the same thing as a bool. *So, aside from the static
member functions you pointed out, I'm at a loss on how you can
transfer 'e' across different event handlers (not inherited but
totally different), other than of course using a 'global' state-
holding class, which is what i do anyway. *So I know I'm on the right
track..
This way of doing things (responding to events, and storing data from
one event that might be required when handling another) is simply
inherent to the event-driven approach. Trying to avoid it serves no
point.
Aug 6 '08 #5
On 6 août, 11:46, raylopez99 <raylope...@yah oo.comwrote:
On Aug 5, 11:38*am, michel.desang.. .@gmail.com wrote:


On 5 août, 19:25, raylopez99 <raylope...@yah oo.comwrote:
KeyDown won't work KeyPress fails KeyDown not seen
inspired by a poster here:http://tinyurl.com/62d97lIfoundsome
interesting stuff, which I reproduce below for newbies like me.
The main reason you would want to do this is for example to trigger
something from an OnPaint event without resorting to boolean switches--
say if a user presses the "M" key while the program is Painting, the
user gets the PaintHandler to do something else. *Arguably it's
quicker than waiting for Paint to finish, though I'm not sure of
that. *BTW I think for KeyPress the form needs to have focus, but I'm
not sure. *But KeyDown I think will work regardless of focus.
RL
public partial class Form1 : Form
* * {
* * * * Keys myGlobalKey;
* * * * char myGlobalChar; *//declare your 'global' (not really)
variables here--important!
// stuff deleted
* * * public Form1()
* * * * {
* * * * * * myGlobalKey = new Keys(); //instantiate here. *For safety
do this before InitializeCompo nent();
* * * * * * myGlobalKey2 = new Keys();
* * * * * * myGlobalChar = new char();
//stuff deleted
// *!!! IMPORTANT – make sure “key preview” property is set to true in
Form!! *Default is False (!)
// InitializeCompo nent(); should have this line (if key preview
property set to true): *this.KeyPrevie w = true
// for Debug. to work below (optional) set debugger windows to operate
(F5 key) and declare “using System.Diagnost ics;”
///////// set up “key down” event (lightning bolt)
* * * * private void Form1_KeyDown(o bject sender, KeyEventArgs e)
* * * * {
* * * * * * myGlobalKey = e.KeyCode;
* * * * * * if (myGlobalKey == Keys.D)
* * * * * * {
* * * * * * * * Debug.WriteLine ("D/d pressed");
* * * * * * * * MessageBox.Show ("D!");
* * * * * * } //works fine from here, for example, but also works from
OnPaint, see below
* * * * * * Invalidate(true ); //refresh the form immeadiately after a
key pressed
* * * * }
// for less bounce (debatable) this is an older way of getting
information from the key, use “KeyPress” event (works with char not
KeyCode). *Not as easy to use most say.
* * * * private void Form1_KeyPress( object sender, KeyPressEventAr gs
e)
* * * * {
* * * * * * //more stable, since key down and up both req'd, but need
control to have focus
* * * * * * myGlobalChar = e.KeyChar; //not e.KeyCode, but returns
character
* * * * * * if (myGlobalChar== 'x')
* * * * * * {
* * * * * * * * Debug.WriteLine ("small X pressed");
* * * * * * * * MessageBox.Show ("x!"); //works fine from here
* * * * * * }
* * * * * * Invalidate(true );
* * * * }
////////// *now, to show keypresses work even from OnPaint, which is
overridden onto the base PaintEventHandl er
protected override void OnPaint(PaintEv entArgs e)
*{
* * *base.OnPaint(e ); //!!! manditory or nothing from Paint Event
handler done. *Putting it at beginning rather than end of OnPaint
executes Paint event handler first rather than last (before rather
than after OnPaint). *Note: Frazier p. 450 to p453 has a discussionon
OnPaint versus PaintEventHandl er base. base.OnPaint(e) will trigger
the PaintEventHandl er
* if (MouseButtons == MouseButtons.Le ft)
* * {
* * * * Debug.WriteLine ("LMB clicked");
* * }
//shows you can get mouse info from inside OnPaint
* if (myGlobalKey == Keys.O)
* {
* * * Debug.WriteLine ("Oh! O pressed inside paint");
* * * MessageBox.Show ("O! from Paint");
* } //works fine, but note: *since OnPaint refreshes so fast, you’ll
get a dozen or so messageboxes even if you press quickly. *Use escape
key to get out of them
* if (myGlobalChar == 'w')
* {
* * * Debug.WriteLine ("small w pressed Paint");
* * * MessageBox.Show ("w! from Paint"); //works fine, but you get lots
of messageboxes, as before
* }
// another way of triggering keyboard using ModifierKeys
* * * *if ((ModifierKeys == Keys.Shift))
* * * *{
* * * * * *Debug.WriteLin e("Shift pressed");
* * * * * *if (Cursor.Positio n.X 50)
* * * * * *{ MessageBox.Show (“shift pressed and cursor50”);}
* * * * } //shows you can get/use mouse cursor from inside OnPaint
// works fine, but I could not get documentation on how ModifierKeys
is declared, so I prefer to use Keys as above.
Hey Ray,
Just one thing : you shouldn't use MessageBox inside a Paint handler,
because of the problems you mention (typically, closing the MessageBox
will cause another repaint, which will cause another MessageBox to
appear, and so on). Just use "Debug.WriteLin e("blh blah");" and when
you type Ctrl-F5, make sure the "Output" window is showing (View/
Output). Pin it down if necessary. That way, all your debug messages
are shown in this window and don't interrupt the main program, or
cause stacks of alert boxes (there's nothing wrong with your program,
it's just a convenience). Thanks for the tutorial !
Michel

Thanks Michel. *If you have a favorite book on C# let me know (I've
ordered a bunch, including Jon Skeet's!)

Tx Peter D., for pointing out Paint should only be for painting. *I
was actually trying to show here how you don't have to use bools to
trigger events in other eventhandlers, but, looking over this code, I
notice essentially the use of 'global' (form wide, namespace wide)
variables does the same thing as a bool. *So, aside from the static
member functions you pointed out, I'm at a loss on how you can
transfer 'e' across different event handlers (not inherited but
totally different), other than of course using a 'global' state-
holding class, which is what i do anyway. *So I know I'm on the right
track..

RL- Masquer le texte des messages précédents -

- Afficher le texte des messages précédents -
Well, Jon Skeet's is pretty much my favorite at the moment, so you
should be all set ! It's both full of info AND very well-written. I
don't know the guy, have never talked to him, even though we have
occasionally participated in the same threads, so it's not a shameless
plug ! (it's called "C# in depth", for those who don't know it yet :
http://csharpindepth.com).

About the transfering of e, the only place where you're still using a
global variable is for checking out which key is pressed (other than
the control keys). There are several solutions to this : the first
obvious one would be to use a keyboard hook into the window's message
pump, but that's a lot of boilerplate code, and it doesn't satisfy
your condition for avoiding globals altogether.

The second one would be to use the GetAsyncKeyStat e function, which is
in user32.dll. To use it, add at the top of your class (just below
"public partial class Form1 : Form") :

[DllImport("User 32.dll")]
private static extern short GetAsyncKeyStat e(short key);

Then, anywhere in your code, you can check whether a key is pressed by
doing the following test :

if (GetAsyncKeySta te((short)Keys. A) < 0)
{
// the letter A is currently pressed, do something with it
}

It even works for Keys.Insert and other non-ASCII keys. If the result
is < 0, the key is pressed, if it's >= 0, the key isn't pressed.

Be aware that it's asynchronous, which implies that it returns the
state of the keys at the moment you're testing it, and not the moment
some other event happened (for instance, if you put such a test inside
an event handler for a mouse click, it won't tell you whether the key
was pressed when the click happened, but when the test was evaluated
(yeah, in this case, you'd have to be pretty fast to have different
results, I just wanted to be thorough :)).

The third solution to avoid globals... Ok, I'm going to use a trick
there... is to use globals. But of a different nature. Let's say that
you want to detect whether the "C" key is pressed because then you
want to draw a circle in your paint event. Instead of having a
KeyState class, you could have, say, an ActionQueue class, and queue
inside the requested actions. Inside the onPaint, you would for
instance check :

if (Actions.Count 0)
{
Action action = Actions.Dequeue (); // I'm not writing the generics
details here to simplify, this is just pseudo-code
if (action == ActionsEnum.Cir cle)
{
DrawCircle();
}
else if (action == ActionsEnum.Era se)
{
ErasePicture();
}
// ...
}

The advantages of this technique are long-term ones : it will simplify
Undo implementation, and possibly the serialization of your actions.
Also, you've transformed arbitrary commands (Keys.C) into meaningful
ones (Actions.Circle , for instance), which will be much easier when
you go back on your code months later (or someone else).

It's much more work, but in the end, I think it's worth it. Also, you
get rid of reading the key state in real-time (just implement the
onKeyPress or onKeyDown event handlers and insert the corresponding
actions in your queue there). You have decoupled the keyboard handling
from the drawing, and in terms of OOP, that's always a Good Thing. :)

But I think that as soon as your program is going to grow, you'll have
to resort to state classes/variables anyway (to store the state of a
tool, for example, or remember settings between sessions). So the
transfering of "e" won' t be such a problem anymore (unless you're
aiming for a time-critical stateless app, in which case solution 2
above should work).

Maybe you would be interested in learning about "finite state
machines", which is a way of programming that has some similarities to
this problem. I cannot tell you more about it because I haven't delved
into it yet, but there is considerable litterature about it all around
and what I read so far was quite interesting (though rather arduous).

Hope this helps !

Michel
Aug 6 '08 #6
On Aug 6, 3:47*am, Pavel Minaev <int...@gmail.c omwrote:
This way of doing things (responding to events, and storing data from
one event that might be required when handling another) is simply
inherent to the event-driven approach. Trying to avoid it serves no
point.
Good, then I'm on the right track, like I said.

RL

Aug 6 '08 #7
On Aug 6, 4:10*am, michel.desang.. .@gmail.com wrote:
>
Well, Jon Skeet's is pretty much my favorite at the moment, so you
should be all set ! It's both full of info AND very well-written. I
don't know the guy, have never talked to him, even though we have
occasionally participated in the same threads, so it's not a shameless
plug ! (it's called "C# in depth", for those who don't know it yet :http://csharpindepth.com).
Yeah Jon's the poor man's Scott Meyers, who wrote some books on C++ in
the late 1990s that got a lot of press ("effective c++"). I read
through some of them, and they were full of good stuff. Mostly, if I
recall correctly, garbage collection was a big problem back then, and
we all know how C# "solved" that problem (is the cure worse than the
disease though?)

About the transfering of e, the only place where you're still using a
global variable is for checking out which key is pressed (other than
the control keys).
There are several solutions to this :
Why would you want a solution? After reading through this thread, I
think from an OOP point of view you should not be designing around
this "problem"/
the first
obvious one would be to use a keyboard hook into the window's message
pump, but that's a lot of boilerplate code, and it doesn't satisfy
your condition for avoiding globals altogether.
Right. I don't want to learn MFC again (I didn't know it all that
well the first time, though I did write some useful programs in C++).
>
The second one would be to use the GetAsyncKeyStat e function, which is
in user32.dll. To use it, add at the top of your class (just below
"public partial class Form1 : Form") :
No way, too complicated.

Be aware that it's asynchronous, which implies that it returns the
state of the keys at the moment you're testing it, and not the moment
some other event happened (for instance, if you put such a test inside
an event handler for a mouse click, it won't tell you whether the key
was pressed when the click happened, but when the test was evaluated
(yeah, in this case, you'd have to be pretty fast to have different
results, I just wanted to be thorough :)).
Well, if it's asynchronous, it might be a good idea for multi-threaded
programs, which is something I have to study at some point, but even
with multi-threaded programs (writing programs to run on multi-core
machines), keeping your event handler events seperate should allow for
multithreading I would imagine.
>
The third solution to avoid globals... Ok, I'm going to use a trick
there... is to use globals.
OK, I got that. That's what I do now--store state information in a
class and pass the class around, between event handlers or between
main forms and sub-forms, etc.
But of a different nature. Let's say that
you want to detect whether the "C" key is pressed because then you
want to draw a circle in your paint event. Instead of having a
KeyState class, you could have, say, an ActionQueue class, and queue
inside the requested actions. Inside the onPaint, you would for
instance check :

if (Actions.Count 0)
{
* Action action = Actions.Dequeue (); // I'm not writing the generics
details here to simplify, this is just pseudo-code
* if (action == ActionsEnum.Cir cle)
Action. I don't know Action. Jon Skeet has a big thing about Action--
in fact, the first page I turned to in his book that I just got today
was on Action! LOL! I'll have to study Action then.
>
The advantages of this technique are long-term ones : it will simplify
Undo implementation, and possibly the serialization of your actions.
Also, you've transformed arbitrary commands (Keys.C) into meaningful
ones (Actions.Circle , for instance), which will be much easier when
you go back on your code months later (or someone else).
I don't get it, but please don't explain, you're wasting your time.
I'm too new. I think you're saying that with "Undo" you have to take
a "snapshot" of the state of the machine at any time, and using your
"global" scheme involving "Action" you can take that "snapshot" easier
than using state variables that are being passed around. OK, if
that's the point, but it's a big over my head now. Anyway I think
they have a macro / method for "Undo" in C#, an [attribute] like
[serialization], and you can pretty much serialize anything (except
hash numbers it turns out). I'll get to it in a month or two.
>
It's much more work, but in the end, I think it's worth it. Also, you
get rid of reading the key state in real-time (just implement the
onKeyPress or onKeyDown event handlers and insert the corresponding
actions in your queue there). You have decoupled the keyboard handling
from the drawing, and in terms of OOP, that's always a Good Thing. :)
Decoupling is good. Tightly coupled versus loosely coupled--the debate
continues! I don't know what they are talking about...
>
But I think that as soon as your program is going to grow, you'll have
to resort to state classes/variables anyway (to store the state of a
tool, for example, or remember settings between sessions). So the
transfering of "e" won' t be such a problem anymore (unless you're
aiming for a time-critical stateless app, in which case solution 2
above should work).
Yes, agreed. I don't really care about transferring 'e' anymore, it
was just an academic question.
>
Maybe you would be interested in learning about "finite state
machines", which is a way of programming that has some similarities to
this problem. I cannot tell you more about it because I haven't delved
into it yet, but there is considerable litterature about it all around
and what I read so far was quite interesting (though rather arduous).
I thought Alan Turning said every PC is a FSM, no? And the famous
"HALT" problem, an infinite loop, 0.99999.... Something like that.
>
Hope this helps !

Michel
No it doesn't! But don't worry about it, half the stuff you did make
sense to me was quite helpful! :-)

RL

Aug 6 '08 #8
On 6 août, 17:52, raylopez99 <raylope...@yah oo.comwrote:
On Aug 6, 4:10*am, michel.desang.. .@gmail.com wrote:
Well, Jon Skeet's is pretty much my favorite at the moment, so you
should be all set ! It's both full of info AND very well-written. I
don't know the guy, have never talked to him, even though we have
occasionally participated in the same threads, so it's not a shameless
plug ! (it's called "C# in depth", for those who don't know it yet :http://csharpindepth.com).

Yeah Jon's the poor man's Scott Meyers, who wrote some books on C++ in
the late 1990s that got a lot of press ("effective c++"). *I read
through some of them, and they were full of good stuff. *Mostly, if I
recall correctly, garbage collection was a big problem back then, and
we all know how C# "solved" that problem (is the cure worse than the
disease though?)
About the transfering of e, the only place where you're still using a
global variable is for checking out which key is pressed (other than
the control keys).
There are several solutions to this :

Why would you want a solution? *After reading through this thread, I
think from an OOP point of view you should not be designing around
this "problem"/
the first
obvious one would be to use a keyboard hook into the window's message
pump, but that's a lot of boilerplate code, and it doesn't satisfy
your condition for avoiding globals altogether.

Right. *I don't want to learn MFC again (I didn't know it all that
well the first time, though I did write some useful programs in C++).
The second one would be to use the GetAsyncKeyStat e function, which is
in user32.dll. To use it, add at the top of your class (just below
"public partial class Form1 : Form") :

No way, too complicated.
Be aware that it's asynchronous, which implies that it returns the
state of the keys at the moment you're testing it, and not the moment
some other event happened (for instance, if you put such a test inside
an event handler for a mouse click, it won't tell you whether the key
was pressed when the click happened, but when the test was evaluated
(yeah, in this case, you'd have to be pretty fast to have different
results, I just wanted to be thorough :)).

Well, if it's asynchronous, it might be a good idea for multi-threaded
programs, which is something I have to study at some point, but even
with multi-threaded programs (writing programs to run on multi-core
machines), keeping your event handler events seperate should allow for
multithreading I would imagine.
The third solution to avoid globals... Ok, I'm going to use a trick
there... is to use globals.

OK, I got that. *That's what I do now--store state information in a
class and pass the class around, between event handlers or between
main forms and sub-forms, etc.
But of a different nature. Let's say that
you want to detect whether the "C" key is pressed because then you
want to draw a circle in your paint event. Instead of having a
KeyState class, you could have, say, an ActionQueue class, and queue
inside the requested actions. Inside the onPaint, you would for
instance check :
if (Actions.Count 0)
{
* Action action = Actions.Dequeue (); // I'm not writing the generics
details here to simplify, this is just pseudo-code
* if (action == ActionsEnum.Cir cle)

Action. *I don't know Action. *Jon Skeet has a big thing about Action--
in fact, the first page I turned to in his book that I just got today
was on Action! LOL! *I'll have to study Action then.
The advantages of this technique are long-term ones : it will simplify
Undo implementation, and possibly the serialization of your actions.
Also, you've transformed arbitrary commands (Keys.C) into meaningful
ones (Actions.Circle , for instance), which will be much easier when
you go back on your code months later (or someone else).

I don't get it, but please don't explain, you're wasting your time.
I'm too new. *I think you're saying that with "Undo" you have to take
a "snapshot" of the state of the machine at any time, and using your
"global" scheme involving "Action" you can take that "snapshot" easier
than using state variables that are being passed around. *OK, if
that's the point, but it's a big over my head now. *Anyway I think
they have a macro / method for "Undo" in C#, an [attribute] like
[serialization], and you can pretty much serialize anything (except
hash numbers it turns out). *I'll get to it in a month or two.
It's much more work, but in the end, I think it's worth it. Also, you
get rid of reading the key state in real-time (just implement the
onKeyPress or onKeyDown event handlers and insert the corresponding
actions in your queue there). You have decoupled the keyboard handling
from the drawing, and in terms of OOP, that's always a Good Thing. :)

Decoupling is good. Tightly coupled versus loosely coupled--the debate
continues! *I don't know what they are talking about...
But I think that as soon as your program is going to grow, you'll have
to resort to state classes/variables anyway (to store the state of a
tool, for example, or remember settings between sessions). So the
transfering of "e" won' t be such a problem anymore (unless you're
aiming for a time-critical stateless app, in which case solution 2
above should work).

Yes, agreed. *I don't really care about transferring 'e' anymore, it
was just an academic question.
Maybe you would be interested in learning about "finite state
machines", which is a way of programming that has some similarities to
this problem. I cannot tell you more about it because I haven't delved
into it yet, but there is considerable litterature about it all around
and what I read so far was quite interesting (though rather arduous).

I thought Alan Turning said every PC is a FSM, no? *And the famous
"HALT" problem, an infinite loop, 0.99999.... Something like that.
Hope this helps !
Michel

No it doesn't! *But don't worry about it, half the stuff you did make
sense to me was quite helpful! :-)

RL
That was the whole point. I know the question was purely academic, and
I submitted the first two solutions two demonstrate why, in the end,
you inevitably would have to fall back on state-keeping.

Just one thing about the Action I was talking about : it was just
meant as an example and I wasn't refering to the Action Jon's talking
about, which is part of the framework. Rewrite that as "PaintActio n"
or "UserAction " or anything that's not used in the frameword. Bad
choice of words !

Anyway, you seem to be having fun with all that and that's all that
matters !

Michel
Aug 6 '08 #9
On Aug 6, 10:54*am, michel.desang.. .@gmail.com wrote:
>
That was the whole point. I know the question was purely academic, and
I submitted the first two solutions two demonstrate why, in the end,
you inevitably would have to fall back on state-keeping.
Ah, now I see. :-)
>
Just one thing about the Action I was talking about : it was just
meant as an example and I wasn't refering to the Action Jon's talking
about, which is part of the framework. Rewrite that as "PaintActio n"
or "UserAction " or anything that's not used in the frameword. Bad
choice of words !
OK. Jon BTW was featured in the MSDN today when my front page news
reader loaded up--LOL, a local celebrity who'se almost famous--with
his book review of a fellow called Nash, "Accelerate d C#". Jon was
very kind to the author in his review, probably because he wants to
work with him in a future book (reading between the lines), though it
seemed the book was a bit esoteric and obtuse for most programmers
like me (the target audience? perhaps like in chess, where the target
audience is always kids, tyros, and people who want to memorize
openings rather than advanced players, because the advanced players
usually don't read chess books, certainly not annotated moves in
books, they just review games played by strong players). Most computer
science books, like chess books, are poorly written I've found--I buy
a half dozen every year and throw out half of them, but I write it off
as a business expense.
>
Anyway, you seem to be having fun with all that and that's all that
matters !
Yes, coding is addictive I find. I'm starting to get into it now,
full swing. Layout is very important I'm finding--user layout so it
looks familiar, because with the Wizard you can do all kinds of crazy
stuff with controls that quickly becomes visual clutter...but I just
love the drag-and-drop stuff for menus and controls, even the timer,
trees, and dialog boxes...great stuff.

RL
Aug 6 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
5766
by: Seash | last post by:
Hi friends , here is the sample code private void txtbox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if(e.KeyChar == 13) //enter { txtbox2.Focus(); }
5
20279
by: Vin | last post by:
Hi, I am using the following code to draw whatever the user draws using x,y. // draws lines directly on a winform. CreateGraphics().DrawLine(APen, x, y, OldX, OldY); Now how do I save the drawing on to a bmp file on my harddisk? C# code in this regard would be very helpful. I tried all forums but invain.
3
9210
by: bardo | last post by:
I have a Datagrid that is inside a panel. I want to use the keyDown event to reconize the arrow keys. But I have no luck at all. The problem is that the keydown event won't fire at all, unless I click on a row (withs will turn blue then) and then click on it again . Now if I press any key the event will fire (except for the arrow keys). I...
20
2559
by: BB | last post by:
Hello all, I am trying to override OnPaint in a custom textbox control (so I can drawstring a caption, etc.). In the code below, I get the "painting the form" message as expected, but not the "painting the control". It also has no effect to explicitly call txtTest.Invalidate or txtTest.Refresh. Am I missing something simple here? Any...
3
10316
by: Colin McGuire | last post by:
Hi there. I have written a small procedure to draw various shapes on things. A bit of it is shown below. Private Sub drawShape(ByVal shapeType As Integer, ByRef g As Graphics) Select Case shapeType Case 1 : g.DrawRectangle(New Pen(Color.Black), 0, 0, 50, 10) Case 2 'draw a circle Case 3 'draw a triangle Case 4 'draw other shape Case 5...
4
1965
by: dominique | last post by:
Hi, In windows forms (vb.net), i use my own controls subclassed from base controls and i override the Onxxx methods. for example: Public Class MyBouton Inherits System.Windows.Forms.Button .. Protected Overrides Sub OnPaint(ByVal pe As
2
7244
by: Will Gillen | last post by:
I am building a hoem theatre app that is controlled by an IR Remote Control. The Remote has some keys that map to "keyboard" commands (i.e. PageUp, PageDown.). In this VB.NET application I have a listbox control that I fill with songs from the MediaPlayer Library (MediaCollection). Now, my remote does not have "Tab" key or "up" and "down"...
3
2569
by: Sam | last post by:
Hello, I'm currently creating a GUI, which consists of a main frame that contains a menu bar,a toolbar and an empty panel, let's call it main_panel. Ideally, I'd like the following functionality: upon choosing an item from the menu bar, a particular graph will be displayed inside main_panel. Now I've taken a look at the...
2
1626
by: mart_nl | last post by:
Dear group, I am trying to move a panel (panel2) around which is inside another panel (panel1). I want the user to be able to use the arrow keys on the keyboard. However when I press either arrow key, focus is set to my toolbar (toolbar1) and you see focus going from pushbutton to pushbutton. I've tried keydown events on mybase,...
0
8149
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8304
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7899
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8175
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6553
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5674
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3805
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
2301
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
1138
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.