怎么禁止某进程抢焦点?

场景是使用WPS运行VBA程序,程序过程中会打开和关闭多个文件,然后每次打开文件WPS窗口就会抢夺焦点,使其窗口前置
由于程序运行需时比较长,所以我会同时去操作其他窗口;这种抢焦点就导致本来在其他窗口的操作被应用在WPS窗口中,轻则把内容输入到刚打开的文件中,重则中断了程序,导致要从头运行……
有什么工具可以阻止某进程抢夺焦点吗?最好是按规则指定进程

感觉不如粗暴解决问题,直接开个虚拟桌面试试

试试用ahk设置窗口扩展样式
winset,ExStyle,0x08000000,窗口id

依然会抢,无论是针对 wps.exe 还是 et.exe 获取窗口ID
即使问AI得到代码:

#Persistent
#NoEnv
SetBatchLines, -1

; 定义 WPS 窗口的类名(可能需要调整)
WPS_ClassName := "WordPadClass"  ; 示例:WordPadClass(WPS 可能不同,需用 Spy++ 查看)

; 主循环,定期检查并修改 WPS 窗口属性
SetTimer, CheckWPSWindows, 500
return

CheckWPSWindows:
    ; 查找所有 WPS 窗口
    WinGet, WPS_Windows, List, ahk_class %WPS_ClassName%
    Loop, %WPS_Windows%
    {
        hwnd := WPS_Windows%A_Index%
        
        ; 检查窗口是否可见(可选)
        WinGet, Style, Style, ahk_id %hwnd%
        if (Style & 0x10000000)  ; WS_VISIBLE
        {
            ; 移除 WS_EX_TOPMOST(防止置顶)
            WinSet, AlwaysOnTop, Off, ahk_id %hwnd%
            
            ; 使用 DllCall 调用 SetWindowLongPtr(64位兼容)
            ; 注意:WS_EX_NOACTIVATE = 0x08000000
            DllCall("SetWindowLongPtr", "Ptr", hwnd, "Int", -20, "Ptr", (DllCall("GetWindowLongPtr", "Ptr", hwnd, "Int", -20) | 0x08000000))
            
            ; 或者直接使用 SetWindowLong(32位兼容,但可能不适用于 64 位系统)
            ; DllCall("SetWindowLong", "Ptr", hwnd, "Int", -20, "Int", (DllCall("GetWindowLong", "Ptr", hwnd, "Int", -20) | 0x08000000))
        }
    }
return

也一样,只是让WPS的窗口不在任务量显示按钮,该抢焦点还是会抢焦点
——
——
或者有没办法是让VBA读写Excel文件但不显示所读写文件的窗口的?

你的意思是虚拟机是吧?这会比较折腾……

意思是在 win10\11新建个桌面吧,在新桌面再运行你的vbs,wps应该不至于自己跳到新桌面上吧?

1 个赞

我本来就一直在用Win10虚拟桌面,WPS抢焦点时会直接自动切换回它所在的桌面(应该是Windows 的机制,哪个桌面有窗口弹出就自动切换到该桌面)

2 个赞
  1. 最小化方式启动
  2. AHK脚本
#Persistent
SetTimer, WatchForeground, 100
Return

WatchForeground:
WinGet, activeProcess, ProcessName, A
if (activeProcess = "notepad.exe") {
    WinMinimize, ahk_exe notepad.exe
}
Return
  1. 第三方软件WindowTopActual Window Manager

我怎么记得以前好像是不跳的?还是我记错了。刚试了下,其他软件也跳 :expressionless_face:

都用vba了,不如用其他的语言,比如python或者r

或者是一个好想法,但目前来说VBA还是相当方便直观
——
刚才看了下Python的区域复制代码,就挺复杂的,但在AI的回答中还是得到了些启发,就是在主要代码段前后加上:

Application.Visible = False

[main process]

Application.Visible = True

这个运行过程中就不再弹窗(也就不会抢焦点;只是在我的程序中明明所有打开文件的代码都包在中间了,依然会在运行之初先弹几次窗……不解),虽然WPS的“窗框”和任务栏按钮依然会显示,但如果切换到其他窗口再点WPS的任务栏按钮的话,WPS窗口也不会有反应;直到最后运行完成再抢焦点;而且感觉比之前要快(不过程序中设置在任务栏显示运行进度的代码也没效果了)。
反正这对于VBA运行程序抢焦点的问题就算是解决了。
——
但还是希望有能阻止程序抢焦点(使其顶多只能闪任务栏按钮),或者“守护”当前程序焦点状态的工具。

1 个赞

可以考虑这个帖子里面的方法, 另外就是其他的窗口前置的软件应该也可以实现。

但是还是感觉如果你要处理的文件比较多的话, 可以交给python或者R来解决。

1 个赞

这里面介绍的是置顶窗口的方法,并没有守护焦点

有需要的话可以考虑

python 可以直接读取 excel 文件,不需要安装 excel 或者 wps

用虚拟机。

wps使用vba本身就是需要抢进程。

你这是又让马儿跑, 还让马儿不迈腿。 :rofl:

根据我的经验有两种可能方案,如果都不行就彻底没戏。
一个是窗口置底(使目标窗口作为桌面的子窗口),一个是令窗口彻底透明。

抢进程没问题,但它抢焦点啊……不过这已经解决了

置底就是一旦发现某窗口是当前窗口,就马上将其发送到窗口序列最后,那也是一种事后应对,只要我按键的时机刚好不是其抢焦点的时刻;彻底透明只不过是皇帝的新窗口…… :joy:

并不是哦,我说的置底是这个:

另外完全透明的窗口是不会抢激活和焦点的,不过问题是有的窗口无法完全透明,你可以试试。

1 个赞

用工具挂起试试

WPS里面的VBA无法控制WPS混合模式外框窗口的最小化(子窗口会最小化,这会让界面显得很另类),所以要么得用AHK要么得手动最小化(点击按钮或Win+D),这样的确不会导致窗口前置,也就是换别的窗口查看不会受到干扰,但是,输入焦点依然会在打开新文件时被抢夺,只是由于screenupdating=false而不会真的把当时的键击输入进去,直到该状态变成true……

我使用 这个帖子 版本的AHK代码,依然也是和最小化一样的效果——不干扰查看,但依然抢键盘焦点……