I want the ToolTip to follow my mouse moving over one control. For example, let's take a panel. When mouse location is inside the Rectangle(100, 100, 50, 50) I want ToolTip to be visible and always on the right down of the mouse. When it's outside this rectangle, I want ToolTip to be invisible.
I tried to do this like that:
ToolTip toolTip = new ToolTip();
int x, y;
protected override void OnMouseMove(MouseEventArgs e)
{
if ((x == e.X) && (y == e.Y) && (new Rectangle(100, 100, 50, 50).Contains(e.Location))
toolTip.Show("some text", this, x + 10, y + 10);
else
{
x = e.X;
y = e.Y;
toolTip.Hide(this);
}
}
But there's a problem - when my toolTip shows up - it gets the focus and after that OnMouseMove(MouseEventArgs e) doesn't work any more. I tried to get the focus to the panel in the end of that function, but it doesn't work. I also tried some tricks with OnMouseHover, but it was the same effect.
Don't use a ToolTip for that - if the Panel is drawn on, draw your own ToolTip; otherwise, use a Panel and respond to MouseMove events from both, but ignore e.Location and instead use System.Windows.Forms.Cursor.Position and PointToClient.
Related
I created a WPF Popup Control on my WPF Form.When I click,the Popup Opens and it also moves properly. but when I Clicked on textbox in popup window then popup moves slightly towards the edge of main window. I don't want to move popup when I clicked on textbox in Popup?
private void MyAddJobPopup_MouseMove(object sender,System.Windows.Input.MouseEventArgs e) {
if (!MyAddJobPopup.IsOpen)
MyAddJobPopup.IsOpen = true;
if (e.LeftButton == MouseButtonState.Pressed) {
var mousePosition = e.GetPosition(this.HardwareElectricalTbl);
this.MyAddJobPopup.HorizontalOffset = mousePosition.X;
this.MyAddJobPopup.VerticalOffset = mousePosition.Y;
}
}
When setting the HorizontalOffset and VerticalOffset they use the top left location of the window, which is not the location you want to set it to, you want to set it to the mouse position minus the mouses previous relative position to the window.
To do this save the following locations when you start clicking (for example inside of an onClick event):
//both should be negative so adding will actually remove from the location which is what you want
float offsetX = this.MyAddJobPopup.HorizontalOffset - mousePosition.X;
float offsetY = this.MyAddJobPopup.VerticalOffset- mousePosition.Y;
then when you set the location add them:
this.MyAddJobPopup.HorizontalOffset = mousePosition.X + offsetX;
this.MyAddJobPopup.VerticalOffset = mousePosition.Y + offsetY;
I'm using this function to move the cursor.
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
When I use a hotkey to trigger it, the cursor will move to the correct coords and next time I move the mouse it continues from that position. Working as intended.
However I need to trigger SetCursorPos during a MouseMove event. If user moves mouse into a certain area I want it to hop to a different place and carry on from there. But right now it hops to the destination and then immediately hops back (90% of the time). How can I avoid that behavior?
Edit: I decided to work around it by clipping the cursor in 1 by 1 px square for 1 mousemove event. Cursor.Clip(MousePosition, new Rectangle(1, 1));
My guess is that there is another control on top of your form in the area where you want to trigger the event. If so, the control is capturing the MouseMove event.
For example, here I've added a green 200x200 panel at position 0, 0 in the upper left hand corner. If the mouse moves over the panel, the form's MouseMove event will stop capturing the mouse cursor position. In my form's mouse_move event, I set the form's text to display the mouse coordinates. Notice the coordinates in the Window Text are still 200, 200 when the mouse was actually at 0, 0 (can't see my cursor due to having to click on SnippingTool.exe to get the screenshot).
To remedy this, use the same code you placed in your form's MouseMove event in the panel's MouseMove event (or whichever control you are using). This results in the correct coordinates in the form's text.
And here is the code (This could obviously be refactored into a single method):
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public Form1()
{
InitializeComponent();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
this.Text = string.Format("X: {0}, Y: {1}", e.X, e.Y);
if (e.X >= 0 && e.X <= 200)
{
if (e.Y >= 0 && e.Y <= 200)
{
SetCursorPos(500, 500);
}
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
this.Text = string.Format("X: {0}, Y: {1}", e.X, e.Y);
if (e.X >= 0 && e.X <= 200)
{
if (e.Y >= 0 && e.Y <= 200)
{
SetCursorPos(500, 500);
}
}
}
}
Hard to say with such little Information (maybe a screenshot of your GUI would help).
You could try:
private void Button_MouseMove_1(object sender, MouseEventArgs e)
{
SetCursorPos(0, 0);
e.Handled = true;
}
Hello it might be a silly question but i can't figure out the problem here.. here is my code to fill a form with a single block:
private void drawBackground()
{
Graphics g = genPan.CreateGraphics();
Image Block = Image.FromFile(#"C:\Users\Administrator\Desktop\movment V1\movment V1\images\BrownBlock.png");
float recWidth = Block.Width;
// rectangle width didnt change the name from previous code, it's picture width.
float recHeight = Block.Height;
// rectangle Heightdidnt change the name from previous code, it's picture Height.
float WinWidth = genPan.Width; // genPan is a panel that docked to the form
float WinHeight = genPan.Height;
float curWidth = 0; //indicates where the next block will be placed int the X axis
float curHeight = 0;//indicates where the next block will be placed int the Y axis
while ((curHeight + recHeight) <= WinHeight)
{
if (curWidth >= WinWidth / 3 || curWidth <= WinWidth / 1.5 ||
curHeight >= WinHeight / 3 || curHeight <= WinHeight / 1.5)
{
g.DrawImage(Block, curWidth, curHeight, recWidth , recHeight );
}
curWidth += recWidth;
if ((WinWidth - curWidth) < recWidth)
{
curWidth = 0;
curHeight += 50;
}
}
}
If I launch this func through a button it will work perfectly fine. But if I launch the func after the InitializeComponent(); method in the constructor OR in a FORM shown event, while the button is still on the form it will execute the func however the block backgroud wont be visible but the grey color will be. but if i remove the button the background will be visible. =\
I cant understand why is it happening, how to fix it and what am I doing wrong.. can anyone explain please..?
You can't really do that using your current logic. The problem is that the control (genPan panel in your case) has its own Paint event that when called, overwriting any graphics you used on it.
Even when you draw in button click it works only until the form is repainted e.g. try focus other window and focus your form again: you will lose what you have drawn.
Proper way to do such things is to write your own class that inherit from some basic control (Panel in your case) then overriding its OnPaint event and draw whatever you want there.
So first, have such class:
public class BlockBackgroundPanel : Panel
{
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Image Block = Image.FromFile(#"C:\Users\Administrator\Desktop\movment V1\movment V1\images\BrownBlock.png");
float recWidth = Block.Width;
//rest of your code, replace "genPan" with "this" as you are inside the Panel
}
}
Then in your .Designer.cs file (you can open it in the Studio) change the code so that genPan will be of your new class instance:
private BlockBackgroundPanel genPan;
//...
this.genPan = new BlockBackgroundPanel ();
If you need to draw background only based on some condition/action/user interaction...
Put the call to this funciton into the forms OnPaint method and enable it only if some bollean variale equals true. And that boolean becomes true, only on button click.
Some hypothetical example:
protected override OnPaint(...) //FORMS ONPAINT OVERRIDE
{
if(needBackGround) //INITIAL VALUE AT STARTUP IS FALSE
drawBackground();
}
public void ButtonClickHandler(...)
{
needBackGround= !needBackGround; //INVERSE THE VALUE OF BOOLEAN
}
This is clearly just a sniplet to give you a hint and not a real code. There could be other problems you will need to face, like: flickering, handling resize, performance... but this is just a point to start.
yea so I have 2 panels with the same width and the same width of data in them. the top panel has autoscroll enabled. I would like to be able to scroll both panels, with the top panel scrollbar. which means that the bottom panel doesn't have a scroll bar. How would I do that?
alt text http://members.multimania.co.uk/jeff1524/pics/scrolling.jpg
EDIT: I tried panel2.AutoScrollPosition = panel1.AutoScrollPosition;
nothing
I also tried
e.Graphics.DrawRectangle(new Pen(Color.Pink,3), 10, 10, 30, 20);
e.Graphics.TranslateTransform(panel1.AutoScrollPosition.X, 0);
no movement on the rectangle.
What am i doing wrong?
Easy peasy. Implement the Scroll event for the 1st panel and have it Invalidate() the 2nd. Draw the text in the 2nd panel's Paint event, using the scroll position of the 1st:
private void panel1_Scroll(object sender, ScrollEventArgs e) {
panel2.Invalidate();
}
private void panel2_Paint(object sender, PaintEventArgs e) {
Point pos = new Point(panel1.AutoScrollPosition.X, 0);
TextRenderer.DrawText(e.Graphics, "nobugz waz here", panel2.Font, pos, Color.Black);
// Draw something
e.Graphics.TranslateTransform(pos.X, pos.Y);
e.Graphics.DrawLine(Pens.Black, 0, 0, 100, 100);
}
Even easier.
Just place the panels inside another panel that has the scroll bar (AutoScroll = true).
I've used this strategy.
I'm developing an app for windows mobile (Compact Framework 2.0). It has a WinForms with a PictureBox.
I want to move the image of the PictureBox but I don't know how to do it so I choose to move the hole PictureBox.
To do it I use this event:
private void imagenMapa_MouseMove(object sender, MouseEventArgs e)
{
imagenMapa.Left = e.X;
imagenMapa.Top = e.Y;
this.Refresh();
}
But when I move the PictureBox it blinks and moves every where.
What I'm doing wrong?
Actual Code (Requires .NET Framework 3.5 and beyond, not sure if this is available in the Compact Framework)...
// Global Variables
private int _xPos;
private int _yPos;
private bool _dragging;
// Register mouse events
pictureBox.MouseUp += (sender, args) =>
{
var c = sender as PictureBox;
if (null == c) return;
_dragging = false;
};
pictureBox.MouseDown += (sender, args) =>
{
if (args.Button != MouseButtons.Left) return;
_dragging = true;
_xPos = args.X;
_yPos = args.Y;
};
pictureBox.MouseMove += (sender, args) =>
{
var c = sender as PictureBox;
if (!_dragging || null == c) return;
c.Top = args.Y + c.Top - _yPos;
c.Left = args.X + c.Left - _xPos;
};
The e.X and e.Y are relative to the picture box (e.g. if the mouse is in the upper left of the picture box, that's 0,0) .
The values for imagenMapa.Left and imagenMapa.Top are relative to the form (or whatever control contains imagenMapa)
If you try to mix values from these two systems without conversion, you're going to get jumps (like you're seeing).
You're probably better off converting the mouse position to the same coordinate system used by the thing that contains the picture box.
You could use imagenMapa.PointToScreen to get the mouse coordinates in screen coordinates (or Cursor.Position to get the position directly), and yourForm.PointToClient to get them back in the form coordinates.
Note that depending on your needs, you could accomplish "moving an image within a control" by overriding/handling the Paint event of a control and drawing the image yourself. If you did this, you could keep everything in the picturebox coordinates, since those are likely what you would use when you called graphicsObject.DrawImage.
e.X & e.Y is in the coordinate space of the pictureBox, imagenMapa.Left & imagenMapa.Top is in the coordinate space of the Form. :-)
Also don't forget to set your form to double buffered, that might help with the flickering, but for the actual positioning of it, I like Daniel L's suggestion
Embrace math!
control.Left = control.Left - (_lastMousePos.X - currentMousePos.X);
control.Top = control.Top - (_lastMousePos.Y - currentMousePos.Y);
Quick explanation:
You get the difference from the mouse positions and apply it to the object you want to move.
Example:
If the old mouse X position is 382, and the new one is 385, then the difference is -3. If the controls current X position is 10 then 10 - (-3) = 13
Why:
It works for anything, and is much cheaper than constantly converting coordinates back and forth.
Actually what you have done is correct. But you gave the MouseMove property to the picturebox. You should give that property to the Form(background).
ex:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
imagenMapa.Left = e.X;
imagenMapa.Top = e.Y;
}