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窗口拖拽不会触发分屏窗口
  • 出于容错率考虑,只有当窗口的左上角顶点(实际上,窗口左上角顶点为窗口的坐标点)在屏幕内才时拖拽窗口才会触发分屏;也就是说,如果窗口拖拽前是最大化或者左上角顶点在屏幕外,拖拽则不会触发分屏,需要先脱回屏内再进行后续操作

你可能感兴趣的:(AutoHotKey技巧4:分屏GUI版出炉!Windows下的分屏软件 - WinSpliter)