I would like to get the key pressed by user on other application. For example, in notepad, not the program itself. Here is my coding that using PostMessage method to continuously send key to notepad but however, I wish to stop it when some key is pressed.
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(
string ClassName,
string WindowName);
[DllImport("User32.dll")]
public static extern IntPtr FindWindowEx(
IntPtr Parent,
IntPtr Child,
string lpszClass,
string lpszWindows);
[DllImport("User32.dll")]
public static extern Int32 PostMessage(
IntPtr hWnd,
int Msg,
int wParam,
int lParam);
private const int WM_KEYDOWN = 0x100;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(Test));
t.Start();
}
Boolean ControlKeyDown = true;
public void Test()
{
// retrieve Notepad main window handle
IntPtr Notepad = FindWindow("Notepad", "Untitled - Notepad");
if (!Notepad.Equals(IntPtr.Zero))
{
// retrieve Edit window handle of Notepad
IntPtr Checking = FindWindowEx(Notepad, IntPtr.Zero, "Edit", null);
if (!Checking.Equals(IntPtr.Zero))
{
while (ControlKeyDown)
{
Thread.Sleep(100);
PostMessage(Checking, WM_KEYDOWN, (int)Keys.A, 0);
}
}
}
}
Hence, my idea is set the ControlKeyDown to false when user pressed X key in notepad. After research through internet, I found out this code and edited:
protected override void OnKeyDown(KeyEventArgs kea)
{
if (kea.KeyCode == Keys.X)
ControlKeyDown = false;
}
Yes, by this, it definitely will stop the looping but this is not I want as it will stop the loop when user presses X key on the program but not in notepad. This is because the KeyEventArgs is System.Windows.Forms.KeyEventArgs and not Notepad.
Need help :(
I guess you are looking for keyboard hooking. See this article, it is c++ but you appear to be agile in p/invoke so you probably get how to port it easily.
You might want to take a look at the SetWindowsHookEx function in the user32.dll.
I also user the gma.UserActivity library to do it in a project.
Related
Is it programmatically possible to turn a monitor on/off through code (C#)?
Did you even try googling it?
First hit:
http://www.codeproject.com/KB/cs/Monitor_management_guide.aspx
I am not surprised you need to use some DLL's supplied by Windows.
(I guessed you needed a C# solution, because that's the only tag you applied).
EDIT February 8th 2013:
It was mentioned that the solution no longer worked under Windows 7 en 8. Well here is one that works nicely under Windows 7, haven't tried Windows 8 yet.
http://cocoa.ninja/posts/Turn-off-your-monitor-in-Csharp.html
namespace MonitorOff {
public enum MonitorState {
MonitorStateOn = -1,
MonitorStateOff = 2,
MonitorStateStandBy = 1
}
public partial class Form1 : Form {
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
public Form1() {
InitializeComponent();
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
}
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) {
SetMonitorInState(MonitorState.MonitorStateOff);
}
private void button1_Click(object sender, EventArgs e) {
SetMonitorInState(MonitorState.MonitorStateOff);
}
private void SetMonitorInState(MonitorState state) {
SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
}
}
}
The answer https://stackoverflow.com/a/713504/636189 above works great for turning off a Windows 7/8 monitor but not for waking it up. On those systems you'll need to do something hackish like this (as found https://stackoverflow.com/a/14171736/636189):
[DllImport("user32.dll")]
static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);
private const int MOUSEEVENTF_MOVE = 0x0001;
private void Wake(){
mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero);
Sleep(40);
mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero);
}
Press the on/off button
If you want to do it in code, apparently this is possible in the Win32 API:
SendMessage hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, param
where WM_SYSCOMMAND = 0x112 and
SC_MONITORPOWER = 0xF170 and
param indicates the mode to put the monitor in:
-1 : on
2 : off
1 : energy saving mode
hWnd can be a handle for any window - so if you have a Form, something like this should work
int WM_SYSCOMMAND = 0x112;
int SC_MONITORPOWER = 0xF170;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
public static void Main(string[] args)
{
Form f = new Form();
bool turnOff = true; //set true if you want to turn off, false if on
SendMessage(f.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)(turnOff ? 2 : -1));
}
Note I haven't actually tried this...
For who wants this functionality on a console application:
using System;
using System.Runtime.InteropServices;
using System.Timers;
namespace TurnScreenOFF
{
class Program
{
private static int WM_SYSCOMMAND = 0x0112;
private static uint SC_MONITORPOWER = 0xF170;
public static void Main(string[] args)
{
SendMessage(GetConsoleWindow(), WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
}
}
Adaptated and tested. 100% working on Windows 8.
This code can be useful for turning on and turning off.. It worked in Windows 7 also.
private int SC_MONITORPOWER = 0xF170;
private uint WM_SYSCOMMAND = 0x0112;
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
enum MonitorState
{
ON = -1,
OFF = 2,
STANDBY = 1
}
private void SetMonitorState(MonitorState state)
{
Form frm = new Form();
SendMessage(frm.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)state);
}
For calling the function you must do like:
SetMonitorState(MonitorState.ON);
OR
SetMonitorState(MonitorState.OFF);
Note: This code tested in WPF Application. With the below namespaces:
using System.Runtime.InteropServices;
using System.Windows.Forms;
I could not find a copy paste example, so created one myself, dont forget to add a reference to System.Windows.Forms.
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace monitor_on_off
{
class Program
{
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);
private const int WmSyscommand = 0x0112;
private const int ScMonitorpower = 0xF170;
private const int MonitorShutoff = 2;
private const int MouseeventfMove = 0x0001;
public static void MonitorOff(IntPtr handle)
{
SendMessage(handle, WmSyscommand, (IntPtr)ScMonitorpower, (IntPtr)MonitorShutoff);
}
private static void MonitorOn()
{
mouse_event(MouseeventfMove, 0, 1, 0, UIntPtr.Zero);
Thread.Sleep(40);
mouse_event(MouseeventfMove, 0, -1, 0, UIntPtr.Zero);
}
static void Main()
{
var form = new Form();
while (true)
{
MonitorOff(form.Handle);
Thread.Sleep(5000);
MonitorOn();
Thread.Sleep(5000);
}
}
}
}
I have gone through every single method that everyone has published for putting a monitor to sleep and waking it later at some other time. Granted the SendMessage() does work with Windows XP but it doesn't wake the monitor after the monitor has been a sleep for a period of time. I have tried using C#, DOS, scripts for playing with power profiles, and Powershell. Eventually I gave up and went back to the beginning and my first thought was proven correct. You need to use the PostMessage() after the monitor has been turned off, better yet, you should probably always use PostMessage();
So all the code that you have seen before is correct, instead use the following:
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern IntPtr PostMessage(int hWnd, int msg, int wParam, int lParam);
PostMessage(-1, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
At this time of execution and working appropriately (May 11, 2015) I am running
Windows 7 Professional Version 6.1.7601 Service Pack 1 Build 7601
Visual Studio Profesional 2013 Version 12.0.31101.00 Update 4
.NET Framework 4.5.51209
C#
My system is completely up to date.
The answer with the least SLOC:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
static class Program
{
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[STAThread]
static void Main()
{
SendMessage(new Form().Handle, 0x0112, 0xF170, 2);
}
}
For Windows 10 (tested on Pro 64 bits), I was able to turn off the monitor using the SendMessage() technique mentioned in this page.
However, impossible for me to turn the monitor back on: the "mouse move" trick did not work, the SendMessage() technique would turn the screen back on for one second then back off and using PostMessage() did not change anything.
But the trick is in fact really simple, all I had to do was simulate a keypress with SendKeys(). I'm using ALT here because in itself it has no impact on the system but it could be any other key.
SendKeys.SendWait("%");
If you're not using Windows.Forms, sending "ALT" also works using SendInput() but it's longer to implement.
I want to minimize a window using C#
Ex : I have opened this path E:\ using
process.start(E:\)
And I want to minimize this path on a certain event.
How can I make that possible?
The following sample Console Application code will minimize all shell explorer views that are opened on E:\ :
class Program
{
static void Main(string[] args)
{
// add a reference to "Microsoft Shell Controls and Automation" COM component
// also add a 'using Shell32;'
Shell shell = new Shell();
dynamic windows = shell.Windows(); // this is a ShellWindows object
foreach (dynamic window in windows)
{
// window is an WebBrowser object
Uri uri = new Uri((string)window.LocationURL);
if (uri.LocalPath == #"E:\")
{
IntPtr hwnd = (IntPtr)window.HWND; // WebBrowser is also an IWebBrowser2 object
MinimizeWindow(hwnd);
}
}
}
static void MinimizeWindow(IntPtr handle)
{
const int SW_MINIMIZE = 6;
ShowWindow(handle, SW_MINIMIZE);
}
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
It's using the Shell Objects for Scripting. Note the usage of the dynamic keyword that's mandatory here because there is no cool typelib, and therefore no intellisense either.
Shell32.Shell objShell = new Shell32.Shell();
objShell.MinimizeAll();
this will help you to minimize all the window Not only Folders all(something like windows + M!!!
Your question is not very clear. If you are using a TreeView control see
MSDN Treeview class. You can then: Expand or Collapse items at will.
You can use the configuration file or a Variable
This is a possible solution and only minimizes the window u opened:
private int explorerWindowNumber;
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MINIMIZE = 0xF020;
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetForegroundWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
public void button1_Click(object sender, EventArgs e)
{
//Start my window
StartMyExplorer();
}
private void StartMyExplorer()
{
Process.Start("D:\\");
Thread.Sleep(1000);
//Get the window id (int)
explorerWindowNumber = GetForegroundWindow();
}
private void button2_Click(object sender, EventArgs e)
{
//Minimize the window i created
SendMessage(explorerWindowNumber, WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
I'm making a simple WinForm car race game. I've got two objects - cars, and they move on the form when key is pressed (Form1KeyDown_Event).
The only thing is, that when one player press a key, the other player cannot press his key (nothing happens). But when the first player releases the key, second player can press one his keys and normally control his car.
How can I listen for two player keys simultaneously? Should I use threads and have each car on its own thread?
Here's a simple example of what you can do in order to listen to several keys at the same time, using the keyup and keydown events instead.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WinFormTest {
public partial class Form1 : Form {
private readonly IDictionary<Keys, bool> downState;
public Form1() {
InitializeComponent();
downState = new Dictionary<Keys, bool>();
downState.Add(Keys.W, false);
downState.Add(Keys.D, false);
KeyDown += remember;
KeyUp += forget;
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
Timer timer = new Timer() { Interval = 100 };
timer.Tick += updateGUI;
timer.Start();
}
private void remember(object sender, KeyEventArgs e) {
downState[e.KeyCode] = true;
}
private void forget(object sender, KeyEventArgs e) {
downState[e.KeyCode] = false;
}
private void updateGUI(object sender, EventArgs e) {
label1.Text = downState[Keys.W] ? "Forward" : "-";
label2.Text = downState[Keys.D] ? "Right" : "-";
}
}
}
You might want to investigate going lower-level and using windows hooks to detect keyboard events. This requires P/Invoking into native methods, but is pretty straight-forward. The hook you'd want is WH_LL_KEYBOARD. Details can be found at pinvoke.net.
You'd need a bit of boilerplate, but it's as close to the keyboard events as you can reasonably expect to get:
[StructLayout(LayoutKind.Sequential)]
public struct KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
public delegate IntPtr LowLevelKeyboardProc(int, IntPtr, KBDLLHOOKSTRUCT);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idhook, LowLevelKeyboardProc proc, IntPtr hMod, uint threadId);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (var curProc = Process.GetCurrentProcess())
using (var curMod = curProc.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curMod.ModuleName), 0u);
}
}
public IntPtr MyKeyboardHook(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT keyboardInfo)
{
if (code < 0)
{
return CallNextHookEx(IntPtr.Zero, wParam, ref keyboardInfo);
}
// Do your thing with the keyboard info.
return CallNextHookEx(IntPtr.Zero, code, wParam, ref keyboardInfo);
}
Make sure to unhook your handler when your app stops needing it. The KBDLLHOOKSTRUCT encapsulates all the info Windows will give you about a keyboard event; details of its members can be found at MSDN.
One detail of this kind of hook is that it gets executed on the thread that registered it, so make sure you take note of that, and don't set it on the UI thread if it's going to do anything long-running.
Im trying to get my program to send messages to control volume but I need a handle.
I currently tried to use broadcast as seen below in the current code but that would cause all processes to send a message causing volume to go up to 100 or 0 and freezing the program. Ive tried using Process.GetCurrentProcess().MainWindowHandle; but that only works if I have a form or command prompt. Note I wish to have this program work using my a modification of my current code.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Utilities
{
static class VolumeMessage
{
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
private static IntPtr Handle = (IntPtr)0xffff;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
public static void Mute()
{
SendMessageW(Handle, WM_APPCOMMAND, Handle,
(IntPtr)APPCOMMAND_VOLUME_MUTE);
}
public static void volumeDown()
{
SendMessageW(Handle, WM_APPCOMMAND, Handle,
(IntPtr)APPCOMMAND_VOLUME_DOWN);
}
public static void volumeUp()
{
SendMessageW(Handle, WM_APPCOMMAND, Handle,
(IntPtr)APPCOMMAND_VOLUME_UP);
}
}
}
You can use
var handle = Process.GetProcessesByName("explorer").First().MainWindowHandle;
Note that for the second parameter you can pass IntPtr.Zero
BTW I faced the same problem, also with mute/volume control...
I think you sometimes just need a form to get windows messages working right, so create one and make it always hidden. We've had to so this previously for something along these lines.
If you really want to do it this way then you could send it to the desktop hwnd I believe. From memory there is an API to get this hwnd which is just something like GetDesktopWindow or something like that.
However there has got to be a better way. Surely an API exists to directly control the volume.
Looking for hints, tips and search terms for changing the text on a win32 window from C#.
More specifically, I'm trying to change the text on the print dialog from "Print" to "OK", as I am using the dialog to create a print ticket and not do any printing.
How can I find the dialog's window handle? Once I've got it, how would I go about finding the button in the child windows of the form? Once I've found that, how would I change the text on the button? And how can I do all this before the dialog is shown?
There's a similar question here, but it points to a CodeProject article that is waaay more complex than needed and is taking me a bit longer to parse through than I'd like to spend on this. TIA.
You should use Spy++ to take a look at the dialog. The class name is important and the control ID of the button. If it is a native Windows dialog then the class name should be "#32770". In which case you'll have a lot of use for my post in this thread. Here is another in C#. You change the button text by P/Invoking SetWindowText() on the button handle.
using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class SetDialogButton : IDisposable {
private Timer mTimer = new Timer();
private int mCtlId;
private string mText;
public SetDialogButton(int ctlId, string txt) {
mCtlId = ctlId;
mText = txt;
mTimer.Interval = 50;
mTimer.Enabled = true;
mTimer.Tick += (o, e) => findDialog();
}
private void findDialog() {
// Enumerate windows to find the message box
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
if (!EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) mTimer.Enabled = false;
}
private bool checkWindow(IntPtr hWnd, IntPtr lp) {
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got it, get the STATIC control that displays the text
IntPtr hCtl = GetDlgItem(hWnd, mCtlId);
SetWindowText(hCtl, mText);
// Done
return true;
}
public void Dispose() {
mTimer.Enabled = false;
}
// P/Invoke declarations
private const int WM_SETFONT = 0x30;
private const int WM_GETFONT = 0x31;
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern IntPtr GetDlgItem(IntPtr hWnd, int item);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SetWindowText(IntPtr hWnd, string txt);
}
Usage:
using (new SetDialogButton(1, "Okay")) {
printDialog1.ShowDialog();
}