tags:

views:

592

answers:

2

I would like to create a Windows Forms application that when run is only visible once another external window (notepad.exe) is enabled/focused. Any hints, I don't know where to begin.

If my form is running I would like it to popup when Notepad is enabled and disappear when Notepad loses focus.

A: 

You could try looking at the Windows automation APIs for C#. With these you should be able to look through all open windows and find Notepad. I haven't looked at the API's a bunch but best base scenario is that there would be a activate/lostfocus event for the window you could handle. Worst case, you could just poll every 100 ms or so and look to see if the Notepad window has focus.

Jacob Adams
A: 

You can do this simply with API calls and a timer. Add this line to your form's using statements:

using System.Runtime.InteropServices;

Next, add these declarations to your form:

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, 
    string lpWindowName); 

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

Finally, put a Timer on your form, and set its Enabled property to true. In its Tick event, put this code:

IntPtr hWndNotepad = FindWindow(null, "Whatever.txt - Notepad");
IntPtr hWndForegroundWindow = GetForegroundWindow();
if (this.Handle != hWndForegroundWindow)
{
    this.Visible = (hWndNotepad == hWndForegroundWindow);
}

I haven't tested this code, but it should work. The code is looking for a specific file to be open in Notepad; a different file would result in different text in the titlebar, so this code wouldn't work. I think that if you change the FindWindow call to FindWindow("notepad", null) it would work with any open instance of Notepad (it might be "notepad.exe" - not sure).

Update: if you want your form to be visible if any instance of Notepad is open, you can instead put this code into your Timer's Tick event:

IntPtr hWndForegroundWindow = GetForegroundWindow();
bool NotepadIsForeground = false;
Process[] procs = Process.GetProcessesByName("notepad");
foreach (Process proc in procs)
{
    if (proc.MainWindowHandle == hWndForegroundWindow)
    {
        NotepadIsForeground = true;
        break;
    }
}
if (this.Handle != hWndForegroundWindow)
{
    this.Visible = NotepadIsForeground;
}

And you'll need this in your using directives:

using System.Diagnostics;

Also not tested, but I'm doing so well today, so why bother?

MusiGenesis
That worked! It's the direction I want to go in. ThanksOne more question? If I click on my form it flashes continually instead of remaining focused (alternates between it and notepad). How do I fix it.
zion
@zion: oops, told you I didn't test it. What was happening was that as soon as you clicked your form, *it* became the foreground window, so the next time the timer went off, your form made itself invisible again. I fixed the code sample.
MusiGenesis
Erp, still not working quite right. Give me a second ...
MusiGenesis
@zion: OK, I just realized that from the way you phrased your question, you only want your form visible when Notepad is the focused window, so when you click on *your* form you would expect your form to then become invisible, since Notepad no longer has the focus. I think the simplest fix is to disable the timer in your form's Activated event, and then re-enable the timer in the form's Deactivate event. This sound right to you?
MusiGenesis
yeah that logic sounds correct, I appreciate the response and the code.
zion