In C#, WPF, could I hide my cursors in all windows? - c#

everyone.
When I develop an application using C#, WPF. I want to hide my cursor in some special area. No matter which application/window on top, the cursor is always hiding.
In WPF Window, normally, we use
this.Cursor = System.Windows.Input.Cursors.None;
But this one could not solve my problem.
I want this situation:
I open my window, the cursor disappears in my window. And then I open a notepad on top of my window, the cursor disappears in the notepad too.
This one is able to do or not? Thank you.

You also can use win32 dll.
internal static class WinCursors
{
[DllImport("user32.dll")]
private static extern int ShowCursor(bool bShow);
internal static void ShowCursor()
{
while (ShowCursor(true) < 0)
{
}
}
internal static void HideCursor()
{
while (ShowCursor(false) >= 0) //使用这个方法可以关闭光标
{
}
}
}

If it area is the same on each Form, you could create a custom BaseForm (or similar) which derives from Form, and put a Label on there and use its MouseEnter and MouseLeave events to hide the cursor.
All your forms can then derive from BaseForm rather than Form so that they all have this area.

Simply inside your mouseEnter event use a cursor hide
private void splitContainer1_Panel2_MouseEnter(object sender, EventArgs e)
{
Cursor.Hide();
}

Have you tried Window Class's event
Activted, FocusableChanged or other relative events

The window on top is the one that controls the mouse cursor. So the only way to do this is to put your window on top, likely by making it Topmost.
If you want to still be able to see the windows underneath it, you can make your window semitransparent. Set the AllowsTransparency property to true and then set your window's background color to a semitransparent color. (You can't make it 100% transparent, because WPF treats full transparency as meaning "there's nothing here, so send mouse events to the next window behind me"; but you can do something like #01000000 that's so close to transparent that nobody will notice it.)

Related

top most window in c#

I have a form application, i want to it to be the the top most. i use
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
this function, it works fine.But when task manager property always on top is checked it fails. And task manager will appear as the top most window.
So my concern is, if there any way to achieve it, or we cant not do it with task manager. it will always appear on the top, or anything else i was missing, or doing wrong.
The MSDN say that HWND_TOPMOST simply Places the window above all non-topmost windows. In other words there are two groups of windows: non-topmost (usual) and topmost and you just sent your window to the other group.
If there is any other topmost window (= task manager in your case), you can switch between them as you normally would between non-topmost windows and they will be overlapping depending on which one is currently active.
If you would like to force your window to be always topmost, I guess you would have to watch for the window deactivation (WM_ACTIVATE message) and then move your window up in the Z-order and also focus your window back - this way you would prevent problems like having your window the only one visible, but having the keyboard focus on another window.
you can try this if you just want your application is always at the top of other application.
private void timer1_Tick(object sender, EventArgs e)
{
this.TopMost = true;
}

Winforms: How to get Mouse Events for Transparent Control on a Transparent Form

I have a transparent form that overlays the desktop in a c# .NET winforms application. The transparency is done by setting the BackColor to bright orange and then setting the TransparencyKey to the same bright orange.
So far this works great and it creates a transparent form. I then want to create a control on the transparent form that draws a rectangle around items on the desktop. So essentially you can think of a transparent button with a rectangular border. To make this happen I currently extend Control and setup the control like this inside of the parent form which is also transparent:
public class CustomControl : Control
{
public CustomControl(Size size, Point point)
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
this.Size = size;
this.Location = point;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen pen = new Pen(Color.Red, 2f);
e.Graphics.DrawRectangle(pen, this.ClientRectangle);
}
}
This creates the exact effect I'm looking for in that there is a control with a solid opaque rectangle border inside a transparent form and you can see the desktop through the control and form (see image below on left side).
The problem is that the transparent area of the control does not receive any mouse events. In fact, it basically doesn't exist. For example, when your mouse goes over the red rectangular border of the control that triggers the Mouse Hover, Mouse Enter, and Mouse Leave events and changes the cursor to whatever you set as this.Cursor for the control. Once, the mouse is in the transparent portion of the control none of these things trigger.
How can I keep things the way they are now in regards to the look of the control but still receive mouse events in the transparent area. In particular I want to receive Mouse Hover and have the controls Cursor value be honored. Note that if I make the BackColor of the control anything other than Color.Transparent then mouse events work fine.
Thank you!
Update
Based on Hans comment I would like to add that we have implemented the above and that it has usually worked (i.e., the transparent area does respond to mouse events). The reason this issue came up is because I recently rebuilt my machine with all the Windows 8.1 updates and latest ATI graphic drivers and after that the above setup no longer works ever (transparent areas on the control no longer receive any mouse events and for all intents and purposes are not part of the control) On my colleague's machine it almost always works although we've occasionally noticed that it won't work but we could never consistently reproduce the issue.
My assumption was that we did something wrong to cause the transparent areas to not respond to mouse events. However, based on Hans' comment, it seems as though the above code should never work and that the only reason it worked was because of a bug in Aero.
The exact color of our transparency key is rgb(255, 128, 0). In addition we did notice that any label controls placed on the transparent form look terrible (per Han's comment).
Update 2
Based on Han's additional comment regarding the Aero transparency bug I have the following updated questions.
Is there any information on this bug somewhere that explains what the bug is?
What is the intended behavior (assume there are no bugs) for transparent areas of a control? Should mouse events (e.g., Mouse Hover) work on the transparent area?
The Final Answer (that usually works)
The answered provided by Reza below did work for me on some of my computers. However, my primary desktop continued to stubbornly refuse to cooperate. Even when copying the exact project between computers using the same version of windows and .NET the problem existed. The issue when it arose was that transparent areas would not trigger mouse events and were not treated as part of the control.
In addition, I noticed the same thing Reza noticed which was that certain TransparencyKey colors flat out did not work. Although I don't know any details of the bug I would have to agree with Hans that there are bugs involved with transparency on WinForms and if anyone is starting from scratch I would go the WPF route and save yourself any possible future headaches.
In the end we ended up implementing a work around based on some of Hans' answers that required using a timer to check the mouse location and nesting two forms (one with opacity set) to be able to manage the mouse cursor. This solution has worked on all our systems and will hopefully hold up until we move over to WPF. I accepted Reza's answer because it seems to work in most places but be aware that it might not work you and there is no rhyme or reason as to why.
For detailed information on the two workaround we implemented please see the following questions and answers by Hans.
MouseHover and MouseLeave Events controlling
How can I add transparency to a c# form while keeping controls visible?
Important
Consider set BackgroundColor of form to Red and TransparencyKey to Red and BackGroundColor of transparent control to Transparent and it will work!
the strange thing that I see is, the approach doesn't work with for example Magenta but works with Red and Blue.
I think you should create your transparent control this way:
Transparent Control Code
public class TransparentControl : Control
{
public TransparentControl()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
private const int WS_EX_TRANSPARENT = 0x20;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
}
And for the mouse events and rendering border when the mouse enters, here is the sample I did Using .Net 4.5 On Windows 8.1:
Create a Form and put a TransparentControl that we created using above code, on it, then handle MouseEnter and MouseLeave and Paint events and paint the border when mouse is in control bouds and handle Click event and show a message.
Form Code
private bool drawBorder;
private void transparentControl1_MouseLeave(object sender, EventArgs e)
{
drawBorder = false;
transparentControl1.Invalidate();
}
private void transparentControl1_MouseEnter(object sender, EventArgs e)
{
drawBorder = true;
transparentControl1.Invalidate();
}
private void transparentControl1_Paint(object sender, PaintEventArgs e)
{
if(drawBorder)
{
using (var pen = new Pen(this.ForeColor, 5))
{
e.Graphics.DrawRectangle(pen, 0, 0, this.transparentControl1.Width - 1, this.transparentControl1.Height - 1);
}
}
}
private void transparentControl1_Click(object sender, EventArgs e)
{
MessageBox.Show("Clicked");
}
Screenshot
The mouse cursor is in the control's area so the black border has been painted.
Important Note
If you draw border the same color as form's transparency key, the border will not be shown.
I think it's okay for the mouse cursor to go in the middle of that overlay box and move with the mouse cursor and the overlay box to make it look like it's a mouse cursor.
Like this picture
I have had similar problem when I use a picturebox control on a transparent form and use the mouseclick event over the control to trigger code. Sometimes the mouseclick is captured and sometimes it isn't. No pattern to it other than the color used as the form background. Red works fine but many other colors do not. Even black does not work consistently. I have found an almost black color that works fine when form.backcolor and form.transparencykey are set to this color. Based on this and others experiences it appears a bug in VB Studio and the way transparency is handled.
Form1.BackColor = Color.FromArgb(64, 0, 0) ' a color that works with transparency and allows picturebox to be clicked

Resize a winform window only when resize end

Is there a way to resize a Winform window just in Resize End?
This means that as long as the mouse is clicked I see lines and only when I leave the mouse (Resize end) window will resize on the screen.
You will need to use DrawReversibleFrame. Default resizing will need to be disabled (FormBorderStyle = FixedSingle).
Basic Logic is -
MouseDown - Begin tracking
MouseMove - Draw Reversible Frame
MouseUp - Stop Drawing Reversible Frame. Resize Form.
Luckily this MSDN post had working code for this. I have a made a working sample for you.
http://www.mediafire.com/download/427g2h2ajm5z62m/ResizeFrame.zip
You will need to tweak this so Form resize only happens when user 'MouseDown' near the border.
If it's fine to only have the contained controls resize then (and the Form itself - immediately) - use the Form's ResizeEnd event.
(I'm assuming this is the case, because usually there is no reason to delay the Form's resize itself, rather the contained controls', because their resize might be 'expensive'.)
Note: "The ResizeEnd event is also generated after the user moves a form".
Try this.
protected override void OnResizeBegin(EventArgs e) {
SuspendLayout();
base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
ResumeLayout();
base.OnResizeEnd(e);
}

"Tint" an entire window, or alternative method of making window look inactive

I have a winforms C# application that opens multiple dialog boxes. To suit the style of the application, I have removed the default title bars for each window and created my own (with control buttons and drag-to-move function).
The problem that now faces me is that without a titlebar, the user has no way of telling which window is the 'active' window when they are manually moved apart (so they are not overlapping).
In any windows application (that uses titlebars), when you try to navigate away from a dialog box back to the main program (without closing the dialog box) - it wont let you. The border of the dialog box flashes and you hear a windows error sound. Some kind of equivalent visual feedback would be great without needing to have the default titlebars - and tinting an entire window darker seems like it would do the trick nicely.
Something like this in pseudo-code, which would nicely tint the parent window whilst a dialog is open:
// tint window now
window.ShowDialog();
// un-tint window
I have tried to place a panel covering everything with colour set to 'transparent' (with the intention of later controlling the opacity of the panel) but the transparency does not seem to work. Any other ideas of accomplishing this? Or does anyone have a better suggestion to achieve the same level of visual feedback?
Summary:
Is there any way to tint an entire window, or overlay it with a colour? If not, could anyone suggest an alternate method of making the window appear 'inactive'?
I would suggest you to create a method in forms you want to disable:
void DisableForm()
{
//some fancy color
this.BackColor = System.Drawing.Color.Khaki;
//and disable all controls owned by form, just to be sure
foreach (var s in this.Controls)
{
((Control)s).Enabled = false;
}
}
and functions which enables back those forms of course.
edit.
also you can set visibility property of controls to false

Can I make a window not resize itself until the user lets go of the mouse button?

I have some screens with a lot of stuff on them, and the redrawing performance is pretty poor. It is possible to set a form into a resizing mode where a rectangle is shown on the screen that denotes the new window dimensions as the user resizes it, but the actual form doesn't resize until they let go of the mouse button?
Thanks!
Yes; this behavior is defined by one of the window styles, which you can turn on/off using the Control.SetStyles method. In particular, I think you want this:
myForm.SetStyle(ControlStyles.ResizeRedraw, false);
You could then hook the mousedown/resize/mouseup events and force the redraw to happen when you wanted.
You can also try turning on the double buffering style:
myForm.SetStyle(ControlStyles.DoubleBuffer, true);
See this article for details: http://msdn.microsoft.com/en-us/library/fkf25009(v=vs.100).aspx
Completely suppressing all drawing is not practical, the window frame painting is out of your direct control. Nor is it necessary, all you have to do is make your drawing fast when the form is being resized. Like this:
private bool fastRender;
protected override void OnResizeBegin(EventArgs e) {
fastRender = true;
base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
base.OnResizeEnd(e);
fastRender = false;
this.Invalidate();
}
And check the fastRender variable in your Paint event handler, drawing only the minimum. Or nothing at all. If the actual delay is caused by a large number of controls then tackle that by making them invisible in ResizeBegin and visible again in ResizeEnd. Easy to do with a Panel. If it is caused by a controls that are docked or have the Anchor set so that they'll resize or move whenever the user resizes the window then you'll find Suspend/ResumeLayout useful.
Have you tried using the DoubleBuffer feature of a winform/control?
How about using ResizeEnd instead of Resize.
Open the window that is abnormally sized; then hold down the control key, hit the + key until you return to your required size. Good luck.

Categories