I want to send message to other process already running. What wrong...? why I am not able to receive messages
My sender code is as below
public partial class RegisterWindowMessage : Form
{
[DllImport("User32.dll", EntryPoint = "SendMessage")]
//private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private static extern int SendMessage(IntPtr hWnd, int Msg, string s, int i);
const int WM_SETTEXT = 0X000C;
public RegisterWindowMessage()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Process[] procs = Process.GetProcesses();
foreach (Process p in procs)
{
if (p.ProcessName.Equals("TaskScheduling"))
{
IntPtr hWnd = p.MainWindowHandle;
Thread.Sleep(1000);
SendMessage(hWnd, WM_SETTEXT, "This is the new Text!!!", 0);
MessageBox.Show("Inside");
}
}
}
private void button2_Click(object sender, EventArgs e)
{
}
}
My receiver code is
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
}
private void frmReceiver_KeyDown(object sender, KeyEventArgs e)
{
// this.lsvMsgList.Items.Add(e.KeyValue.ToString());
}
protected override void WndProc(ref Message m)
{
MessageBox.Show(m.Msg.ToString());
MessageBox.Show(m.LParam.ToString());
MessageBox.Show(m.WParam.ToString());
if (m.LParam.ToInt32() == 1)
{
}
else
{
base.WndProc(ref m);
}
}
}
I want to know why i am not able to receive message. Let me know where I am wrong
Related
I currently have a Unity3D program being embedded in a WPF page using a WindowsFormsHost. However, whenever scrolling on the page when not focused on the unity application, the exe still captures that input and does what the Unity exe is supppossed to do. Is there some way to distinguish between what is from when Unity is focused and when it's not?
I've tried looking in the process class to see if there was any methods or properties related to focus, to no avail. I've also tried looking in Unity's native classes to check for focus on the application before accepting input, again to no avail.
This is how I'm embedding the application in WPF
[DllImport("User32.dll")]
static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private Process process;
private IntPtr unityHWND = IntPtr.Zero;
private const int WM_ACTIVATE = 0x0006;
private readonly IntPtr WA_ACTIVE = new IntPtr(1);
private readonly IntPtr WA_INACTIVE = new IntPtr(0);
private bool hasStartedOnce = false;
public UnityUserControl()
{
InitializeComponent();
try
{
StartProgram(this.Panel1.Handle.ToInt32());
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public void StopUnity()
{
process.Kill();
this.Refresh();
}
public Int32 GetPanelHandle()
{
return this.Panel1.Handle.ToInt32();
}
public void StartProgram(Int32 panelHandleInt)
{
try
{
if (File.Exists("SamMaintenanceRackRobot.exe"))
{
process = new Process();
process.StartInfo.FileName = "SamMaintenanceRackRobot.exe";
process.StartInfo.Arguments =
"-parentHWND " + panelHandleInt + " " + Environment.CommandLine;
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.WaitForInputIdle();
Thread.Sleep(1000);
EnumChildWindows(Panel1.Handle, WindowEnum, IntPtr.Zero);
this.Load += UserControl1_Loaded;
hasStartedOnce = true;
}
}
void UserControl1_Loaded(object sender, EventArgs e)
{
Window window = Application.Current.MainWindow;
window.Closing += window_Closing;
}
void window_Closing(object sender, global::System.ComponentModel.CancelEventArgs e)
{
DeactivateUnityWindow();
}
private void ActivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
}
private void DeactivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
}
private int WindowEnum(IntPtr hwnd, IntPtr lparam)
{
unityHWND = hwnd;
ActivateUnityWindow();
return 0;
}
private void panel1_Resize(object sender, EventArgs e)
{
MoveWindow(unityHWND, 0, 0, Panel1.Width, Panel1.Height, true);
ActivateUnityWindow();
}
I'm currently trying to set a single key as global hook. Howerver, I was perhaps wondering if it's possible to manipulate this code, so that a single button is set as a global hot key?
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
const int B = 0x42;
const int MOD_SHIFT = 0x0004;
const int WM_HOTKEY = 0x0312;
private void Form1_Load(object sender, EventArgs e)
{
RegisterHotKey(this.Handle, 1, B + MOD_SHIFT, (int)Keys.X);
RegisterHotKey(this.Handle, 2, B + MOD_SHIFT, (int)Keys.Y);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 1);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY && (int)m.WParam == 1)
MessageBox.Show("Hotkey X pressed.");
if (m.Msg == WM_HOTKEY && (int)m.WParam == 2)
MessageBox.Show("Hotkey Y pressed.");
base.WndProc(ref m);
}
}
}
I've a simple script which looks at the clipboard. Once it's changed it throws an event that looks at the text contained and uses that text to populate a datagrid.
The event is working perfectly fine and retrieve the text as expected, but when I try to add a row to the datagrid nothing happens. Any suggestion?
public void ClipBoardHasChanged(ClipboardMonitor m, ClipboardChangedEventArgs e)
{
string clipBoardValue = (string)e.ClipboardChangedEventArgsT.GetData(DataFormats.StringFormat, true);
this.dataGridView1.Rows.Add();
this.dataGridView1.Rows[0].Cells[0].Value = clipBoardValue;
}
The Class of Clipboard
namespace MarketMatrixCorrelation
{
[DefaultEvent("ClipboardChanged")]
public class ClipboardMonitor : Control
{
IntPtr nextClipboardViewer;
[DllImport("User32.dll")]
protected static extern int SetClipboardViewer(int hWndNewViewer);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
public ClipboardMonitor()
{
this.BackColor = System.Drawing.Color.Red;
this.Visible = false;
nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);
}
/// <summary>
/// Clipboard contents changed.
/// </summary>
public delegate void ClipboardChanged(ClipboardMonitor s, ClipboardChangedEventArgs e);
public event ClipboardChanged ClipboardChangedT = delegate { };
protected override void Dispose(bool disposing)
{
ChangeClipboardChain(this.Handle, nextClipboardViewer);
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
// defined in winuser.h
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
switch (m.Msg)
{
case WM_DRAWCLIPBOARD:
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
OnClipboardChanged();
break;
case WM_CHANGECBCHAIN:
if (m.WParam == nextClipboardViewer)
nextClipboardViewer = m.LParam;
else
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
default:
base.WndProc(ref m);
break;
}
}
//Catch when something is posted on the clipboard
private void OnClipboardChanged()
{
try
{
ClipboardChangedEventArgs iData = new ClipboardChangedEventArgs();
iData.ClipboardChangedEventArgsT = Clipboard.GetDataObject();
if (iData.ClipboardChangedEventArgsT.GetDataPresent(DataFormats.StringFormat))
{
ClipboardChangedT(this, iData);
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
public class ClipboardChangedEventArgs : EventArgs
{
private IDataObject DataObject;
public IDataObject ClipboardChangedEventArgsT
{
set
{
DataObject = value;
}
get
{
return this.DataObject;
}
}
}
}
Just place the ClipBoardMonitor in your Form and paste this in Form Load Event
private void Form1_Load(object sender, EventArgs e)
{
this.clipboardMonitor1.ClipboardChangedT += (o, ex) =>
{
string clipBoardValue = (string)ex.ClipboardChangedEventArgsT.GetData(DataFormats.StringFormat, true);
object[] row = { clipBoardValue };
this.dataGridView1.Rows.Add(row);
};
}
In C# Windows.Forms I want to intercept the paste-windowmessage for a combobox. As this doesn't work by overriding the WndProc-method of the combobox, because I would need to override the WndProc of the textbox inside the combobox, I decided to create a custom class of type NativeWindow which overrides the WndProc. I assign the handle and release it, when the combobox-handle gets destroyed. But when Dispose for the combobox is called the problem is that I get an InvalidOperationException saying that an invalid cross-thread operation occured and that the combobox was accessed from a thread other than the thread it was created on. Any ideas what is going wrong here?
In the following you'll see, how my classes look like:
public class MyCustomComboBox : ComboBox
{
private WinHook hook = null;
public MyCustomComboBox()
: base()
{
this.hook = new WinHook(this);
}
private class WinHook : NativeWindow
{
public WinHook(MyCustomComboBox parent)
{
parent.HandleCreated += new EventHandler(this.Parent_HandleCreated);
parent.HandleDestroyed += new EventHandler(this.Parent_HandleDestroyed);
}
protected override void WndProc(ref Message m)
{
// do something
base.WndProc(ref m);
}
private void Parent_HandleCreated(object sender, EventArgs e)
{
MyCustomComboBox cbx = (MyCustomComboBox)sender;
this.AssignHandle(cbx.Handle);
}
private void Parent_HandleDestroyed(object sender, EventArgs e)
{
this.ReleaseHandle();
}
}
}
Per Hans' suggestion, I modified the code to use CB_GETCOMBOBOXINFO from one of his own examples.
public class PastelessComboBox : ComboBox {
private class TextWindow : NativeWindow {
[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private struct COMBOBOXINFO {
public Int32 cbSize;
public RECT rcItem;
public RECT rcButton;
public int buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
private static extern IntPtr SendMessageCb(IntPtr hWnd, int msg, IntPtr wp, out COMBOBOXINFO lp);
public TextWindow(ComboBox cb) {
COMBOBOXINFO info = new COMBOBOXINFO();
info.cbSize = Marshal.SizeOf(info);
SendMessageCb(cb.Handle, 0x164, IntPtr.Zero, out info);
this.AssignHandle(info.hwndEdit);
}
protected override void WndProc(ref Message m) {
if (m.Msg == (0x0302)) {
MessageBox.Show("No pasting allowed!");
return;
}
base.WndProc(ref m);
}
}
private TextWindow textWindow;
protected override void OnHandleCreated(EventArgs e) {
textWindow = new TextWindow(this);
base.OnHandleCreated(e);
}
protected override void OnHandleDestroyed(EventArgs e) {
textWindow.ReleaseHandle();
base.OnHandleDestroyed(e);
}
}
In a KeyDown event I used SuppressKeyPress to avoid calling KeyPress and KeyUp events. However, although the KeyPress event was stopped the KeyUp event still fires. Why is this?
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.H)
{
listBox1.Items.Add("key down" + e.KeyCode);
// e.SuppressKeyPress = true;
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 'h')
{
listBox1.Items.Add("key press" + e.KeyChar);
}
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode==Keys.H)
{
listBox1.Items.Add("key up" + e.KeyCode);
}
}
Taking a look at how SuppressHeyPress is handled in Control class:
protected virtual bool ProcessKeyEventArgs(ref Message m)
{
// ...
if (e.SuppressKeyPress)
{
this.RemovePendingMessages(0x102, 0x102);
this.RemovePendingMessages(0x106, 0x106);
this.RemovePendingMessages(0x286, 0x286);
}
return e.Handled;
}
it's obvious you can't do something like this to suppress a WM_KEYUP message (when a you process the KeyDown event, a KeyPress message is already sent to your control, but the KeyUp message won't fire until the user release the key).
You can test this with following code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage([In, Out] ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove);
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int pt_x;
public int pt_y;
}
private void RemovePendingMessages(Control c, int msgMin, int msgMax)
{
if (!this.IsDisposed)
{
MSG msg = new MSG();
IntPtr handle = c.Handle;
while (PeekMessage(ref msg, new HandleRef(c, handle), msgMin, msgMax, 1))
{
}
}
}
private void SuppressKeyPress(Control c)
{
this.RemovePendingMessages(c, 0x102, 0x102);
this.RemovePendingMessages(c, 0x106, 0x106);
this.RemovePendingMessages(c, 0x286, 0x286);
}
private void SuppressKeyUp(Control c)
{
this.RemovePendingMessages(c, 0x101, 0x101);
this.RemovePendingMessages(c, 0x105, 0x105);
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.H)
{
SuppressKeyPress(sender); // will work
SuppressKeyUp(sender); // won't work
}
}
A solution would be to use a boolean flag suppressKeyUp, set it to true at KeyDown and check it and resetting it in KeyUp, but you'll have to check it thoroughly and see what happens when the user misbehaves (like pressing two keys).
Yeah, try putting
e.Handled = true;
after the e.Suppress... = true;.