setForegroundWindow 的使用方法有哪些?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了setForegroundWindow 的使用方法有哪些?相关的知识,希望对你有一定的参考价值。

有没有实例. vb的。 窗口置前

  setForegroundWindow 的使用方法如下:
  SetForegroundWindow函数将创建指定的窗口,并激活到前台窗口的线程 。键盘输入窗口,并为用户更改不同的视觉线索。该系统分配一个优先略高前景的窗口,比它其他线程创建的线程。 语法
  BOOL SetForegroundWindow( HWND HWND ); 参数 HWND
  [in]应该被激活,并带到前景的窗口句柄。 返回值
  如果窗口被带到前台,返回值为非零。 如果窗口不带到前景,返回值是零。 备注
  Windows 98/Me的系统限制哪些进程可以设置前台窗口。一个进程可以设置前台窗口,仅当下列条件之一为真 :
  这个过程是前台进程。
  这个过程是由前台进程的开始。
  过程中收到的最后一个输入事件。
  没有前台进程。
  前台进程正在被调试。
  前景不被锁定(见LockSetForegroundWindow)。 前景锁定超时已过期(看到
  SPI_GETFOREGROUNDLOCKTIMEOUTSystemParametersInfo)。 Windows 2000/XP的:没有菜单处于活动状态。
  这一变化,应用程序不能强制一个窗口到前台,而用户是另一个窗口的工作。相反,前台和后台的Windows激活窗口(见 SetActiveWindow)和调用函数通知用户 。然而,在Microsoft Windows 98和Windows Millennium Edition(Windows Me)中,如果一个nonforeground线程调用SetForegroundWindow,并通过一个没有被调用线程创建的窗口的句柄,窗口不闪现在任务栏上。SetForegroundWindow行为相同的,因为它没有在Windows 95和Microsoft Windows NT 4.0,安装应用程序时,更改前景色锁超时值 。这可以从下面的函数调用设置或安装应用程序:
  SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
  这种方法允许在Windows 98/Windows Me和Windows 2000/Windows
  XPSetForegroundWindow行为作为Windows 95和Windows NT 4.0相同,分别为所有应用程序,。安装应用程序,这样做是使用户是不会改变的行为感到惊讶的用户发出警告。在Windows上的Windows 2000和Windows XP,调用失败,除非调用线程可以改变前台窗口,因此必须从一个安装或修补应用程序调用。欲了解更多信息,请参阅前景和背景窗口。
  一个过程,可以设置前台窗口可以使另一个进程通过调用前台窗口
  AllowSetForegroundWindow功能。dwProcessId和所指定的过程中失去了到前台窗口设置下一次输入用户生成的能力,除非输入是在这个过程中,或在下一次进程调用AllowSetForegroundWindow,除非指定过程。
  前台进程可以禁用调用SetForegroundWindow调用的LockSetForegroundWindow函数。
  保证SetForegroundWindow成功
  在SetForegroundWindow之前比较早的时候(比如main函数里)调用一下以下代码:
  DWORD dwTimeout = -1;
  SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&dwTimeout, 0);
  if (dwTimeout >= 100)
  SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
  
  HWND hForeWnd = NULL;
  HWND hWnd= FindWindow(NULL, ""); DWORD dwForeID; DWORD dwCurID;
  hForeWnd = GetForegroundWindow(); dwCurID = GetCurrentThreadId();
  dwForeID = GetWindowThreadProcessId( hForeWnd, NULL ); AttachThreadInput( dwCurID, dwForeID, TRUE); ShowWindow( hWnd, SW_SHOWNORMAL );
  SetWindowPos( hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE ); SetWindowPos( hWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE ); SetForegroundWindow( hWnd );
  AttachThreadInput( dwCurID, dwForeID, FALSE);
  
  第一段代码:
  后果是如果执行到if里面的语句,会因为user profile的更改回写和WM_SETTINGCHANGE的广播而导致这个API调用本身卡两三秒。 第二段代码:
  设置当前某窗口为当前窗口,有几个步骤要做: 1.得到窗口句柄FindWindow
  2.切换键盘输入焦点AttachThreadInput
  3.显示窗口ShowWindow(有些窗口被最小化/隐藏了)
  4.更改窗口的Zorder,SetWindowPos使之最上,为了不影响后续窗口的Zorder,改完之后,再还原
  5.最后SetForegroundWindow
参考技术A  MSDN:http://msdn.microsoft.com/en-us/library/ms633539(v=VS.85).aspx 下面是谷歌翻译,有些语句不是很流畅。
  SetForegroundWindow函数将创建指定的窗口,并激活到前台窗口的线程 。键盘输入窗口,并为用户更改不同的视觉线索。该系统分配一个优先略高前景的窗口,比它其他线程创建的线程。
语法
  BOOL SetForegroundWindow(
     HWND HWND );
参数
HWND
  [in]应该被激活,并带到前景的窗口句柄。
返回值
  如果窗口被带到前台,返回值为非零。
  如果窗口不带到前景,返回值是零。
备注
  Windows 98/Me的系统限制哪些进程可以设置前台窗口。一个进程可以设置前台窗口,仅当下列条件之一为真 :
    这个过程是前台进程。
    这个过程是由前台进程的开始。
    过程中收到的最后一个输入事件。
    没有前台进程。
    前台进程正在被调试。
    前景不被锁定(见LockSetForegroundWindow)。
    前景锁定超时已过期(看到SPI_GETFOREGROUNDLOCKTIMEOUTSystemParametersInfo)。
    Windows 2000/XP的:没有菜单处于活动状态。
  这一变化,应用程序不能强制一个窗口到前台,而用户是另一个窗口的工作。相反,前台和后台的Windows激活窗口(见 SetActiveWindow)和调用函数通知用户 。然而,在Microsoft Windows 98和Windows Millennium Edition(Windows Me)中,如果一个nonforeground线程调用SetForegroundWindow,并通过一个没有被调用线程创建的窗口的句柄,窗口不闪现在任务栏上。SetForegroundWindow行为相同的,因为它没有在Windows 95和Microsoft Windows NT 4.0,安装应用程序时,更改前景色锁超时值 。这可以从下面的函数调用设置或安装应用程序:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

  这种方法允许在Windows 98/Windows Me和Windows 2000/Windows XPSetForegroundWindow行为作为Windows 95和Windows NT 4.0相同,分别为所有应用程序,。安装应用程序,这样做是使用户是不会改变的行为感到惊讶的用户发出警告。在Windows上的Windows 2000和Windows XP,调用失败,除非调用线程可以改变前台窗口,因此必须从一个安装或修补应用程序调用。欲了解更多信息,请参阅前景和背景窗口。
  一个过程,可以设置前台窗口可以使另一个进程通过调用前台窗口AllowSetForegroundWindow功能。dwProcessId和所指定的过程中失去了到前台窗口设置下一次输入用户生成的能力,除非输入是在这个过程中,或在下一次进程调用AllowSetForegroundWindow,除非指定过程。
  前台进程可以禁用调用SetForegroundWindow调用的LockSetForegroundWindow函数。

  保证SetForegroundWindow成功
  在SetForegroundWindow之前比较早的时候(比如main函数里)调用一下以下代码:
DWORD dwTimeout = -1;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&dwTimeout, 0);
if (dwTimeout >= 100)
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);


HWND hForeWnd = NULL;
HWND hWnd= FindWindow(NULL, "");
DWORD dwForeID;
DWORD dwCurID;

hForeWnd = GetForegroundWindow();
dwCurID = GetCurrentThreadId();
dwForeID = GetWindowThreadProcessId( hForeWnd, NULL );
AttachThreadInput( dwCurID, dwForeID, TRUE);
ShowWindow( hWnd, SW_SHOWNORMAL );
SetWindowPos( hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
SetWindowPos( hWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
SetForegroundWindow( hWnd );
AttachThreadInput( dwCurID, dwForeID, FALSE);

  第一段代码:
    后果是如果执行到if里面的语句,会因为user profile的更改回写和WM_SETTINGCHANGE的广播而导致这个API调用本身卡两三秒。
  第二段代码:
    设置当前某窗口为当前窗口,有几个步骤要做:
    1.得到窗口句柄FindWindow
    2.切换键盘输入焦点AttachThreadInput
    3.显示窗口ShowWindow(有些窗口被最小化/隐藏了)
    4.更改窗口的Zorder,SetWindowPos使之最上,为了不影响后续窗口的Zorder,改完之后,再还原
    5.最后SetForegroundWindow
  想必看到上述代码就明白了这个函数失败的原因了吧。
参考技术B 先打开一个记事本,让他不是当前窗口(无焦点)。程序里建一个Command1,单击按钮看看效果。
代码如下。
=================
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Sub Command1_Click()
Dim h As Long
h = FindWindow("notepad", vbNullString)
SetForegroundWindow h
End Sub本回答被提问者采纳
参考技术C

    函数功能:该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。

    函数原型:BOOL SetForegroundWindow()。

    返回值:如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零。

    备注:前台窗口是z序顶部的窗口,是用户的工作窗口。在一个多任务优先抢占环境中,应让用户控制前台窗口。

参考技术D SetForegroundWindow函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。详情
    在线客服官方服务
      官方网站费用查询充值交费业务办理宽带提速

模拟全局热键

【中文标题】模拟全局热键【英文标题】:Simulate global hotkey 【发布时间】:2016-02-28 14:32:39 【问题描述】:

您好,我正在使用 Visual c++ 我有一个工作程序,除了一件事我希望它能够使用单独的屏幕截图程序。我安装了单独的截图程序,它有一个注册的热键来截图,我希望我的程序来做。

我用 FindWindow 尝试了 keybd_event 和 SendInput,它在记事本上运行良好,但它的屏幕截图程序运行最小化或隐藏,我知道 SetForegroundWindow 的问题。

有没有办法让它像我刚刚在键盘上按下的所有窗口一样的 Windows 系统,就像真正的热键一样?它的屏幕截图程序可以使用真正的热键正常工作。

【问题讨论】:

【参考方案1】:

也许键盘挂钩可以解决问题?

example 1 example 2 example 3

并不完美,但它们非常全球化

【讨论】:

好的,我可以了解钩子,但这可以按下按键还是只听?是其他程序有热键,我想我的程序按下它。 看来我明白了。您想模拟击键,以便外部程序截取屏幕截图,对吗?好吧,那不是您遇到问题的热键。顺便说一句,请考虑以下几点: * 从您自己的代码中获取截图非常容易 * 您可以将自己的热键与对上述程序的某种管道调用结合起来 但是无论如何,您现在想要的解决方案是 SendInput() .是的,您已经尝试过了,但如果实施得当,应该可以工作。【参考方案2】:

这是一个全局热键的源代码。它已设置为侦听 CTRL + y 组合键。一旦 CTRL + y 被触发,它就会抓取屏幕截图。

要关闭全局热键,只需按 CTRL + q

要隐藏控制台窗口并保持热键在后台运行,请按 CTRL + w

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <iostream>
#include <windows.h>
#include <stdio.h>

HHOOK hKeyboardHook;
__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam);
void MessageLoop();
DWORD WINAPI my_HotKey(LPVOID lpParm);
int toggleVisibility = 1;

int screenResolutionX = GetSystemMetrics(SM_CXSCREEN);
int screenResolutionY = GetSystemMetrics(SM_CYSCREEN);
POINT startCoord,endCoord;
void grabScreenshot(POINT a, POINT b);

/*********************************************
***                                        ***
***                                        ***
**********************************************/


int main(int argc, char** argv)

    /* uncomment to hide console window */
    //ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);

    HANDLE hThread;
    DWORD dwThread;

    printf("\n  s c r e e n s h o t   H O T K E Y    \n\n");
    printf("press  CTRL-y  for  screenshot \n");
    printf("press  CTRL-w  to hide or make console window visible  \n");
    printf("press  CTRL-q  to quit  \n");
    printf("\n\n");

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)   my_HotKey, (LPVOID) argv[0], NULL, &dwThread);

    if (hThread) return WaitForSingleObject(hThread,INFINITE);
    else return 1;



/*********************************************
***                                        ***
***                                        ***
**********************************************/


__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam)
    DWORD SHIFT_key=0;
    DWORD CTRL_key=0;
    DWORD ALT_key=0;


    if  ( (nCode == HC_ACTION) &&   ((wParam == WM_SYSKEYDOWN) ||  (wParam == WM_KEYDOWN) ) ) 
        KBDLLHOOKSTRUCT hooked_key =    *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = 0;

        int i = GetKeyNameText(dwMsg,   (lpszKeyName+1),0xFF) + 1;

        int key = hooked_key.vkCode;

        SHIFT_key = GetAsyncKeyState(VK_SHIFT);
        CTRL_key  = GetAsyncKeyState(VK_CONTROL);
        ALT_key   = GetAsyncKeyState(VK_MENU);

        //printf("%c",key);

        if ( (key >= 'A') && (key <= 'Z') || (key >= 'a') && (key <= 'z') || (key >= '0') && (key <= '9') ) 

            if  (GetAsyncKeyState(VK_SHIFT)>= 0) key +=32;

            /*********************************************
            ***   Hotkey scope                         ***
            ***   do stuff here                        ***
            **********************************************/

            if ( (CTRL_key !=0) && (key == 'y') || (key == 'Y') ) 

               CTRL_key=0;

               // grab a screenshot

                startCoord.x=0;
                startCoord.y=0;

                endCoord.x=screenResolutionX;
                endCoord.y=screenResolutionY;

                ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
                Sleep(1000);
                grabScreenshot(startCoord,endCoord);

                ShowWindow(FindWindowA("ConsoleWindowClass", NULL), true);

                printf("\nThe Screenshot is in the Clipboard  \n\n");
            

            //******************************************************

            if ( (CTRL_key !=0) && (key == 'q') ||  (key == 'Q') ) 
                MessageBox(NULL, "\n\n\n\nShutting down\n\nPress  OK   to close\n\n", "                                     H O T K E Y                                            ", MB_OK);
               PostQuitMessage(0);
            

            //******************************************************

            if ( (CTRL_key !=0) && (key == 'w') ||  (key == 'W') ) 

                toggleVisibility = - toggleVisibility;

                if (toggleVisibility >0 ) 
                    ShowWindow(FindWindowA("ConsoleWindowClass", NULL), true);
                
                else
                    ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
                
            

            SHIFT_key = 0;CTRL_key = 0; ALT_key = 0;
        
    
    return CallNextHookEx(hKeyboardHook,    nCode,wParam,lParam);



/*********************************************
***                                        ***
***                                        ***
**********************************************/

void MessageLoop()

    MSG message;
    while (GetMessage(&message,NULL,0,0))
        TranslateMessage( &message );
        DispatchMessage( &message );
    


/*********************************************
***                                        ***
***                                        ***
**********************************************/


DWORD WINAPI my_HotKey(LPVOID lpParm)
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR) lpParm);
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx (  WH_KEYBOARD_LL, (HOOKPROC) KeyboardEvent,   hInstance,  NULL    );
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;



/*********************************************
***                                        ***
***                                        ***
**********************************************/


void grabScreenshot(POINT a, POINT b)

    // copy screen to bitmap
    HDC     hScreen = GetDC(NULL);
    HDC     hDC     = CreateCompatibleDC(hScreen);
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x-a.x), abs(b.y-a.y));
    HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
    BOOL    bRet    = BitBlt(hDC, 0, 0, abs(b.x-a.x), abs(b.y-a.y), hScreen, a.x, a.y, SRCCOPY);

    // save bitmap to clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBitmap);
    CloseClipboard();

    // clean up
    SelectObject(hDC, old_obj);
    DeleteDC(hDC);
    ReleaseDC(NULL, hScreen);
    DeleteObject(hBitmap);

【讨论】:

以上是关于setForegroundWindow 的使用方法有哪些?的主要内容,如果未能解决你的问题,请参考以下文章

SetForegroundWindow 没有设置焦点

使用 JNA SetForeGroundWindow

SetForegroundWindow 没有激活我的窗口

将后台窗口激活到前台的方法(使用AttachThreadInput和SetForegroundWindow两个API)

SetForegroundWindow 不适用于最小化进程[重复]

SetForegroundWindow的失效问题: 跨进程的窗口前置。