Candy

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; AHK版本:1.1.15.0.4
; 脚本版本:2.0.0.6
; 版本日期 : 2014年09月10日
; 语言:       中文
; 适用平台:Win7
; 作者:		妖(aamii@qq.com)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
SetWorkingDir,%A_ScriptDir%
#MaxThreadsPerHotkey 5
#SingleInstance force
#WinActivateForce
#ClipboardTimeout 500
Process Priority,,High
coordmode,Mouse,screen
coordmode,Menu
SetTitleMatchMode,2
DetectHiddenWindows On
AutoTrim,on
SetBatchLines -1
ComObjError(0)
Menu, Tray, UseErrorLevel
; #NoTrayIcon
SkSub_CreatTrayMenu()   ;显示一个自定义的托盘菜单
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_My_global_and_PreDefined_Var:
	global szMenuIdx:={}      ;菜单用1
	global szMenuContent:={}      ;菜单用2
	global szMenuWhichFile:={}      ;菜单用3
	global GeneralSettings_ini     := "iniGeneralSettings.ini"
	IniRead All_MyVar,%GeneralSettings_ini%,MyVar		   	;读取我的变量,进行环境变量设置
	loop,parse,All_MyVar,`n
	{
		MyVar_Key:=RegExReplace(A_LoopField,"=.*?$")  	 ;用户自定义变量的key
		MyVar_Val:=RegExReplace(A_LoopField,"^.*?=") 		;用户自定义变量的value
		if (MyVar_Key && MyVar_Val && not instr(MyVar_Key," "))  ;抛弃空变量以及含空格的变量
			%MyVar_Key%=%MyVar_Val%   					;这样的写法不会传递环境变量。EnvSet,%MyVar_Key%,"%MyVar_Val%" ;另一种写法,可以传递环境变量到被他启动的应用程序
	}
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_SetHotKey:         ;热键定义段,这个部分要插入到“全脚本的自动运行部分去”,可用Gosub解决。
	IniRead,Candy_hotkey,%GeneralSettings_ini%,Candy_Hotkey           ;读取整个热键定义字段,自定义热键格式:   热键=配置文件
	Loop,parse,Candy_hotkey,`n     ;循环读取ini里面,热键定义字段的每一行
	{
		Hotkey,% RegExReplace(A_loopfield,"=.*?$"),Label_Candy_Start,On,UseErrorLevel   ;左边是热键
		If ErrorLevel  ;热键出错
            MsgBox % "您定义的热键:      "   RegExReplace(A_loopfield,"=.*?$")   "     不可用,请检查!"
	}
    Return
 /*
╔══════════════════════════════════════╗
>>>                                         ║
╚══════════════════════════════════════╝
*/
Label_Candy_Start:
;     CandyStartTick :=A_TickCount  ;若要评估出menu时间,这里需打开 ,共三处,1/3
    SkSub_Clear_CandyVar()
    MouseGetPos,,,Candy_CurWin_id         ;当前鼠标下的进程ID
    WinGet, Candy_CurWin_Fullpath,ProcessPath,Ahk_ID %Candy_CurWin_id%    ;当前进程的路径
    WinGetTitle, Candy_Title,Ahk_ID %Candy_CurWin_id%    ;当前进程的标题
    Candy_Saved_ClipBoard := ClipboardAll
    Clipboard =
    Send, ^c
    ClipWait,0.5
    If ( ErrorLevel  )          ;如果没有选择到什么东西,则退出
    {
        Clipboard := Candy_Saved_ClipBoard    ;还原粘贴板
        Candy_Saved_ClipBoard =
        Return
    }
    Candy_isFile := DllCall("IsClipboardFormatAvailable", "UInt", 15)   ;是否是文件类型
    Candy_isHtml := DllCall("RegisterClipboardFormat", "str", "HTML Format")  ;是否Html类型
    CandySel=%Clipboard%
    CandySel_Rich:=ClipboardAll
    Clipboard := Candy_Saved_ClipBoard  ;还原粘贴板
    Candy_Saved_ClipBoard =
    IniRead,Candy_ProFile_Ini,%GeneralSettings_ini%,Candy_Hotkey,%A_Thishotkey%    ;本热键所调取的配置文件
    Transform,Candy_ProFile_Ini,Deref,%Candy_ProFile_Ini%                         ;ini文件路径可以使用自定义变量以及环境变量
    IfNotExist %Candy_ProFile_Ini%         ;如果配置文件不存在,则发出警告,且终止
    {
        MsgBox 对热键%A_thishotkey% 定义的配置文件不存在! `n--------`n请检查%Candy_ProFile_Ini%
        Return
    }
    SplitPath,Candy_ProFile_Ini,,Candy_Profile_Dir,,Candy_ProFile_Ini_NameNoext
 /*
╔══════════════════════════════════════╗
>>>                                  ║
╚══════════════════════════════════════╝
*/
    If(Fileexist(CandySel) && RegExMatch(CandySel,"^(\\|.:\)")) ;文件或者文件夹,不再支持相对路径的文件路径,但容许“文字模式的全路径”
    {
        Candy_isFile:=1     ;如果是“文字型”的有效路径,强制认定为文件
        SplitPath,CandySel,CandySel_FileNameWithExt,CandySel_ParentPath,CandySel_Ext,CandySel_FileNameNoExt,CandySel_Drive
        SplitPath,CandySel_ParentPath,CandySel_ParentName,,,, ;用这个提取“所在文件夹名”
        If InStr(FileExist(CandySel), "D")  ;区分是否文件夹,Attrib= D ,则是文件夹
        {
            CandySel_FileNameNoExt:=CandySel_FileNameWithExt
            CandySel_Ext:=RegExMatch(CandySel,"^.:\$") ? "Drive":"Folder"            ;细分:盘符或者文件夹
        }
        Else  If (CandySel_Ext="")       ;若不是文件夹,且无后缀,则定义为NoExt
        {
            CandySel_Ext:="NoExt"
        }
        if (CandySel_ParentName="")
            CandySel_ParentName:=RTrim(CandySel_Drive,":")
    }
    Else if(instr(CandySel,"`n") And  Candy_isFile=1)  ;如果包含多行,且粘贴板性质为文件,则是“多文件”
    {
        CandySel_Ext:="MultiFiles" ;多文件的后缀=MultiFiles
        CandySel_FirstFile:=RegExReplace(CandySel,"(.*)r.*","$1")  ;取第一行
        SplitPath ,CandySel_FirstFile,,CandySel_ParentPath,,  ;以第一行的父目录为“多文件的父目录”
        If RegExMatch(CandySel_ParentPath,":(|\)$")  ;如果父目录是磁盘根目录,用盘符做父目录名。
            CandySel_ParentName:= RTrim(CandySel_ParentPath,":")
        else  ;否则,提取父目录名
            CandySel_ParentName:= RegExReplace(CandySel_ParentPath, ".*\(.*)$", "$1")
    }
    Else     ;文本类型
    {
        ;-----------特殊文字串辨析-------------------
        IniRead Candy_User_defined_TextType,%Candy_ProFile_Ini%,user_defined_TextType  ;是否符合用户正则定义的文本类型,有优先顺序的,排在前面的优先
        loop,parse,Candy_User_defined_TextType,`n
        {
            If(RegExMatch(CandySel,RegExReplace(A_LoopField,"^.*?=")))     ;根据ini里面用户自定义段,逐条查看,右侧是正则规则
            {
                CandySel_Ext:=RegExReplace(A_LoopField,"=.*?$")   ;左边是“文本某类型”
                Candy_Cmd:=SkSub_Regex_IniRead(Candy_ProFile_Ini, "TextType", "i)(^||)" CandySel_Ext "($||)") ;获取该类型的”操作设定“
                If(Candy_Cmd!="Error")            ;如果有相应后缀组的定义,则跳出去运行。
                {
                    Goto Label_Candy_Read_Value
                    Break
                }
            }
        }

        IniRead,Candy_ShortText_Length,%Candy_ProFile_Ini%,Candy_Settings,ShortText_Length,80   ;没有定义,则根据所选文本的长短,设定为长文本或者短文本
        CandySel_Ext:=StrLen(CandySel) >>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_Read_Value:
    Candy_Type          :=Candy_isFile> 0 ? "FileType":"TextType"         ;根据Candy_isFile判断类型,在相应的INI段里面查找定义
    Candy_Type_Any   :=Candy_isFile> 0 ? "AnyFile":"AnyText"         ;根据Candy_isFile判断类型,对应的Any的名称
    Candy_Cmd:=SkSub_Regex_IniRead(Candy_ProFile_Ini, Candy_Type, "i)(^||)" CandySel_Ext "($||)")  ;查找后缀群定义
    If(Candy_Cmd="Error")            ;如果没有相应后缀组的定义;下面这些啰嗦的写法是为了各种容错
    {
        IfExist,%Candy_Profile_Dir%%CandySel_Ext%.ini   ;看是否有 后缀.ini 的配置文件存在
        {
            Candy_Cmd:="menu|" CandySel_Ext   ;同时,转化为Menu|命令行写法
        }
        Else
        {
            IniRead,Candy_Cmd, %Candy_ProFile_Ini%,%Candy_Type%,%Candy_Type_Any%   ;如果没有则看看 Any在ini的定义有没有
            If(Candy_Cmd="Error")   ;没有对AnyFile(或AnyText)的定义,则看是否有 AnyFile.ini或AnyText.ini配置存在
            {
                IfExist,%Candy_Profile_Dir%%Candy_Type%.ini   ;有,则以此为准
                {
                    Candy_Cmd:="menu|" Candy_Type   ;同时,转化为Menu|命令行写法
                }
                Else
                {
                    Run,%CandySel%, ,UseErrorLevel  ;层层把关都没有么,好失望的说,就直接运行吧
                    Return
                }
            }
        }
    }
    If !(RegExMatch(Candy_Cmd,"i)^Menu|"))
    {
        Goto Label_Candy_RunCommand            ;如果不是menu指令,直接运行应用程序
    }
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_DrawMenu:
    Menu,CandyTopLevelMenu,add
    Menu,CandyTopLevelMenu,DeleteAll
    CandyMenu_IconSize:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "MenuIconSize",16)
    CandyMenu_IconDir:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "MenuIconDir")  ;菜单图标位置

 ;加第一行菜单,缩略显示选中的内容,该菜单让你拷贝其内容
    CandyMenu_FirstItem:=Strlen(CdSel_NoSpace:=Trim(CandySel)) >20 ? SubStr(CdSel_NoSpace,1,10) . "..." . SubStr(CdSel_NoSpace,-10) : CdSel_NoSpace
    Menu CandyTopLevelMenu,Add,%CandyMenu_FirstItem%,Label_Candy_CopyFullpath
    Candy_Firstline_Icon:=SkSub_Get_Firstline_Icon(CandySel_Ext,CandySel,CandyMenu_IconDir "Extension")
    Menu CandyTopLevelMenu,icon,%CandyMenu_FirstItem%,%Candy_Firstline_Icon%,,%CandyMenu_IconSize%
    Menu CandyTopLevelMenu,Add

    arrCandyMenuFrom:=StrSplit( Candy_Cmd,"|")
    CandyMenu_ini:= arrCandyMenuFrom[2]="" ? Candy_ProFile_Ini_NameNoext : arrCandyMenuFrom[2]
    CandyMenu_sec:= arrCandyMenuFrom[3]="" ? "Menu" : arrCandyMenuFrom[3]

    szMenuIdx:={}
    szMenuContent:={}
    szMenuWhichFile:={}
    SkSub_GetMenuItem(Candy_Profile_Dir,CandyMenu_ini,CandyMenu_sec,"CandyTopLevelMenu","")
    SkSub_DeleteSubMenus("CandyTopLevelMenu")

    For,k,v in szMenuIdx
    {
        SkSub_CreateMenu(v,"CandyTopLevelMenu","Label_Candy_HandleMenu",CandyMenu_IconDir,CandyMenu_IconSize)
    }
    MouseGetPos,CandyMenu_X, CandyMenu_Y
    MouseMove,CandyMenu_X,CandyMenu_Y,0
    MouseMove,CandyMenu_X,CandyMenu_Y,0
;     ToolTip,% A_TickCount-CandyStartTick,200,0     ;若要评估出menu时间,这里需打开 ,共三处,2/3
    Menu,CandyTopLevelMenu,shOW
;     ToolTip ;若要评估出menu时间,这里需打开 ,共三处,3/3
    Return

;================菜单处理================================
Label_Candy_HandleMenu:
    If GetKeyState("Ctrl")			    ;[按住Ctrl则是进入配置]
    {
        Candy_ctrl_ini_fullpath:=Candy_Profile_Dir . "" . szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem] . ".ini"
        Candy_Ctrl_Regex:= "=s*Q" szMenuContent[ A_thisMenu "/" A_ThisMenuItem] "Es*$"
        SkSub_EditConfig(Candy_ctrl_ini_fullpath,Candy_Ctrl_Regex)
    }
    else
    {
        Candy_Cmd := szMenuContent[ A_thisMenu "/" A_ThisMenuItem]
        CandyError_From_Menu:=1
        Goto Label_Candy_RunCommand
    }
    return

Label_Candy_CopyFullpath:
    If GetKeyState("Ctrl")			    ;[按住Ctrl则是进入主配置]
    {
        Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
        SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
    }
    Else
        Clipboard:=CandySel
    Return
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_RunCommand:
    Candy_Cmd:=SkSub_EnvTrans(Candy_Cmd)  ;替换自变量以及系统变量,Ini里面用~%表示一个%,当然要用~~%,表示一个原义的~%
    Candy_Cmd=%Candy_Cmd%
    If (instr(Candy_Cmd,"{SetClipBoard:pure}")+instr(Candy_Cmd,"{SetClipBoard:rich}") )       ;这个开关指令会修改系统粘贴板,不会对命令行本身产生作用。所以先要从命令行替换掉。
    {
        Clipboard:=InStr(Candy_Cmd,"{SetClipBoard:pure}") ? CandySel : CandySel_Rich
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){SetClipBoard:.*}")
    }
    If (instr(Candy_Cmd,"{icon:")) ;icon图标
    {
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){icon:.*}")
    }
    If Candy_Cmd=   ;如果只想进行以上两步操作,如果运行的指令为空,则直接退出
        Return
    If instr(Candy_Cmd,"{date:")     ; 时间参数!定义方法为:{date:yyyy_MM_dd} 冒号:后面的部分可以随意定义
    {
        Candy_Time_Mode:=RegExReplace(Candy_Cmd,"i).*{date:(.*?)}.*","$1")
        FormatTime,Candy_Time_Formated,%A_nOW%,%Candy_Time_Mode%
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){date:(.*?)}",Candy_Time_Formated)
    }
    If instr(Candy_Cmd,"{in:")    ; in:多文件的后缀包含
    {
        Candy_in_M:="i`am)^.*.(" RegExReplace(Candy_Cmd,"i).*{in:(.*?)}.*","$1") ")$"
        Grep(CandySel, Candy_in_M, CandySel, 1, 0, "`n")
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){in:.*}")
        If  (CandySel="")
            Return
        Else
            StringReplace,CandySel,CandySel,`n,`r`n,all
    }
    If instr(Candy_Cmd,"{ex:")    ; ex:多文件的后缀排除
    {
        Candy_ex_M:="i`am)^.*.(" RegExReplace(Candy_Cmd,"i).*{ex:(.*?)}.*","$1") ")$R?"    ;可用,只是多了一个”后空白问题“
        CandySel:=RegExReplace(CandySel,Candy_ex_M)
        CandySel:=RegExReplace(CandySel,"s*$","")         ;清除后空白 CandySel:=trim(CandySel,"`r`n")         ;清除后空白
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){ex:.*}")
        Clipboard:=CandySel
        If  (CandySel="")
            Return
    }
    If instr(Candy_Cmd,"{input:")   ;特别的参数:带有prompt提示文字的input 例:{Input:请输入延迟时间,以ms为单位},支持多个input输入
    {    ;如果要输入密码,请写成{input:提示文字:hide}
        CdInput_P=1
        Candy_Cmd_tmp:=Candy_Cmd
        While	CdInput_P :=	RegExMatch(Candy_Cmd_tmp, "i){input:(.*?)}", CdInput_M, CdInput_P+strlen(CdInput_M))
        {
            CdInput_Prompt:= RegExReplace(CdInput_M,"i).*{input:(.*?)(:hide)?}.*","$1")
            CdInput_Hide:= RegExMatch(CdInput_M,"i){input:.*?:hide}") ? "hide":""
            Gui +LastFound +OWnDialogs +AlwaysOnTop
            InputBox, CdInput_txt,Candy InputBox,`n%CdInput_Prompt% ,%CdInput_Hide%, 285, 175,,,,,
            If ErrorLevel
                Return
            Else
                StringReplace,Candy_Cmd,Candy_Cmd,%CdInput_M%,%CdInput_txt%
        }
    }
    If instr(Candy_Cmd,"{box:Filebrowser}")
    {
        FileSelectFile, f_File ,,, 请选择文件
        If ErrorLevel
            return
        StringReplace,Candy_Cmd,Candy_Cmd,{box:Filebrowser},%f_File%,All
    }
    If instr(Candy_Cmd,"{box:mFilebrowser}")
    {
        FileSelectFile, f_File ,M, , 请选择文件
        If ErrorLevel
            return
        CdMfile_suffix  := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:.*LastFile(.*?)}.*","$1")
        CdMfile_prefix  := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:(.*?)FirstFile.*","$1")
        CdMfile_midfix := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:.*FirstFile(.*?)LastFile.*}.*","$1")
        Firstline:=RegExReplace(f_File,"n.*")
        no_Firstline:=RegExReplace(f_File,"^.*?n","$1")
        StringReplace  ,CandySel_list,no_Firstline,`n,%CdMfile_midfix%%Firstline%/,all
        CandySel_list=%CdMfile_prefix%%Firstline%%CandySel_list%%CdMfile_suffix%
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){.*FirstFile.*LastFile.*}",CandySel_list)
    }
    If instr(Candy_Cmd,"{box:folderbrowser}")
    {
        FileSelectFolder, f_Folder , , , 请选择文件夹
        If f_Folder 
            StringReplace,Candy_Cmd,Candy_Cmd,{box:folderbrowser},%f_Folder%,All
        Else
            Return
    }
    Candy_Cmd:=RegExReplace(Candy_Cmd,"(?>>>                                                  ║
╚══════════════════════════════════════╝
*/
    Candy_All_Cmd:="web|keys|cando|cango|run|openwith|SetClipBoard|msgbox|config|openwith|ow|rund|runp"
    If Not RegExMatch(Candy_Cmd,"i)^s*(" Candy_All_Cmd ")s*|")
        Candy_Cmd=OpenWith|%Candy_Cmd% ;如果没有,则人为补一个OpenWith
    Candy_Cmd:=RegExReplace(Candy_Cmd,"~|",Chr(3))
    arrCandy_Cmd_Str:=StrSplit(Candy_Cmd,"|"," `t")
    Candy_Cmd_Str1:=arrCandy_Cmd_Str[1]
    Candy_Cmd_Str2:=RegExReplace(arrCandy_Cmd_Str[2],Chr(3),"|")
    Candy_Cmd_Str3:=RegExReplace(arrCandy_Cmd_Str[3],Chr(3),"|")
    If (Candy_Cmd_Str1="web")
    {
        SkSub_WebSearch(Candy_CurWin_Fullpath,RegExReplace(Candy_Cmd,"i)^web|(s+|)|s+"))
    }
    Else If (Candy_Cmd_Str1="Keys")  ;如果是以keys|开头,则是发热键
    {
       Send %Candy_Cmd_Str2%
    }
    Else If (Candy_Cmd_Str1="MsgBox")  ;如果是以MsgBox|开头,则是发一个提示框
    {
        Gui +LastFound +OWnDialogs +AlwaysOnTop
        MsgBox %Candy_Cmd_Str2%
    }
    Else If (Candy_Cmd_Str1="Config")
    {
        for k,v in szMenuWhichfile
            Config_files .= v "`n"
        Config_files:=RemoveDuplicates(Config_files)
        Loop ,parse, Config_files,`n
            SkSub_EditConfig(Candy_Profile_Dir . "" A_LoopField ".ini","")
        Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
            SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
    }
    Else If (Candy_Cmd_Str1="SetClipBoard")   ;之前的开关,只能把选中的内容放进粘贴板,而这个指令,则可以把后面跟随的内容放进粘贴板。(更丰富)
    {
        Clipboard := Candy_Cmd_Str2
    }
    Else If (Candy_Cmd_Str1="Cando")  ;如果是以Cando|开头,则是运行一些内部程序,方便与你的其它脚本进行挂接
    {
        CandySelected:=CandySel    ;兼容以前的cando变量写法
        If IsLabel("Cando_" . Candy_Cmd_Str2)                       ;程序内置的别名
            Goto % "Cando_" . Candy_Cmd_Str2
        Else
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="Cango")   ;如果是以Cango|开头,则是运行一些外部ahk程序,方便与你的其它脚本进行挂接
    {
        IfExist,%Candy_Cmd_Str2%
            Run %ahk% "%Candy_Cmd_Str2% %Candy_Cmd_Str3%" ;外部的ahk代码段,你的ahk可以带参数
        Else
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="OpenWith" or Candy_Cmd_Str1="OW")     ;OpenWith|指定用某程序打开选定的内容,这时候,应用程序后面不能带任何命令行,(严格的说是目标参数是且仅是“被选内容“,只是被省略了)
    {
        Run ,%Candy_Cmd_Str2% "%CandySel%",%Candy_Cmd_Str3%,%Candy_Cmd_Str4% UseErrorLevel             ;1:程序  2:工作目录 3:状态
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="Run")     ;其后面要带命令行,即使操作对象是被选中的文件,也不能省略
    {
        Run,%Candy_Cmd_Str2% ,%Candy_Cmd_Str3%,%Candy_Cmd_Str4% UseErrorLevel             ;1:程序  2:工作目录 3:状态
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="RunD")     ;格式为RunD|应用程序|应用程序的标题|x|y|等待时间
    {       ;没发现这个x,y起作用的情况,暂时放着
        Run,%Candy_Cmd_Str2%,, UseErrorLevel
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
        else
        {
            Sleep,% (Candy_Cmd_Str4="") ? 1000 : arrCandy_Cmd_Str[6]
            WinWaitActive, %Candy_Cmd_Str3% ,,5
            WinActivate, %Candy_Cmd_Str3%
            Candy_RunD_x:=arrCandy_Cmd_Str[4] ? arrCandy_Cmd_Str[4] : 100
            Candy_RunD_y:=arrCandy_Cmd_Str[5] ? arrCandy_Cmd_Str[5] : 100
            PostMessage, 0x233, HDrop( CandySel,Candy_RunD_x,Candy_RunD_y), 0,, %Candy_Cmd_Str3%
        }
    }
    Else If (Candy_Cmd_Str1="RunP")     ;格式为RunP|应用程序|应用程序的标题|等待时间;;
    {
        Clipboard := CandySel_Rich
        Run,%Candy_Cmd_Str2%,, UseErrorLevel
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
        else
        {
            Sleep,% (Candy_Cmd_Str4="") ? 1000 : Candy_Cmd_Str4
            WinWaitActive, %Candy_Cmd_Str3% ,,5
            WinActivate, %Candy_Cmd_Str3%
            Send ^v
        }
    }
    Return
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_ErrorHandle: ;出错啦!
	If (SkSub_IniRead(Candy_ProFile_Ini,"Candy_Settings","ShowError", 0)=1 )     ;看看出错提示开关打开了没有,打开了的话,就显示出错信息
	{
		Gui +LastFound +OwnDialogs +AlwaysOnTop
        MsgBox, 4116,, 下述命令行定义出错: `n---------------------`n%Candy_Cmd%`n---------------------`n后缀名: %CandySel_Ext%`n`n立即配置相应ini?
		IfMsgBox Yes
		{
            if (CandyError_From_Menu=1)
            {
                Candy_This_ini:=szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem]
                Candy_ctrl_ini_fullpath:=Candy_Profile_Dir . "" . szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem] . ".ini"
                Candy_Ctrl_Regex:= "=s*Q" szMenuContent[ A_thisMenu "/" A_ThisMenuItem] "Es*$"
                SkSub_EditConfig(Candy_ctrl_ini_fullpath,Candy_Ctrl_Regex)
            }
            else
            {
                Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
                SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
            }
		}
	}
	Return

 /*
╔══════════════════════════════════════╗
>>>                                  ║
╚══════════════════════════════════════╝
*/
SkSub_GetMenuItem(IniDir,IniNameNoExt,Sec,TopRootMenuName,Parent="")   ;从一个ini的某个段获取条目,用于生成菜单。
{
    Items:=SkSub_IniRead_Section(IniDir "" IniNameNoExt ".ini",sec)         ;本次菜单的发起地
    StringReplace,Items,Items,△,`t,all
    Loop,parse,Items,`n
    {
        Left:=RegExReplace(A_LoopField,"(?]*")
        Right:=RegExReplace(A_LoopField,"^.*?=s*(.*)s*$","$1")
        If (RegExMatch(left,"^/|//|/$|^$")) ;如果最右端是/,或者最左端是/,或者存在//,则是一个错误的定义,抛弃
            Continue
        If RegExMatch(Left,"i)(^|/)+$")   ;如果左边的最末端是仅仅一个"独立的" + 号
        {
            m_Parent := InStr(Left,"/") > 0 ? RegExReplace(Left,"/[^/]*$") "/" : ""  ;如果+号前面有存在上级菜单,则有上级菜单,否则没有
            Right:=RegExReplace(Right,"~|",Chr(3))
            arrRight:=StrSplit(Right,"|"," `t")
            rr1:=arrRight[1]
            rr2:=RegExReplace(arrRight[2],Chr(3),"|")
            rr3:=RegExReplace(arrRight[3],Chr(3),"|")
            rr4:=RegExReplace(arrRight[4],Chr(3),"|")
            If (rr1="Menu")   ;如果后面是“插入(子)菜单”的命令 ,则极有可能菜单里面还有“嵌套的下级菜单”。。
            {
                m_ini:= (rr2="") ? IniNameNoExt :  rr2
                m_sec:= (rr3="") ? "Menu" : rr3
				m_Parent:=Parent "" m_Parent
                this:=SkSub_GetMenuItem(IniDir,m_ini,m_sec,TopRootMenuName,m_Parent)      ;嵌套,循环使用此函数,以便处理“其他文件里的,插入的菜单”
            }
;             用+的方法,可以让你快速扩展自己定义的子菜单,否则直接可以写在左侧了。
        }
        Else
        {
            szMenuIdx.insert( Parent ""  Left )
            szMenuContent[ TopRootMenuName "/" Parent "" Left] := Right
            szMenuWhichFile[ TopRootMenuName "/" Parent "" Left] :=IniNameNoExt
        }
    }
}
SkSub_DeleteSubMenus(TopRootMenuName)
{
    For i,v in szMenuIdx
    {
        If instr(v,"/")>0
        {
            Item:=RegExReplace(v, "(.*)/.*", "$1")
            Menu,%TopRootMenuName%/%Item%,add
            Menu,%TopRootMenuName%/%Item%,DeleteAll
        }
    }
}
SkSub_CreateMenu(Item,ParentMenuName,label,IconDir,IconSize)    ;条目,它所处的父菜单名,菜单处理的目标标签
{  ;送进来的Item已经经过了“去空格处理”,放心使用
    arrS:=StrSplit(Item,"/"," `t")
    _s:=arrS[1]
    if arrS.Maxindex()= 1      ;如果里面没有 /,就是最终的”菜单项“。添加到”它的父菜单”上。
    {
        If InStr(_s,"-") = 1       ;-分割线
        Menu, %ParentMenuName%, Add
        Else If InStr(_s,"*") = 1       ;* 灰菜单
        {
            _s:=Ltrim(_s,"*")
            Menu, %ParentMenuName%, Add,       %_s%,%Label%
            Menu, %ParentMenuName%, Disable,  %_s%
        }
        Else
        {
            y:=szMenuContent[ ParentMenuName "/" Item]
            z:=SkSub_Get_MenuItem_Icon( y ,IconDir)
            Menu, %ParentMenuName%, Add,  %_s%,%Label%
            Menu, %ParentMenuName%, icon,  %_s%,%z%,,%IconSize%
        }
    }
    Else     ;如果有/,说明还不是最终的菜单项,还得一层一层分拨出来。
    {
        _Sub_ParentName=%ParentMenuName%/%_s%
        StringTrimLeft,_subItem,Item,strlen(_s)+1
        SkSub_CreateMenu(_subItem,_Sub_ParentName,label,IconDir,IconSize)
        Menu,%ParentMenuName%,add,%_s%,:%_Sub_ParentName%
    }
}
SkSub_EnvTrans(v)
{
    v:=RegExReplace(v,"~%",Chr(3))
    Transform,v,Deref,%v% ;解决Sala的ini中支持%A_desktop%或%windir%等ahk变量或系统环境变量的解释问题,@sunwind @小古
    v:=RegExReplace(v,Chr(3),"%")
    Return v
}
SkSub_Get_Firstline_Icon(ext,fullpath,iconpath)
{
	IfExist,%iconpath%%ext%.ico             ;如果固定的文件夹里面存在该类型的图标
		x := iconpath "" ext ".ico"
	Else If ext in  bmp,gif,png,jpg,ico,icl,exe,dll
		x := fullpath
	Else
		x:=AssocQueryApp(Ext)
	Return %x%
}
SkSub_Get_MenuItem_Icon(item,iconpath)   ; item=需要获取图标的条目,iconpath=你定义的图标库文件夹
{
	cmd:=RegExReplace(item,"^s+|(|s+)|[^!]*[^>]*")
    If instr(item,"{icon:")     ; 有图标硬定义
    {
        Path_Icon:=RegExReplace(item,"i).*{icon:(.*?)}.*","$1")
        If(Fileexist(Path_Icon))         ;若有全路径的图标存在
			return Path_Icon
		If(Fileexist(iconpath "MyIcon" Path_Icon))       ;若在MyIcon文件夹里面
			return iconpath "MyIcon" Path_Icon
    }
	Else if FileExist(iconpath "Command" cmd ".ico")      ;若存在 "命令名.ico" 文件
	{
		Return  iconpath "Command" cmd ".ico"
	}
	item:=SkSub_envtrans(item)
	if RegExMatch(item,"i)^(ow|openwith|rot|run|roa|runp|rund)|") ;运行命令类
	{
		cmd_removed:=RegExReplace(item,"^.*?|")      ;里面纯粹的 应用程序 路径
		x:=RegExReplace(cmd_removed,"i)exe[^!]*[^>]*", "exe")
		Return %x%
	}
	Else if instr(item,".exe") ;省略了指令的openwith|
	{
		x:=RegExReplace(item,"i).exe[^!]*[^>]*", ".exe")
		Return %x%
	}
	Else
	{
		t:=RegExReplace(item,"s*|.*?$")       ;去除运行参数,只保留第一个|最前面的部分
		x:=AssocQueryApp(t)
		Return %x%
	}
}
AssocQueryApp(sExt)
{
    sExt =.%sExt%  ;ASSOCSTR_EXECUTABLE
    DllCall("shlwapi.dllAssocQueryString", "uint", 0, "uint", 2, "uint", &sExt, "uint", 0, "uint", 0, "uint*", iLength)
    VarSetCapacity(sApp, 2*iLength, 0)
    DllCall("shlwapi.dllAssocQueryString", "uint", 0, "uint", 2, "uint", &sExt, "uint", 0, "str", sApp, "uint*", iLength)
    Return sApp
}
SkSub_Regex_IniRead(ini,sec,reg)      ;正则方式的读取,等号左侧符合正则条件
{  ;在ini的某个段内,查找符合某正则规则的字符串,并返回value值
	IniRead,keylist,%ini%,%sec%,
	Loop,Parse,keylist,`n
	{
		t:=RegExReplace(A_LoopField,"=.*?$")
		If(RegExMatch(t, reg))
		{
			Return % RegExReplace(A_LoopField,"^.*?=")
			Break
		}
	}
	Return "Error"
}
SkSub_IniRead(ini, sec, key="", default = "")   ;iniread的函数化
{
	IniRead, v, %ini%, %sec%, %key%, %default%
	Return, v
}
SkSub_IniRead_Section(ini,sec)
{  ;返回全部某段的内容,函数化而已
	IniRead,keylist,%ini%,%sec%              ;提取[sec]段里面所有的群组
		Return %keylist%
}
grep(h, n, ByRef v, s = 1, e = 0, d = "")
{
	v =
	StringReplace, h, h, %d%, , All
	Loop
		If s := RegExMatch(h, n, c, s)
			p .= d . s, s += StrLen(c), v .= d . (e ? c%e% : c)
		Else Return, SubStr(p, 2), v := SubStr(v, 2)
}
SkSub_UrlEncode(str, enc="UTF-8")
{
    enc:=trim(enc)
    If enc=
        Return str
   hex := "00", func := "msvcrt" . (A_IsUnicode ? "swprintf" : "sprintf")
   VarSetCapacity(buff, size:=StrPut(str, enc)), StrPut(str, &buff, enc)
   While (code := NumGet(buff, A_Index - 1, "UChar")) && DllCall(func, "Str", hex, "Str", "%%%02X", "UChar", code, "Cdecl")
   encoded .= hex
   Return encoded
}
SkSub_WebSearch(Win_Full_Path,Http)
{
	all_browser:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "InUse_Browser")
	DefaultBrowser:=SkSub_EnvTrans(SkSub_IniRead(GeneralSettings_ini, "General_Settings", "Default_Browser"))
	;第①步,看当前当前激活窗口 是否 浏览器
	If Win_Full_Path Contains %All_Browser%
	{
		Browser:=Win_Full_Path
	}
	;第②步,看进程里面有没有浏览器,若有,看能被提取出来(防止虚拟桌面的隔离,妖自己的需求)
	Else Loop,Parse,All_Browser,`,   ;看所有定义的浏览器,
	{
		Useful_FullPath:=SkSub_process_exist_and_useful(A_LoopField)
		If (  Useful_FullPath!= 0  and Useful_FullPath!= 1 )
		{
			Browser:=Useful_FullPath
			Break
		}
	}
	; 第③步	,都没有么,看ini默认浏览器是否符合条件
	If ( Browser="")  ;看ini默认浏览器,a。看进程中是否有,并且能被提取出来(防止虚拟桌面的隔离,妖自己的需求)。b。或者进程里面没有。
	{
		DefaultBrowser_去除参数:= RegExReplace(DefaultBrowser, "exe[^!]*[^>]*", "exe")
		SplitPath ,DefaultBrowser_去除参数,DefaultBrowser_name
		Useful_FullPath:=SkSub_process_exist_and_useful(DefaultBrowser_name)
		If (  Useful_FullPath!= 0  And FileExist(DefaultBrowser_去除参数))
		{
			Browser:=DefaultBrowser
		}
	}
	; 第④部,最终运行
	If Browser ;如果取到了浏览器
	{
		SplitPath,browser,,,,browser_namenoext
        Browser_Args:=SkSub_IniRead(GeneralSettings_ini, "WebBrowser's_CommandLIne", browser_namenoext)
		If (Browser_Args!="Error")  ;有些浏览器,必须带参数,比如config或者单进程限制等待,所以在ini里面提供了一个定义的地方。
		{
			Browser := Browser " " Browser_Args
		}
		Run,% Browser . " """ . Http . """"
		IfInString Browser,firefox.exe
			WinActivate,Mozilla Firefox Ahk_Class MozillaWindowClass
		Else
			WinActivate Ahk_PID %ErrorLevel%
	}
	Else ;没有浏览器么
	{  ;看注册表 是否有默认的浏览器
		RegRead, RegDefaultBrowser, HKEY_CLASSES_ROOT, httpshellopencommand
		StringReplace, RegDefaultBrowser, RegDefaultBrowser,"
		SplitPath, RegDefaultBrowser,,RDB_Dir,,RDB_NameNoExt,
		Run,% RDB_Dir . "" . RDB_NameNoExt . ".exe" . " """ . Http . """",,UseErrorLevel
		If errorlevel
		{
			Run,% "iexplore.exe " . site . """"	  ;internet explorer
		}
	}
}
;============================================================================================================
SkSub_process_exist_and_useful(Process_name)        ;判断某个进程是否存在且能有效运行,如果不用desktops,这段代码可以清除掉。
{
	Process,exist,%Process_name%
	WinGet, Process_Fullpath,ProcessPath,Ahk_PID %ErrorLevel%
	If (ErrorLevel!=0 And  Process_Fullpath!="")
		Return %Process_Fullpath%
	Else if ErrorLevel=0
		Return 1
	Else
		Return 0
}
HDrop(fnames,x=0,y=0)
{
	characterSize := A_IsUnicode ? 2 : 1
	fns:=RegExReplace(fnames,"n$")
	fns:=RegExReplace(fns,"^n")
	hDrop:=DllCall("GlobalAlloc","UInt",0x42,"UInt",20+(StrLen(fns)*characterSize)+characterSize*2)
	p:=DllCall("GlobalLock","UInt",hDrop)
	NumPut(20, p+0)  ;offset
	NumPut(x,  p+4)  ;pt.x
	NumPut(y,  p+8)  ;pt.y
	NumPut(0,  p+12) ;fNC
	NumPut(A_IsUnicode ? 1 : 0,  p+16) ;fWide
	p2:=p+20
	Loop,Parse,fns,`n,`r
	{
		DllCall("RtlMoveMemory","UInt",p2,"Str",A_LoopField,"UInt",StrLen(A_LoopField)*characterSize)
		p2+=StrLen(A_LoopField)*characterSize + characterSize
	}
	DllCall("GlobalUnlock","UInt",hDrop)
	Return hDrop
}
SkSub_EditConfig(inifile,regex="") ;编辑配置文件!
{
	if not fileExist(inifile)      ;动态菜单未必有ini文件存在
		return
	if (regex"")  ;如果送了正则表达式进来
	{
		Loop
		{
			FileReadLine, L, %inifile%, %A_Index%
			if ErrorLevel
				break
			if regexmatch(L,regex)
			{
				LineNo:=a_index
				break
			}
		}
	}
	TextEditor:=SkSub_EnvTrans(SkSub_IniRead(GeneralSettings_ini, "General_Settings", "Default_TextEditor"))  ;默认文本编辑器
	TextEditor:=FileExist(TextEditor) ? TextEditor:"notepad.exe"       ;文本编辑器
	SplitPath,TextEditor,,,,namenoext
	LineJumpArgs:=SkSub_IniRead(GeneralSettings_ini, "TextEditor's_CommandLine", namenoext)
	if  (LineJumpArgs="Error" or LineNo="" )
		cmd :=TextEditor " " inifile
	else
	{
		cmd :=TextEditor " " LineJumpArgs
		StringReplace,cmd,cmd,$(FILEPATH),%inifile%
		StringReplace,cmd,cmd,$(LINENUM),%LineNo%
	}
	Run,%cmd%,,UseErrorLevel,TextEditor_PID
	WinActivate ahk_pid %TextEditor_PID%
	return
}

SkSub_Clear_CandyVar()
{
	Global
    CandySel:=
    CandySel_LinkTarget:=
    CandySel_Ext:=
    CandySel_FileNamenoExt:=
    CandySel_ParentPath:=
    CandySel_ParentName:=
    CandySel_Drive:=
	Config_files:=
	CandyError_From_Menu:=0
}

RemoveDuplicates(Str, Delimiter="`n")
{
        Str_sort :=	Str
        Sort, Str_sort, U
        Loop, parse, Str_sort, `n, `r
        {
            Str_m :=	"`am)^" A_LoopField "$"
            Str :=	RegExReplace(Str,Str_m,"","",-1,RegExMatch(Str,Str_m)+StrLen(A_LoopField))
        }
        return %	Trim(RegExReplace(Str,"v+","`n"))
}
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
SkSub_CreatTrayMenu()
{

  Menu, Tray, Icon,candy.ico
  Menu, Tray, NoStandard
  Menu, tray, add, 关于与提示,TrayHandle_About
  Menu, tray, add ; 分隔符
  Menu, tray, add, 编辑全局配置,TrayHandle_GeneralSettings
  Menu, tray, add, 重启脚本,TrayHandle_ReLoad
  Menu, tray, add, 退出,TrayHandle_Exit
}
/*
╔══════════════════════════════════════╗
>>>                         ║
╚══════════════════════════════════════╝
*/
TrayHandle_ReLoad:
  Reload
Return
TrayHandle_Exit:
  ExitApp
Return

TrayHandle_GeneralSettings:
    SkSub_EditConfig(GeneralSettings_ini,"")
    return

TrayHandle_About:
  MsgBox, , About Candy,
  ( LTrim
    版本 Candy2.0.0.6

    作者:万年书妖
    邮箱:aamii@qq.com
    QQ:710117768

    如果你是首次试用,请学习如何手动修改配置
    交流请进QQ群: 3222783

    随代码带有四套配置,请选中文件或文本后分别用^f1~f4进行体验
  )
  Return

Candy

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; AHK版本:1.1.15.0.4
; 脚本版本:2.0.0.6
; 版本日期 : 2014年09月10日
; 语言:       中文
; 适用平台:Win7
; 作者:		妖(aamii@qq.com)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
SetWorkingDir,%A_ScriptDir%
#MaxThreadsPerHotkey 5
#SingleInstance force
#WinActivateForce
#ClipboardTimeout 500
Process Priority,,High
coordmode,Mouse,screen
coordmode,Menu
SetTitleMatchMode,2
DetectHiddenWindows On
AutoTrim,on
SetBatchLines -1
ComObjError(0)
Menu, Tray, UseErrorLevel
; #NoTrayIcon
SkSub_CreatTrayMenu()   ;显示一个自定义的托盘菜单
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_My_global_and_PreDefined_Var:
	global szMenuIdx:={}      ;菜单用1
	global szMenuContent:={}      ;菜单用2
	global szMenuWhichFile:={}      ;菜单用3
	global GeneralSettings_ini     := "iniGeneralSettings.ini"
	IniRead All_MyVar,%GeneralSettings_ini%,MyVar		   	;读取我的变量,进行环境变量设置
	loop,parse,All_MyVar,`n
	{
		MyVar_Key:=RegExReplace(A_LoopField,"=.*?$")  	 ;用户自定义变量的key
		MyVar_Val:=RegExReplace(A_LoopField,"^.*?=") 		;用户自定义变量的value
		if (MyVar_Key && MyVar_Val && not instr(MyVar_Key," "))  ;抛弃空变量以及含空格的变量
			%MyVar_Key%=%MyVar_Val%   					;这样的写法不会传递环境变量。EnvSet,%MyVar_Key%,"%MyVar_Val%" ;另一种写法,可以传递环境变量到被他启动的应用程序
	}
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_SetHotKey:         ;热键定义段,这个部分要插入到“全脚本的自动运行部分去”,可用Gosub解决。
	IniRead,Candy_hotkey,%GeneralSettings_ini%,Candy_Hotkey           ;读取整个热键定义字段,自定义热键格式:   热键=配置文件
	Loop,parse,Candy_hotkey,`n     ;循环读取ini里面,热键定义字段的每一行
	{
		Hotkey,% RegExReplace(A_loopfield,"=.*?$"),Label_Candy_Start,On,UseErrorLevel   ;左边是热键
		If ErrorLevel  ;热键出错
            MsgBox % "您定义的热键:      "   RegExReplace(A_loopfield,"=.*?$")   "     不可用,请检查!"
	}
    Return
 /*
╔══════════════════════════════════════╗
>>>                                         ║
╚══════════════════════════════════════╝
*/
Label_Candy_Start:
;     CandyStartTick :=A_TickCount  ;若要评估出menu时间,这里需打开 ,共三处,1/3
    SkSub_Clear_CandyVar()
    MouseGetPos,,,Candy_CurWin_id         ;当前鼠标下的进程ID
    WinGet, Candy_CurWin_Fullpath,ProcessPath,Ahk_ID %Candy_CurWin_id%    ;当前进程的路径
    WinGetTitle, Candy_Title,Ahk_ID %Candy_CurWin_id%    ;当前进程的标题
    Candy_Saved_ClipBoard := ClipboardAll
    Clipboard =
    Send, ^c
    ClipWait,0.5
    If ( ErrorLevel  )          ;如果没有选择到什么东西,则退出
    {
        Clipboard := Candy_Saved_ClipBoard    ;还原粘贴板
        Candy_Saved_ClipBoard =
        Return
    }
    Candy_isFile := DllCall("IsClipboardFormatAvailable", "UInt", 15)   ;是否是文件类型
    Candy_isHtml := DllCall("RegisterClipboardFormat", "str", "HTML Format")  ;是否Html类型
    CandySel=%Clipboard%
    CandySel_Rich:=ClipboardAll
    Clipboard := Candy_Saved_ClipBoard  ;还原粘贴板
    Candy_Saved_ClipBoard =
    IniRead,Candy_ProFile_Ini,%GeneralSettings_ini%,Candy_Hotkey,%A_Thishotkey%    ;本热键所调取的配置文件
    Transform,Candy_ProFile_Ini,Deref,%Candy_ProFile_Ini%                         ;ini文件路径可以使用自定义变量以及环境变量
    IfNotExist %Candy_ProFile_Ini%         ;如果配置文件不存在,则发出警告,且终止
    {
        MsgBox 对热键%A_thishotkey% 定义的配置文件不存在! `n--------`n请检查%Candy_ProFile_Ini%
        Return
    }
    SplitPath,Candy_ProFile_Ini,,Candy_Profile_Dir,,Candy_ProFile_Ini_NameNoext
 /*
╔══════════════════════════════════════╗
>>>                                  ║
╚══════════════════════════════════════╝
*/
    If(Fileexist(CandySel) && RegExMatch(CandySel,"^(\\|.:\)")) ;文件或者文件夹,不再支持相对路径的文件路径,但容许“文字模式的全路径”
    {
        Candy_isFile:=1     ;如果是“文字型”的有效路径,强制认定为文件
        SplitPath,CandySel,CandySel_FileNameWithExt,CandySel_ParentPath,CandySel_Ext,CandySel_FileNameNoExt,CandySel_Drive
        SplitPath,CandySel_ParentPath,CandySel_ParentName,,,, ;用这个提取“所在文件夹名”
        If InStr(FileExist(CandySel), "D")  ;区分是否文件夹,Attrib= D ,则是文件夹
        {
            CandySel_FileNameNoExt:=CandySel_FileNameWithExt
            CandySel_Ext:=RegExMatch(CandySel,"^.:\$") ? "Drive":"Folder"            ;细分:盘符或者文件夹
        }
        Else  If (CandySel_Ext="")       ;若不是文件夹,且无后缀,则定义为NoExt
        {
            CandySel_Ext:="NoExt"
        }
        if (CandySel_ParentName="")
            CandySel_ParentName:=RTrim(CandySel_Drive,":")
    }
    Else if(instr(CandySel,"`n") And  Candy_isFile=1)  ;如果包含多行,且粘贴板性质为文件,则是“多文件”
    {
        CandySel_Ext:="MultiFiles" ;多文件的后缀=MultiFiles
        CandySel_FirstFile:=RegExReplace(CandySel,"(.*)r.*","$1")  ;取第一行
        SplitPath ,CandySel_FirstFile,,CandySel_ParentPath,,  ;以第一行的父目录为“多文件的父目录”
        If RegExMatch(CandySel_ParentPath,":(|\)$")  ;如果父目录是磁盘根目录,用盘符做父目录名。
            CandySel_ParentName:= RTrim(CandySel_ParentPath,":")
        else  ;否则,提取父目录名
            CandySel_ParentName:= RegExReplace(CandySel_ParentPath, ".*\(.*)$", "$1")
    }
    Else     ;文本类型
    {
        ;-----------特殊文字串辨析-------------------
        IniRead Candy_User_defined_TextType,%Candy_ProFile_Ini%,user_defined_TextType  ;是否符合用户正则定义的文本类型,有优先顺序的,排在前面的优先
        loop,parse,Candy_User_defined_TextType,`n
        {
            If(RegExMatch(CandySel,RegExReplace(A_LoopField,"^.*?=")))     ;根据ini里面用户自定义段,逐条查看,右侧是正则规则
            {
                CandySel_Ext:=RegExReplace(A_LoopField,"=.*?$")   ;左边是“文本某类型”
                Candy_Cmd:=SkSub_Regex_IniRead(Candy_ProFile_Ini, "TextType", "i)(^||)" CandySel_Ext "($||)") ;获取该类型的”操作设定“
                If(Candy_Cmd!="Error")            ;如果有相应后缀组的定义,则跳出去运行。
                {
                    Goto Label_Candy_Read_Value
                    Break
                }
            }
        }

        IniRead,Candy_ShortText_Length,%Candy_ProFile_Ini%,Candy_Settings,ShortText_Length,80   ;没有定义,则根据所选文本的长短,设定为长文本或者短文本
        CandySel_Ext:=StrLen(CandySel) >>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_Read_Value:
    Candy_Type          :=Candy_isFile> 0 ? "FileType":"TextType"         ;根据Candy_isFile判断类型,在相应的INI段里面查找定义
    Candy_Type_Any   :=Candy_isFile> 0 ? "AnyFile":"AnyText"         ;根据Candy_isFile判断类型,对应的Any的名称
    Candy_Cmd:=SkSub_Regex_IniRead(Candy_ProFile_Ini, Candy_Type, "i)(^||)" CandySel_Ext "($||)")  ;查找后缀群定义
    If(Candy_Cmd="Error")            ;如果没有相应后缀组的定义;下面这些啰嗦的写法是为了各种容错
    {
        IfExist,%Candy_Profile_Dir%%CandySel_Ext%.ini   ;看是否有 后缀.ini 的配置文件存在
        {
            Candy_Cmd:="menu|" CandySel_Ext   ;同时,转化为Menu|命令行写法
        }
        Else
        {
            IniRead,Candy_Cmd, %Candy_ProFile_Ini%,%Candy_Type%,%Candy_Type_Any%   ;如果没有则看看 Any在ini的定义有没有
            If(Candy_Cmd="Error")   ;没有对AnyFile(或AnyText)的定义,则看是否有 AnyFile.ini或AnyText.ini配置存在
            {
                IfExist,%Candy_Profile_Dir%%Candy_Type%.ini   ;有,则以此为准
                {
                    Candy_Cmd:="menu|" Candy_Type   ;同时,转化为Menu|命令行写法
                }
                Else
                {
                    Run,%CandySel%, ,UseErrorLevel  ;层层把关都没有么,好失望的说,就直接运行吧
                    Return
                }
            }
        }
    }
    If !(RegExMatch(Candy_Cmd,"i)^Menu|"))
    {
        Goto Label_Candy_RunCommand            ;如果不是menu指令,直接运行应用程序
    }
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_DrawMenu:
    Menu,CandyTopLevelMenu,add
    Menu,CandyTopLevelMenu,DeleteAll
    CandyMenu_IconSize:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "MenuIconSize",16)
    CandyMenu_IconDir:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "MenuIconDir")  ;菜单图标位置

 ;加第一行菜单,缩略显示选中的内容,该菜单让你拷贝其内容
    CandyMenu_FirstItem:=Strlen(CdSel_NoSpace:=Trim(CandySel)) >20 ? SubStr(CdSel_NoSpace,1,10) . "..." . SubStr(CdSel_NoSpace,-10) : CdSel_NoSpace
    Menu CandyTopLevelMenu,Add,%CandyMenu_FirstItem%,Label_Candy_CopyFullpath
    Candy_Firstline_Icon:=SkSub_Get_Firstline_Icon(CandySel_Ext,CandySel,CandyMenu_IconDir "Extension")
    Menu CandyTopLevelMenu,icon,%CandyMenu_FirstItem%,%Candy_Firstline_Icon%,,%CandyMenu_IconSize%
    Menu CandyTopLevelMenu,Add

    arrCandyMenuFrom:=StrSplit( Candy_Cmd,"|")
    CandyMenu_ini:= arrCandyMenuFrom[2]="" ? Candy_ProFile_Ini_NameNoext : arrCandyMenuFrom[2]
    CandyMenu_sec:= arrCandyMenuFrom[3]="" ? "Menu" : arrCandyMenuFrom[3]

    szMenuIdx:={}
    szMenuContent:={}
    szMenuWhichFile:={}
    SkSub_GetMenuItem(Candy_Profile_Dir,CandyMenu_ini,CandyMenu_sec,"CandyTopLevelMenu","")
    SkSub_DeleteSubMenus("CandyTopLevelMenu")

    For,k,v in szMenuIdx
    {
        SkSub_CreateMenu(v,"CandyTopLevelMenu","Label_Candy_HandleMenu",CandyMenu_IconDir,CandyMenu_IconSize)
    }
    MouseGetPos,CandyMenu_X, CandyMenu_Y
    MouseMove,CandyMenu_X,CandyMenu_Y,0
    MouseMove,CandyMenu_X,CandyMenu_Y,0
;     ToolTip,% A_TickCount-CandyStartTick,200,0     ;若要评估出menu时间,这里需打开 ,共三处,2/3
    Menu,CandyTopLevelMenu,shOW
;     ToolTip ;若要评估出menu时间,这里需打开 ,共三处,3/3
    Return

;================菜单处理================================
Label_Candy_HandleMenu:
    If GetKeyState("Ctrl")			    ;[按住Ctrl则是进入配置]
    {
        Candy_ctrl_ini_fullpath:=Candy_Profile_Dir . "" . szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem] . ".ini"
        Candy_Ctrl_Regex:= "=s*Q" szMenuContent[ A_thisMenu "/" A_ThisMenuItem] "Es*$"
        SkSub_EditConfig(Candy_ctrl_ini_fullpath,Candy_Ctrl_Regex)
    }
    else
    {
        Candy_Cmd := szMenuContent[ A_thisMenu "/" A_ThisMenuItem]
        CandyError_From_Menu:=1
        Goto Label_Candy_RunCommand
    }
    return

Label_Candy_CopyFullpath:
    If GetKeyState("Ctrl")			    ;[按住Ctrl则是进入主配置]
    {
        Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
        SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
    }
    Else
        Clipboard:=CandySel
    Return
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_RunCommand:
    Candy_Cmd:=SkSub_EnvTrans(Candy_Cmd)  ;替换自变量以及系统变量,Ini里面用~%表示一个%,当然要用~~%,表示一个原义的~%
    Candy_Cmd=%Candy_Cmd%
    If (instr(Candy_Cmd,"{SetClipBoard:pure}")+instr(Candy_Cmd,"{SetClipBoard:rich}") )       ;这个开关指令会修改系统粘贴板,不会对命令行本身产生作用。所以先要从命令行替换掉。
    {
        Clipboard:=InStr(Candy_Cmd,"{SetClipBoard:pure}") ? CandySel : CandySel_Rich
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){SetClipBoard:.*}")
    }
    If (instr(Candy_Cmd,"{icon:")) ;icon图标
    {
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){icon:.*}")
    }
    If Candy_Cmd=   ;如果只想进行以上两步操作,如果运行的指令为空,则直接退出
        Return
    If instr(Candy_Cmd,"{date:")     ; 时间参数!定义方法为:{date:yyyy_MM_dd} 冒号:后面的部分可以随意定义
    {
        Candy_Time_Mode:=RegExReplace(Candy_Cmd,"i).*{date:(.*?)}.*","$1")
        FormatTime,Candy_Time_Formated,%A_nOW%,%Candy_Time_Mode%
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){date:(.*?)}",Candy_Time_Formated)
    }
    If instr(Candy_Cmd,"{in:")    ; in:多文件的后缀包含
    {
        Candy_in_M:="i`am)^.*.(" RegExReplace(Candy_Cmd,"i).*{in:(.*?)}.*","$1") ")$"
        Grep(CandySel, Candy_in_M, CandySel, 1, 0, "`n")
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){in:.*}")
        If  (CandySel="")
            Return
        Else
            StringReplace,CandySel,CandySel,`n,`r`n,all
    }
    If instr(Candy_Cmd,"{ex:")    ; ex:多文件的后缀排除
    {
        Candy_ex_M:="i`am)^.*.(" RegExReplace(Candy_Cmd,"i).*{ex:(.*?)}.*","$1") ")$R?"    ;可用,只是多了一个”后空白问题“
        CandySel:=RegExReplace(CandySel,Candy_ex_M)
        CandySel:=RegExReplace(CandySel,"s*$","")         ;清除后空白 CandySel:=trim(CandySel,"`r`n")         ;清除后空白
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){ex:.*}")
        Clipboard:=CandySel
        If  (CandySel="")
            Return
    }
    If instr(Candy_Cmd,"{input:")   ;特别的参数:带有prompt提示文字的input 例:{Input:请输入延迟时间,以ms为单位},支持多个input输入
    {    ;如果要输入密码,请写成{input:提示文字:hide}
        CdInput_P=1
        Candy_Cmd_tmp:=Candy_Cmd
        While	CdInput_P :=	RegExMatch(Candy_Cmd_tmp, "i){input:(.*?)}", CdInput_M, CdInput_P+strlen(CdInput_M))
        {
            CdInput_Prompt:= RegExReplace(CdInput_M,"i).*{input:(.*?)(:hide)?}.*","$1")
            CdInput_Hide:= RegExMatch(CdInput_M,"i){input:.*?:hide}") ? "hide":""
            Gui +LastFound +OWnDialogs +AlwaysOnTop
            InputBox, CdInput_txt,Candy InputBox,`n%CdInput_Prompt% ,%CdInput_Hide%, 285, 175,,,,,
            If ErrorLevel
                Return
            Else
                StringReplace,Candy_Cmd,Candy_Cmd,%CdInput_M%,%CdInput_txt%
        }
    }
    If instr(Candy_Cmd,"{box:Filebrowser}")
    {
        FileSelectFile, f_File ,,, 请选择文件
        If ErrorLevel
            return
        StringReplace,Candy_Cmd,Candy_Cmd,{box:Filebrowser},%f_File%,All
    }
    If instr(Candy_Cmd,"{box:mFilebrowser}")
    {
        FileSelectFile, f_File ,M, , 请选择文件
        If ErrorLevel
            return
        CdMfile_suffix  := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:.*LastFile(.*?)}.*","$1")
        CdMfile_prefix  := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:(.*?)FirstFile.*","$1")
        CdMfile_midfix := RegExReplace(Candy_Cmd,"i).*{box:mFilebrowser:.*FirstFile(.*?)LastFile.*}.*","$1")
        Firstline:=RegExReplace(f_File,"n.*")
        no_Firstline:=RegExReplace(f_File,"^.*?n","$1")
        StringReplace  ,CandySel_list,no_Firstline,`n,%CdMfile_midfix%%Firstline%/,all
        CandySel_list=%CdMfile_prefix%%Firstline%%CandySel_list%%CdMfile_suffix%
        Candy_Cmd:=RegExReplace(Candy_Cmd,"i){.*FirstFile.*LastFile.*}",CandySel_list)
    }
    If instr(Candy_Cmd,"{box:folderbrowser}")
    {
        FileSelectFolder, f_Folder , , , 请选择文件夹
        If f_Folder 
            StringReplace,Candy_Cmd,Candy_Cmd,{box:folderbrowser},%f_Folder%,All
        Else
            Return
    }
    Candy_Cmd:=RegExReplace(Candy_Cmd,"(?>>>                                                  ║
╚══════════════════════════════════════╝
*/
    Candy_All_Cmd:="web|keys|cando|cango|run|openwith|SetClipBoard|msgbox|config|openwith|ow|rund|runp"
    If Not RegExMatch(Candy_Cmd,"i)^s*(" Candy_All_Cmd ")s*|")
        Candy_Cmd=OpenWith|%Candy_Cmd% ;如果没有,则人为补一个OpenWith
    Candy_Cmd:=RegExReplace(Candy_Cmd,"~|",Chr(3))
    arrCandy_Cmd_Str:=StrSplit(Candy_Cmd,"|"," `t")
    Candy_Cmd_Str1:=arrCandy_Cmd_Str[1]
    Candy_Cmd_Str2:=RegExReplace(arrCandy_Cmd_Str[2],Chr(3),"|")
    Candy_Cmd_Str3:=RegExReplace(arrCandy_Cmd_Str[3],Chr(3),"|")
    If (Candy_Cmd_Str1="web")
    {
        SkSub_WebSearch(Candy_CurWin_Fullpath,RegExReplace(Candy_Cmd,"i)^web|(s+|)|s+"))
    }
    Else If (Candy_Cmd_Str1="Keys")  ;如果是以keys|开头,则是发热键
    {
       Send %Candy_Cmd_Str2%
    }
    Else If (Candy_Cmd_Str1="MsgBox")  ;如果是以MsgBox|开头,则是发一个提示框
    {
        Gui +LastFound +OWnDialogs +AlwaysOnTop
        MsgBox %Candy_Cmd_Str2%
    }
    Else If (Candy_Cmd_Str1="Config")
    {
        for k,v in szMenuWhichfile
            Config_files .= v "`n"
        Sort, Config_files, U
        Loop ,parse, Config_files,`n
            SkSub_EditConfig(Candy_Profile_Dir . "" A_LoopField ".ini","")
        Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
            SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
    }
    Else If (Candy_Cmd_Str1="SetClipBoard")   ;之前的开关,只能把选中的内容放进粘贴板,而这个指令,则可以把后面跟随的内容放进粘贴板。(更丰富)
    {
        Clipboard := Candy_Cmd_Str2
    }
    Else If (Candy_Cmd_Str1="Cando")  ;如果是以Cando|开头,则是运行一些内部程序,方便与你的其它脚本进行挂接
    {
        CandySelected:=CandySel    ;兼容以前的cando变量写法
        If IsLabel("Cando_" . Candy_Cmd_Str2)                       ;程序内置的别名
            Goto % "Cando_" . Candy_Cmd_Str2
        Else
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="Cango")   ;如果是以Cango|开头,则是运行一些外部ahk程序,方便与你的其它脚本进行挂接
    {
        IfExist,%Candy_Cmd_Str2%
            Run %ahk% "%Candy_Cmd_Str2% %Candy_Cmd_Str3%" ;外部的ahk代码段,你的ahk可以带参数
        Else
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="OpenWith" or Candy_Cmd_Str1="OW")     ;OpenWith|指定用某程序打开选定的内容,这时候,应用程序后面不能带任何命令行,(严格的说是目标参数是且仅是“被选内容“,只是被省略了)
    {
        Run ,%Candy_Cmd_Str2% "%CandySel%",%Candy_Cmd_Str3%,%Candy_Cmd_Str4% UseErrorLevel             ;1:程序  2:工作目录 3:状态
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="Run")     ;其后面要带命令行,即使操作对象是被选中的文件,也不能省略
    {
        Run,%Candy_Cmd_Str2% ,%Candy_Cmd_Str3%,%Candy_Cmd_Str4% UseErrorLevel             ;1:程序  2:工作目录 3:状态
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
    }
    Else If (Candy_Cmd_Str1="RunD")     ;格式为RunD|应用程序|应用程序的标题|x|y|等待时间
    {       ;没发现这个x,y起作用的情况,暂时放着
        Run,%Candy_Cmd_Str2%,, UseErrorLevel
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
        else
        {
            Sleep,% (Candy_Cmd_Str4="") ? 1000 : arrCandy_Cmd_Str[6]
            WinWaitActive, %Candy_Cmd_Str3% ,,5
            WinActivate, %Candy_Cmd_Str3%
            Candy_RunD_x:=arrCandy_Cmd_Str[4] ? arrCandy_Cmd_Str[4] : 100
            Candy_RunD_y:=arrCandy_Cmd_Str[5] ? arrCandy_Cmd_Str[5] : 100
            PostMessage, 0x233, HDrop( CandySel,Candy_RunD_x,Candy_RunD_y), 0,, %Candy_Cmd_Str3%
        }
    }
    Else If (Candy_Cmd_Str1="RunP")     ;格式为RunP|应用程序|应用程序的标题|等待时间;;
    {
        Clipboard := CandySel_Rich
        Run,%Candy_Cmd_Str2%,, UseErrorLevel
        If (ErrorLevel = "Error")               ;如果运行出错的话
            Goto Label_Candy_ErrorHandle
        else
        {
            Sleep,% (Candy_Cmd_Str4="") ? 1000 : Candy_Cmd_Str4
            WinWaitActive, %Candy_Cmd_Str3% ,,5
            WinActivate, %Candy_Cmd_Str3%
            Send ^v
        }
    }
    Return
 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
Label_Candy_ErrorHandle: ;出错啦!
	If (SkSub_IniRead(Candy_ProFile_Ini,"Candy_Settings","ShowError", 0)=1 )     ;看看出错提示开关打开了没有,打开了的话,就显示出错信息
	{
		Gui +LastFound +OwnDialogs +AlwaysOnTop
        MsgBox, 4116,, 下述命令行定义出错: `n---------------------`n%Candy_Cmd%`n---------------------`n后缀名: %CandySel_Ext%`n`n立即配置相应ini?
		IfMsgBox Yes
		{
            if (CandyError_From_Menu=1)
            {
                Candy_This_ini:=szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem]
                Candy_ctrl_ini_fullpath:=Candy_Profile_Dir . "" . szMenuWhichFile[ A_thisMenu "/" A_ThisMenuItem] . ".ini"
                Candy_Ctrl_Regex:= "=s*Q" szMenuContent[ A_thisMenu "/" A_ThisMenuItem] "Es*$"
                SkSub_EditConfig(Candy_ctrl_ini_fullpath,Candy_Ctrl_Regex)
            }
            else
            {
                Candy_Ctrl_Regex:="i)(^s*||)" CandySel_Ext "(||s*)[^=]*="
                SkSub_EditConfig(Candy_Profile_ini,Candy_Ctrl_Regex)
            }
		}
	}
	Return

 /*
╔══════════════════════════════════════╗
>>>                                  ║
╚══════════════════════════════════════╝
*/
SkSub_GetMenuItem(IniDir,IniNameNoExt,Sec,TopRootMenuName,Parent="")   ;从一个ini的某个段获取条目,用于生成菜单。
{
    Items:=SkSub_IniRead_Section(IniDir "" IniNameNoExt ".ini",sec)         ;本次菜单的发起地
    StringReplace,Items,Items,△,`t,all
    Loop,parse,Items,`n
    {
        Left:=RegExReplace(A_LoopField,"(?]*")
        Right:=RegExReplace(A_LoopField,"^.*?=s*(.*)s*$","$1")
        If (RegExMatch(left,"^/|//|/$|^$")) ;如果最右端是/,或者最左端是/,或者存在//,则是一个错误的定义,抛弃
            Continue
        If RegExMatch(Left,"i)(^|/)+$")   ;如果左边的最末端是仅仅一个"独立的" + 号
        {
            m_Parent := InStr(Left,"/") > 0 ? RegExReplace(Left,"/[^/]*$") "/" : ""  ;如果+号前面有存在上级菜单,则有上级菜单,否则没有
            Right:=RegExReplace(Right,"~|",Chr(3))
            arrRight:=StrSplit(Right,"|"," `t")
            rr1:=arrRight[1]
            rr2:=RegExReplace(arrRight[2],Chr(3),"|")
            rr3:=RegExReplace(arrRight[3],Chr(3),"|")
            rr4:=RegExReplace(arrRight[4],Chr(3),"|")
            If (rr1="Menu")   ;如果后面是“插入(子)菜单”的命令 ,则极有可能菜单里面还有“嵌套的下级菜单”。。
            {
                m_ini:= (rr2="") ? IniNameNoExt :  rr2
                m_sec:= (rr3="") ? "Menu" : rr3
				m_Parent:=Parent "" m_Parent
                this:=SkSub_GetMenuItem(IniDir,m_ini,m_sec,TopRootMenuName,m_Parent)      ;嵌套,循环使用此函数,以便处理“其他文件里的,插入的菜单”
            }
;             用+的方法,可以让你快速扩展自己定义的子菜单,否则直接可以写在左侧了。
        }
        Else
        {
            szMenuIdx.insert( Parent ""  Left )
            szMenuContent[ TopRootMenuName "/" Parent "" Left] := Right
            szMenuWhichFile[ TopRootMenuName "/" Parent "" Left] :=IniNameNoExt
        }
    }
}
SkSub_DeleteSubMenus(TopRootMenuName)
{
    For i,v in szMenuIdx
    {
        If instr(v,"/")>0
        {
            Item:=RegExReplace(v, "(.*)/.*", "$1")
            Menu,%TopRootMenuName%/%Item%,add
            Menu,%TopRootMenuName%/%Item%,DeleteAll
        }
    }
}
SkSub_CreateMenu(Item,ParentMenuName,label,IconDir,IconSize)    ;条目,它所处的父菜单名,菜单处理的目标标签
{  ;送进来的Item已经经过了“去空格处理”,放心使用
    arrS:=StrSplit(Item,"/"," `t")
    _s:=arrS[1]
    if arrS.Maxindex()= 1      ;如果里面没有 /,就是最终的”菜单项“。添加到”它的父菜单”上。
    {
        If InStr(_s,"-") = 1       ;-分割线
        Menu, %ParentMenuName%, Add
        Else If InStr(_s,"*") = 1       ;* 灰菜单
        {
            _s:=Ltrim(_s,"*")
            Menu, %ParentMenuName%, Add,       %_s%,%Label%
            Menu, %ParentMenuName%, Disable,  %_s%
        }
        Else
        {
            y:=szMenuContent[ ParentMenuName "/" Item]
            z:=SkSub_Get_MenuItem_Icon( y ,IconDir)
            Menu, %ParentMenuName%, Add,  %_s%,%Label%
            Menu, %ParentMenuName%, icon,  %_s%,%z%,,%IconSize%
        }
    }
    Else     ;如果有/,说明还不是最终的菜单项,还得一层一层分拨出来。
    {
        _Sub_ParentName=%ParentMenuName%/%_s%
        StringTrimLeft,_subItem,Item,strlen(_s)+1
        SkSub_CreateMenu(_subItem,_Sub_ParentName,label,IconDir,IconSize)
        Menu,%ParentMenuName%,add,%_s%,:%_Sub_ParentName%
    }
}
SkSub_EnvTrans(v)
{
    v:=RegExReplace(v,"~%",Chr(3))
    Transform,v,Deref,%v% ;解决Sala的ini中支持%A_desktop%或%windir%等ahk变量或系统环境变量的解释问题,@sunwind @小古
    v:=RegExReplace(v,Chr(3),"%")
    Return v
}
SkSub_Get_Firstline_Icon(ext,fullpath,iconpath)
{
	IfExist,%iconpath%%ext%.ico             ;如果固定的文件夹里面存在该类型的图标
		x := iconpath "" ext ".ico"
	Else If ext in  bmp,gif,png,jpg,ico,icl,exe,dll
		x := fullpath
	Else
		x:=AssocQueryApp(Ext)
	Return %x%
}
SkSub_Get_MenuItem_Icon(item,iconpath)   ; item=需要获取图标的条目,iconpath=你定义的图标库文件夹
{
	cmd:=RegExReplace(item,"^s+|(|s+)|[^!]*[^>]*")
    If instr(item,"{icon:")     ; 有图标硬定义
    {
        Path_Icon:=RegExReplace(item,"i).*{icon:(.*?)}.*","$1")
        If(Fileexist(Path_Icon))         ;若有全路径的图标存在
			return Path_Icon
		If(Fileexist(iconpath "MyIcon" Path_Icon))       ;若在MyIcon文件夹里面
			return iconpath "MyIcon" Path_Icon
    }
	Else if FileExist(iconpath "Command" cmd ".ico")      ;若存在 "命令名.ico" 文件
	{
		Return  iconpath "Command" cmd ".ico"
	}
	item:=SkSub_envtrans(item)
	if RegExMatch(item,"i)^(ow|openwith|rot|run|roa|runp|rund)|") ;运行命令类
	{
		cmd_removed:=RegExReplace(item,"^.*?|")      ;里面纯粹的 应用程序 路径
		x:=RegExReplace(cmd_removed,"i)exe[^!]*[^>]*", "exe")
		Return %x%
	}
	Else if instr(item,".exe") ;省略了指令的openwith|
	{
		x:=RegExReplace(item,"i).exe[^!]*[^>]*", ".exe")
		Return %x%
	}
	Else
	{
		t:=RegExReplace(item,"s*|.*?$")       ;去除运行参数,只保留第一个|最前面的部分
		x:=AssocQueryApp(t)
		Return %x%
	}
}
AssocQueryApp(sExt)
{    ;http://www.autohotkey.com/board/topic/54927-regread-associated-program-for-a-file-extension/
    sExt =.%sExt%  ;ASSOCSTR_EXECUTABLE
    DllCall("shlwapi.dllAssocQueryString", "uint", 0, "uint", 2, "uint", &sExt, "uint", 0, "uint", 0, "uint*", iLength)
    VarSetCapacity(sApp, 2*iLength, 0)
    DllCall("shlwapi.dllAssocQueryString", "uint", 0, "uint", 2, "uint", &sExt, "uint", 0, "str", sApp, "uint*", iLength)
    Return sApp
}
SkSub_Regex_IniRead(ini,sec,reg)      ;正则方式的读取,等号左侧符合正则条件
{  ;在ini的某个段内,查找符合某正则规则的字符串,并返回value值
	IniRead,keylist,%ini%,%sec%,
	Loop,Parse,keylist,`n
	{
		t:=RegExReplace(A_LoopField,"=.*?$")
		If(RegExMatch(t, reg))
		{
			Return % RegExReplace(A_LoopField,"^.*?=")
			Break
		}
	}
	Return "Error"
}
SkSub_IniRead(ini, sec, key="", default = "")   ;iniread的函数化
{
	IniRead, v, %ini%, %sec%, %key%, %default%
	Return, v
}
SkSub_IniRead_Section(ini,sec)
{  ;返回全部某段的内容,函数化而已
	IniRead,keylist,%ini%,%sec%              ;提取[sec]段里面所有的群组
		Return %keylist%
}
grep(h, n, ByRef v, s = 1, e = 0, d = "")   ; ;by polythene
{
	v =
	StringReplace, h, h, %d%, , All
	Loop
		If s := RegExMatch(h, n, c, s)
			p .= d . s, s += StrLen(c), v .= d . (e ? c%e% : c)
		Else Return, SubStr(p, 2), v := SubStr(v, 2)
}
SkSub_UrlEncode(str, enc="UTF-8")       ;From Ahk Forum
{
    enc:=trim(enc)
    If enc=
        Return str
   hex := "00", func := "msvcrt" . (A_IsUnicode ? "swprintf" : "sprintf")
   VarSetCapacity(buff, size:=StrPut(str, enc)), StrPut(str, &buff, enc)
   While (code := NumGet(buff, A_Index - 1, "UChar")) && DllCall(func, "Str", hex, "Str", "%%%02X", "UChar", code, "Cdecl")
   encoded .= hex
   Return encoded
}
SkSub_WebSearch(Win_Full_Path,Http)
{
	all_browser:=SkSub_IniRead(GeneralSettings_ini, "General_Settings", "InUse_Browser")
	DefaultBrowser:=SkSub_EnvTrans(SkSub_IniRead(GeneralSettings_ini, "General_Settings", "Default_Browser"))
	;第①步,看当前当前激活窗口 是否 浏览器
	If Win_Full_Path Contains %All_Browser%
	{
		Browser:=Win_Full_Path
	}
	;第②步,看进程里面有没有浏览器,若有,看能被提取出来(防止虚拟桌面的隔离,妖自己的需求)
	Else Loop,Parse,All_Browser,`,   ;看所有定义的浏览器,
	{
		Useful_FullPath:=SkSub_process_exist_and_useful(A_LoopField)
		If (  Useful_FullPath!= 0  and Useful_FullPath!= 1 )
		{
			Browser:=Useful_FullPath
			Break
		}
	}
	; 第③步	,都没有么,看ini默认浏览器是否符合条件
	If ( Browser="")  ;看ini默认浏览器,a。看进程中是否有,并且能被提取出来(防止虚拟桌面的隔离,妖自己的需求)。b。或者进程里面没有。
	{
		DefaultBrowser_去除参数:= RegExReplace(DefaultBrowser, "exe[^!]*[^>]*", "exe")
		SplitPath ,DefaultBrowser_去除参数,DefaultBrowser_name
		Useful_FullPath:=SkSub_process_exist_and_useful(DefaultBrowser_name)
		If (  Useful_FullPath!= 0  And FileExist(DefaultBrowser_去除参数))
		{
			Browser:=DefaultBrowser
		}
	}
	; 第④部,最终运行
	If Browser ;如果取到了浏览器
	{
		SplitPath,browser,,,,browser_namenoext
        Browser_Args:=SkSub_IniRead(GeneralSettings_ini, "WebBrowser's_CommandLIne", browser_namenoext)
		If (Browser_Args!="Error")  ;有些浏览器,必须带参数,比如config或者单进程限制等待,所以在ini里面提供了一个定义的地方。
		{
			Browser := Browser " " Browser_Args
		}
		Run,% Browser . " """ . Http . """"
		IfInString Browser,firefox.exe
			WinActivate,Mozilla Firefox Ahk_Class MozillaWindowClass
		Else
			WinActivate Ahk_PID %ErrorLevel%
	}
	Else ;没有浏览器么
	{  ;看注册表 是否有默认的浏览器
		RegRead, RegDefaultBrowser, HKEY_CLASSES_ROOT, httpshellopencommand
		StringReplace, RegDefaultBrowser, RegDefaultBrowser,"
		SplitPath, RegDefaultBrowser,,RDB_Dir,,RDB_NameNoExt,
		Run,% RDB_Dir . "" . RDB_NameNoExt . ".exe" . " """ . Http . """",,UseErrorLevel
		If errorlevel
		{
			Run,% "iexplore.exe " . site . """"	  ;internet explorer
		}
	}
}
;============================================================================================================
SkSub_process_exist_and_useful(Process_name)        ;判断某个进程是否存在且能有效运行,如果不用desktops,这段代码可以清除掉。
{
	Process,exist,%Process_name%
	WinGet, Process_Fullpath,ProcessPath,Ahk_PID %ErrorLevel%
	If (ErrorLevel!=0 And  Process_Fullpath!="")
		Return %Process_Fullpath%
	Else if ErrorLevel=0
		Return 1
	Else
		Return 0
}
HDrop(fnames,x=0,y=0)    ;http://www.autohotkey.com/board/topic/41467-make-ahk-drop-files-into-other-applications/page-2
{
	characterSize := A_IsUnicode ? 2 : 1
	fns:=RegExReplace(fnames,"n$")
	fns:=RegExReplace(fns,"^n")
	hDrop:=DllCall("GlobalAlloc","UInt",0x42,"UInt",20+(StrLen(fns)*characterSize)+characterSize*2)
	p:=DllCall("GlobalLock","UInt",hDrop)
	NumPut(20, p+0)  ;offset
	NumPut(x,  p+4)  ;pt.x
	NumPut(y,  p+8)  ;pt.y
	NumPut(0,  p+12) ;fNC
	NumPut(A_IsUnicode ? 1 : 0,  p+16) ;fWide
	p2:=p+20
	Loop,Parse,fns,`n,`r
	{
		DllCall("RtlMoveMemory","UInt",p2,"Str",A_LoopField,"UInt",StrLen(A_LoopField)*characterSize)
		p2+=StrLen(A_LoopField)*characterSize + characterSize
	}
	DllCall("GlobalUnlock","UInt",hDrop)
	Return hDrop
}
SkSub_EditConfig(inifile,regex="") ;编辑配置文件!
{
	if not fileExist(inifile)      ;动态菜单未必有ini文件存在
		return
	if (regex"")  ;如果送了正则表达式进来
	{
		Loop
		{
			FileReadLine, L, %inifile%, %A_Index%
			if ErrorLevel
				break
			if regexmatch(L,regex)
			{
				LineNo:=a_index
				break
			}
		}
	}
	TextEditor:=SkSub_EnvTrans(SkSub_IniRead(GeneralSettings_ini, "General_Settings", "Default_TextEditor"))  ;默认文本编辑器
	TextEditor:=FileExist(TextEditor) ? TextEditor:"notepad.exe"       ;文本编辑器
	SplitPath,TextEditor,,,,namenoext
	LineJumpArgs:=SkSub_IniRead(GeneralSettings_ini, "TextEditor's_CommandLine", namenoext)
	if  (LineJumpArgs="Error" or LineNo="" )
		cmd :=TextEditor " " inifile
	else
	{
		cmd :=TextEditor " " LineJumpArgs
		StringReplace,cmd,cmd,$(FILEPATH),%inifile%
		StringReplace,cmd,cmd,$(LINENUM),%LineNo%
	}
	Run,%cmd%,,UseErrorLevel,TextEditor_PID
	WinActivate ahk_pid %TextEditor_PID%
	return
}

SkSub_Clear_CandyVar()
{
	Global
    CandySel:=
    CandySel_LinkTarget:=
    CandySel_Ext:=
    CandySel_FileNamenoExt:=
    CandySel_ParentPath:=
    CandySel_ParentName:=
    CandySel_Drive:=
	Config_files:=
	CandyError_From_Menu:=0
}

 /*
╔══════════════════════════════════════╗
>>>                                                  ║
╚══════════════════════════════════════╝
*/
SkSub_CreatTrayMenu()
{

  Menu, Tray, Icon,candy.ico
  Menu, Tray, NoStandard
  Menu, tray, add, 关于与提示,TrayHandle_About
  Menu, tray, add ; 分隔符
  Menu, tray, add, 编辑全局配置,TrayHandle_GeneralSettings
  Menu, tray, add, 重启脚本,TrayHandle_ReLoad
  Menu, tray, add, 退出,TrayHandle_Exit
}
/*
╔══════════════════════════════════════╗
>>>                         ║
╚══════════════════════════════════════╝
*/
TrayHandle_ReLoad:
  Reload
Return
TrayHandle_Exit:
  ExitApp
Return

TrayHandle_GeneralSettings:
    SkSub_EditConfig(GeneralSettings_ini,"")
    return

TrayHandle_About:
  MsgBox, , About Candy,
  ( LTrim
    版本 Candy2.0.0.6

    作者:万年书妖
    邮箱:aamii@qq.com
    QQ:710117768

    如果你是首次试用,请学习如何手动修改配置
    交流请进QQ群: 3222783

    随代码带有四套配置,请选中文件或文本后分别用^f1~f4进行体验
  )
  Return

给TA捐赠
共{{data.count}}人
人已捐赠
其他

Context

2020-1-20 17:03:00

其他

Candy精简调用版(便于其他AHK脚本调配)

2020-1-21 12:39:02

个人中心
购物车
优惠劵
有新私信 私信列表
搜索