tags:

views:

49

answers:

3

I 'answered' this in a related question - but it is more of an additional question that I having trouble with and I need more recent answers...

Basically I have an application that stays open on the screen and the user can press a button on my app once they have made an entry into one of three 3rd party applications.

When they click the button on my app, I need to determine which of the three applications they last used in order to know which database to talk to. I have gone down the route of looking at GetForeGroundWindow and GetWindow however the Window handle I get from GetWindow always refers to a window with title M. I have used the Winternal Explorer tool from the Managed Windows API tools and I can locate the M handle being returned and it is a 'child' of the process that I am after - but from this handle I cant get the process name.

I have done up a small example app using simple windows forms - and I lauch it and then make Notepad the focus and then click on my button and I get the handle - but when looking at the MainWindowHandle of all the processes, it is not listed, but using Winternal Explorer I can see that is a sub process of the notepad process.

Any suggestions on why I am only getting this subprocess handle returned instead of the actual process handle??

Sample code is below - being run on a Windows XP sp 3 machine

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

namespace TestWindowsAPI
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr thisWindow = GetForegroundWindow();
            IntPtr lastWindow = GetWindow(thisWindow, 2);

            tbThisWindow.Text = thisWindow.ToString();
            tbLastWindow.Text = lastWindow.ToString();
        }
    }
}
+2  A: 

You can use GetWindowThreadProcessId to get the process id from the (sub)window handle:

uint lastProcess;
GetWindowThreadProcessId(lastWindow, out lastProcess);
Pent Ploompuu
A: 

Try overriding the WndProc (or adding an IMessageFilter) for each of the programs and returning an "app ID" when a particular message is sent. Then just use SendMessage on the window handle to get the app ID.

wj32
+2  A: 

Pent Ploompuu - that was spot on - excellent work! Cheers

For anyone else - this is what my test function ended up looking like:

private void button1_Click(object sender, EventArgs e)
    {
        IntPtr thisWindow = GetForegroundWindow();
        IntPtr lastWindow = GetWindow(thisWindow, 2);

        uint processID = 0;
        var parentWindow = GetWindowThreadProcessId(lastWindow, out processID);

        tbThisWindow.Text = thisWindow.ToString();
        tbLastWindow.Text = lastWindow.ToString();
        tbParentWindow.Text = parentWindow.ToString();

        tbLastProcess.Text = processID.ToString();
        var processName = from cp in Process.GetProcesses() where cp.Id == processID select cp.ProcessName;

        tbParentName.Text = processName.FirstOrDefault();
    }
Paul T