views:

28

answers:

2

I have a method that gets called into a new thread like so:

    if (!_isPlaying)
    {
        _playBackThread = new Thread(PlayMacroEvents);
        _playBackThread.Start();
        ...
    }

The method looks like:

Process proc = Process.GetProcessesByName("notepad").FirstOrDefault();
            if (proc != null)
            {
                SetForegroundWindow(proc.MainWindowHandle);
            }

            int loopCount = this.dsUserInput.Tables[0].Rows.Count;
            for (int i = 0; i < loopCount; i++)
            {
                foreach(MacroEvent macroEvent in _events)
                { 
                    Thread.Sleep(macroEvent.TimeSinceLastEvent);
                    switch (macroEvent.MacroEventType)
                    {
            ...

The problem I'm having is that if notepad is not already up (not minimized) there is enough delay between setting the foreground window and the macro output that often the first series of commands is not shown. How can I put enough of a pause to make sure that the window is up before the the macros start kicking in? A Thread.Sleep() between SetForegroundWindow() and the for loop does not seem to do the trick. Ideas?

+1  A: 

Use some api to get the active window, and wait until the window belonging to notepad is the active one

Onkelborg
Which API should I look at?
manyxcxi
GetForegroundWindow ( http://msdn.microsoft.com/en-us/library/ms633505(VS.85).aspx ) is probably going to make it. P/Invoke: http://pinvoke.net/default.aspx/user32/GetForegroundWindow.html
Onkelborg
Ignoring the chance of an infinite loop I put in the following code and it still skips the first line of text input.IntPtr activeWindowHandle = GetForegroundWindow(); while ((!activeWindowHandle.Equals(proc.MainWindowHandle))) { if (!activeWindowHandle.Equals(proc.MainWindowHandle)) { activeWindowHandle = GetForegroundWindow(); } }
manyxcxi
Hm, might be something else.. If you make sure that notepad is the foreground window manually, and you don't invoke SetForegroundWindow, is everything executed as intended? (Use a timer or similar)
Onkelborg
What I found happening is that, no matter how long I sleep for, the application (notepad) always comes up, right AFTER the thread.sleep, even if the GetForegroundWindow is called BEFORE the thread.sleep.
manyxcxi
I finally figured it out! I need to ALSO call the ShowWindow user32 method (before the SetForegroundWindow).
manyxcxi
A: 

The reason the first series of inputs were being dropped is because I also had to include the command to ShowWindow like so..

in the class header:

private const int SW_RESTORE = 9;
[DllImport("user32")]
private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
...

In the macro thread method I changed

    if (proc != null)
    {
        SetForegroundWindow(proc.MainWindowHandle);
    }

to look like:

   if (proc != null)
    {

        ShowWindow(proc.MainWindowHandle, SW_RESTORE);
        SetForegroundWindow(proc.MainWindowHandle);
    }
manyxcxi