Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Your problem in fact is to allow your <code>Console</code> application to control the <code>Winforms</code> application. So to make it simple, I make this demo and it's easy to implement your own way:</p> <p>Your <code>Console</code> application code:</p> <pre><code> //Must add reference to System.Drawing.dll //using namespaces: using System.Runtime.InteropServices; using System.Drawing; //.......................... class Program { //This is used to send custom message to your Winforms [DllImport("user32")] private static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); //This is used to find your winforms window [DllImport("user32", CharSet=CharSet.Auto)] private static extern IntPtr FindWindow(string className, string windowName); //This is used to register custom message so that it's ensured to be unique [DllImport("user32")] private static extern int RegisterWindowMessage(string msgName); //Our main method static void Main(string[] args) { int red = RegisterColorCode(Color.Red); int yellow = RegisterColorCode(Color.Yellow); while (true) { Console.Write("Enter color letter: "); string r = Console.ReadLine().ToLower(); int msg = 0; if(r == "r") msg = red; if(r == "y") msg = yellow; //You can define more colors if (hwnd == IntPtr.Zero) hwnd = FindWindow(null, "Winforms Application"); if(hwnd != IntPtr.Zero) SetBackColor(msg); } } IntPtr hwnd = IntPtr.Zero; static int RegisterColorCode(Color c){ return RegisterWindowMessage(c.ToString()); } static void SetBackColor(int colorCode){ SendMessage(hwnd, colorCode, IntPtr.Zero, IntPtr.Zero); } } </code></pre> <p>Your <code>Winforms</code> application code:</p> <pre><code>public class Form1 : Form { [DllImport("user32")] private static extern int RegisterWindowMessage(string msgName); public Form1(){ InitializeComponent(); red = RegisterColorCode(Color.Red); yellow = RegisterColorCode(Color.Yellow); //Set your form caption to a specified (must be unique at the time it runs) Text = "Winforms Application"; } int red,yellow;//you can define more private int RegisterColorCode(Color c){ return RegisterWindowMessage(c.ToString()); } protected override void WndProc(ref Message m) { switch(m.Msg){ case red: yourButton.BackColor = Color.Red; return; case yellow: yourButton.BackColor = Color.Yellow; return; } base.WndProc(ref m); } } </code></pre> <p>This is a very simple application model, it uses <code>Message</code> to communicate with other windows. However it has some limitation. As you can see, we have to define <code>certain Color codes</code> which can be sent from this to that in both sides. I'm trying to send any data from this to that via the <code>Message.WParam</code> and <code>Message.LParam</code> pointers. However it's not such easy. Different processes have different blocks of memory which are protected.</p> <p>I use <code>FindWindow</code> to find the <code>winforms window</code>, which is not always true (there may be some other windows having the same caption). However it's just for demonstrative purpose, it's not complete, it's just a demo. You can search for how to find the exact window (it's not too complicated, just more code to work with).</p> <p>If you want to send arbitrary data between windows, you can try other <code>IPC</code> approaches. If I can improve this answer (so that we can send arbitrary color from <code>Console</code> to your <code>winforms</code>), I'll update later.</p> <h2>UPDATE</h2> <p>The solution above works great for simple requirement, it just sends <strong>custom messages</strong> to signal what the sender wants the receiver to do. However to send arbitrary data, you have to send the message <code>WM_COPYDATA = 0x4a</code>. There is a struct of <code>COPYDATASTRUCT</code> which contains data to be sent and some code to identify what the sender wants the receiver to do. Here is the demo for you:</p> <p>Console code:</p> <pre><code> class Program { [DllImport("user32")] private static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam); [DllImport("user32", CharSet=CharSet.Auto)] private static extern IntPtr FindWindow(string className, string windowName); static void Main(string[] args) { IntPtr hwnd = IntPtr.Zero; while (true) { //require entering 3 elements of a Color: RED GREEN BLUE (each one is maximum at 255 and minimum at 0 Console.Write("Enter color R G B: ");//should enter something like 100 200 50 string[] s = Console.ReadLine().Split(new string[]{" "}, StringSplitOptions.RemoveEmptyEntries); Color colorToBeSent = Color.FromArgb(int.Parse(s[0]),int.Parse(s[1]), int.Parse(s[2])); COPYDATASTRUCT data = new COPYDATASTRUCT(); try { data.dwData = new IntPtr(123456); data.cbSize = Marshal.SizeOf(typeof(Color)); data.lpData = Marshal.AllocHGlobal(data.cbSize); Marshal.StructureToPtr(colorToBeSent, data.lpData, true); if (hwnd == IntPtr.Zero) hwnd = FindWindow(null, "Winforms Application"); if (hwnd != IntPtr.Zero) { SendMessage(hwnd, 0x4a, IntPtr.Zero, ref data); } } finally { Marshal.FreeHGlobal(data.lpData); } } } public struct COPYDATASTRUCT { public IntPtr dwData; public int cbSize; public IntPtr lpData; } </code></pre> <p>Winforms code:</p> <pre><code>public class Form1 : Form { public Form1() { InitializeComponent(); } protected override void WndProc(ref Message m){ if(m.Msg == 0x4a)//WM_COPYDATA { COPYDATASTRUCT data = (COPYDATASTRUCT) m.GetLParam(typeof(COPYDATASTRUCT)); if (data.dwData.ToInt32() == 123456)//Check if this is sent from your Console { Color c = (Color)Marshal.PtrToStructure(data.lpData, typeof(Color)); yourButton.BackColor = c; return; } } base.WndProc(ref m); } public struct COPYDATASTRUCT { public IntPtr dwData; public int cbSize; public IntPtr lpData; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload