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 have an background WinForms application, which doesn't show any windows usually. But it shows a form on top most without activation, when occurred some app event. And I have a problem that when users clicks on the form and after this application closes this form and showes another instance of form, then last one shows without top most option (it shows under all opened windows). And I really don't understand why.
I noticed, that problem disappears when I run application with overloaded method:
Application.Run(new TestForm());
But my application is background and so I need to use follow overloaded method:
Application.Run();
And a problem appears again...
I maximally simplified my code to make my problem more clear.
Here is code of my form:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace winscr
{
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
this.Load += Form_Load;
}
void Form_Load(object sender, EventArgs e)
{
//-1 HWND_BOTTOM Places the window at the bottom of the Z order
//0x0010 SWP_NOACTIVATE Does not activate the window.
//0x0002 SWP_NOMOVE Retains the current position (ignores X and Y parameters).
//0x0001 SWP_NOSIZE Retains the current size (ignores the cx and cy parameters).
//always returns true
bool result = SetWindowPos(this.Handle, new IntPtr(-1), 0, 0, 0, 0, 0x0010 | 0x0002 | 0x0001);
this.Text = result + " " + DateTime.Now.ToString();
}
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
protected static extern bool SetWindowPos(
IntPtr hWnd, // window handle
IntPtr hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags); // window positioning flags
protected override bool ShowWithoutActivation { get { return true; } }
}
}
And code of Program class:
using System;
using System.Windows.Forms;
namespace winscr
{
static partial class Program
{
static TestForm frm;
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//I use timer only for example on stackoverflow. In my real program form appears after particular events
Timer tmr = new System.Windows.Forms.Timer();
tmr.Interval = 2000;
tmr.Tick += new EventHandler(tmr_Tick);
tmr.Enabled = true;
Application.Run();
//Application.Run(new TestForm()); //if I use this overloading, then all works without any bugs
}
static void tmr_Tick(object sender, EventArgs e)
{
if (frm != null)
{
//close previous instance of form
frm.Close();
}
//construct and show new form
frm = new TestForm();
frm.Show();
}
}
}
Here is direct link to the project with this code (you can just run project and try to reproduce problem):
http://hidescreener.com/downloads/?r=form_top_most_tests.zip
And I recorded the video, in which I show this problem:
http://youtu.be/mxJYZE-oMDI
Please, help me to solve this problem. I have trying to solve it for 2 days.
P.S. I found like problem Really annoying bug with TopMost property in Windows Forms but there is no answer...
Updated:
Thanks for the Hans Passant's and King King's comments.
It was found that this problem only occurs in Windows XP.
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 trying to write an application that senses when someone taps and holds something. I am using windows forms. I tried using the mouse down even but it doesn't appear to fire all the time. This is also going to be a multi touch application. I'm going to have two buttons , and the user can tap and hold one button, while they press on the other button. Or Just press one button. I'm not even sure how a windows form app can handle that.
All the examples inhave seen for a windows touch app use xaml. Is this really the only way to capture tap and hold ??
I'm essentially making an onscreen keyboard here, and I don't think that isnpossible WITHOUT windows forms. Correct me if I am wrong here.
Any help or guidance in this is greatly appreciated. Thanks.
If your program is running on Windows 8, you can use the WM_POINTER API to get the input you need. Override WndProc to capture the messages. You will have to do some P/Invoke to get it working, but it's not terribly hard. Here's some incomplete code to get you started, you'll need to add cases for up, down, and update events for each type of pointer you want to track. Keep track of the pointer IDs to process multi touch. To handle the press-and-hold you'll need to track the time yourself from WM_POINTERDOWN to WM_POINTERUP and act accordingly. Hope this helps.
public const int WM_POINTERDOWN = 0x0246;
public const int WM_POINTERUP = 0x0247;
public const int WM_POINTERUPDATE = 0x0245;
public enum POINTER_INPUT_TYPE : int
{
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
PT_PEN = 0x00000003,
PT_MOUSE = 0x00000004
}
public static uint GET_POINTERID_WPARAM(uint wParam) { return wParam & 0xFFFF; }
[DllImport("User32.dll")]
public static extern bool GetPointerType(uint pPointerID, out POINTER_INPUT_TYPE pPointerType);
protected override void WndProc(ref Message m)
{
bool handled = false;
uint pointerID;
POINTER_INPUT_TYPE pointerType;
switch(m.Message)
{
case WM_POINTERDOWN:
pointerID = User32.GET_POINTERID_WPARAM((uint)m.WParam);
if (User32.GetPointerType(pointerID, out pointerType))
{
switch (pointerType)
{
case POINTER_INPUT_TYPE.PT_PEN:
// Stylus Down
handled = true;
break;
case POINTER_INPUT_TYPE.PT_TOUCH:
// Touch down
handled = true;
break;
}
}
break;
}
if (handled)
m.Result = (IntPtr)1;
base.WndProc(ref m);
}
This question has been around for a while and might benefit from a simple approach. You can simulate the "tap and hold" (or click and hold) by measuring the time between the MouseDown event and the Click event (which fires before MouseUp). If the time is greater than some value then you cancel the Click and (perhaps) fire your own TapAndHold event. I have created a test control that anyone can use to try this approach out. Just add a UserControl to your test app (I called mine TestTapAndHold) and then paste in the following:
public partial class TestTapAndHold : UserControl
{
private string showText = "Tap Me";
private DateTime mouseDown;
private const int holdTime = 500;
public TestTapAndHold()
{
InitializeComponent();
this.Paint += drawText;
}
public delegate void OnTapAndHold(EventArgs e);
public event OnTapAndHold TapAndHold;
private void drawText(object sender, PaintEventArgs e)
{
using (var drawBrush = new SolidBrush(Color.Black))
{
e.Graphics.DrawString(showText, Font, drawBrush, new Point(5,3));
}
}
protected override void OnClick(EventArgs e)
{
if (DateTime.Now.Subtract(mouseDown).Milliseconds >= holdTime)
{
showText = "Tap Hold";
TapAndHold?.Invoke(e);
} else
{
base.OnClick(e);
showText = "Tapped";
}
Invalidate();
}
private void TestTapAndHold_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = DateTime.Now;
}
}
Build the app and then pop one of the test controls onto a form. You can then add an event handler to your form like:
private void testTapAndHold1_TapAndHold(EventArgs e)
{
MessageBox.Show("You tapped and Held");
}
This general approach enabled me to add "Tap and Hold" functionality to a Windows Forms app running on a Microsoft Surface 4
I'm using a Form to show notifications (it appears at the bottom right of the screen), but when I show this form it steals the focus from the main Form. Is there a way to show this "notification" form without stealing focus?
Hmmm, isn't simply overriding Form.ShowWithoutActivation enough?
protected override bool ShowWithoutActivation
{
get { return true; }
}
And if you don't want the user to click this notification window either, you can override CreateParams:
protected override CreateParams CreateParams
{
get
{
CreateParams baseParams = base.CreateParams;
const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOOLWINDOW = 0x00000080;
baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );
return baseParams;
}
}
Stolen from PInvoke.net's ShowWindow method:
private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
int hWnd, // Window handle
int hWndInsertAfter, // Placement-order handle
int X, // Horizontal position
int Y, // Vertical position
int cx, // Width
int cy, // Height
uint uFlags); // Window positioning flags
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowInactiveTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
frm.Left, frm.Top, frm.Width, frm.Height,
SWP_NOACTIVATE);
}
(Alex Lyman answered this, I'm just expanding it by directly pasting the code. Someone with edit rights can copy it over there and delete this for all I care ;) )
This is what worked for me. It provides TopMost but without focus-stealing.
protected override bool ShowWithoutActivation
{
get { return true; }
}
private const int WS_EX_TOPMOST = 0x00000008;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_TOPMOST;
return createParams;
}
}
Remember to omit setting TopMost in Visual Studio designer, or elsewhere.
This is stolen, err, borrowed, from here (click on Workarounds):
https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost
If you're willing to use Win32 P/Invoke, then you can use the ShowWindow method (the first code sample does exactly what you want).
Doing this seems like a hack, but it seems to work:
this.TopMost = true; // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top
Edit: Note, this merely raises an already created form without stealing focus.
The sample code from pinvoke.net in Alex Lyman/TheSoftwareJedi's answers will make the window a "topmost" window, meaning that you can't put it behind normal windows after it's popped up. Given Matias's description of what he wants to use this for, that could be what he wants. But if you want the user to be able to put your window behind other windows after you've popped it up, just use HWND_TOP (0) instead of HWND_TOPMOST (-1) in the sample.
In WPF you can solve it like this:
In the window put these attributes:
<Window
x:Class="myApplication.winNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Notification Popup" Width="300" SizeToContent="Height"
WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>
The last one attribute is the one you need ShowActivated="False".
I have something similar, and I simply show the notification form and then do
this.Focus();
to bring the focus back on the main form.
Create and start the notification Form in a separate thread and reset the focus back to your main form after the Form opens. Have the notification Form provide an OnFormOpened event that is fired from the Form.Shown event. Something like this:
private void StartNotfication()
{
Thread th = new Thread(new ThreadStart(delegate
{
NotificationForm frm = new NotificationForm();
frm.OnFormOpen += NotificationOpened;
frm.ShowDialog();
}));
th.Name = "NotificationForm";
th.Start();
}
private void NotificationOpened()
{
this.Focus(); // Put focus back on the original calling Form
}
You can also keep a handle to your NotifcationForm object around so that it can be programmatically closed by the main Form (frm.Close()).
Some details are missing, but hopefully this will get you going in the right direction.
This works well.
See: OpenIcon - MSDN and SetForegroundWindow - MSDN
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern bool OpenIcon(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ActivateInstance()
{
IntPtr hWnd = IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;
// Restore the program.
bool result = OpenIcon(hWnd);
// Activate the application.
result = SetForegroundWindow(hWnd);
// End the current instance of the application.
//System.Environment.Exit(0);
}
You might want to consider what kind of notification you would like to display.
If it's absolutely critical to let the user know about some event, using Messagebox.Show would be the recommended way, due to its nature to block any other events to the main window, until the user confirms it. Be aware of pop-up blindness, though.
If it's less than critical, you might want to use an alternative way to display notifications, such as a toolbar on the bottom of the window. You wrote, that you display notifications on the bottom-right of the screen - the standard way to do this would be using a balloon tip with the combination of a system tray icon.
You can handle it by logic alone too, although I have to admit that the suggestions above where you end up with a BringToFront method without actually stealing focus is the most elegant one.
Anyhow, I ran into this and solved it by using a DateTime property to not allow further BringToFront calls if calls were made already recently.
Assume a core class, 'Core', which handles for example three forms, 'Form1, 2, and 3'. Each form needs a DateTime property and an Activate event that call Core to bring windows to front:
internal static DateTime LastBringToFrontTime { get; set; }
private void Form1_Activated(object sender, EventArgs e)
{
var eventTime = DateTime.Now;
if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
Core.BringAllToFront(this);
LastBringToFrontTime = eventTime;
}
And then create the work in the Core Class:
internal static void BringAllToFront(Form inForm)
{
Form1.BringToFront();
Form2.BringToFront();
Form3.BringToFront();
inForm.Focus();
}
On a side note, if you want to restore a minimized window to its original state (not maximized), use:
inForm.WindowState = FormWindowState.Normal;
Again, I know this is just a patch solution in the lack of a BringToFrontWithoutFocus. It is meant as a suggestion if you want to avoid the DLL file.
I don't know if this is considered as necro-posting, but this is what I did since I couln't get it working with user32's "ShowWindow" and "SetWindowPos" methods. And no, overriding "ShowWithoutActivation" doesn't work in this case since the new window should be always-on-top.
Anyway, I created a helper method that takes a form as parameter; when called, it shows the form, brings it to the front and makes it TopMost without stealing the focus of the current window (apparently it does, but the user won't notice).
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern IntPtr SetForegroundWindow(IntPtr hWnd);
public static void ShowTopmostNoFocus(Form f)
{
IntPtr activeWin = GetForegroundWindow();
f.Show();
f.BringToFront();
f.TopMost = true;
if (activeWin.ToInt32() > 0)
{
SetForegroundWindow(activeWin);
}
}
I know it may sound stupid, but this worked:
this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
I needed to do this with my window TopMost. I implemented the PInvoke method above but found that my Load event wasn't getting called like Talha above. I finally succeeded. Maybe this will help someone. Here is my solution:
form.Visible = false;
form.TopMost = false;
ShowWindow(form.Handle, ShowNoActivate);
SetWindowPos(form.Handle, HWND_TOPMOST,
form.Left, form.Top, form.Width, form.Height,
NoActivate);
form.Visible = true; //So that Load event happens
You don't need to make it anywhere near as complicated.
a = new Assign_Stock();
a.MdiParent = this.ParentForm;
a.Visible = false; //hide for a bit.
a.Show(); //show the form. Invisible form now at the top.
this.Focus(); //focus on this form. make old form come to the top.
a.Visible = true; //make other form visible now. Behind the main form.
Github Sample
Form.ShowWithoutActivation Property
Add this in your child form class
protected override bool ShowWithoutActivation
{
get { return true; }
}
Working Code
Form2
public partial class Form2 : Form
{
Form3 c;
public Form2()
{
InitializeComponent();
c = new Form3();
}
private void textchanged(object sender, EventArgs e)
{
c.ResetText(textBox1.Text.ToString());
c.Location = new Point(this.Location.X+150, this.Location.Y);
c .Show();
//removethis
//if mdiparent 2 add this.focus() after show form
c.MdiParent = this.MdiParent;
c.ResetText(textBox1.Text.ToString());
c.Location = new Point(this.Location.X+150, this.Location.Y);
c .Show();
this.Focus();
////-----------------
}
}
Form3
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
//ShowWithoutActivation = false;
}
protected override bool ShowWithoutActivation
{
get { return true; }
}
internal void ResetText(string toString)
{
label2.Text = toString;
}
}
When you create a new form using
Form f = new Form();
f.ShowDialog();
it steals focus because your code can't continue executing on the main form until this form is closed.
The exception is by using threading to create a new form then Form.Show(). Make sure the thread is globally visible though, because if you declare it within a function, as soon as your function exits, your thread will end and the form will disappear.
Figured it out: window.WindowState = WindowState.Minimized;.