美文网首页「河许人」Autohotkey
AutoHotKey技巧4:分屏GUI版出炉!Windows下的

AutoHotKey技巧4:分屏GUI版出炉!Windows下的

作者: 雷霆同学 | 来源:发表于2018-10-24 23:25 被阅读111次

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

        本文链接:https://www.haomeiwen.com/subject/qmuftqtx.html