1

I'm having trouble figuring out the correct way to raise an event only if the desired window handle can be found (ie. "DesiredWindow" is currently running on the machine).

Currently, my application will SetForegroundWindow and send a keypress to the proper window as long as that application is running; My issue is: If the desired window isn't available (ie. the target application is not running), it will still send the keypress to any active window when the event is raised, even though I've specified the window handle that I want to send it to, and that window handle does not exist on the system.

What I'm wondering is: Is it possible to tell my application to only send the keypress if the particular lpWindowName exists, and do nothing if the specified window name cannot be found?

Pseudo code:

public partial class form1: Form
{
    [DllImport("User32.dll")]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("User32.dll")]
    static extern int SetForegroundWindow(IntPtr hWnd);
    static IntPtr DesiredWindow = FindWindow(null, "(Desired Window Name)");

    public form1()
    {
        InitializeComponent();
    }

    //...

                private void MyEvent()
            {   
                if (DesiredWindow cannot be found)
                {
                 return; //Do not send KeyPress
                }

                SetForegroundWindow(DesiredWindow); 
                Thread.Sleep(50);
                Keyboard.KeyPress(Keys.(WhateverKey));
            }
}

I've tried:

            private void MyEvent()
            {                       
                if (!DesiredWindow)
                {
                    MessageBox.Show("DesiredWindow not found");
                    return;
                }                  
                SetForegroundWindow(DesiredWindow);
                Thread.Sleep(50);
                Keyboard.KeyPress(Keys.WhateverKey);
            }

But I get the error Operator '!' cannot be applied to operand of type 'IntPtr'

I've also tried:

            private void MyEvent()
            {                       
                if (DesiredWindow == IntPtr.Zero)
                {
                    MessageBox.Show("DesiredWindow not found");
                    return;
                }                  
                SetForegroundWindow(DesiredWindow);
                Thread.Sleep(50);
                Keyboard.KeyPress(Keys.WhateverKey);
            }

But nothing seems to happen when I use this method.

I've added MessageBox.Show("DesiredWindow not found"); into the if statement to let me know if it's working, but the messagebox pops up even when the desired window is available.

Another method I've tried is:

            private void MyEvent()
            {                       
                if (DesiredWindow > 0)
                {                  
                SetForegroundWindow(DesiredWindow);
                Thread.Sleep(50);
                Keyboard.KeyPress(Keys.WhateverKey);
                }
            }

But I get the error Operator '>' cannot be applied to operand of type 'IntPtr' or 'Int'

I'm not sure the correct way of checking to see if DesiredWindow exists.

Patrick
  • 430
  • 6
  • 21
  • `else if (msg.Equals("Message"))` what is this..? are you missing some code..? – MethodMan Feb 19 '16 at 17:14
  • Sorry, that's just what triggers my event. It's a TCP client/server app where the server sends a different keystroke depending on the message it receives from the client. I suppose I'll leave that part out, to avoid confusion – Patrick Feb 19 '16 at 17:17
  • @MethodMan I edited the question to avoid confusion on the event being raised, and added more detail on my attempts. – Patrick Feb 19 '16 at 17:47
  • SetForegroundWindow() returns *bool*. Don't waste it. – Hans Passant Feb 19 '16 at 19:02
  • @HansPassant I'm not quite sure what you mean by that. Would you mind elaborating? Thanks – Patrick Feb 19 '16 at 19:22
  • 1
    It returns *false* when the handle you passed is not valid or because you were not allowed to change the foreground window. Never attempt to send anything when you get *false*, it won't go to the right window. – Hans Passant Feb 19 '16 at 19:25
  • How could I update my code to tell it not to send the keypress if `SetForegroundWindow(DesiredWindow)` returns false? – Patrick Feb 19 '16 at 19:28

1 Answers1

1

Not sure if you had referenced the right libraries, I have tried your codes and they worked without any problem. Please see the working codes as below:

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("User32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll")]
        private static extern int SetForegroundWindow(IntPtr hWnd);

        private const string DesiredWindowTitle = "(Desired Window Name)";

        // do not invoke the method to find the window when the form was constructing
        // private static IntPtr DesiredWindow = FindWindow(null, DesiredWindowTitle);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // find the window at run time
            IntPtr DesiredWindow = FindWindow(null, DesiredWindowTitle);

            if (DesiredWindow == IntPtr.Zero)
            {
                return; //Do not send KeyPress
            }

            SetForegroundWindow(DesiredWindow);
            Thread.Sleep(50);
            Keyboard.KeyPress(Keys.(WhateverKey));
        }
    }
}
Lin Song Yang
  • 1,936
  • 19
  • 17
  • Thanks, that worked perfectly. On a side note: Is there a reason I need to find the window when the event is raised, rather than when the form is constructed? Just for future reference, because in my mind (I'm very much a beginner) it just seemed like a cleaner method, with less code, but obviously was incorrect. – Patrick Feb 19 '16 at 21:26
  • Not sure the reason why, guess at that time when the form was constructing, the underlying OS is trying to allocate a new window handle to the new form. Meanwhile, at the time when your event is raised, the window handle previously found may be not there any more, so the handle could be invalid. – Lin Song Yang Feb 19 '16 at 21:34
  • Hmm okay. I only asked because I have around 100 almost identical events, so that ends up being a lot of lines of code for something so simple... I'll see if I can figure out another way to tidy it up; if not, I guess it's time to get my copy/paste on... Thanks for your help – Patrick Feb 19 '16 at 21:48
  • 1
    Pat, you could wrap the logic to a separate method, and then invoke that method from your 100~ events :) – Lin Song Yang Feb 19 '16 at 22:03
  • That's what I've been working on. Still trying to sort it out, but if I run into trouble, I'll ask a new question. Thank you – Patrick Feb 19 '16 at 22:13