WinAutoHide – 让窗口贴边隐藏(更新到v1.02)

前情提要

求一款小巧的可弹出的文件浏览器(资源管理器)继续讨论:

见到有用户想要可弹出的文件管理器,我就想到QQ,就想到贴边自动隐藏,就想到AutoHotkey……于是立马去找。

先找到的是这个(不推荐点进去):
AHK 实现 靠边自动隐藏显示窗口 – AutoAHK
……居然需要先付积分才能看,这么抠……

于是换个关键词再找(想不到用英文关键词没找到什么有用的东西,后来才发现“屏幕边缘”(screen side)这关键词太low了),就找到 @scavin 的古早贴:
WinAutoHide - 让窗口贴边隐藏 - 小众软件
可是青蛙的github页面却只是简单复制了原始文件,并没有青蛙在上面正文说的修改:
GitHub - scavin/winautohide: 贴边隐藏当前窗口
而且有在自动隐藏窗口打开菜单时窗口会隐藏的毛病。

所以我修改出了自己的版本:

通过快捷键让当前窗口往指定边缘隐藏;鼠标移到该边缘时弹出已自动隐藏窗口;鼠标移开再自动隐藏;(v1.02)鼠标拖动已自动隐藏窗口可取消自动隐藏。

2024-03-01: v1.01 hzhbest修改:机制优化,现在在自动隐藏窗口打开菜单时该窗口会保持显示;增加初始隐藏时的过渡移动,让你看清窗口隐藏到哪。
2024-03-20: v1.02 hzhbest修改:增加机制,移动显形的自动隐藏窗口将直接使其取消自动隐藏状态;为此,自动隐藏窗口的标题栏样式也作了调整。
欢迎提出有益需求,能实现的我都会在上面更新。 Text

6 个赞

试用了下,非常好用 :+1:

啊,好古老的内容。实际上代码是 火山 修改的,我也只是 fork 了源项目。

太古老了太古老了。

另外你这个不改用 AHK v2 么?

之前讨论过了啊,不得以就改,能用就不改。我之前改一个脚本到v2是因为v1对于数组支持有问题(不知是我写法的问题还是怎样,也没人能回答)。

1 个赞

我有个感觉,GitHub 的那一份代码,也不是火山当年修改过的代码…

他修改的那一份,估计是真丢了…

autoahk 就是 ahk 界的败类,建站的时候就冒称 AutoHotkey 官方中文,修改了官网的编辑器就说是原创,真的恶心

2 个赞

不知道怎么把这个合并到另一个.ahk里,常用几个快捷键都在一个文档,这个简单复制过去没法正常运行。

主要是因为该脚本在主过程和函数之间有一个结束主过程的命令:


(结束主过程后只通过热键和定时器触发功能)
而且该脚本还带自己的菜单项,你要整合进别的脚本的话你要权衡该脚本的功能怎么取舍或变更调用方式。

不懂编程。但看了好像都是return结束,不明白为什么不能触发。也就定义了快捷键。ahk不都是顺序执行。

MButton::
if (A_Cursor = “IBeam”)
{
Send,^v
Return
}else
{
Send,{Click, M}
Return
}
;Alt+C执行Ctrl+C, Alt+C
!c::
;Sleep,300
Send,^c
Send,!j
Sleep,200
Send,^v
Send,{Enter}
Return

在原代码第29行粘贴应该可以

将窗口贴边隐藏后,拖动窗口似乎无法解除贴边状态,我还尝试一个较为极端的用法:贴边隐藏后再将窗口全屏 在这种情况下,窗口将始终处于“悬浮显示”状态(置顶)
能否监测窗口位置及大小变化,以此来解除贴边隐藏状态

我想要以此解除贴边状态 的 主要原因是我认为 按键盘有点打断我的鼠标操作

分享下我自用的函数 (V2)。区别是使用窗口消息 (更灵敏),没使用定时器,减少性能消耗。相应的,变成非活动则触发隐藏。
想要鼠标离开窗口即隐藏,除了定时器,有两个方向:1,在窗口边缘绘制 1 像素的透明边框,鼠标向外移动则隐藏。2,使用系统钩子,监听鼠标离开窗口事件。

EdgeHiding(hwnd, to := 1) {
	if id := DllCall('FindWindowW', "ptr", 0, "str", 'EdgeHiding_' hwnd, "ptr")
		return SendMessage(40400, , , , id)

	WinGetPos &x, &y, &w, &h, hwnd
	b := SysGet(4)

	switch to ;1下 ,2左, 3上, 4右
	{
		case 1:
			mx := x
			my := A_ScreenHeight - h
			ax := x
			ay := A_ScreenHeight - 2
			aw := w
			ah := 2
		case 2:
			mx := 0
			my := y
			ax := -20
			ay := y
			aw := 22
			ah := h - b
		case 3:
			mx := x
			my := -20
			ax := x
			ay := 0
			aw := w
			ah := 22
		default:
			mx := A_ScreenWidth - w
			my := y
			ax := A_ScreenWidth - 1
			ay := y
			aw := 1
			ah := h - b
	}

	WinMove mx, my, , , hwnd
	WinSetAlwaysOnTop 1, hwnd
	WinHide hwnd
	WinSetStyle -0xC00000, hwnd
	WinSetExStyle +0x80, hwnd

	ui := Gui('+Owner -Caption AlwaysOnTop +ToolWindow +E0x8000000', 'EdgeHiding_' hwnd)
	ui.show("NoActivate  x" ax " y" ay " w" aw " h" ah)

	WinSetTransparent 1, ui.hwnd
	ui.OnMessage(0x200, EdgeHiding_show)
	ui.OnMessage(40400, EdgeHiding_destroy)

	ui.win := hwnd
	ui.x := x
	ui.y := y
}

EdgeHiding_destroy(ui, *) {
	ui.de := 1
	WinActivate ui.hwnd
	Sleep 20

	WinSetAlwaysOnTop 0, ui.win
	WinSetStyle +0xC00000, ui.win
	WinSetExStyle -0x80, ui.win

	WinShow ui.win
	WinMove ui.x, ui.y, , , ui.win
	WinActivate ui.win
	ui.destroy()
}

EdgeHiding_show(ui, *) {
	ui.OnMessage(0x200, EdgeHiding_show, 0)
	ui.Hide()
	if !WinExist(ui.win)
		return SendMessage(40400, , , , ui.hwnd)
	
	WinShow ui.win
	WinActivate ui.win
	WinWaitNotActive ui.win
	if ui.de
		return
	WinHide ui.win
	ui.show('NoActivate')
	ui.OnMessage(0x200, EdgeHiding_show)
}

Quicker里的贴边动作也可以实现,少装一个专门软件。

捣鼓了一下,通过检测窗口弹出后鼠标离开时窗口位置,实现了拖动窗口取消隐藏状态;现在就隐藏多个窗口显隐发生冲突问题未解决。

原脚本是跳转调用的;我想改成函数调用,然后就一团麻了……不爽直接回退了……
这是逼我

重写吗? :face_with_spiral_eyes:

2 个赞

你好,我测试了下您的代码 没生效呀,请问下是不是不兼容windows11呀?这个功能非常想要,谢谢

1、能对桌面起作用。 :rofl:
2、隐藏后显示状态,我调了一下窗口大小,然后…… :smiling_face_with_tear:

软件挺好的,不过发现一个bug,只要当前窗口是chrome的时候,贴边隐藏的窗口在显示之后就无法自动隐藏了,当前窗口切换到别的窗口就没这个bug了

你改的不对, 多窗口隐藏,全局 “ui” 变量就冲突了。
ui.OnMessage() 是 V2 最新的特性
我脚本默认使用"#DefineDefaultObjectValue",所以能直接读ui.de,可以修改为 if ui.HasOwnProp(“de”)

那就是版本太新了,哈哈
现在官网直接下载版本v2貌似还不支持这个,只有ui.onevent()

额忘了多窗口情况

大佬给弄个完善版吧,v2令我头大,还得加个退出脚本恢复窗口功能

大佬求个完整版吧,求求了