寻个autohotkey, 让我可以按下alt键后, bandicam的录屏窗口可以跟随鼠标移动

我非常喜欢hypercam的设置热键, 让录屏窗口可以跟随鼠标移动的功能. 但它除此之外几乎一无是处.

2023/10/26 补充实际操作的视图:

Untitled Project

于是想将这个功能在bandicam上实现, 我自己尝试做个, 但是无奈水平太差, 连窗口移动都实现不了.

我将自己做的未完成的脚本放在这里, 见笑了, 期待高手帮我实现我需要的功能.

#p:: :将来换成alt键按下, 然后loop什么的?

win_id := WinExist("ahk_class TARGETRECT")
;MsgBox %win_id%
bandi_win := ahk_id %win_id%

if win_id {
	WinGetPos, X, Y,,, %bandi_win% ; https://www.autohotkey.com/docs/v1/misc/WinTitle.htm#ahk_id
	MsgBox %X% and %Y%
	WinMove, %bandi_win%,, 50, 50 ; 为什么bandi_win不能移动?
	}
Return

追随鼠标是 Bandicam 的自带功能

他说的应该是像camtasia那样的智能聚焦功能,录制的时候是全屏或者大范围,按下某个键才跟随鼠标,其实我也想要这样的功能 :face_with_peeking_eye:

是按下某键(我想要alt键)后, 窗口才自动跟随鼠标进行移动.

bandicam自带的"鼠标追随"有2个问题: 1, 不显示矩形框, 不知道录制范围是哪里? 2, 一直鼠标追随, 在录制其中一些不必要录制的鼠标轨迹也都录制下来了.

在bandicam的矩形窗口虽然可以拖拽进行移动, 但不如我设想的按下某键后自动追随鼠标来的自然, 鼠标不会在录制中频繁的消失.

哈, 我偶尔也会用camtasia,
不知道还有这个功能,
我看了下网上的教程: Camtasia实用技巧之智能聚焦_喀秋莎添加变焦 在动画面板中可以通过添加关键帧在时间轴中添加变焦点,通过设置变-CSDN博客
发现这个是在后期的时候进行编辑的做法.
camtasia的长项就是后期编辑.

但我目前倾向于使用简单的工具,
录制一些基本的操作步骤保留下来
尽量的简洁清晰.

:slight_smile:

为了方便大家了解我需要的结果,
我补充了两幅在hypercam中操作的图片.

用ZoomIt软件可以实现类似的效果, Zoomit屏幕缩放使用方法 - 知乎 (zhihu.com),但是总感觉没那味 ::

明白了,你说的方式的确更实用 :ok_hand:

WinMove, ahk_class TARGETRECT, ,50,50

你直接这么写就行了吧,我试了下可以啊

另附完整可用版 ahk v1:
按下f1开始追随鼠标,再次按下f1退出追随

CoordMode, Mouse , Screen
key:=0
SetTimer,gomove,2
return

f1::key:=! Key

gomove:
if key
{
  MouseGetPos , OutputVarX, OutputVarY
  ControlGetPos , , , OutWidth, OutHeight, , ahk_class TARGETRECT
  newx:=OutputVarX-OutWidth/2
  newy:=OutputVarY-OutHeight/2
  WinMove, ahk_class TARGETRECT, ,newx,newy
}
return

感谢 @dog 我还是更希望得到按 alt 触发窗口移动. :slight_smile:

我在你的代码基础上做了一些改动, 似乎有点儿像我需要的样子了, 但是有下面的问题:

  • 无法实现单独按下 alt 触发. 现在只能暂时 alt+1 触发, 然后放开 1 键, 但 alt 一直按着, 可以实现窗口跟随.
  • 代码触发执行的时候, 时候窗口直接跳到左上角, 我使用msgbox取首次运行的值, 发现它会锁定座标5:43, 即便随着我的鼠标她可以进行微小的移动, 但每次ControlGetPos都会让框口的座标恢复 5:43. 不知道哪里出错了? (我是4k屏, 所以文字有 150% 的缩放)

以下是我的代码:

#IfWinExist ahk_class TARGETRECT

$<!1::
Loop{
	if GetKeyState("alt", "p") {
	
		MouseGetPos , mouseX, mouseY
		sleep, 50
		MouseGetPos , mouseNewX, mouseNewY
		mouseMoveX := mouseNewX-mouseX
		mouseMoveY := mouseNewY-mouseY
		
		
		ControlGetPos , winX, winY, , , , ahk_class TARGETRECT
		
		MsgBox % winX winY ; 代码初始的时候, 这里不知道为什么立刻变成 5 43?
		
		winX := winX + mouseMoveX
		winY := winY + mouseMoveY
		
;		ToolTip, %winX% %winY%
		
		WinMove, ahk_class TARGETRECT, ,winX+mouseMoveX,winY+mouseMoveY
		}
	Else {
;		ToolTip
		Break
		}
	}

#IfWinExist

我将代码换成 @dog 的思路, 即: 通过window的常宽来判断位移, 代码如下.

但也有问题:

  • 在我的屏幕使用150%放大的情况下, 运行程序会跳开一定距离. 当我将屏幕恢复成100%显示的时候相对就好一些.
  • 即便在100%的时候, 触发脚本时还会有一个跳跃, 使用窗口长宽和鼠标位置进行推测的时候, 默认以鼠标的位置为中心移动窗口. 而鼠标在其他位置的时候, 窗口就要弹到以鼠标为中心的位置. 所以引发程度不同的窗口跳跃. 而我期望的方式是无论鼠标在什么位置, 在脚本触发后, 窗口都随着鼠标的移动距离而进行移动. 哪怕鼠标在窗口之外也是如此. 而不要跳回到鼠标位置再跟随. 本来我想使用鼠标移动的改变来对窗口进行定位, 如上贴的方式, 但无奈 ControlGetPos 获取的座标一直是个固定值.

代码:

#IfWinExist ahk_class TARGETRECT

$<!1::
Loop{
	if GetKeyState("alt", "p") {
	
			MouseGetPos , mouseX, mouseY
			ControlGetPos , , , winW, winH, , ahk_class TARGETRECT
			newx:=mouseX-winW/2
			newy:=mouseY-winH/2
			WinMove, ahk_class TARGETRECT, ,newx,newy
			Sleep, 10
			}
	Else {
;		ToolTip
		Break
		}
	}

#IfWinExist

zoomit确实是个神器, 但如果想要配合矩形窗口录屏(不是全屏录制), 可能有些不足:

  • zoomit放大功能可能适合全屏录制时候使用, 而使用第三方工具进行窗口录屏的时候, 连第三方工具的窗口都会被放大, 造成无法定位录制位置的尴尬. 而且鼠标会变成2个.
  • 其实已经是矩形窗格录制了, 按理说已经是在录制细节部分, 就不需要放大了.
  • zoomit新版自带了录制功能, 好像是个全屏录制工具? 但需要windows高版本才能支持.
  • zoomit比较擅长屏幕标记, 但我目前想找的是能方便的随鼠标移动录制窗口的功能. 可能这两个工具并没有太多的相似性.

无论如何感谢你的推荐.

搞定了,试了下这样确实更舒服欸

CoordMode, Mouse , Screen
key:=0
SetTimer,gomove,2
return

~alt::
{
MouseGetPos , VarX0, VarY0
WinGetPos , winx, winy, , , ahk_class TARGETRECT
key:=1
keywait, Alt,L
key:=0
}

gomove:
if key
{
  MouseGetPos , VarX1, VarY1
  newx:=winx+VarX1-VarX0
  newy:=winy+VarY1-VarY0
  WinMove, ahk_class TARGETRECT, ,newx,newy
}
return

感谢 @dog 这个脚本完美实现了我的想法.

多问一句, 是否需要前后加上 #IfWinExist, 让这个脚本只有在bandicam启用的时候才执行, 这样会减少一些和其他脚本的冲突? 如果多个脚本一起执行的话, 有没有必要这么做呢?

没啥区别吧,因为用了settimer,那段代码一直在运行。
#IfWinExist只对快捷键有效,对于settimer没效果。
我觉得最好是单独放一个脚本里,你用录屏软件时候再打开。

settimer是一直运行的啊~~~

那我上面9楼的思路: 在alt按下, 当#IfWinExist 满足时再执行 loop+sleep 的方法会不会更好一些呢?

可惜我水平太次, 搞不定那些具体的步骤.

现在的电脑,不差这点蚊子脚一样的性能,损耗几乎没有的
当然,你也可以研究研究你的方案

我尝试的使用我的思路, 并且偷了 @dog 代码中的一些, 居然改进了很多, 代码放在最后. 但仍然不能作为成品使用, 这里并标记了其中的问题, 在解决之前, 还是 @dog 提供的settimer的脚本比较好用.

  • 我使用的是4k屏幕, 为了显示清楚还做了屏幕放大(150%). 这种方法获得窗口新的位置似乎不能简单的 winX + mouseNewX - mouseX, 我尝试做了个倍数 winX + (mouseNewX - mouseX) * 1.5 也不行. 不知道怎么做才能在我这样放大过的屏幕准确计算出窗口的应该移动到的位置.
  • 原来代码中使用了 ControlGetPos, 窗口会锁定到 5:43 的固定位置, 但换成 WinGetPos就好了. 不知河谷.
  • CoordMode, Mouse , Screen 不知道是做什么的. 放上和不放区别不大?
#IfWinExist ahk_class TARGETRECT

CoordMode, Mouse , Screen

~Alt::
Loop{
	if GetKeyState("alt", "p") {
		
		MouseGetPos , mouseX, mouseY
		sleep, 50
		MouseGetPos , mouseNewX, mouseNewY
		
		WinGetPos , winX, winY, , , ahk_class TARGETRECT
		
		winX := winX + (mouseNewX - mouseX) * 1.5
		winY := winY + (mouseNewY - mouseY) * 1.5
		
		WinMove, ahk_class TARGETRECT, ,winX,winY
		}
	Else {
		Break
		}
	}


#IfWinExist

研究了一下屏幕缩放, 找到了官方的相关链接:

在我的代码中加入了一句: DllCall("SetThreadDpiAwarenessContext", "ptr", -4, "ptr"), 整个代码就基本可以使用了:

#IfWinExist ahk_class TARGETRECT

CoordMode, Mouse , Screen
DllCall("SetThreadDpiAwarenessContext", "ptr", -4, "ptr")

~Alt::
Loop{
	if GetKeyState("alt", "p") {
		
		MouseGetPos , mouseX, mouseY
		sleep, 50
		MouseGetPos , mouseNewX, mouseNewY
		
		WinGetPos , winX, winY, , , ahk_class TARGETRECT
		
		winX := winX + mouseNewX - mouseX
		winY := winY + mouseNewY - mouseY
		
		WinMove, ahk_class TARGETRECT, ,winX,winY
		}
	Else {
		Break
		}
	}


#IfWinExist

@dog 请问如果我想将触发键更改为右侧的alt键, 该如何做呢?

我将代码中的两个alt键改为: ~RAlt::GetKeyState("RAlt", "p"), 但是按左边的alt仍然会触发. 不知何故?

感谢.