SetForegroundWindow Win32-API not always works on Windows-7

BIG NOTE

After messing with this API for the last 2 months, the solution/s below are all not stable solutions, but they work in some/most cases, depends on your environment, so keep that in mind.
 

The solution

The trick is to make windows ‘think’ that our process and the target window (hwnd) are related by attaching the threads (using AttachThreadInput API) and using an alternative API: BringWindowToTop.
 
Forcing Window/Internet Explorer to the foreground

private static void ForceForegroundWindow(IntPtr hWnd)
{
    uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), 
        IntPtr.Zero);
    uint appThread = GetCurrentThreadId();
    const uint SW_SHOW = 5;
if (foreThread != appThread)
    {
        AttachThreadInput(foreThread, appThread, true);
        BringWindowToTop(hWnd);
        ShowWindow(hWnd, SW_SHOW);
        AttachThreadInput(foreThread, appThread, false);
    }
    else
    {
        BringWindowToTop(hWnd);
        ShowWindow(hWnd, SW_SHOW);
    }
}

A more advanced implementation of AttachedThreadInputAction pattern
The idea is to attach to the target process thread and preform an action.

public static void AttachedThreadInputAction(Action action)
{
    var foreThread = GetWindowThreadProcessId(GetForegroundWindow(), 
        IntPtr.Zero);
    var appThread = GetCurrentThreadId();
    bool threadsAttached = false;
try
    {
        threadsAttached =
            foreThread == appThread ||
            AttachThreadInput(foreThread, appThread, true);
if (threadsAttached) action();
        else throw new ThreadStateException("AttachThreadInput failed.");
    }
    finally
    {
        if (threadsAttached)
            AttachThreadInput(foreThread, appThread, false);
    }
}

Usage

public const uint SW_SHOW = 5;
///<summary>
/// Forces the window to foreground.
///</summary>
///hwnd”>The HWND.</param>
public static void ForceWindowToForeground(IntPtr hwnd)
{
    AttachedThreadInputAction(
        () =>
        {
            BringWindowToTop(hwnd);
            ShowWindow(hwnd, SW_SHOW);
        });
}
public static IntPtr SetFocusAttached(IntPtr hWnd)
{
    var result = new IntPtr();
    AttachedThreadInputAction(
        () =>
        {
            result = SetFocus(hWnd);
        });
    return result;
}

Importing Win32-API to do the job

[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, 
    out uint lpdwProcessId);
// When you don't want the ProcessId, use this overload and pass 
// IntPtr.Zero for the second parameter
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, 
    IntPtr ProcessId);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
/// The GetForegroundWindow function returns a handle to the 
/// foreground window.
[DllImport("user32.dll")] 
public static extern IntPtr GetForegroundWindow(); 
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, 
    uint idAttachTo, bool fAttach); 
[DllImport("user32.dll", SetLastError = true)] 
public static extern bool BringWindowToTop(IntPtr hWnd); 
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(HandleRef hWnd); 
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

Abstract

After an interesting research, a solution found to force a window to the top in order to simulate user key presses using SendKeys.

Problem description

We want to type-keys to simulation user key presses like: strings, enters, tabs…
We are using SendKeys API. This API require that the wanted target window will be in the foreground and the wanted control will be in focus.
Seems that since 2007, Vista added  UAC (User Account Control) and , in a nutshell, SetForegroundWindow is not working as expected.
After researching the problem, the behavior is that calling SetForegroundWindow for the first time fails (returns false).
After extensive research and readings, it seems that ‘SetForegroundWindow’ have new rules (for security reasons) and the main idea is that ‘An application can’t force another application to be in the foreground, unless it created it or related to it somehow’ (the full rules can be found here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx, see ‘Rules’)

Resources

转载于:https://www.cnblogs.com/cicaday/p/5549252.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值