Postmessage not being sent until window receives focus. C# .NET - c#

I'm trying to Postmessage send key inputs to an application. The issue is that the message is being sent only when the application becomes active or gains focus.
Here is my goal:
I need the application to receive inputs either while it is not focused, or via some pseudo-focus called via postmessage before the input is sent (I have tried: NativeMethods.PostMessage(mainHwnd, 0x0007, 0, 0); "0x0007" is WM_SETFOCUS but this doesn't do anything). Any assistance would be very helpful, I've been at this for more hours than I care to count.🙏
Here is all of the relevant code I'm using:
using System.Runtime.InteropServices;
using System;
using System.Windows.Forms;
using System.Threading;
internal static class NativeMethods
{
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, UInt32 uMsg, Int32 wParam, Int32 lParam);
}
class Test
{
const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
//const int WM_SETFOCUS = 0x0007;
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
public static void SendKey()
{
IntPtr mainHwnd = NativeMethods.FindWindow(null, "Test Application");
NativeMethods.PostMessage(mainHwnd, WM_KEYDOWN, (int)Keys.A, 0);
Thread.Sleep(50);
NativeMethods.PostMessage(mainHwnd, WM_KEYUP, (int)Keys.A, 0);
}
}
class TryTheThing{
public void Send() {
Test.SendKey();
}
}

Windows does not allow you to send keystrokes to non-focused applications. Your only option is to force the window to be focused first. This can be achieved by P/Invoking SetForegroundWindow():
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
NativeMethods.SetForegroundWindow(mainHwnd);

Related

user32.dll SendMessage VolumeUp and VolumeDown issue

I'm trying to make a Unity3D Application that can control the volume of another application. So far I've gotten it to work to change the volume of ALL applications, but I'm having trouble to get it to change just one, e.g. Spotify. This is on Windows 8, but I'd like it to work for Windows 7 as well.
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow();
public void DecreaseVolume()
{
IntPtr hWnd = FindWindow("SpotifyMainWindow", "Spotify");
if (hWnd == IntPtr.Zero)
return;
uint pID;
GetWindowThreadProcessId(hWnd, out pID);
Debug.Log(pID);
SendMessage(hWnd, WM_APPCOMMAND, hWnd, (IntPtr)APPCOMMAND_VOLUME_DOWN);
}
public void IncreaseVolume()
{
// same as above, but with APPCOMMAND_VOLUME_UP
}
I'm pretty sure I'm getting the correct handle (hWnd) from FindWindow() because the pID printed out matches the PID of Spotify in my Task Manager, however all this does is change the volume of everything instead of just Spotify. This is the same result as if I didn't specify a specific handle e.g.
SendMessage(IntPtr.Zero, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_DOWN);
or if I use GetActiveWindow().
I've never messed around with these windows api stuff until today, so any help would be very appreciated!

C# SetWindowsHookEx with DirectX

I'm about to write something like a screenshot programm. For now I used the PrintWindow function with the handle of the active window -> GetForgroundWindow and to start it I set a hook on the keyboard. When I capture normal windows on the desktop it's ok, besides there is no hardware accelerated effects, but in a game the hook doesn't seem to work. (I know, that the PrintWindow won't do anything here, I'm implementing a SlimDX class at the time) Is that some sort of a problem with the game-side modified message loop? And if yes, is there a way to make it work :D I would appreciate a C# way, cause I'm bad at programming UI with C++ ^^
I hope it is just some sort of bug...
Greetz Coldi
EDIT:
public class KeyboardHook
{
#region Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x0100;
static LowLevelKeyboardProc m_proc = HookCallback;
static IntPtr m_hookID = IntPtr.Zero;
static Screenshot m_screen;
public static void Hook(Screenshot screenshotManager)
{
m_screen = screenshotManager;
m_hookID = SetHook(m_proc);
}
public static void Unhook()
{
UnhookWindowsHookEx(m_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
#if DEBUG
Debug.WriteLine(((System.Windows.Forms.Keys)vkCode).ToString());
#endif
if ((System.Windows.Forms.Keys)vkCode == m_screen.CaptureKey)
{
m_screen.CaptureSimple();
}
}
return CallNextHookEx(m_hookID, nCode, wParam, lParam);
}
}
So on desktop it works pretty fine, but when I start a DirectX application, the keyhook doesn't get any pressed key (HookCallback isn't handeled)

c# capture scrolling window

I want to create a program, which could make screenshot of scrolling window. As opposed to making screenshots, scrolling another app is difficult for me. Basing on a few scripts from web, I’ve written that:
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;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace scroller
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
private void Form1_Load(object sender, EventArgs e)
{
List<IntPtr> result = new List<IntPtr>();
Thread.Sleep(5000);
IntPtr ParenthWnd = GetForegroundWindow();
if (!ParenthWnd.Equals(IntPtr.Zero))
{
StringBuilder myStringBuilder = new StringBuilder(256);
GetWindowText(ParenthWnd, myStringBuilder, 256);
this.Text = myStringBuilder.ToString();
IntPtr prevChild = IntPtr.Zero;
IntPtr currChild = IntPtr.Zero;
while (true)
{
currChild = FindWindowEx(ParenthWnd, prevChild, null, null);
if (currChild == IntPtr.Zero) break;
result.Add(currChild);
prevChild = currChild;
}
}
for(int i=0 ;i<=result.Count-1;i++){
IntPtr myHandle = result[i];
SetActiveWindow(ParenthWnd);
SwitchToThisWindow(myHandle, true);
SetScrollPos(myHandle, 0x1, 0, true);
PostMessage(myHandle, 0x115, 4 + 0x10000 * 0,0);
}
}
}
}
This waits 5 seconds, and moves scrollbars of all windows to top. It works e.g. with notepad, but not with web browsers, ms word and many others. What am I doing wrong?

Get key from any process

Ive seen many solutions online but none does exactly what I want. What is the best/simplest way to get any keys pressed in a given process (not my console applicaton) while my application is running in background. I dont need the modifiers or anything.
If you don't particularly care which process the keys are being pressed in the easiest method would be to call GetAsyncKeyState. It's rather limited though as it does not hook the keyboard and requires you to call it continuously. The best approach in my opinion is to hook the keyboard.
Using SetWindowsHookEx you can actually explicitly specify the identifier of the thread with which the hook procedure is to be associated so you can hook keys for a specific process (see dwThreadId).
Here's a class that you can use (originally found on a Micrsoft blog but I cannot seem to find the authors name at the moment!)
public delegate IntPtr KeyboardProcess(int nCode, IntPtr wParam, IntPtr lParam);
public sealed class KeyboardHook
{
public static event EventHandler<KeyPressedEventArgs> KeyPressed;
private const int WH_KEYBOARD = 13;
private const int WM_KEYDOWN = 0x0100;
private static KeyboardProcess keyboardProc = HookCallback;
private static IntPtr hookID = IntPtr.Zero;
public static void CreateHook()
{
hookID = SetHook(keyboardProc);
}
public static void DisposeHook()
{
UnhookWindowsHookEx(hookID);
}
private static IntPtr SetHook(KeyboardProcess keyboardProc)
{
using (Process currentProcess = Process.GetCurrentProcess())
using (ProcessModule currentProcessModule = currentProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD, keyboardProc, GetModuleHandle(currentProcessModule.ModuleName), 0);
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyPressed != null)
KeyPressed(null, new KeyPressedEventArgs((Keys)vkCode));
}
return CallNextHookEx(hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProcess lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
}
public class KeyPressedEventArgs : EventArgs
{
public Keys KeyCode { get; set; }
public KeyPressedEventArgs(Keys Key)
{
KeyCode = Key;
}
}
Implementation via Console Application:
class Program
{
static void Main(string[] args)
{
KeyboardHook.CreateHook();
KeyboardHook.KeyPressed += KeyboardHook_KeyPressed;
Application.Run();
KeyboardHook.DisposeHook();
}
static void KeyboardHook_KeyPressed(object sender, KeyPressedEventArgs e)
{
Console.WriteLine(e.KeyCode.ToString());
}
}
What you're looking for is called a global keyboard hook. You can find more information and examples on MSDN.
Oh, so you're looking for "Autofire" in old-school gaming terms?
Instead of writing your own keyboard hook app (unless you're doing it for fun/the thrill of it/the exercise) you might want to look at AutoIt or AutoHotkey, which are both pretty good for keyboard/mouse automation.
See this thread for instance... http://www.autohotkey.com/board/topic/40598-autofire-keyboard/
I have found a way to hook only for a process.
You may need it.
int ProcessId = GetProcessesByName("Your_app_here").FirstOrDefault().Id;
private IntPtr SetHook(KeyboardHookHandler proc)
{
return SetWindowsHookEx(13, proc, GetModuleHandle(Process.GetProcessById(ProcessId).MainModule.ModuleName), GetWindowThreadProcessId(GetModuleHandle(Process.GetProcessById(ProcessId).MainModule.ModuleName), out int MainThreadId));
}
Remember to import these methods.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookHandler lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

How to give input to a windows application programmatically?

This is with reference to this question:
How to read output and give input to a program from c program?
I found the answer to the above question very useful. In the same way, can I do it for windows applications? Like can I give input into a Windows form (like .net, C# applications) application's text box programmatically? Can I do the action of button click from a program?
If so, can I do it from a C program (with Tiny C compiler or any other on windows platform)? If not, how and in which language can I do it? Please don't take it as a silly question. Any example codes will be very much appreciated.
Edit: Can I do the same with web applications and web pages?
If your application mainly just needs to manipulate other windows, by sending keystrokes etc. i would use AutoIt. It's mainly function is exactly this job and it does it very well.
So maybe you should give it a try, cause not every problem is a nail and can be solved with a hammer (C#) ;-))
You can enumerate all the windows of the system.
You can send windows messages to any window.
E.g. to set the text of a textbox you have to send a WM_SETTEXT message.
FYI: Winspector is a very interesting tool which makes heavy use of this as well (also to debug or otherwise first inspect the windows you're trying to programmatically access).
You might also be interested in this:
AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required!
As fretje pointed out, you can certainly do it.
It's much more challenging for windows apps. Because individual controls also count as windows, the total window count will be much higher than you might expect; and finding the specific control you want to send input to can take a lot of work.
But you can programmatically move, resize, check, fill, maximize or otherwise affect an app's windows, once you know which one is your target.
I wrote code to do the discovery process a few years ago. It found all the windows of a target app, then using their size & location data, produced a translucent overlay of each child window, along with the handle number. So I could visually tell which control went with which handle.
EDIT: Added some code. This is some basic C# interop code that will let you make easy calls into user32.dll, which holds the fns to which fretje referred. This just gives you the basic calls for discovery and manipulation; you'll still have to do the hard work of enumerating and examining what you find. If you can find a 3rd-party package that does the job for you, save yourself the trouble; I only did it as a learning experience, and it was pretty laborious.
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
namespace WinAPI
{
[Flags] public enum WindowStyleFlags : uint
{
WS_OVERLAPPED = 0x00000000,
WS_POPUP = 0x80000000,
// more...
}
[Flags] public enum ExtendedWindowStyleFlags: int
{
WS_EX_DLGMODALFRAME = 0x00000001,
WS_EX_NOPARENTNOTIFY = 0x00000004,
// more...
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct POINT
{
public int Left;
public int Top;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct FLASHWINFO
{
public int cbSize;
public IntPtr hwnd;
public int dwFlags;
public int uCount;
public int dwTimeout;
}
public delegate int EnumWindowsCallback( IntPtr hwnd, int lParam );
public class User32Dll
{
// Constants & fields
public const int FLASHW_STOP = 0;
public const int FLASHW_CAPTION = 0x00000001;
// lots, lots more, web search for them...
// Self-added, don't know if correct
[DllImport("user32")]
public extern static bool CloseWindow( IntPtr hWnd );
[DllImport("user32")]
public extern static IntPtr GetDesktopWindow();
[DllImport("user32")]
public extern static IntPtr GetForegroundWindow();
[DllImport("user32")]
public extern static int GetDlgItem( IntPtr hWnd, int wMsg );
[DllImport("user32")]
public extern static int GetListBoxInfo( IntPtr hWnd );
[DllImport("user32")]
public extern static bool MoveWindow( IntPtr hWnd, int X, int Y, int Width, int Height, bool Repaint );
[DllImport( "user32" )]
public static extern int SendMessage( IntPtr hWnd, int uMsg, IntPtr wParam, StringBuilder lpString );
[DllImport("user32")]
public static extern bool SetWindowPos( IntPtr hWnd, IntPtr afterWnd, int X, int Y, int cX, int cY, uint uFlags );
[DllImport("user32")]
public extern static int BringWindowToTop (IntPtr hWnd);
[DllImport("user32")]
public extern static int EnumWindows( EnumWindowsCallback lpEnumFunc, int lParam );
[DllImport("user32")]
public extern static int EnumChildWindows( IntPtr hWndParent, EnumWindowsCallback lpEnumFunc, int lParam );
[DllImport( "user32.dll" )]
public static extern int EnumThreadWindows( IntPtr hWndParent, EnumWindowsCallback callback, int lParam );
[DllImport( "user32.dll" )]
public static extern int FindWindow( string lpClassName, string WindowName );
[DllImport( "user32.dll" )]
public static extern int FindWindowEx( IntPtr hWnd, IntPtr hWnd2, string lpsz, string lpsz2 );
[DllImport("user32")]
public extern static int FlashWindow ( IntPtr hWnd, ref FLASHWINFO pwfi);
[DllImport("user32")]
public extern static IntPtr GetAncestor( IntPtr hWnd, uint gaFlags );
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int GetClassName ( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static uint GetWindowLong( IntPtr hwnd, int nIndex);
[DllImport("user32")]
public extern static int GetClientRect( IntPtr hWnd, ref RECT lpRect);
[DllImport("user32")]
public extern static int GetWindowRect( IntPtr hWnd, ref RECT lpRect);
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int GetWindowText( IntPtr hWnd, StringBuilder lpString, int cch );
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int GetWindowTextLength( IntPtr hWnd );
[DllImport("user32")]
public extern static int IsIconic(IntPtr hWnd);
[DllImport("user32")]
public extern static int IsWindowVisible( IntPtr hWnd );
[DllImport("user32")]
public extern static int IsZoomed(IntPtr hwnd);
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int PostMessage( IntPtr hWnd, int wMsg, int wParam, int lParam);
[DllImport( "user32.dll" )]
public static extern int RealGetWindowClass( IntPtr hWnd, StringBuilder pszType, uint bufferSize );
[DllImport("user32")]
public extern static int ScreenToClient( IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int SendMessage( IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public extern static int SetForegroundWindow (IntPtr hWnd);
[DllImport( "user32.dll" )]
public static extern int SetWindowText( IntPtr hWnd, string lpsz );
}
}
Check out the following SO question. There are numerous vendor and open-source tools to do this for you, so you don't have to code at to the Win32 API.
automated-testing-of-windows-forms

Categories

Resources