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

SetForegroundWindow Win32-API not always works on Windows-7的更多相关文章

  1. C#调用Win32 api学习总结

    从.NET平台调用Win32 API Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微 ...

  2. 【.Net】从.NET平台调用Win32 API

    小序        Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制 ...

  3. Win32 API编程——前言

    一丶什么是Win32 API? 微软为了保护操作系统的安全性和稳定性,把系统分为内核层和用户层(内核层的代码只能在当CPU的特权级为R0状态下执行,用户层的代码在CPU特权级为R0和R3都能执行),w ...

  4. How to change windows applicatioin's position via Win32 API

    可以使用的Win32 API是: [DllImport("user32.dll")] private extern static bool SetWindowPos(IntPtr ...

  5. WIN32 API ------ 最简单的Windows窗口封装类

    1 开发语言抉择 1.1 关于开发Win32 程序的语言选择 C还是C++ 在决定抛弃MFC,而使用纯Win32 API 开发Window桌面程序之后,还存在一个语言的选择,这就是是否使用C++.C+ ...

  6. 初次认识 C# win32 api

    第一次接触win32api,刚开始的时候有点迷迷糊糊的. Windows API 就是windows应用程序接口. win api向上就是windows应用程序,向下就是windows操作系统核心. ...

  7. Serial Port Programming using Win32 API(转载)

    In this tutorial we will learn How to communicate with an external device like a microcontroller boa ...

  8. 【温故Delphi】GAEA用到Win32 API目录

    Delphi是Windows平台下著名的快速应用程序开发工具,它在VCL中封装并使用了大量的Win32 API. GAEA基于VCL开发的工具类产品,在程序中使用了大量的Win32 API,将经常用到 ...

  9. 【C#】分享基于Win32 API的服务操作类(解决ManagedInstallerClass.InstallHelper不能带参数安装的问题)

    注:这里的服务是指Windows 服务. ------------------201508250915更新------------------ 刚刚得知TransactedInstaller类是支持带 ...

  10. C#中导入Win32 API函数

    C#中导入Win32 API的方法: 1.引用命名空间 using System.Net.Security; using System.Runtime.InteropServices; 2. [Dll ...

随机推荐

  1. PySe-008-开启浏览器的手机模式

    以 Chrome 为例,通过设置 chromeoption 的参数即可实现启动浏览器后,开启手机模式.相应设置的源代码如下所示: chromeOptions = webdriver.ChromeOpt ...

  2. windows环境在本地配nginx

    本地搭建了前端项目,但奈何有时候需要https访问的需求,所以做了一个尝试在本地(windows环境)下配置nginx,最终的效果就是 搭建的时候,遇到两个问题: 第一个是如果要在本地搭建https, ...

  3. Oracle中对XMLType的简单操作(extract、extractvalue...)

    Oracle中对XMLType的简单操作(extract.extractvalue...)    1.下面先创建一个名未test.xml的配置文件. <?xml version="1. ...

  4. NetCore2.0下使用EF CodeFirst创建数据库

    本文所使用的VS版本:VS2017 15.3.0 首先新建一个.net core项目  取名NetCoreTask 使用模型视图控制器方式 新建Model层 在Model层下新建一个user实体类 1 ...

  5. git----------如何安装gitlab,使用步骤。

    1.配置yum源        vim /etc/yum.repos.d/gitlab-ce.repo 2.复制以下内容到打开的文件中: [gitlab-ce]     name=Gitlab CE ...

  6. C语言实现迷宫小游戏

    代码如下,时间太晚,有空补注释: #include<stdio.h> #include<string.h> #include<time.h> #include< ...

  7. 排序之选择排序(SelectSort)

    package com.sort; /* * 选择排序 * 把第一位与其他数进行比较,这样每轮比较都会出现一个最大值或最小值 * 根据需要让升序或降序排列 */ public class Select ...

  8. linux 下的OpenGL的安装配置

    https://blog.csdn.net/qq_38228254/article/details/78521155 本人亲测有效

  9. 一个handle使用更新线程的实例

    handle更新线程实例 package com.example.administrator.handle; import android.app.Activity;import android.os ...

  10. h5页面在ios机上禁止长按复制

    (注意,增加之后需要对input的另外设置,不然输入框无法输入)场景:H5出现一个按钮需要长按几秒展示动画的,如:skcs.net-tactic.com/wap/peace/index,这时就需要用到 ...