Using visual studio 2015 I use a picture box as a player and have it move up, down, left and right. When the picture box moves it shrinks and then looks like it teleports. That is not what it is supposed to do. How do I properly get the picture box to change whenever I press the wasd keys?
if (e.KeyCode == Keys.D)
{
x += 6;
playerBox.Image = Properties.Resources.playerRight;
}
//moves player right and changes the image
Just add to / subtract, the picturebox Top and Left:
if (e.KeyCode == Keys.D)
{
playerBox.Left += 6;
playerBox.Image = Properties.Resources.playerRight;
}
also to avoid changing photo everytime if the direction has not changed you may do something like this:
if (e.KeyCode == Keys.D)
{
playerBox.Left += 6;
if((Keys)playerBox.Tag!=e.KeyCode)
playerBox.Image = Properties.Resources.playerRight;
}
You must of course set some inital value for playerBox.Tag or you will get an error as it cant be cast to Keys
I need some really accurate way to determine when surface dial rotation end:
private void OnRotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
double angle = args.RotationDeltaInDegrees;
}
I stay really lost about how can determine in ultra accurate way when rotation end.
This is my first try but work super erratic.
bool start = true;
private void OnRotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
if (start == true)
{
start = false;
//send mouse left down event relative to mouse position
VirtualMouse.LeftDown(0, 0);
}
if (timer != null)
{
timer.Tick -= timer_Tick;
}
timer = new DispatcherTimer { Interval = TimeSpan.FromMillisecond(10) };
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
if (args.RotationDeltaInDegrees > 0)
{
//move mouse 1 pixel + Y relative to mouse postion
VirtualMouse.Move(0, 1);
}
else
{
//move mouse 1 pixel - Y relative to mouse postion
VirtualMouse.LeftDown(0, -1);
}
}
void timer_Tick(object sender, EventArgs e)
{
start = true;
//release the left mouse down relative to mouse position
VirtualMouse.LeftUp(0, 0);
}
When I said accurate, I mean some way to detect in any scenario.
Example, if you rotate slow and timer is around 1ms, every new event from dial (rotated slow) never reach the unhook in time. If I increase the timer all the whole detection result in a non accurate process adding non desired latency.
I know this not is the way to go, just testing, but not idea how can achieve a proper detection in scenarios when I rotate the dial slow, or faster for obtain a real indicator the dial stop of rotate or is rotating.
Determine when rotation start is a cake, but rotarion end?
Surface dial can provide precision of 0.1 degres, is really accurate optical device. So one complete rotation is capable of provide 3600 events/angles report.
......dont know, thinking and thinking.
The code:
private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
if (leave == true)
{
timer1.Interval = 10;
}
}
I want to do that if i turn the mouse wheel to my side down it will slow the timer will increase the interval and if i turn the wheel up it will decrease the interval.
How can i do it ?
Use MouseEventArgs.Delta property
The mouse wheel combines the features of a wheel and a mouse button.
The wheel has discrete, evenly spaced notches. When you rotate the
wheel, a wheel message is sent as each notch is encountered. One wheel
notch, a detent, is defined by the windows constant WHEEL_DELTA, which
is 120. A positive value indicates that the wheel was rotated
forward (away from the user); a negative value indicates that the
wheel was rotated backward (toward the user).
private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta > 0) //moved forward
{
timer1.Interval += 1000;
}
else //moved backword
{
timer1.Interval -= 1000;
}
}
MouseEventArgs.Delta Checks how much the mouse has been moved. If delta is positive increase speed, if delta is negative decrease speed.
The link (http://msdn.microsoft.com/en-us/library/system.windows.forms.mouseeventargs.delta.aspx) shows how to use delta using C#
Mousewheel
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.mousewheel.aspx
I am doing a simple C# program of the game Knights Tour in C# the hard way to learn all I can of C#. I have a board and a knight piece and the knight is a custom panel with the picture of the knight.
What I am attempting to do is allow the user to click and drag the knight piece control during run time (exactly the way you can move the control in design time to place it), but for whatever reason I have getting some very undesired results.
private void KTmain_Load(object sender, EventArgs e)
{
boolKnightmoves = false;
}
private void kpcKnight_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
boolKnightmoves = true;
intCurMouseX = e.X;
intCurMouseY = e.Y;
break;
case MouseButtons.Right:
case MouseButtons.Middle:
case MouseButtons.XButton1:
case MouseButtons.XButton2:
case MouseButtons.None:
default:
boolKnightmoves = false;
break;
}
}
private void kpcKnight_MouseUp(object sender, MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
boolKnightmoves = false;
break;
case MouseButtons.Right:
case MouseButtons.Middle:
case MouseButtons.XButton1:
case MouseButtons.XButton2:
case MouseButtons.None:
default:
boolKnightmoves = false;
break;
}
}
private void kpcKnight_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (boolKnightmoves)
{
txtTest.Text = e.X + ", " + e.Y;
txtTest.Text += Environment.NewLine + kpcKnight.Location;
int i = e.X == intCurMouseX ? 0 : e.X > intCurMouseX ? 1 : -1;
int j = e.Y == intCurMouseY ? 0 : e.Y > intCurMouseY ? 1 : -1;
txtTest.Text += Environment.NewLine + i.ToString() + ", " + j.ToString();
kpcKnight.Location = new Point(
kpcKnight.Location.X + i,
kpcKnight.Location.Y + j);//e.Y == intCurMouseY ? 0 : e.Y > intCurMouseY ? 1 : -1);
//e.X == intCurMouseX ? 0 : e.X > intCurMouseX ? 1 : -1,
intCurMouseX = e.X;
intCurMouseY = e.Y;
}
}
private void kpcKnight_MouseLeave(object sender, EventArgs e)
{
boolKnightmoves = false;
}
private void kpcKnight_LocationChanged(object sender, EventArgs e)
{
kpcKnight.Refresh();
}
I see no real reason why this code would not do the same thing, but I am obviously missing something. When I click on the knight and move it, it does not move at the same speed as the mouse, it moves much slower. It also fades while moving it where you cant see it.
How do i make the knight piece move the same way it does in the form designer in a way that makes sense moving a chess piece across a chess board?
Any assistance will be appreciated.
I updated the code a bit and it does seem to help, but the animation aspect of it is still quite choppy and the panel picks up a bit of the background as it moves and placed.
how does it do it in the form designer so smoothly?
private void kpcKnight_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (boolKnightmoves)
{
txtTest.Text = e.X + ", " + e.Y;
txtTest.Text += Environment.NewLine + kpcKnight.Location;
int x = kpcKnight.Location.X + e.X - intCurMouseX;
int y = kpcKnight.Location.Y + e.Y - intCurMouseY;
kpcKnight.Location = new Point(x, y);
kpcKnight.Refresh();
/*
int i = e.X == intCurMouseX ? 0 : e.X > intCurMouseX ? 1 : -1;
int j = e.Y == intCurMouseY ? 0 : e.Y > intCurMouseY ? 1 : -1;
txtTest.Text += Environment.NewLine + i.ToString() + ", " + j.ToString();
kpcKnight.Location = new Point(
kpcKnight.Location.X + i,
kpcKnight.Location.Y + j);//e.Y == intCurMouseY ? 0 : e.Y > intCurMouseY ? 1 : -1);
//e.X == intCurMouseX ? 0 : e.X > intCurMouseX ? 1 : -1,
intCurMouseX = e.X;
intCurMouseY = e.Y;*/
}
}
Why don't you just set the Knights position the same as the mouse position in the Mouse_Move method?
Something like:
kpcKnight.Location = new Point(e.X, e.Y)
Obviously you can make it move nicer by knowing where the Knight got initially clicked and move smoothly according to that delta without having the initial jitter.
It's drawing so slowly because you're moving a panel with every mouse motion. That means the form needs to redraw itself several times, and a complete form redraw is expensive.
The basic solution is - don't change the panel's position that often.
I see two ways of doing it.
The first way is simple, but may look jerky. Don't draw every mouse movement. Draw every 5th one, or some arbitrary number you set. Basically keep a counter that you set to 0 on mouse down, and every time you get a mouse move, check if ++counter % n == 0. If so, do the actual drawing. Just make sure to draw on mouse up, as well. Or, just as effectively, only draw when one mouse movement is a certain number of points in x or y away from the previous position.
The second idea is more complicated, but should be the fastest, least jerky thing you can do. Don't move the panel at all while the mouse is moving. Instead, make the panel disappear, and set the cursor to a custom cursor showing the knight. On mouse up, reset the cursor, move the panel and make it visible. This should be about as fast as you can get.
Edit
I'm going to go into the realm of metaphor here, just to get a few things across. Animation is an aspect of C#, but it's not one of the features of it. (i.e., you can accomplish it, but it doesn't have much to make these things easy on you, and it's not a simple key feature.) So... metaphor.
Think of the controls you've placed on your screen to make your board and knight as a bunch of cars packed tight into a parking lot. All you're doing is looking at the parking lot from a helicopter high up. What you're telling the runtime to do, every time you move a component, is completely bulldoze the cars off the parking lot, then place them with a crane in new positions. That's the scope that I'm talking about when I say "a complete form redraw is expensive."
Instead, what you want to do from your helicopter is percieve that the cars are magically changing position. Rather than have a bulldozer and a crane, just blank out your helicopter view, take a snapshot of what you want to see, and change the snapshot little by little, until it looks the way you want. That's what the second suggestion is - don't consantly force the form to recalculate each component's look. Instead, put the animation above the form, and only change the form when you're done.
The keywords you want to search for are "gdi+" (the .NET graphics package), and animation. MouseMove wouldn't hurt, and Paint is the event where you may need to do the animations. There are plenty of places you can find, though How to draw rectangle on MouseDown/Move c# could be a good start.
Edit #2
One last suggestion I have. You can use this in addition to any animation you make. Functionally, it satisfies your requirements on its own, but it's probably not what you're looking for. Track the mouse, and modify the background image of whatever panel the mouse is hovering over. In that case, you'll want to be looking at ImageList, and simple properties like your control BackgroundImage. This could be nice even if you do have a better animation working. You can easily use this to show "the knight can't move here" or "the knight has already moved here." Since it's changing your component instead of moving your component, it's really inexpensive to do, and can easily keep up with your mouse movement. It may be sufficient to imply the movement you want, and it will teach you aspects of winforms that are more important and frequently used than animation and GDI+ rendering.
All you need is:
private int intCurMouseX, intCurMouseY;
private void kpcKnight_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
intCurMouseX = e.X;
intCurMouseY = e.Y;
}
}
private void kpcKnight_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
kpcKnight.Location = new Point(
kpcKnight.Location.X + (e.X - intCurMouseX),
kpcKnight.Location.Y + (e.Y - intCurMouseY));
}
}
Transparency in .Net is a bit of a misnomer. The background simply becomes the color of the parent container. When your controls overlap with each, as will likely be the case when the pieces are dragged across the board, then you'll see the "background" of the piece because controls are rectangular. One option would be to actually CLIP the PictureBox so it is an irregular shape. This can be accomplished by creating a Region() from a GraphicsPath() and then assigning that to the Region() property of the PictureBox. A simplistic approach is to use whatever color is in the top left of the Image and use that as the "mask" color. Next walk the entire image and only add locations where pixels are not the mask color to the GraphicsPath(). This only needs to be done once with the PictureBox after the Image() has been assigned. Again, this approach requires that the "background" of your image (the parts you do NOT want to keep) are all the same color, AND also that this color is not present anywhere as part of the image you want to keep. Here's an example:
private void Form1_Load(object sender, EventArgs e)
{
// perform this for all your PictureBox pieces:
this.ClipPictureBoxPiece(this.kpcKnight);
// ...
// ...
}
private void ClipPictureBoxPiece(PictureBox pb)
{
if (pb != null && pb.Image != null)
{
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
using (Bitmap bmp = new Bitmap(pb.Image))
{
Color mask = bmp.GetPixel(0, 0);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
if (!bmp.GetPixel(x, y).Equals(mask))
{
gp.AddRectangle(new Rectangle(x, y, 1, 1));
}
}
}
}
pb.Region = new Region(gp);
}
}
I've just made some simple code to track the mouse offset from where Mouse Down to its current position on Mouse Move within a PictureBox. I'm outputting the difference to a label and it works fine.
So say I mousedown at X: 20 Y: 20 then move mouse left by 5. My result is X: 15 Y:20.
Now the issue is when I take these results (diffX and diffY) and add them to an integer (testOne and testTwo). The result is exponentially different.
Most relevant is that when I keep the mouse in the same position without moving it but just holding the button. The results continue to increase.
I have reduced my problem to the following code:
Point startPoint = new Point();
bool dragging = false;
int testOne = 30;
int testTwo = 30;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
int diffX = (pictureBox1.PointToClient(e.Location).X - startPoint.X);
int diffY = (pictureBox1.PointToClient(e.Location).Y - startPoint.Y);
label9.Text = diffX.ToString(); //Works, shows desired result
label10.Text = diffY.ToString(); //also works fine
testOne = (testOne + diffX); //Issue here
testTwo = (testTwo + diffY); //and here
label11.Text = (testOne).ToString(); //Unexpected results output
label12.Text = (testTwo).ToString();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (!dragging) //Incase the mouse down was repeating, it's not
{
startPoint = pictureBox1.PointToClient(e.Location);
dragging = true;
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (dragging)
dragging = false;
}
I'm using C# WinForms in VS 2008, Framework 3.5
any insight would be great, maybe this is a bug or I've simply overlooked something simple. Any ideas or if you can re-produce.
Cheers
Craig
It looks as though you are subtracting the current point from the start point, not the last point. Set startPoint to the current point at the end of your mousemove function.
startPoint = pictureBox1.PointToClient(e.Location);
Whe you don't move mouse you should not be getting MouseMove events... Also clicking mouse button will send you MouseMove. In genral MouseMove is send whenever it seems practical and you should be ready to handle 0 movements too.
The value of testOne and testTwo measures "Sum of all mouse movements" which will grow as long as mouse offset (diffX/Y) is positive (essentially it is integral of mose movements). What your expectations for this values?