AutoHotKey技巧4:分屏GUI版出炉!Windows下的分屏软件 - WinSpliter

上上一篇文章中,介绍了用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
}

软件效果

image.png
image.png
image.png
image.png

使用方法

  • 双击WinSpliter.exe,软件会常驻后台,屏幕右下角托盘区会出现图标
  • 鼠标右键点击托盘图标,会出现菜单,设置进入软件设置界面,退出则关闭软件进程
  • 鼠标左键点击图片图标,则直接进入设置界面,方块大小决定了分屏窗口的图形大小,数值越大图形越大;底边距离决定了分屏窗口离屏幕底边的距离,数值越大离底边越远
  • 鼠标左键按下拖动任意窗口(经测试大部分窗口都有效,少部分app窗口拖动不会触发,待后续优化),按下状态稍作保持(正常情况下几百毫秒),屏幕上会出现分屏窗口;鼠标按下状态下移动到1#~9#分屏按钮上,在分屏窗口消失前迅速点击某一个分屏按钮,分屏动作立即完成

不足和限制

由于完成时间很短,现在功能还停留在初级阶段,还存在一些问题。

  • 分屏窗口触发有不灵敏和迟滞现象,甚至有时候不会触发分屏
  • 部分app窗口拖拽不会触发分屏窗口
  • 出于容错率考虑,只有当窗口的左上角顶点(实际上,窗口左上角顶点为窗口的坐标点)在屏幕内才时拖拽窗口才会触发分屏;也就是说,如果窗口拖拽前是最大化或者左上角顶点在屏幕外,拖拽则不会触发分屏,需要先脱回屏内再进行后续操作
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容