When dragging a borderless form to the top of the screen; if the Y coordinate is negative, it sets it back to 0. What I'm looking to do is be able to drag the form above the top, where the Y coordinate would be negative, the same way you can with every other side of the screen.
Here is what I have tried:
public partial class BorderlessForm : Form
{
public BorderlessForm()
{
InitializeComponent();
}
private bool _isNegative;
private Point _negative;
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) {
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative) {
Location = _negative;
}
//base.OnResizeEnd(e);
}
protected override void OnMove(EventArgs e)
{
if (Location.Y < 0) {
_isNegative = true;
_negative = Location;
}
else {
_isNegative = false;
}
//base.OnMove(e);
}
}
This was the best I could come up with after thinking on it for a while. The problem is that when the mouse is released and the form is finished moving, OnMove is called before OnResizeEnd, and _isNegative is then set back to false. At least, that is what I assume is happening.
Do I have the right idea, or is there some better way to go about this?
So, I thought more about what isaeid said, and was able to come up with a solution. Still not sure if this is the best way to go about it, but here it is:
public partial class ImageForm : PerPixelAlphaForm
{
public ImageForm()
{
InitializeComponent();
}
private bool _isNegative;
private Point _negative;
private bool _flag;
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) {
NativeMethods.ReleaseCapture();
NativeMethods.SendMessage(Handle, NativeMethods.WM_NCLBUTTONDOWN, NativeMethods.HT_CAPTION, 0);
}
}
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative) {
Location = _negative;
_isNegative = false;
}
}
protected override void OnMove(EventArgs e)
{
if (Location.Y < 0) {
_isNegative = true;
_flag = true;
_negative = Location;
}
else {
if (_flag) {
_flag = false;
return;
}
_isNegative = false;
}
}
}
You can change some events like this:
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative)
{
Location = _negative;
}
oldRight = this.Right;
oldBottom = this.Bottom;
//base.OnResizeEnd(e);
}
protected override void OnMove(EventArgs e)
{
if ( this.Right == oldRight || this.Bottom == oldBottom)
return;
if (Location.Y < 0)
{
_isNegative = true;
_negative = Location;
}
else
{
_isNegative = false;
}
//base.OnMove(e);
}
When top or left of window is changed, dotnet determines location of window is changed and calls onmove event, i consider if right or bottom of the window is not changed so window's location is not changed.
Add this codes too:
int oldBottom, oldRight;
private void BorderlessForm_Load(object sender, EventArgs e)
{
oldRight = this.Right;
oldBottom = this.Bottom;
}
Related
Well, I made a script to just jump to work in several games, and I would like my program to have a button to activate and deactivate it so that it doesn't disturb me when I'm not playing (when minimizing the game), I managed to make the script run when I clicked on the activate button, but I don't have the slightest idea of how to put it to disable / pause on the "Desativar" button, and when I click again on "Activate" where it left off.
I'm going to apologize for my English if something is wrong
ps: I'm a newbie
Code:
public partial class Pular : Form
{
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(Keys vKey);
[DllImport("user32.dll")]
static extern void mouse_event(int a, int b, int c, int d, int swed);
int m3DOWN = 0x0020;
int m3UP = 0x0040;
public Pular()
{
InitializeComponent();
btnDesativar.Enabled = false;
}
private void Pular_Load(object sender, EventArgs e)
{
}
void jump()
{
while (true)
{
if (GetAsyncKeyState(Keys.Space) <0)
{
mouse_event(m3DOWN, 0, 0, 0, 0);
Thread.Sleep(9);
mouse_event(m3UP, 0, 0, 0, 0);
Thread.Sleep(9);
}
Thread.Sleep(10);
}
}
private void btnAtivar_Click(object sender, EventArgs e)
{
btnAtivar.Enabled = false;
btnDesativar.Enabled = true;
Thread jp = new Thread(jump) { IsBackground = true };
jp.Start();
}
private void btnDesativar_Click(object sender, EventArgs e)
{
btnDesativar.Enabled = false;
btnAtivar.Enabled = true;
}
I'm trying to make a program where when I click left click it drags the mouse down without me moving my mouse down for a game but it does not move the game at all. It moves my cursor outside of the game but does not move inside the game.
public static Point Position { get; set; }
public Anti_Recoil()
{
InitializeComponent();
}
private void Anti_Recoil_Load(object sender, EventArgs e)
{
this.BackColor = Color.Wheat;
this.TransparencyKey = Color.Wheat;
this.TopMost = true;
int initialStyle = GetWindowLong(this.Handle, -20);
SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);
PointConverter pc = new PointConverter();
Point pt = new Point();
pt = (Point)pc.ConvertFromString("765, 500");
Cursor.Position = pt;
}
private void Anti_Recoil_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Z)
Hide();
}
Use my class
First, add my class to your project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Input;
namespace Hector.Framework.Utils
{
public class Peripherals
{
public class Mouse
{
public static int X
{
get => Cursor.Position.X;
}
public static int Y
{
get => Cursor.Position.Y;
}
public static void MoveToPoint(int X, int Y)
{
Win32.SetCursorPos(X, Y);
}
public static void Hide()
{
Cursor.Hide();
}
public static void Show()
{
Cursor.Show();
}
public static bool IsHidden
{
get => Cursor.Current == null;
}
/// <summary>
/// ButtonNumber: 0-None 1-Left 2-Middle 3-Right 4-XButton1 5-XButton2
/// </summary>
public static bool MouseButtonIsDown(int ButtonNumber)
{
bool outValue = false;
bool isLeft = Control.MouseButtons == MouseButtons.Left;
bool isRight = Control.MouseButtons == MouseButtons.Right;
bool isMiddle = Control.MouseButtons == MouseButtons.Middle;
bool isXButton1 = Control.MouseButtons == MouseButtons.XButton1;
bool isXButton2 = Control.MouseButtons == MouseButtons.XButton2;
switch (ButtonNumber)
{
case 0:
outValue = false;
break;
case 1:
outValue = isLeft;
break;
case 2:
outValue = isMiddle;
break;
case 3:
outValue = isRight;
break;
case 4:
outValue = isXButton1;
break;
case 5:
outValue = isXButton2;
break;
}
return outValue;
}
/// <summary>
/// This function is in Alpha Phase
/// </summary>
/// <param name="FocusedControl">The control that is scrolled; If the control has no focus, it will be applied automatically</param>
/// <param name="FontSize">This is used to calculate the number of pixels to move, its default value is 20</param>
static int delta = 0;
static int numberOfTextLinesToMove = 0;
static int numberOfPixelsToMove = 0;
public static bool GetWheelValues(Control FocusedControl, out int Delta, out int NumberOfTextLinesToMove, out int NumberOfPixelsToMove, int FontSize = 20)
{
try
{
if (FocusedControl == null) throw new NullReferenceException("The FocusedControl can not bel null");
if (!FocusedControl.Focused) FocusedControl.Focus();
FocusedControl.MouseWheel += (object sender, MouseEventArgs e) =>
{
delta = e.Delta;
numberOfTextLinesToMove = e.Delta * SystemInformation.MouseWheelScrollLines / 120;
numberOfPixelsToMove = numberOfTextLinesToMove * FontSize;
};
Delta = delta;
NumberOfTextLinesToMove = numberOfTextLinesToMove;
NumberOfPixelsToMove = numberOfPixelsToMove;
return true;
}
catch
{
Delta = 0;
NumberOfTextLinesToMove = 0;
NumberOfPixelsToMove = numberOfPixelsToMove;
return false;
}
}
private class Win32
{
[DllImport("User32.Dll")]
public static extern long SetCursorPos(int x, int y);
[DllImport("User32.Dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT point);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
}
}
}
}
Then where you need to check the mouse's status,
bool MouseLeftButton = Hector.Framework.Utils.Peripherals.Mouse.MouseButtonIsDown(1);
And try this:
private void Form2_Load(object sender, EventArgs e)
{
Hector.Framework.Utils.Peripherals.Mouse.MoveToPoint(300, 0); //Move the cursor to Top
}
//Then use timer to move the cursor
int a = 0;
private void timer1_Tick(object sender, EventArgs e)
{
Hector.Framework.Utils.Peripherals.Mouse.MoveToPoint(300, a += 1);
}
if(MouseLeftButton)
{
timer1.Start(); //timer is initialized
}
I been searching around for a solution for my problem but for now I wasn't able to get any sucessfull code for what I want to do. So, I have a form without border that is filled with 2 custom panels, so there is no way to the user click on the frame, thinking in that, I implement a code that when user click on a panel, this will call a function on my form that recive by parameter the event of the mouse.
This is the code of my Panel (note that both of my panels in the frame are the same class, it's just 2 diferent instances)
public class MyPanel : System.Windows.Forms.Panel{
(...)
private void MyPanel_MouseDown(object sender, MouseEventArgs e)
{
BarraSms.getInstance().mouseDown(e);
}
private void MyPanel_MouseMove(object sender, MouseEventArgs e)
{
BarraSms.getInstance().mouseMove(e);
}
}
And this is the code of my form:
public partial class BarraSms : Form
{
private Point mousePoint;
(...)
public void mouseDown(MouseEventArgs e) {
mousePoint = new Point(-e.X, -e.Y);
}
public void mouseMove(MouseEventArgs e) {
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Point mousePos = Control.MousePosition;
mousePos.Offset(mousePoint .X, mousePoint .Y);
this.Location = mousePos;
}
}
}
Is there something that I'm missing?
Thank you in advance for the help.
The working code (update), problem solved by: x4rf41
The MyPanel Class :
MouseMove += MyPanel_MouseMove; // added in class constructer
the BarraSms class (Form)
public partial class BarraSms : Form
{
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public void mouseMove(MouseEventArgs e) {
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
ReleaseCapture();
SendMessage(this.Handle, WM_NCLBUTTONDOWN, new IntPtr(HT_CAPTION), IntPtr.Zero);
Point loc = this.Location;
writeCoordToBin(loc.X, loc.Y);
}
}
}
There is much better solution for that using the windows api function.
The way you use it, you will have a problem when you move the form very fast and the mouse goes out of the panel. I had the exact same problem.
try this:
using System.Runtime.InteropServices;
and in your Form class
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public void mouseMove(MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
ReleaseCapture();
SendMessage(this.Handle, WM_NCLBUTTONDOWN, new IntPtr(HT_CAPTION), IntPtr.Zero);
}
}
no need for a mouseDown event for this
Your private methods in MyPanel cannot be called by the framework. You need to declare them as follows:
protected override void OnMouseDown(MouseEventArgs e)
{
var parent = this.Parent as BarraSms;
parent.mouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
var parent = this.Parent as BarraSms;
parent.mouseMove(e);
}
Try this:
public void mouseMove(MouseEventArgs e) {
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Point currentPos = Location;
currentPos.Offset(e.X + mousePoint.X, e.Y + mousePoint.Y);
this.Location = currentPos;
}
//Or simply use Location.Offset(e.X + mousePoint.X, e.Y + mousePoint.Y);
}
You have to use Location (the current location of the form), not the Control.MousePosition which is the location of mouse on screen.
UPDATE: Looks like you don't even know how to register event handlers, try modifying your panel class like this:
public class MyPanel : System.Windows.Forms.Panel{
//(...)
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
BarraSms.getInstance().mouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
BarraSms.getInstance().mouseMove(e);
}
}
I have a WPF application that by stakeholder requirement must have a WindowStyle="None", ResizeMode="NoResize" and AllowTransparency="True". I know that by not using the Windows chrome, you have to re-implement many of the OS window-handling features. I was able to create a working custom minimize button, however I was not able to re-implement the feature where Windows minimize the application when you click on the Taskbar icon at the bottom of your screen.
The user requirement is such that the application should minimize on taskbar icon click and restore on clicking again. The latter has never stopped working but I have not been able to implement the former. Here is the code that I am using:
public ShellView(ShellViewModel viewModel)
{
InitializeComponent();
// Set the ViewModel as this View's data context.
this.DataContext = viewModel;
this.Loaded += new RoutedEventHandler(ShellView_Loaded);
}
private void ShellView_Loaded(object sender, RoutedEventArgs e)
{
var m_hWnd = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(m_hWnd).AddHook(WindowProc);
}
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == NativeMethods.CS_DBLCLKS)
{
this.WindowState = WindowState.Minimized;
// handled = true
}
return IntPtr.Zero;
}
/// <summary>
/// http://msdn.microsoft.com/en-us/library/ms646360(v=vs.85).aspx
/// </summary>
internal class NativeMethods
{
public const int SC_RESTORE = 0xF120;
public const int SC_MINIMIZE = 0xF020;
public const int SC_CLOSE = 0xF060;
public const int WM_SYSCOMMAND = 0x0112;
public const int WS_SYSMENU = 0x80000;
public const int WS_MINIMIZEBOX = 0x20000;
public const int CS_DBLCLKS = 0x8;
NativeMethods() { }
}
Use ResizeMode="CanMinimize". This will allow you to minimize to the taskbar.
I have used this code in the past to minimize/maximize Windows using WPF's WindowStyle=None
private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
AdjustWindowSize();
}
private void AdjustWindowSize()
{
if (this.WindowState == WindowState.Maximized)
{
this.WindowState = WindowState.Normal;
}
else
{
this.WindowState = WindowState.Maximized;
}
}
private void FakeTitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton == MouseButton.Left)
{
if (e.ClickCount == 2)
{
AdjustWindowSize();
}
else
{
Application.Current.MainWindow.DragMove();
}
}
}
I just realized that if ResizeMode=NoResize than this happens, if it is equal to CanResize than you do not disable the OS feature to minimize via Taskbar icon click. I'm voting to close this question.
I want to hide my mouse cursor after an idle time and it will be showed up when I move the mouse. I tried to use a timer but it didn't work well. Can anybody help me? Please!
If you are using WinForms and will only deploy on Windows machines then it's quite easy to use user32 GetLastInputInfo to handle both mouse and keyboard idling.
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
}
And then in your Form
public partial class MyForm : Form
{
Timer activityTimer = new Timer();
TimeSpan activityThreshold = TimeSpan.FromMinutes(2);
bool cursorHidden = false;
public Form1()
{
InitializeComponent();
activityTimer.Tick += activityWorker_Tick;
activityTimer.Interval = 100;
activityTimer.Enabled = true;
}
void activityWorker_Tick(object sender, EventArgs e)
{
bool shouldHide = User32Interop.GetLastInput() > activityThreshold;
if (cursorHidden != shouldHide)
{
if (shouldHide)
Cursor.Hide();
else
Cursor.Show();
cursorHidden = shouldHide;
}
}
}
Here is a contrived example of how to do it. You probably had some missing logic that was overriding the cursor's visibility:
public partial class Form1 : Form
{
public TimeSpan TimeoutToHide { get; private set; }
public DateTime LastMouseMove { get; private set; }
public bool IsHidden { get; private set; }
public Form1()
{
InitializeComponent();
TimeoutToHide = TimeSpan.FromSeconds(5);
this.MouseMove += new MouseEventHandler(Form1_MouseMove);
}
void Form1_MouseMove(object sender, MouseEventArgs e)
{
LastMouseMove = DateTime.Now;
if (IsHidden)
{
Cursor.Show();
IsHidden = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan elaped = DateTime.Now - LastMouseMove;
if (elaped >= TimeoutToHide && !IsHidden)
{
Cursor.Hide();
IsHidden = true;
}
}
}
Need to account for Environment.Tickcount being negative:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
{
int idleTime = unchecked(Environment.TickCount - (int)plii.dwTime);
return TimeSpan.FromMilliseconds(idleTime);
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
}
If you try to hide the cursor from another thread you need to call Invoke(...) on the winform to enter the UI thread. Had cost me some headegg why Cursor.Hide() wasn't working. Also "PInvoke ShowCursor(bool bShow)" has the benefit to return the Show/Hide-Count.
[DllImport("user32.dll")]
static extern int ShowCursor(bool bShow);
private System.Timers.Timer _timerMouseAutoHide;
Point _lastPos = new Point(int.MaxValue);
readonly Stopwatch _stopwatch = new Stopwatch();
private int _cursorVisibilityCount = 0;
private void InitMouseAutoHide()
{
if (_timerMouseAutoHide != null)
return;
_timerMouseAutoHide = new Timer(100){AutoReset = false};
_timerMouseAutoHide.Elapsed += MouseAutoHideHit;
_timerMouseAutoHide.Start();
_stopwatch.Restart();
}
private void MouseAutoHideHit(object pSender, ElapsedEventArgs pE)
{
try
{
if (IsDisposed)
return;
var lCurrentPos = Cursor.Position;
var lCursorHasMoved = _lastPos != lCurrentPos;
_lastPos = lCurrentPos;
if (_cursorVisibilityCount < 0 && lCursorHasMoved)
{
//Cursor is not Visible and Mouse has moved
_cursorVisibilityCount = ShowCursor();
Debug.WriteLine($"Visible {lCurrentPos}, ShowCursor={_cursorVisibilityCount}");
}
else if (_cursorVisibilityCount > -1 && _stopwatch.ElapsedMilliseconds > 3000)
{
//Cursor is Visible and Mouse didn't move fox x ms.
_cursorVisibilityCount = HideCursor();
Debug.WriteLine($"Hidden {lCurrentPos}, ShowCursor={_cursorVisibilityCount}");
}
if (lCursorHasMoved)
_stopwatch.Restart();
}
catch (Exception lEx)
{
GLog.Error(lEx);
}
finally
{
_timerMouseAutoHide?.Start();
}
}
public int ShowCursor()
{
var lCursorVisibilityCount = 0;
Invoke(new Action(() =>
{
do
{
lCursorVisibilityCount = ShowCursor(true);
} while (lCursorVisibilityCount < 0);
}));
return lCursorVisibilityCount;
}
public int HideCursor()
{
var lCursorVisibilityCount = 0;
Invoke(new Action(() =>
{
do
{
lCursorVisibilityCount = ShowCursor(false);
} while (lCursorVisibilityCount > -1);
}));
return lCursorVisibilityCount;
}