Moving console application into background at user's option - c#

I've seen a few solutions for the question in the title, but they all don't do what I want.
I have ch = Console.ReadKey().KeyChar; , if a user inputs 'y' I want the app to go into background. if user inputs 'n' the program continues like nothing happened. Is this possible? I did a lot of research but still couldn't find one that fits me.
Here is what i have till now:
char ch = '0';
Console.WriteLine("Enter Log File Destenation:");
string url = Console.ReadLine();
Console.WriteLine("Run In BackGround ? (Defaul Set to False)";
ch = Console.ReadKey().KeyChar;
if (ch == 'y')
{
//Move To Background
}
// continue with program
It's a bitcoin rate logger. it takes the bitrate from a websites title and logs it into a txt file which destination is set by user at the start of the program.
after the destination is set, it asks if it should run in the background or not.
either way the program enters a while(true) loop for log.

Use SetWindowPos method with the param HWND_BOTTOM
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out W32RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct W32RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public const uint HWND_BOTTOM = 1;
static void Main(string[] args)
{
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
W32RECT rect;
GetWindowRect(handle , out rect); //to get position and size of your console
SetWindowPos(handle, IntPtr.Zero, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, HWND_BOTTOM);//to set background position of your console with the same size and screen's position
}
}
}
Not tested but it will be working
Source : http://www.developpez.net/forums/d199635/environnements-developpement/delphi/setforegroundwindow-setbackgroundwindow/ (I can translate if you need)

Related

Creating a 'Ghost Mouse' to simulate mouse clicks

I know there are already a million threads about this, but I've spent countless hours trying to find a solution and i'm hoping I can find it here instead.
My goal is to create a 'Ghost mouse', meaning that I want to be able to simulate mouse clicks on a certain position in a minimized window, without moving my own cursor our mouse. I want to be able to browse the internet and click on other stuff, while the program does its own thing. This is a feature that many game bots have, but my intention is not to create a bot, but only to experience with.
So far i've managed to simulate mouse clicks, but with my actual mouse.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
public static void LeftClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
static void Main(string[] args)
{
System.Threading.Thread.Sleep(5000);
Point pt = new Point(1259, 560);
Cursor.Position = pt;
LeftClick();
}
As far as I know, calling mouse_event will not click in minimized windows.
You have to use SendMessage WinApi for this.
First, acquire a handle for the process, either using OpenProcess or Process.GetProcessesByName(processName).First().MainWindowHandle, then you may use the following code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
public static IntPtr makeLParam(int x, int y)
{
return (IntPtr)((y << 16) | x);
}
public static void sendMouseClick(IntPtr handle, int x, int y)
{
SendMessage(handle, WM_LBUTTONDOWN, (IntPtr)1, makeLParam(x, y));
SendMessage(handle, WM_LBUTTONUP, (IntPtr)1, makeLParam(x, y));
}
Please note that this code is a bit old and might not still work. Also, keep in mind the game protections prevents acquiring handles for the game process. In addition, some games might query the mouse position from the windows rather than using the ones provided with SendMessage

c# mouse_event does not fire on certain application

I am creating a console application that should simulate a click inside a certain application.
Im currently playing around with the external methods, for now i only want the program to click at the current mouse position every second:
public class Navigation
{
private const uint MOUSEEVENTF_MOVE = 0x0001;
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const uint MOUSEEVENTF_RIGHTUP = 0x0010;
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern bool SetCursorPos(uint x, uint y);
[DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
private string processName;
public Navigation(string processName)
{
this.processName = processName;
}
public void test()
{
while (true)
{
//SetForegroundWindow(Process.GetProcessesByName(processName)[0].MainWindowHandle);
Thread.Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN, 0, 0, 0, UIntPtr.Zero);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP, 0, 0, 0, UIntPtr.Zero);
}
}
}
When starting the program and running the test() method the mouse indeed clicks every second, i can move the mouse around the screen and it will click at everything, notepad, spotify etc... EXECPT for the one application that i want to target ...
That is, when i hover the mouse above the particular application i want to click on, nothing happens. I read about putting the target process in the foreground, if i do that the application is put in the foreground but it still does not recieve any clicks.
For example if i hover the mouse above a button inside the application i want to target my program does not click it. When moving the mouse back outside it starts simulating clicks again. Any thoughts?
EDIT: I am following this tutorial

What makes this click through?

I'm trying to figure out how this code works but I just can not figure out what makes it click through.
Yes, this code is not mine since i'm trying to learn/understand it.
Assume I want the tranparancy but not the click through what needs to be changed and why?
I have been over the Windows styles pages over and over and still can not get my head around the click through part.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class TransparentWindow : MonoBehaviour
{
[SerializeField]
private Material m_Material;
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const int HWND_TOPMOST = -1;
void Start()
{
#if !UNITY_EDITOR // You really don't want to enable this in the editor..
int fWidth = Screen.width;
int fHeight = Screen.height;
var margins = new MARGINS() { cxLeftWidth = -1 };
var hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
// Transparent windows with click through
SetWindowLong(hwnd, -20, 524288 | 32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes(hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
DwmExtendFrameIntoClientArea(hwnd, ref margins);
#endif
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
}
This function:
SetWindowLong(hwnd, -20, 524288 | 32);
does the trick. Windows implements the rule that Mircosoft made which is that a window that is transparent to the user must be transparent to the mouse.
With the transparency bit set WS_EX_TRANSPARENT the window becomes transparent to mouse too and click passes to the painted layer behind the transparent window.
You need not understand but make use of this 'OS feature' which was probably implemented to cover for something else.
Read this article about the subject and this answer that explains the parameters

c# Mouse click simulation to hwnd at x/y position

at the last 3 Days I found a lot of code for simulating mouse clicks to other windows. but none of them has worked.
I have the window handle hwnd and the X/Y position (pixel) where the click has to be.
The X/Y position is the position inside the window.
The best code I've found is this:
public void click(IntPtr hWnd, int x, int y)
{
RECT rec = new RECT();
GetWindowRect(hWnd, ref rec);
int newx = x - rec.Left;
int newy = y - rec.Top;
SendMessage(hWnd, WM_LBUTTONDOWN, 1, ((newy << 0x10) | newx));
SendMessage(hWnd, WM_LBUTTONUP, 0, ((newy << 0x10) | newx));
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr A_0, int A_1, int A_2, int A_3);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
But it does not work 100% correctly.
It simulates a mouseclick at the correct window, but at the position of my real cursor.
And after this click my mouse jumps to a random position on the screen.
I hope someone has a working code and a small description how it works.
Thanks
Use this code to simulate the left mouse click in a certain position
//This is a replacement for Cursor.Position in WinForms
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
//This simulates a left mouse click
public static void LeftMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}

C# : Application in which monitor?

There are two monitors and an application (e.g. IE) is currently active/displayed in the 2nd monitor. How do I detect if an application is in 1st or 2nd monitor.
I need to know this - to show a userform just on top of the application irrespective of the monitor in which it is. I know what the WindowText (Title) would be (if that helps).
Right now I just show my form near the system tray but would like to show it on top of the application.
// FORM POSITION
this.StartPosition = FormStartPosition.Manual;
Rectangle workArea = Screen.PrimaryScreen.WorkingArea;
int left = workArea.Width - this.Width;
int top = workArea.Height - this.Height;
this.Location = new Point(left, top);
This was converted from VB but should work.
The Test() method shows how you would use it.
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
public static RECT GetWindowLocationByName(string name)
{
IntPtr handle = FindWindow(default(string), name);
RECT result = default(RECT);
GetWindowRect(handle, ref result);
return result;
}
public static void Test()
{
dynamic location = GetWindowLocationByName("Untitled - Notepad");
Screen result = null;
foreach (Screen s in Screen.AllScreens) {
if (s.WorkingArea.IntersectsWith(new Rectangle(location.Left, location.Top, location.Right - location.Left, location.Bottom - location.Top))) {
result = s;
}
}
}
Edit: More Info
Step 1: Get the window handle
Step 2: Get the window rect (location/size)
Step 3: Determin which monitor the window resides on
If your looking at overlyaying one window on top of another you don't actually need to know which monitor it is on just the position and size of the window relative to the desktop. In both windows forms and WPF when you set the window location X / Left is the distance in pixels from the left side of the left most monitor. E.g if you have two montior 1024 pixels wide setting X / Left to 2000 will put the window 86 pixels into right hand monitor.
To get the windows position of another process you could use the library mentioned here
How to get and set the window position of another application in C#
You should then be able to check on which screen the position of the rectangle is
private Screen IsVisibleOnScreen(Rectangle rect)
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen.WorkingArea.IntersectsWith(rect))
{
return Screen;
}
}
return null;
}

Categories

Resources