I have the following issue:
I have window with two textboxes. When I click in a textbox and then click anywhere else (even outside the window), the mouse click position should be written into the textbox.
I found the MouseKeyHook library, in which a demo shows how the mouse position is updated in a windows form. But I did not manage to apply the code to my problem yet. I don't even know where I should write the code found in the demo.
What I came up with so far is the following:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace LineClicker
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void StarttextBox_GotFocus(object sender, RoutedEventArgs e)
{
Mouse.Capture(StarttextBox);
StarttextBox.Text = string.Format(" x {0} , y {1}", PointToScreen(Mouse.GetPosition(this)).X, PointToScreen(Mouse.GetPosition(this)).Y);
}
}
}
This is the code for one textBox. When I click in it, x and y coordinates are displayed. They are not absolute, I think this is due to the parameter this in the GetPosition method. What do I have to choose instead of this?
Another thing is that the position is not updated always. When I move the mouse to the lower right corner of my desktop and then activate the textbox by tabbing into it, the position doesn't get updated.
What are the steps to do here?
I was able to achieve this result using Cursor.Position:
A Point that represents the cursor's position in screen coordinates.
Example
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void textBox_GotFocus(object sender, RoutedEventArgs e)
{
var postion = System.Windows.Forms.Cursor.Position;
textBox.Text = string.Format($"{postion.X}, {postion.Y}");
}
}
}
You can see from the the Microsoft reference source that Cursor.Position is defined as:
public static Point Position {
get {
NativeMethods.POINT p = new NativeMethods.POINT();
UnsafeNativeMethods.GetCursorPos(p);
return new Point(p.x, p.y);
}
set {
IntSecurity.AdjustCursorPosition.Demand();
UnsafeNativeMethods.SetCursorPos(value.X, value.Y);
}
}
So just like in yan yankelevich's answer, it still uses SetCursorPos, but this way it is easier to call.
Apart from that it probably just depends on whether or not you are happy to include the reference to System.Windows.Forms.
First you will need to get the absolute mouse position (not relative to your window or your controls). To do this you need one of these options (from here : https://stackoverflow.com/a/4232281/4664754) :
By adding a reference to System.Windows.Forms in your project ( go in References in your solution explorer -> Right Click -> Add a Reference -> Assemblys-> Framework -> Tick the box near System.Windows.Forms).
Then add this static funtcion in some class (let's call it MouseHelper.cs) :
public static Point GetMousePositionWindowsForms()
{
System.Drawing.Point point = Control.MousePosition;
return new Point(point.X, point.Y);
}
By pasting this code in your MainWindow.xaml.cs:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
public static Point GetMousePosition()
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return new Point(w32Mouse.X, w32Mouse.Y);
}
Whatever the way you choose you will need to call one of those functions in your OnFocusChanged this way :
private void StarttextBox_GotFocus(object sender, RoutedEventArgs e)
{
Mouse.Capture(StarttextBox);
Point mouseCoord = MouseHelper.GetMousePositionWindowsForms();
// Or if you choose the other way :
//Point mouseCoord = GetMousePosition();
StarttextBox.Text = string.Format(" x {0} , y {1}", mouseCoord.X, mouseCoord .Y);
}
This way the coordinates should be correct.
For your problem of coordinates not displaying at the right time, i think your focus solution is not what you are looking for.
You should try to implement something like this : https://stackoverflow.com/a/2064009/4664754 and change your textboxes values every time the TheMouseMoved event is called
Related
I have a control in a WPF application that contains a text box and a submit button. The submit button is set as the "default" so that if the user presses Enter while the cursor is in the text box, the click handler for the button is run. The process kicked off by the click handler is lengthy, so I use a wait cursor coded like the following:
public class WaitCursor: IDisposable
{
private readonly System.Windows.Input.Cursor _oldCursor = null;
public WaitCursor()
{
_oldCursor = System.Windows.Input.Mouse.OverrideCursor;
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
// *** 1
}
~WaitCursor()
=> Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool unused)
{
System.Windows.Input.Mouse.OverrideCursor = _oldCursor;
// *** 2
}
}
If I type in the text box, the mouse cursor disappears. This is standard behaviour on Windows that I have observed in many applications. However, if I type in the text box and then press Enter without moving the mouse, then the mouse cursor is not shown while the application is busy - even if the user is moving it around. Effectively, the mouse cursor becomes invisible whenever it's over my application's windows, and remains that way until the application ceases being busy. This is undesirable.
I tried adding System.Windows.Forms.Cursor.Show() at the position marked with // *** 1 in my code above. This solved the problem of the cursor not being shown. But it introduced a new problem, in that the cursor no longer gets automatically hidden when the user types into text boxes in the application thereafter (for the lifetime of the application). The documentation page on Cursor.Show() says that calls to the Show() and Hide() methods should be paired, so I tried adding System.Windows.Forms.Cursor.Hide() at the position marked with // *** 2. This fixed all observed issues.
But I am not comfortable with this solution, for 2 reasons:
I am using a combination of the facilities provided by System.Windows.Forms.Cursor and System.Windows.Input.Cursor. This feels like it must be incorrect.
I am not comfortable instructing the application to "hide" the cursor when I do not in fact want the cursor to be hidden, even though the observed behaviour is that I merely undo the effect of the earlier call to Show(). It seems like something that isn't the intent of the framework designers (it really looks like what they had in mind was that you would Hide() the cursor and later Show() it) and might therefore break unpredictably.
What's the correct/proper way of solving this problem? If there is an officially sanctioned way to do this then I want to do that.
What about moving (simulated from code behind) the mouse before you start your process?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
KeyDown += _OnKeyDown;
}
[DllImport("User32.dll")]
private static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
public static Point GetMousePosition()
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return new Point(w32Mouse.X, w32Mouse.Y);
}
private void _OnKeyDown(object sender, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.Key == Key.Enter)
{
Point pos = GetMousePosition();
SetCursorPos((int)pos.X + 1, (int)pos.Y); //move 1 pixel
SetCursorPos((int)pos.X - 1, (int)pos.Y); //move back to original position
//start your process afterwards ..
}
}
I've got a little problem and tried to solve it now for nearly 6 to 8 hours but I didn't find any matching answer. I'm a complete newbie to WPF, so please point me any errors I made.
At first I have the following in my App.xaml.cs:
namespace WpfVideowand
{
public partial class App : Application
{
...
private void Application_Startup(object sender, StartupEventArgs e)
{
foreach (System.Windows.Forms.Screen MyScreen in System.Windows.Forms.Screen.AllScreens)
{
List<string> MyStrings = Xml.GetScreens(i);
if (MyStrings[1] == "true")
{
OpenWindow(MyScreen, MyStrings[0], i);
}
i++;
Shelf MyShelf = new Shelf(MyScreen, i, MyStrings[0]);
MyShelf.Show();
}
}
private void OpenWindow(System.Windows.Forms.Screen myScreen, string configName, int screenNumber)
{
Shelf NewShelf = new Shelf(myScreen, screenNumber, configName);
}
}
}
And inside the Shelf.xaml.cs it looks this way:
namespace WpfVideowand
{
public partial class Shelf : Window
{
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
System.Windows.Forms.Screen _Screen { get; set; }
...
public Shelf(System.Windows.Forms.Screen myScreen, int screenNumber, string configName)
{
InitializeComponent();
_Screen = myScreen;
ShowOnMonitor(screenNumber);
...
}
private void ShowOnMonitor(int screenNumber)
{
System.Windows.Forms.Screen[] ScreenArray;
ScreenArray = System.Windows.Forms.Screen.AllScreens;
int XCoord = Convert.ToInt32(ScreenArray[screenNumber].Bounds.Left);
this.Left = XCoord;
int YCoord = Convert.ToInt32(ScreenArray[screenNumber].Bounds.Top);
this.Top = XCoord;
IntPtr active = GetActiveWindow();
System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(window => new WindowInteropHelper(window).Handle == active).Name = "Monitor" + screenNumber.ToString();
System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(window => new WindowInteropHelper(window).Handle == active).WindowState = WindowState.Maximized;
}
...
}
}
The way described above worked fine in Windows Forms Application. In WPF I have the problem, that I get the error message, that rectangle (the window) would have no Top or Left property.
I even tried it in some other ways, like creating with
System.Windows.Forms.Screen _screen = System.Windows.Forms.Screen.FromControl(this);
an object, that would have .Top and .Left. But there I get the message, that I cannot convert a Shelf-object into a System.Windows.Forms.Control.
Anyone a suggestion, how I could make my Screens appear on the monitor where it should be?
Ok, I found it myself...
For anyone who is interested in finding some answers to this problem here it is:
At first, see that you have the correct reference implemented. For this you need System.Drawing and System.Windows.Forms. (Afterwards you have to declare many things explicit, like System.Windows.Controls.Button instead of Button, etc.)
Then see that you start the app with something like Startup="Application_Startup" and not an uri, because you want to start many forms and not only one.
Afterwards be absolutly sure to NOT set the Windowstyle to maximized in the XAML (this did cost me nearly 4 hours. In between i grew 56 grey hairs). Use this in the Code-Behind:
System.Windows.Application.Current.Windows.OfType().SingleOrDefault(window => new WindowInteropHelper(window).Handle == active).WindowState = WindowState.Maximized;
I'm trying to archive the blinking effect as shown in the image with my C# main form. I've Googled a lot and I've seen that it is possible with System.Windows.Shell and TaskbarItemInfo. This seems much more easy than downloading and importing those dlls.
I know how to make a new TaskbarItemInfo, but I don't know how I can connect it to the main form.
Any suggestions how I can do this with the System.Windows.Shell reference?
Cant See the image..are you talking about the windows 7 blinking effect
To make a new TaskbarItemInfo:
public TaskbarItemInfo TaskbarItemInfo { get; set; }
public Form1()
{
InitializeComponent();
this.TaskbarItemInfo = new TaskbarItemInfo();//
}
But I prefer this:
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern int FlashWindow(IntPtr Hwnd, bool Revert);
// check if window is minimised
private void Form4_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
FlashWindow(this.Handle, false);
}
This should work..
Also
// Flash window until it recieves focus
FlashWindow.Flash(this);
// Flash window 5 times
FlashWindow.Flash(this, 5);
// Start Flashing "Indefinately"
FlashWindow.Start(this);
// Stop the "Indefinate" Flashing
FlashWindow.Stop(this);
Can someone please help me and give me an example/idea?
I want to determien when the user is standing on a link (the cursor changed from arrow to click hand) and when it happen will show MessageBox.Show("You are standing on link");
It needs to be solution that work on all the versions of Windows so please be creative.
EX. The program run on background (Process is running in loop), and when the user is standing on link any ware (in IE browser for ex.) automatically it pops up a massage ("you are standing on link")
Thanks
As you haven't specified, I will assume you are using Win Forms. To capture the hover, simply subscribe to the OnMouseHover event, e.g.
yourLinkLabel.MouseHover += yourLinkLabel_MouseHover;
...
private void yourLinkLabel_MouseHover(object sender, EventArgs e)
{
MessageBox.Show("You are standing on link");
}
This comes with my official "Works on my machine" stamp of approval. This may not work for you and is complete guess on my part. Having said that:
[StructLayout(LayoutKind.Sequential)]
public struct CursorInfo {
public int Size;
public int Flags;
public IntPtr Handle;
public System.Drawing.Point Position;
}
public class NativeMethods {
[DllImport("user32.dll")]
public static extern bool GetCursorInfo(out CursorInfo info);
}
(SNIP)
while (true) {
CursorInfo info = new CursorInfo();
info.Size = Marshal.SizeOf(info.GetType());
if (NativeMethods.GetCursorInfo(out info)) {
if (info.Handle.ToInt32() == 65571) {
Console.WriteLine("Hand");
}
}
System.Threading.Thread.Sleep(100);
}
I'm an extreme newbie at C#, but I've been slowly moving through the Head Start C# tutorial book (and finding it extremely enjoyable so far). However, I've hit a wall on the first "lab" assignment: They give code for controlling a PictureBox, and I can get that code to work on the main Form, but I can't get it to work from within a Class. I've gone back over the old lessons, and I've got a fairly good idea of what I'm missing, but for the life of me I can't figure out how to access the main Form's PictureBox from within my class (as the tutorial is telling me I should do).
It's a bit frustrating, because I didn't jump ahead in the book at all, but I'd swear we haven't covered this yet. Anyway, appealing to Real programmers.
Here's the code provided in the tutorial, in a section called "Your object can control things on your form" (p208 for anyone with the book).
Point p = MyPictureBox.Location
p.x += distance;
MyPictureBox.Location = p
Below I'm posting the relevant (I think?) parts of my code below. Button1 works for me when compiled, Button2 "works," in the sense that the current class just tells it to print the passed INT because I've commented out the code I can't get to work.
Thanks in advance!
Code for the Form1:
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// Namespaces I'll need.
namespace Troubleshooting_PicBoxes
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); // Start all the Form1 stuff (all IDE-generated)
}
private void button1_Click(object sender, EventArgs e) //method from clicking the first button
{
int distance = 5; // Create this variable called "distance"
Point BoxMovement = MyPictureBox.Location; //create a point called BoxMovement
BoxMovement.X += distance; // Adjust the X of BoxMovement by my distance int.
MyPictureBox.Location = BoxMovement; // now adjust the Box by the Point's location.
}
private void button2_Click(object sender, EventArgs e)
{
PicMover PicMoverObject1 = new PicMover(); // Reserve Space for&Create object
PicMoverObject1.MoveThatPic(5); // Execute Object Method with a value of 5
}
}
}
Code for the PicMover class:
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Troubleshooting_PicBoxes
{
class PicMover
{
public void MoveThatPic(int distance) // New method,
// takes a variable called Distance.
{
MessageBox.Show(distance.ToString()); // Just show us that Variable.
// I need to be able to access Form1's picture box before I can use this. :(
/* Point BoxMovement = MyPictureBox.Location; //create a point called BoxMovement
BoxMovement.X += distance; // Adjust the X of that by distance.
MyPictureBox.Location = BoxMovement; // now adjust the Box by the Point's location.
*/
}
}
}
If you need to access something, why don't you just give it access? Like passing it as a argument to the method.
public void MoveThatPic(PictureBox picBox, int distance) // New method,
// takes a variable called Distance.
{
MessageBox.Show(distance.ToString()); // Just show us that Variable.
// I need to be able to access Form1's picture box before I can use this. :(
Point BoxMovement = picBox.Location; //create a point called BoxMovement
BoxMovement.X += distance; // Adjust the X of that by distance.
picBox.Location = BoxMovement; // now adjust the Box by the Point's location.
}
now in button2 click event handler:
private void button2_Click(object sender, EventArgs e)
{
PicMover PicMoverObject1 = new PicMover(); // Reserve Space for&Create object
PicMoverObject1.MoveThatPic(MyPictureBox, 5); // Execute Object Method with a value of 5
}
The tutorial code LOOKS like you are grabbing the location from your class (MyPictureBox.Location) then changing the location, then moving your object to that new location.
Point p = MyPictureBox.Location // Save the location of your object
p.x += distance; // Increase the distance
MyPictureBox.Location = p // Set your object to the new location
The second button press event is different. Perhaps you should be returning a location from the function? So, when you call the function, you set the PictureBox on the main form to the value returned.
If you want to create a general purpose class that can be accessed from any Form ... that creates an instance of it ... to move any PictureBox on that Form, then 'Deerchao's answer shows you how to do it.
Although ... consider ... every Form is going to have declare its own instance of PicMover; Form1's instance of PicMover is not "visible" to any other Form unless you also somehow publish it.
To put it more technically : the PicMover class, as defined here, exists in the Scope of the Application NameSpace; it's a template for creating type of object that every other Class in the Application can use to make an instance of, but that no Class in the Application "has" an instance of by default.
Here's an alternative to Deerchao's excellent answer that demonstrates "injection" : injection is appropriate when you want an instance of a class to "hold onto" a reference : in this example we say that the Form's instance of a PictureBox gets "bound" to an instance of the 'PicMover class :
We declare a Public Property within the class 'PicMover that will hold a reference to Form1's PictureBox :
public class picMover
{
// note use of C# 3.0 automatic property feature here
public PictureBox myPictureBox { get; set; }
public void movePic(int distance)
{
// note test for null here
if (myPictureBox != null)
{
myPictureBox.Left += distance;
}
}
}
So in Form1 after you create the instance of 'PicMover, you set its internal PictureBox Property, and then use its internal 'movePic method : like this :
// instance of PicMover created in the Form's scope
picMover myPicMover = new picMover();
private void Form1_Load(object sender, EventArgs e)
{
// when the Form loads inject the reference to the PictureBox instance into the instance of 'PicMover
myPicMover.myPictureBox = pictureBox1;
}
private void button1_Click(object sender, EventArgs e)
{
myPicMover.movePic(23);
}
Note that, imho, testing to make sure an "injected" reference to an object exists, by testing for null before using it is a good habit to get into.
Another way you can get an instance of the PictureBox object "bound" into an instance of 'PicMover is to pass the instance of the PictureBox to the Constructor of the class as a parameter : I bet by the time I finish posting this, someone else will have already posted an answer showing that technique. You might want to "inject" using a Public Property as shown here when you expect the internal reference to be changed vs. passing the PictureBox in to the Constructor of the Class when you don't expect it to be changed.
Another strategy is to make 'PicMover a public static class, with public static methods : then every Form can "see it," and there's no need for any form to make an instance of it (in fact you can't "instance" a static class if you wanted to : that's what a static class is).