上上一篇文章中,介绍了用autohotkey脚本配合快捷键在Windows下给窗口分屏,但是没有做出界面总是有点不开心,经过几天研究,终于成功了!
exe软件和ahk脚本下载地址:点击跳转
脚本源码
自认为注释已经很充分了,配合autohotkey中文帮助应该不难理解:
global _WinTitle ;要分屏的窗口名称
global _MousePosx, _MousePosy ;鼠标坐标
global EditBs, EditDfa ;Block Size和Distance from edge的编辑框
;Bs:分屏窗口的大小 Dfa:分屏窗口到屏幕底边的距离
global _ReadBs, _ReadDfa ;从ini文件中读出来的Bs和Dfa值
#Persistent ;让脚本持久运行(即直到用户关闭或遇到 ExitApp)。
#SingleInstance,force
Menu, Tray, NoStandard
programName := "WinSpliter"
Menu, Tray, Click, 1 ;单击执行OnClick
Menu, Tray, Add, 设置(config), OnClick ;增加右键菜单
Menu, Tray, Add, 退出(Quit),OnExit
Menu, Tray, Default, 设置(config)
Menu, Tray, Tip, %programName% ;鼠标悬停
;return
while True ;主程序从这里开始,无限循环检测是否有拖拽窗口行为
{
DetectWinDrag()
}
OnExit: ;右键托盘点击退出则关闭app
ExitApp
return
OnClick: ;点击托盘图标或者右键点击设置,检测是否存在设置窗口
IFWinNotExist WinSpliter Config ;如果设置窗口没打开,则打开设置界面
ShowWinConfig()
return
ShowWinConfig() ;显示设置窗口
{
IniRead, _ReadBs, config.ini, config, Bs, 60 ;从ini中读取Bs值,如果没有,则置为60
IniRead, _ReadDfa, config.ini, config, Dfa, 60 ;从ini中读取Dfa值,如果没有,则置为60
if (_ReadBs=A_space) OR (_ReadBs<0) OR (_ReadFfa=A_space) OR (_ReadDfa<0) ;增加容错率,当Bs/Dfa等于空或者小于0时不执行动作
{
MsgBox Ini value error, set default! ;如果数值异常,则报错,并重置为60
_ReadBs := 60
_ReadDfa := 60
}
WinSet, TransColor, Off ;设置窗口不需要透明,分屏窗口是透明的,这里需要关闭
Gui, Font, S15 CDefault, Verdana ;添加窗口控件
Gui, Add, Text, x22 y29 w200 h30 , 方块大小
Gui, Add, Text, x22 y119 w200 h30 , 底边距离
Gui, Font, S12 CDefault, Verdana
Gui, Add, Text, x22 y59 w200 h20 , Block size
Gui, Add, Text, x22 y149 w200 h20 , Distance from edge
Gui, Add, Edit, x242 y39 w60 h30 vEditBs, %_ReadBs%
Gui, Add, Edit, x242 y129 w60 h30 vEditDfa, %_ReadDfa%
; Generated using SmartGUI Creator 4.0
Gui, Show, x285 y202 h189 w326, WinSpliter Config
Return
GuiClose:
GuiControlGet, _VarBs,, EditBs ;从设置窗口获取Bs/Dfa数值
GuiControlGet, _VarDfa,, EditDfa
IniWrite, %_VarBs%, config.ini, config, Bs ;关闭时保存Bs/Dfa数值到ini文件
IniWrite, %_VarDfa%, config.ini, config, Dfa
IfWinExist WinSpliter Config ;增加容错率,如果有设置窗口则销毁当前GUI
Gui, Destroy
return
}
ShowWinSplit()
{
;从ini文件中读出来的Bs和Dfa值
IniRead, _ReadBs, config.ini, config, Bs, 60
IniRead, _ReadDfa, config.ini, config, Dfa, 60
BtW = %_ReadBs% ;按钮宽度
BtH := BtW*2 ;按钮高度
BtW2 := BtW*2 ;2倍按钮宽度
BtW3 := BtW*3
BtW4 := BtW*4
BtW5 := BtW*5
BtW6 := BtW*6
BtW7 := BtW*7
BtW8 := BtW*8
BtW9 := BtW*9
BtW10 := BtW*10
BtW11 := BtW*11
BtW12 := BtW*12
TextPosx := BtW*7-100
TextPosy := BtH+10
CustomColor = EEAA99 ; 可以为任意 RGB 颜色 (在下面会被设置为透明).
Gui +LastFound +AlwaysOnTop -Caption +ToolWindow ; +ToolWindow 避免显示任务栏按钮和 alt-tab 菜单项.
Gui, Color, %CustomColor%
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Gui, Add, Button, x0 y0 w%BtW% h%BtH% gTest1, 1# ;点击不同的分屏按钮会连接到各自的子程序
Gui, Add, Button, x%BtW% y0 w%BtW% h%BtH% gTest2, 2#
Gui, Add, Button, x%BtW2% y0 w%BtW% h%BtH% gTest3, 3#
Gui, Add, Button, x%BtW4% y0 w%BtW% h%BtW% gTest4, 4#
Gui, Add, Button, x%BtW5% y0 w%BtW% h%BtW% gTest5, 5#
Gui, Add, Button, x%BtW4% y%BtW% w%BtW% h%BtW% gTest6, 6#
Gui, Add, Button, x%BtW5% y%BtW% w%BtW% h%BtW% gTest7, 7#
Gui, Add, Button, x%BtW4% y%BtW% w%BtW% h%BtW% gTest6, 6#
Gui, Add, Button, x%BtW5% y%BtW% w%BtW% h%BtW% gTest7, 7#
Gui, Add, Button, x%BtW7% y0 w%BtW2% h%BtH% gTest8, 8#
Gui, Add, Button, x%BtW9% y0 w%BtW% h%BtH% ,
Gui, Add, Button, x%BtW11% y0 w%BtW% h%BtH% ,
Gui, Add, Button, x%BtW12% y0 w%BtW2% h%BtH% gTest9, 9#
Gui, Add, Text, x%TextPosx% y%TextPosy% w200 h20 +Center, Select Split Option
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 让此颜色的所有像素透明且让文本显示为半透明 (150):
WinSet, TransColor, %CustomColor% 150
_GuiPosy := A_ScreenHeight - BtH - _ReadDfa ;控制分屏窗口距离屏幕底边的距离
Gui, Show, xCenter y%_GuiPosy% NoActivate ; NoActivate 让当前活动窗口继续保持活动状态.
return
Test1: ;通过各自的子程序传递参数对当前窗口进行分屏
Split(1)
return
Test2:
Split(2)
return
Test3:
Split(3)
return
Test4:
Split(4)
return
Test5:
Split(5)
return
Test6:
Split(6)
return
Test7:
Split(7)
return
Test8:
Split(8)
return
Test9:
Split(9)
return
}
DetectWinDrag() ;检测是否有窗口拖拽行为
{ ;基本原理:当按键按下时记录当前窗口位置,延时一段时间,鼠标抬起时窗口位置变化则发生拖拽
static DragFlag = 0
CoordMode, Mouse ;获取的坐标是相对于整个屏幕的
MouseGetPos, _MousePosx, _MousePosy, _MouseWin ;获取当前鼠标的坐标和鼠标下的窗口
GetKeyState, _LButtonState, LButton, P
if _LButtonState = D ;如果鼠标是按下状态
{
if DragFlag = 0 ;且拖拽标志位为0
{
DragFlag := 1
WinGetPos, _WinPosx, _WinPosy,,, ahk_id %_MouseWin% ;将鼠标坐标暂存变量1和2都设置为当前坐标值
WinGetPos, _WinPosx2, _WinPosy2,,, ahk_id %_MouseWin%
WinGetTitle, _WinTitle, A ;获取当前窗口的标题
}
}
else if _LButtonState = U ;当鼠标抬起
{
if DragFlag = 1
{
DragFlag = 0
Sleep 500
IfWinExist ,,Select Split Option ;增加容错率,如果有分屏窗口,在摧毁当前GUI
Gui, Destroy
}
}
Sleep 50
if DragFlag = 1
{
WinGetPos, _WinPosx2, _WinPosy2,,, ahk_id %_MouseWin% ;将此时的窗口坐标存到暂存变量2中
if (_WinPosx > 0) AND (_WinPosy > 0) AND (_WinPosx2 > 0) AND (_WinPosy2 > 0) ;增加容错率,拖拽前后的坐标都大于0才进行下面动作
{
if (_WinPosx != _WinPosx2) OR (_WinPosy != _WinPosy2) ;当前后坐标不相等的时候,显示分屏窗口
{
ShowWinsplit()
}
}
}
}
Split(num) ;当前窗口三分屏函数
{
w := A_ScreenWidth/3+15 ;窗口宽度=屏幕横像素/3+15,直接除以3,3个窗口排不满,原因未知
h := A_ScreenHeight ;窗口高度=屏幕纵像素
pox_x = 0
pox_y = 0 ;窗口位置纵坐标=0,即窗口放到最顶部
if (num=1)
{
pos_x := 0 ;如果1,则窗口横坐标位置=0,即窗口放到屏幕左上角,宽度为1/3屏幕,高度为屏幕高度
pos_y := 0
w := A_ScreenWidth/3+15
h := A_ScreenHeight
}
else if(num=2)
{
pos_x := A_ScreenWidth/3
pos_y := 0
w := A_ScreenWidth/3+15
h := A_ScreenHeight
}
else if(num=3)
{
pos_x := A_ScreenWidth/3*2
pos_y := 0
w := A_ScreenWidth/3+15
h := A_ScreenHeight
}
else if(num=4)
{
pos_x := 0
pos_y := 0
w := A_ScreenWidth/2+15
h := A_ScreenHeight/2+15
}
else if(num=5)
{
pos_x := A_ScreenWidth/2
pos_y := 0
w := A_ScreenWidth/2+15
h := A_ScreenHeight/2+15
}
else if(num=6)
{
pos_x := 0
pos_y := A_ScreenHeight/2
w := A_ScreenWidth/2+15
h := A_ScreenHeight/2+15
}
else if(num=7)
{
pos_x := A_ScreenWidth/2
pos_y := A_ScreenHeight/2
w := A_ScreenWidth/2+15
h := A_ScreenHeight/2+15
}
else if(num=8)
{
pos_x := 0
pos_y := 0
w := A_ScreenWidth/3*2+15
h := A_ScreenHeight
}
else if(num=9)
{
pos_x := A_ScreenWidth/3
pos_y := 0
w := A_ScreenWidth/3*2+15
h := A_ScreenHeight
}
else
return ;如果函数传入其他数字,则return退出函数
;WinRestore %_WinTitle% ;如果当前窗口为最大化或者最小化状态,直接使用WinMove函数是不能移动和改变其大小的
;所以先使用WinRestore取消其最大化或者最小化状态,A表示当前窗口
WinMove, %_WinTitle%,, pos_x, pox_y, w, h ;调用WinMove函数,按照设定值改变窗口位置和大小
;WinMove, %_WinTitle%,, pos_x,pos_y, w, h
IfWinExist ,,Select Split Option ;增加容错率,如果有分屏窗口,在摧毁当前GUI
Gui Destroy
}
软件效果
使用方法
- 双击WinSpliter.exe,软件会常驻后台,屏幕右下角托盘区会出现图标
- 鼠标右键点击托盘图标,会出现菜单,设置进入软件设置界面,退出则关闭软件进程
- 鼠标左键点击图片图标,则直接进入设置界面,方块大小决定了分屏窗口的图形大小,数值越大图形越大;底边距离决定了分屏窗口离屏幕底边的距离,数值越大离底边越远
- 鼠标左键按下拖动任意窗口(经测试大部分窗口都有效,少部分app窗口拖动不会触发,待后续优化),按下状态稍作保持(正常情况下几百毫秒),屏幕上会出现分屏窗口;鼠标按下状态下移动到1#~9#分屏按钮上,在分屏窗口消失前迅速点击某一个分屏按钮,分屏动作立即完成
不足和限制
由于完成时间很短,现在功能还停留在初级阶段,还存在一些问题。
- 分屏窗口触发有不灵敏和迟滞现象,甚至有时候不会触发分屏
- 部分app窗口拖拽不会触发分屏窗口
- 出于容错率考虑,只有当窗口的左上角顶点(实际上,窗口左上角顶点为窗口的坐标点)在屏幕内才时拖拽窗口才会触发分屏;也就是说,如果窗口拖拽前是最大化或者左上角顶点在屏幕外,拖拽则不会触发分屏,需要先脱回屏内再进行后续操作