|
在某些情况下,我们希望把某个窗口自动激活,比如,下午3点钟要参加项目调度例会,因此,希望提前10分钟弹出提示窗口并且确保该窗口在最前端显示出来。
这种情况,就需要使用SetForeGroundWindow来激活指定的提示窗口。
但是,很多人试过用SetForeGroundWindow激活指定窗口,发现只能使该窗口的任务栏图标闪烁而不能真正让该窗口激活。
那么,为什么SetForeGroundWindow会“失效”呢?又如何来解决这种问题呢?
查看MSDN对该函数的解释:
The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:
1、The process is the foreground process.
2、The process was started by the foreground process.
3、The process received the last input event.
4、There is no foreground process.
5、The foreground process is being debugged.
6、The foreground is not locked (see LockSetForegroundWindow).
7、The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
我们可以了解到,要确保SetForeGroundWindow成功,至少要满足上述7个条件中的一个条件。
因此,我们可以把SetForeGroundWindow命令附加到当前活动线程中去使之得到执行,即通过满足条件1来使得该命令成功运行。此种解决方法,需要获取当前前台窗口的线程ID,并给该线程附加输入命令,因此,还需要用到以下4个Win32 API函数:
GetForegroundWindow
GetWindowThreadProcessId
GetCurrentThreadId
AttachThreadInput
具体实现如下(以在EXCEL VBA环境中举例):
- #If Win64 Then
- Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As Long
- Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
- Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
- Private Declare PtrSafe Function AttachThreadInput Lib "user32" (ByVal idAttach As Long, ByVal idAttachTo As Long, ByVal fAttach As Long) As Long
- Private Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
- #Else
- Private Declare Function GetForegroundWindow Lib "user32" () As Long
- Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
- Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
- Private Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Long, ByVal idAttachTo As Long, ByVal fAttach As Long) As Long
- Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
- #End If
- Sub 按钮1_单击()
- Application.OnTime Now + TimeValue("00:00:05"), "显r_定时"
- End Sub
- '求问:
- '怎么恢复excel的窗口排在最前面,并显示msgbox窗口
- Sub 显r_定时()
- Dim hCurWnd As Long, dwCurID As Long, dwMyID As Long
-
- hCurWnd = GetForegroundWindow() '获取前台窗口句柄
- dwCurID = GetWindowThreadProcessId(hCurWnd, 0) '根据前台窗口句柄,获取其线程ID
- dwMyID = GetCurrentThreadId() '获取本程序的线程ID
- AttachThreadInput dwCurID, dwMyID, True '把本程序的输入命令附加到指定的线程(即台前窗口的线程)
-
- '-------------------------激活指定窗口
- 'SetForegroundWindow ThisWorkbook.Windows(1).hwnd
- ThisWorkbook.Activate '在Excel VBA中,ThisWorkbook.Activate等效于SetForegroundWindow ThisWorkbook.Windows(1).hwnd
- MsgBox "答案是可以看见这个窗口"
- '--------------------------
- AttachThreadInput dwCurID, dwMyID, False '切断附加关系。此时,指定的窗口成为真正的前台窗口。
- End Sub
复制代码
这里,AttachThreadInput函数很关键,可以说,它就是抢话筒的,雅称“麦霸”。如果没有它,SetForegroundWindow的发言是不被“重视”的,只能让窗口的任务栏图标闪烁一两下而已。
最前端显示.rar
(13.66 KB, 下载次数: 100)
|
评分
-
1
查看全部评分
-
|