发表回复 
Notify() 改造中
2014-09-21, 19 : 44
Notify() 改造中
Notify() 是我最常用的库之一,可作为老脚本,又追求兼容各种版本,所以代码又臭又长。
现在正在尝试用各种新特性改造它,有兴趣可以参与。

定时器方面,直接借助了L大的脚本 SetTimerEx()


代码: (全选)
f2::

Notify("BBB","AAA",4,{GC:"0x062A48", TC:"White", MC:"White", IW:29, IH:-1, Image: A_ScriptDir "\Attached\Icon\Timing.ico"})
Notify("BBB","AAA",4,{GC:"0x062A48", TC:"White", MC:"White", IW:59, IH:-1, Image: A_ScriptDir "\Attached\Icon\Quicktime-01.ico"})
Return


Notify(Title="Notify()",Message="",Duration="",Options="")
{
static Notify:=[],GNList:=[], ACList, ATList, AXList, Exit, _Wallpaper_, _Title_, _Message_, _Progress_, _Image_, Saved,Flash:=[],Destroy:=[]
static GF := 50             ; 桂第一号
static GL := 74             ; 桂最后一个号码(其定义范围,并允许计数)

static Default:={GC : "FFFFAA",GR : 9,GT : "Off",BC : "000000",BK : "Silver",BW : 2,BR : 13,BT : 105,BF : 350,TS : 10,TW : 625,TC : "Default",TF : "Hiragino Sans GB W3",MS : 10,MW : "Default"
,MC : "Default",MF : "Default",SI : 0,SC : 0,ST : 0,IW : 32,IH : 32,IN : 0,XF : "Arial Black",XC : "Default",XS : 12,XW : 800,PC : "Default",PB : "Default"}
Critical
if IsObject(Title)
{

if Title.Destroy
{
Destroy.Remove(Title.Destroy,"").stop

GK := Title.Destroy  + GF - 1
Gui, % GK + GL - GF + 1 ":Destroy"
If ST
{
  Gui, %GK%:+LastFound
  DllCall("AnimateWindow","UInt",WinExist(),"Int",ST,"UInt", "0x00050001")
}
Gui, %GK%:Destroy
GNList.Remove(GK,"")
If (Exit = GK)
  ExitApp
Return 1

}
else if Title.Flash
{
Title.Flash += GF - 1
FlashGN2 := Title.Flash + GL - GF + 1
If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, %BK%
Else
  Gui, %FlashGN2%:Color, %BC%
Return
}

}

f:=Default.Clone()
for i,n in Options
f[i]:=n

;——— 如果选择结束 ——————————————————————————————————————




  wPW := ((PW<>"") ? ("w" PW) : (""))        ; 需要改进的,明确的规模和进度宽度的处理不当
  hPH := ((PH<>"") ? ("h" PH) : (""))

  If GW <>
  {
   wGW = w%GW%
   wPW := "w" GW - 20
  }
  hGH := ((GH<>"") ? ("h" GH) : (""))
  wGW_ := ((GW<>"") ? ("w" GW - 20) : (""))
  hGH_ := ((GH<>"") ? ("h" GH - 20) : (""))
;————————————————————————————————————
If Duration =                ; 如果持续时间不使用,或设置为默认 ""
  Duration = 30
GN := GF                ; 发现使用下一个可用的GUI数,从开始的GF(默认为50)
Loop                ; within the defined range GF to GL

if !GNList[GN]
   Break
  Else
   If (++GN > GL)                ;=== too many notifications open, returns 0, handle this error in the calling script
    Return 0                          ; 这是不常见的屏幕是由这点太混乱反正

GNList[GN]:=1
GN2 := GN + GL - GF + 1

If AC <>                ; saves the action to be used when clicked or timeout (or x-button is clicked)
  ACList .= "|" GN "=" AC            ; need to add different clicks for Title, Message, Image as well
If AT <>                ; saved internally in a list, then parsed by the timer or click routine
  ATList .= "|" GN "=" AT            ; to run the script-side subroutine/label "AC=LabelName"
If AX <>
  AXList .= "|" GN "=" AX


P_DHW := A_DetectHiddenWindows            ; start finding location based on what other Notify() windows are on the screen
P_TMM := A_TitleMatchMode            ; saved to restore these settings after changing them, so the calling script won't know
DetectHiddenWindows On            ; as they are needed to find all as they are being made as well... or hidden for some reason...
SetTitleMatchMode 1            ; and specific window title match is a little more failsafe
If (WinExist("_Notify()_GUI_"))              ;=== find all Notifications from ALL scripts, for placement
  WinGetPos, OtherX, OtherY                   ;=== change this to a loop for all open notifications and find the highest?
DetectHiddenWindows %P_DHW%            ;=== using the last Notify() made at this point, which may be better
SetTitleMatchMode %P_TMM%            ; and the global settings are restored for the calling thread

Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border        ; here begins the creation of the window
Gui, %GN%:Color, % f.GC            ; with the logic to add or not add certain controls, Wallpaper, Image, Title, Progress, Message
If FileExist(WP)                ; and some placement logic depending if they are used or not... could definitely be improved
{
  Gui, %GN%:Add, Picture, x0 y0 w0 h0 v_Wallpaper_, % WP    ; wallpaper added first, stretched to size later
  ImageOptions = x+8 y+4
}

If (f.Image <>    "")            ; icon image added next, sized, and spacing added for whats next
{
  If FileExist(f.Image)
   Gui, %GN%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.IN " v_Image_ " ImageOptions, % f.Image
  Else
  Gui, %GN%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.Image " v_Image_ " ImageOptions, % A_WinDir "\system32\shell32.dll"

  ImageOptions = x+10
}

If (Title <>    "")            ; icon image added next, sized, and spacing added for whats next
{
  Gui, %GN%:Font, % "w" f.IW " s" f.TS " c" f.TC, % f.TF
  Gui, %GN%:Add, Text, %ImageOptions% BackgroundTrans v_Title_, % Title
}


If f.PG                ; 那么进度条,如果要求
  Gui, %GN%:Add, Progress, % "Range0-" PG " " wPW " " hPH " c" f.PC " Background" f.PB " v_Progress_"
Else
  If ((Title) && (Message))            ; some spacing tweaks if both used
   Gui, %GN%:Margin, , -5

If Message <>                ; and finally the message text control if used
{
  Gui, %GN%:Font, % "w" f.MW " s" f.MS " c" f.MC, % f.MF
  Gui, %GN%:Add, Text, BackgroundTrans v_Message_, % Message
}

If ((Title) && (Message))            ; final spacing
  Gui, %GN%:Margin, , 8            
Gui, %GN%:Show, Hide %wGW% %hGH%, _Notify()_GUI_        ; final sizing
Gui  %GN%:+LastFound            ; would like to get rid of this to prevent calling script being affected
WinGetPos, GX, GY, GW, GH            ; final positioning
GuiControl, %GN%:, _Wallpaper_, % "*w" GW " *h" GH " " WP    ; stretch that wallpaper to size
GuiControl, %GN%:MoveDraw, _Title_,    % "w" GW-20 " h" GH-10    ; poor handling of text wrapping when gui has explicit size called
GuiControl, %GN%:MoveDraw, _Message_,  % "w" GW-20 " h" GH-10    ; needs improvement (and if image is used or not)
If AX <>                ; add the corner "X" for closing with a different action than otherwise clicked
{
  GW += 10
  Gui, %GN%:Font, % "w" f.XW " s" f.XS " c" f.XC, Arial Black          ; —(multiply) is the character used for the X-Button
  Gui, %GN%:Add, Text, % "x" GW-15 " y-2 Center w12 h20 g_Notify_Kill_" GN - GF + 1, % chr(0x00D7) ;鬃
}
Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% BackgroundTrans g_Notify_Action_Clicked_     ; to catch clicks anywhere on the gui
If (f.GR)                    ; 可能要在单独的标题/消息/等行动拆除
  WinSet, Region, % "0-0 w" GW " h" GH " R" f.GR "-" f.GR
If (f.GT)                    ; 非功能性的GT选项,因为边境GUI碍事
  WinSet, Transparent, % f.GT                ; will be addressed someday, leaving it in

SysGet, Workspace, MonitorWorkArea                ; positioning
NewX := WorkSpaceRight-GW-5
If (OtherY)
  NewY := OtherY-GH-2-f.BW*2
Else
  NewY := WorkspaceBottom-GH-5
If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20        ; border gui
Gui, %GN2%:Color, % f.BC
Gui  %GN2%:+LastFound

If (f.BR)
  WinSet, Region, % "0-0 w" GW+(f.BW*2) " h" GH+(f.BW*2) " R" f.BR "-" f.BR
If (f.BT)
  WinSet, Transparent, % f.BT

Gui, %GN2%:Show, % "Hide x" NewX-f.BW " y" NewY-f.BW " w" GW+(f.BW*2) " h" GH+(f.BW*2), _Notify()_BGGUI_     ; actual creation of border gui! but still not shown
Gui, %GN%:Show,  % "Hide x" NewX " y" NewY " w" GW, _Notify()_GUI_            ; actual creation of Notify() gui! but still not shown
Gui  %GN%:+LastFound                    ; need to get rid of this so calling script isn't affected


If f.SI
  DllCall("AnimateWindow","UInt",WinExist(),"Int",f.SI,"UInt","0x00040008")        ; 动画中,如果使用Si
Else
  Gui, %GN%:Show, NA, _Notify()_GUI_                ; 否则,只显示

Gui, %GN2%:Show, NA, _Notify()_BGGUI_                ; and the border shown
WinSet, AlwaysOnTop, On                    ; and set to Always on Top

If ((Duration < 0) OR (Duration = "-0"))                ; 保存在内部的ExitApp命令应该发生在这
  Exit := GN                        ; 通知dissappears
If (Duration)    
Destroy[GN - GF + 1]:=SetTimerEx(- Abs(Duration) * 1000, "Notify", {Destroy:GN - GF + 1})
            ; timer set depending on Duration parameter
Else
Flash[GN - GF + 1]:=SetTimerEx(- Abs(Duration) * 1000, "Notify", {Flash:GN - GF + 1})
                ; timer set to flash border if the Notify has 0 (infinite) duration
Notify[GN - GF + 1]:=f
Return %GN%                    ; end of Notify(), returns Gui ID number used

;==========================================================================
;========================================== when a notification is clicked:

_Notify_Action_Clicked_:                ; option AC=Label means Label: subroutine will be called here when clicked
; Critical
ls:=A_Gui - GF + 1

Destroy.Remove(ls,"").stop


Gui, % A_Gui + GL - GF + 1 ":Destroy"
If SC
{
  Gui, %A_Gui%:+LastFound
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
}
Gui, %A_Gui%:Destroy
If (ACList)
  Loop,Parse,ACList,|
   If ((Action := SubStr(A_LoopField,1,2)) = A_Gui)
   {
    Temp_Notify_Action:= SubStr(A_LoopField,4)
    StringReplace, ACList, ACList, % "|" A_Gui "=" Temp_Notify_Action, , All
    If IsLabel(_Notify_Action := Temp_Notify_Action)
     Gosub, %_Notify_Action%
    _Notify_Action =
    Break
   }
GNList.Remove(A_Gui,"")
Flash.Remove(ls,"").stop



If (Exit = A_Gui)
  ExitApp
Return
}

原版:
代码: (全选)
;———————————————————————————
;————      Notify() 0.4991 by gwarble       ————
;———                                           ———
;——     easy multiple tray area notifications     ——
;—    http://www.autohotkey.net/~gwarble/Notify/    —
;———————————————————————————
;
; Notify([Title,Message,Duration,Options])
;
; Duration  seconds to show notification [Default: 30]
;             0  for permanent/remain until clicked (flashing)
;            -3  negative value to ExitApp on click/timeout
;           "-0" for permanent and ExitApp when clicked (needs "")
;
; Options   string of options, single-space seperated, ie:
;           "TS=16 TM=8 TF=Times New Roman GC_=Blue SI_=1000"
;           most options are remembered (static), some not (local)
;           Option_= can be used for non-static call, ie:
;           "GC=Blue" makes all future blue, "GC_=Blue" only takes effect once
;           "Wait=ID"   to wait for a notification
;           "Update=ID" to change Title, Message, and Progress Bar (with 'Duration')
;
; Return   ID (Gui Number used)
;          0 if failed (too many open most likely)
;          VarValue if Options includes: Return=VarName
;———————————————————————————

Notify(Title="Notify()",Message="",Duration="",Options="")
{
static GNList, ACList, ATList, AXList, Exit, _Wallpaper_, _Title_, _Message_, _Progress_, _Image_, Saved
static GF := 50             ; 桂第一号
static GL := 74             ; Gui Last  Number (which defines range and allowed count)
static GC,GR,GT,BC,BK,BW,BR,BT,BF        ; static options, remembered between calls
static TS,TW,TC,TF,MS,MW,MC,MF
static SI,SC,ST,IW,IH,IN,XC,XS,XW,PC,PB
Critical
IW=32
If (Options)            ; skip parsing steps if Options param isn't used
{
  If (A_AutoTrim = "Off")
  {
   AutoTrim, On
   _AutoTrim = 1
  } ; —
  Options = %Options%
  Options.=" "            ; poor whitespace handling for next parsing step (ensures last option is parsed)
  Loop,Parse,Options,=         ; parse options string at "="s, needs better whitespace handling
  {
      If A_Index = 1        ; first option handling
        Option := A_LoopField        ; sets options VarName
      Else            ; for the rest after the first,
      {            ; split at the last space, apply the first chunk to the VarValue for the last Option
        %Option% := SubStr(A_LoopField, 1, (pos := InStr(A_LoopField, A_Space, false, 0))-1)
        %Option% = % %Option%
        Option   := SubStr(A_LoopField, pos+1)    ; and set the next option to the last chunk (from the last space to the "=")
      }
  }
  If _AutoTrim
   AutoTrim, Off
  If Wait <>            ; 选项​​等待= ID使用,正常通知窗口没有被创建
  {
      If Wait Is Number        ; 等待一个特定的通知
      {
        Gui %Wait%:+LastFound        ; i'd like to remove this to not affect calling script...
        If NotifyGuiID := WinExist()    ; but think i have to use hWnd's for reference instead of gui numbers which will
        {            ; probably happen in my AHK_L transition since gui numbers won't matter anymore
          WinWaitClose, , , % Abs(Duration)    ; wait to close for duration
          If (ErrorLevel && Duration < 1)    ; destroys window when done waiting if duration is negative
          {            ; otherwise lets the calling script procede after waiting the duration (without destroying)
            Gui, % Wait + GL - GF + 1 ":Destroy"    ; destroys border gui
            If ST
              DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt","0x00050001") ; 幻灯片窗口到右边,如果ST或SC的使用
            Gui, %Wait%:Destroy        ; and destroys it
          }
        }
      }
      Else            ; wait for all notify's if "Wait=All" is used in the options string
      {            ; loops through all existing notify's and performs the same wait logic
        Loop, % GL-GF        ; (with or without destroying if negative or not)
        {
          Wait := A_Index + GF - 1
          Gui %Wait%:+LastFound
          If NotifyGuiID := WinExist()
          {
            WinWaitClose, , , % Abs(Duration)
            If (ErrorLevel && Duration < 1)
            {
              Gui, % Wait + GL - GF + 1 ":Destroy"    ; destroys border gui
              If ST
                DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt","0x00050001") ; 滑动窗口的右侧,如果使用ST或SC
              Gui, %Wait%:Destroy        ; and destroys it
            }
          }
        }
        GNList := ACList := ATList := AXList := ""    ; clears internal variables since they're all destroyed now
      }
      Return
  }
  If Update <>            ; 使用时,通知窗口选项“更新= ID”将不会创建
  {            ; 标题,消息,图片和进步位置可以更新
      If Title <>
       GuiControl, %Update%:,_Title_,%Title%
      If Message <>
       GuiControl, %Update%:,_Message_,%Message%
      If Duration <>
       GuiControl, %Update%:,_Progress_,%Duration%
      If Image <>
       GuiControl, %Update%:,_Image_,%Image%
      If Wallpaper <>
       GuiControl, %Update%:,_Wallpaper_,%Image%
      Return
  }
  If Style = Save            ; 选择“样式=保存”来保存现有的窗口风格
  {            ; 并以“风格=负载”它召唤回来后
   Saved := Options " GC=" GC " GR=" GR " GT=" GT " BC=" BC " BK=" BK " BW=" BW " BR=" BR " BT=" BT " BF=" BF
   Saved .= " TS=" TS " TW=" TW " TC=" TC " TF=" TF " MS=" MS " MW=" MW " MC=" MC " MF=" MF
   Saved .= " IW=" IW " IH=" IH " IN=" IN " PW=" PW " PH=" PH " PC=" PC " PB=" PB " XC=" XC " XS=" MS " XW=" XW
   Saved .= " SI=" SI " SC=" SC " ST=" ST " WF=" Image " IF=" IF
  }            ; this needs some major improvement to have multiple saved instead of just one, otherwise pointless
  If Return <>
   Return, % (%Return%)
  If Style <>            ; option "Style=Default will reset all variables back to defaults... except options also specified
  {            ; so "Style=Default GC=Blue" is allowed, which will reset all defaults and then set GC=Blue
   If Style = Default
    Return % Notify(Title,Message,Duration,    ; maybe handled poorly by calling itself, but it saves having to have the defaults set in two areas... thoughts?
(
"GC= GR= GT= BC= BK= BW= BR= BT= BF= TS= TW= TC= TF=
MS= MW= MC= MF= SI= ST= SC= IW=
IH= IN= XC= XS= XW= PC= PB= " Options "Style=")
)            ; below are more internally saved styles, which may move to an auxiliary function at some point, but could use some improvement
   Else If Style = ToolTip
    Return % Notify(Title,Message,Duration,"SI=50 GC=FFFFAA BC=00000 GR=0 BR=0 BW=1 BT=255 TS=8 MS=8 " Options "Style=")
   Else If Style = BalloonTip
    Return % Notify(Title,Message,Duration,"SI=350 GC=FFFFAA BC=00000 GR=13 BR=15 BW=1 BT=255 TS=10 MS=8 AX=1 XC=999922 IN=8 Image=" A_WinDir "\explorer.exe " Options "Style=")
   Else If Style = Error
    Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=10 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
   Else If Style = Warning
    Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=9 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
   Else If Style = Info
    Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=8 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
   Else If Style = Question
    Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 Image=24 IW=32 IH=32 " Options "Style=")
   Else If Style = Progress
    Return % Notify(Title,Message,Duration,"SI=100 GC=Default BC=00000 GR=9 BR=13 BW=2 BT=105 TS=10 MS=10 PG=100 PH=10 GW=300 " Options "Style=")
   Else If Style = Huge
    Return % Notify(Title,Message,Duration,"SI=100 ST=200 SC=200 GC=FFFFAA BC=00000 GR=27 BR=39 BW=6 BT=105 TS=24 MS=22 " Options "Style=")
   Else If Style = Load
    Return % Notify(Title,Message,Duration,Saved)
  }
}
;——— end if options ——————————————————————————————————————

  GC_ := GC_<>"" ? GC_ : GC := GC<>"" ? GC : "FFFFAA"        ; defaults are set here, and static overrides are used and saved
  GR_ := GR_<>"" ? GR_ : GR := GR<>"" ? GR : 9        ; and non static options (with OP_=) are used but not saved
  GT_ := GT_<>"" ? GT_ : GT := GT<>"" ? GT : "Off"
  BC_ := BC_<>"" ? BC_ : BC := BC<>"" ? BC : "000000"
  BK_ := BK_<>"" ? BK_ : BK := BK<>"" ? BK : "Silver"
  BW_ := BW_<>"" ? BW_ : BW := BW<>"" ? BW : 2
  BR_ := BR_<>"" ? BR_ : BR := BR<>"" ? BR : 13
  BT_ := BT_<>"" ? BT_ : BT := BT<>"" ? BT : 105
  BF_ := BF_<>"" ? BF_ : BF := BF<>"" ? BF : 350
  TS_ := TS_<>"" ? TS_ : TS := TS<>"" ? TS : 10
  TW_ := TW_<>"" ? TW_ : TW := TW<>"" ? TW : 625
  TC_ := TC_<>"" ? TC_ : TC := TC<>"" ? TC : "Default"
  TF_ := TF_<>"" ? TF_ : TF := TF<>"" ? TF : "Hiragino Sans GB W3"
  MS_ := MS_<>"" ? MS_ : MS := MS<>"" ? MS : 10
  MW_ := MW_<>"" ? MW_ : MW := MW<>"" ? MW : "Default"
  MC_ := MC_<>"" ? MC_ : MC := MC<>"" ? MC : "Default"
  MF_ := MF_<>"" ? MF_ : MF := MF<>"" ? MF : "Default"
  SI_ := SI_<>"" ? SI_ : SI := SI<>"" ? SI : 0
  SC_ := SC_<>"" ? SC_ : SC := SC<>"" ? SC : 0
  ST_ := ST_<>"" ? ST_ : ST := ST<>"" ? ST : 0
  IW_ := IW_<>"" ? IW_ : IW := IW<>"" ? IW : 32
  IH_ := IH_<>"" ? IH_ : IH := IH<>"" ? IH : 32
  IN_ := IN_<>"" ? IN_ : IN := IN<>"" ? IN : 0
  XF_ := XF_<>"" ? XF_ : XF := XF<>"" ? XF : "Arial Black"
  XC_ := XC_<>"" ? XC_ : XC := XC<>"" ? XC : "Default"
  XS_ := XS_<>"" ? XS_ : XS := XS<>"" ? XS : 12
  XW_ := XW_<>"" ? XW_ : XW := XW<>"" ? XW : 800
  PC_ := PC_<>"" ? PC_ : PC := PC<>"" ? PC : "Default"
  PB_ := PB_<>"" ? PB_ : PB := PB<>"" ? PB : "Default"

  wPW := ((PW<>"") ? ("w" PW) : (""))        ; needs improvement, poor handling of explicit sizes and progress widths
  hPH := ((PH<>"") ? ("h" PH) : (""))
  If GW <>
  {
   wGW = w%GW%
   wPW := "w" GW - 20
  }
  hGH := ((GH<>"") ? ("h" GH) : (""))
  wGW_ := ((GW<>"") ? ("w" GW - 20) : (""))
  hGH_ := ((GH<>"") ? ("h" GH - 20) : (""))
;————————————————————————————————————
If Duration =                ; 如果持续时间不使用,或设置为默认 ""
  Duration = 30
GN := GF                ; find the next available gui number to use, starting from GF (default 50)
Loop                ; within the defined range GF to GL
  IfNotInString, GNList, % "|" GN
   Break
  Else
   If (++GN > GL)                ;=== too many notifications open, returns 0, handle this error in the calling script
    Return 0                          ; this is uncommon as the screen is too cluttered by this point anyway
GNList .= "|" GN
GN2 := GN + GL - GF + 1

If AC <>                ; saves the action to be used when clicked or timeout (or x-button is clicked)
  ACList .= "|" GN "=" AC            ; need to add different clicks for Title, Message, Image as well
If AT <>                ; saved internally in a list, then parsed by the timer or click routine
  ATList .= "|" GN "=" AT            ; to run the script-side subroutine/label "AC=LabelName"
If AX <>
  AXList .= "|" GN "=" AX


P_DHW := A_DetectHiddenWindows            ; start finding location based on what other Notify() windows are on the screen
P_TMM := A_TitleMatchMode            ; saved to restore these settings after changing them, so the calling script won't know
DetectHiddenWindows On            ; as they are needed to find all as they are being made as well... or hidden for some reason...
SetTitleMatchMode 1            ; and specific window title match is a little more failsafe
If (WinExist("_Notify()_GUI_"))              ;=== find all Notifications from ALL scripts, for placement
  WinGetPos, OtherX, OtherY                   ;=== change this to a loop for all open notifications and find the highest?
DetectHiddenWindows %P_DHW%            ;=== using the last Notify() made at this point, which may be better
SetTitleMatchMode %P_TMM%            ; and the global settings are restored for the calling thread

Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border        ; here begins the creation of the window
Gui, %GN%:Color, %GC_%            ; with the logic to add or not add certain controls, Wallpaper, Image, Title, Progress, Message
If FileExist(WP)                ; and some placement logic depending if they are used or not... could definitely be improved
{
  Gui, %GN%:Add, Picture, x0 y0 w0 h0 v_Wallpaper_, % WP    ; wallpaper added first, stretched to size later
  ImageOptions = x+8 y+4
}
If Image <>                ; icon image added next, sized, and spacing added for whats next
{
  If FileExist(Image)
   Gui, %GN%:Add, Picture, w%IW_% h%IH_% Icon%IN_% v_Image_ %ImageOptions%, % Image
  Else
   Gui, %GN%:Add, Picture, w%IW_% h%IH_% Icon%Image% v_Image_ %ImageOptions%, %A_WinDir%\system32\shell32.dll
  ImageOptions = x+10
}
If Title <>                ; title text control added next, if used
{
  Gui, %GN%:Font, w%TW_% s%TS_% c%TC_%, %TF_%
  Gui, %GN%:Add, Text, %ImageOptions% BackgroundTrans v_Title_, % Title
}
If PG                ; then the progress bar, if called for
  Gui, %GN%:Add, Progress, Range0-%PG% %wPW% %hPH% c%PC_% Background%PB_% v_Progress_
Else
  If ((Title) && (Message))            ; some spacing tweaks if both used
   Gui, %GN%:Margin, , -5
If Message <>                ; and finally the message text control if used
{
  Gui, %GN%:Font, w%MW_% s%MS_% c%MC_%, %MF_%
  Gui, %GN%:Add, Text, BackgroundTrans v_Message_, % Message
}
If ((Title) && (Message))            ; final spacing
  Gui, %GN%:Margin, , 8            
Gui, %GN%:Show, Hide %wGW% %hGH%, _Notify()_GUI_        ; final sizing
Gui  %GN%:+LastFound            ; would like to get rid of this to prevent calling script being affected
WinGetPos, GX, GY, GW, GH            ; final positioning
GuiControl, %GN%:, _Wallpaper_, % "*w" GW " *h" GH " " WP    ; stretch that wallpaper to size
GuiControl, %GN%:MoveDraw, _Title_,    % "w" GW-20 " h" GH-10    ; poor handling of text wrapping when gui has explicit size called
GuiControl, %GN%:MoveDraw, _Message_,  % "w" GW-20 " h" GH-10    ; needs improvement (and if image is used or not)
If AX <>                ; add the corner "X" for closing with a different action than otherwise clicked
{
  GW += 10
  Gui, %GN%:Font, w%XW_% s%XS_% c%XC_%, Arial Black          ; —(multiply) is the character used for the X-Button
  Gui, %GN%:Add, Text, % "x" GW-15 " y-2 Center w12 h20 g_Notify_Kill_" GN - GF + 1, % chr(0x00D7) ;鬃
}
Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% BackgroundTrans g_Notify_Action_Clicked_     ; to catch clicks anywhere on the gui
If (GR_)                    ; may have to be removed for seperate title/message/etc actions
  WinSet, Region, % "0-0 w" GW " h" GH " R" GR_ "-" GR_
If (GT_)                    ; non-functioning GT option, since the border gui gets in the way
  WinSet, Transparent, % GT_                ; will be addressed someday, leaving it in

SysGet, Workspace, MonitorWorkArea                ; positioning
NewX := WorkSpaceRight-GW-5
If (OtherY)
  NewY := OtherY-GH-2-BW_*2
Else
  NewY := WorkspaceBottom-GH-5
If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20        ; border gui
Gui, %GN2%:Color, %BC_%
Gui  %GN2%:+LastFound
If (BR_)
  WinSet, Region, % "0-0 w" GW+(BW_*2) " h" GH+(BW_*2) " R" BR_ "-" BR_
If (BT_)
  WinSet, Transparent, % BT_

Gui, %GN2%:Show, % "Hide x" NewX-BW_ " y" NewY-BW_ " w" GW+(BW_*2) " h" GH+(BW_*2), _Notify()_BGGUI_     ; actual creation of border gui! but still not shown
Gui, %GN%:Show,  % "Hide x" NewX " y" NewY " w" GW, _Notify()_GUI_            ; actual creation of Notify() gui! but still not shown
Gui  %GN%:+LastFound                    ; need to get rid of this so calling script isn't affected
If SI_
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SI_,"UInt","0x00040008")        ; animated in, if SI is used
Else
  Gui, %GN%:Show, NA, _Notify()_GUI_                ; otherwise, just shown
Gui, %GN2%:Show, NA, _Notify()_BGGUI_                ; and the border shown
WinSet, AlwaysOnTop, On                    ; and set to Always on Top

If ((Duration < 0) OR (Duration = "-0"))                ; saves internally that ExitApp should happen when this
  Exit := GN                        ; notify dissappears
If (Duration)    
  SetTimer, % "_Notify_Kill_" GN - GF + 1, % - Abs(Duration) * 1000            ; timer set depending on Duration parameter
Else
  SetTimer, % "_Notify_Flash_" GN - GF + 1, % BF_                ; timer set to flash border if the Notify has 0 (infinite) duration

Return %GN%                    ; end of Notify(), returns Gui ID number used

;==========================================================================
;========================================== 通知被点击时:
_Notify_Action_Clicked_:                ; 选项​​AC = LABEL指标签:子程序将在这里被称为点击时
; Critical
SetTimer, % "_Notify_Kill_" A_Gui - GF + 1, Off
Gui, % A_Gui + GL - GF + 1 ":Destroy"
If SC
{
  Gui, %A_Gui%:+LastFound
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
}
Gui, %A_Gui%:Destroy
If (ACList)
  Loop,Parse,ACList,|
   If ((Action := SubStr(A_LoopField,1,2)) = A_Gui)
   {
    Temp_Notify_Action:= SubStr(A_LoopField,4)
    StringReplace, ACList, ACList, % "|" A_Gui "=" Temp_Notify_Action, , All
    If IsLabel(_Notify_Action := Temp_Notify_Action)
     Gosub, %_Notify_Action%
    _Notify_Action =
    Break
   }
StringReplace, GNList, GNList, % "|" A_Gui, , All
SetTimer, % "_Notify_Flash_" A_Gui - GF + 1, Off
If (Exit = A_Gui)
  ExitApp
Return

;==========================================================================
;=========================================== 当通知超时:
_Notify_Kill_1:
_Notify_Kill_2:        ; 这需要一个不同的方法,太多的标签
_Notify_Kill_3:        ; 它们被用于定时器,对于每个不同的通知()的基础上持续时间。 。 。
_Notify_Kill_4:
_Notify_Kill_5:
_Notify_Kill_6:
_Notify_Kill_7:
_Notify_Kill_8:
_Notify_Kill_9:
_Notify_Kill_10:
_Notify_Kill_11:
_Notify_Kill_12:
_Notify_Kill_13:
_Notify_Kill_14:
_Notify_Kill_15:
_Notify_Kill_16:
_Notify_Kill_17:
_Notify_Kill_18:
_Notify_Kill_19:
_Notify_Kill_20:
_Notify_Kill_21:
_Notify_Kill_22:
_Notify_Kill_23:
_Notify_Kill_24:
_Notify_Kill_25:
Critical
StringReplace, GK, A_ThisLabel, _Notify_Kill_
SetTimer, _Notify_Flash_%GK%, Off
GK := GK + GF - 1
Gui, % GK + GL - GF + 1 ":Destroy"
If ST
{
  Gui, %GK%:+LastFound
  DllCall("AnimateWindow","UInt",WinExist(),"Int",ST,"UInt", "0x00050001")
}
Gui, %GK%:Destroy
StringReplace, GNList, GNList, % "|" GK, , All
If (Exit = GK)
  ExitApp
Return 1

;==========================================================================
;======================================== flashes a permanent notification:
_Notify_Flash_1:
_Notify_Flash_2:
_Notify_Flash_3:
_Notify_Flash_4:        ;这需要一种不同的方法,太多的标签
_Notify_Flash_5:        ;它们被用于定时器,不同的为每个通知()的基础上闪光的速度...
_Notify_Flash_6:        ; when duration is 0 (infinite)
_Notify_Flash_7:        ; this may feature may be removed completely, Update given the ability to affect GC and BC
_Notify_Flash_8:        ; and then the flashing could be handled script-side via returned gui number and a script-side timer
_Notify_Flash_9:
_Notify_Flash_10:
_Notify_Flash_11:
_Notify_Flash_12:
_Notify_Flash_13:
_Notify_Flash_14:
_Notify_Flash_15:
_Notify_Flash_16:
_Notify_Flash_17:
_Notify_Flash_18:
_Notify_Flash_19:
_Notify_Flash_20:
_Notify_Flash_21:
_Notify_Flash_22:
_Notify_Flash_23:
_Notify_Flash_24:
_Notify_Flash_25:
StringReplace, FlashGN, A_ThisLabel, _Notify_Flash_
FlashGN += GF - 1
FlashGN2 := FlashGN + GL - GF + 1
If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, %BK%
Else
  Gui, %FlashGN2%:Color, %BC%
Return
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
[+] 1用户表示感谢kongqir
2014-09-21, 19 : 51
RE: Notify() 改造中
原版那么长呢..
可别改造成H+HY独占版呀...

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-21, 22 : 25 (这个帖子最后修改于: 2014-09-21 22 : 48 by kongqir.)
RE: Notify() 改造中
代码: (全选)
[hy]
方式=
禁用=  
函数=
别名=ty_u_@r_a_l1
key=f2
内容=1
[c]
f2::

Notify("BBB","AAA",4,{GC:"0x062A48", TC:"White", MC:"White", IW:29, IH:-1, Image: A_ScriptDir "\Attached\Icon\Timing.ico"})
Notify("BBB","AAA",1,{GC:"0x062A48", TC:"White", MC:"White", IW:59, IH:-1, Image: A_ScriptDir "\Attached\Icon\Quicktime-01.ico"})
Return


Notify(Title="Notify()",Content="",Duration="",Options="")
{
static Notify:=[],GNList:=[], ACList, ATList, AXList, Exit, _Wallpaper_, _Title_, _Content_, _Progress_, _Image_, Saved,Flash:=[],Destroy:=[]
static Default:={GC : "FFFFAA",GR : 9,GT : "Off",BC : "000000",BK : "Silver",BW : 2,BR : 13,BT : 105,BF : 350,TS : 10,TW : 625,TC : "Default",TF : "Hiragino Sans GB W3",MS : 10,MW : "Default"
,MC : "Default",MF : "Default",SI : 0,SC : 0,ST : 0,IW : 32,IH : 32,IN : 0,XF : "Arial Black",XC : "Default",XS : 12,XW : 800,PC : "Default",PB : "Default"}

    Critical
    if IsObject(f:=Title)
    {
        if f.d
        {
            (d:=Notify.Remove(f.d,"")).stop
            Gui, % "f" f.d ":Destroy"
            d.st?DllCall("AnimateWindow","UInt",d.hwnd,"Int",ST,"UInt", "0x00050001"):""
            Gui, % "n" f.d ":Destroy"
            If (Exit = f.d)
                ExitApp
        }
        else if f.f
        {
            d:=Notify[f.d]
            If Flashed%FlashGN2% := !Flashed%FlashGN2% ;这句不明白
                Gui, % "f" f.f ":Color", % d.BK
            Else
                Gui, % "f" f.f ":Color",, % d.BC

        } else
        {
            If d:=Notify[f.w].hwnd
            {        
            WinWaitClose, % "ahk_id " d, , % Abs(f.t)
            If (ErrorLevel && f.t < 1)
                Notify({d:f.w})
            }
        }
        Return
    }

    Duration?"":Duration:=30,f:=Default.Clone()
    for i,n in Options
        f[i]:=n


    If (f.Wait!="")
    {
        If f.Wait Is Number
            Notify({w:f.w,t:Duration})
        Else            
            for i,n in Notify
                Notify({w:i.w,t:Duration})
        Return
    }

    If (f.Update!="")
    {            
        If (f.Title!="")
            GuiControl, % f.Update ":",_Title_,% f.Title
        If (f.Message!="")
            GuiControl, % f.Update ":",_Message_,% f.Message
        If (f.Duration!="")
            GuiControl, % f.Update ":",_Progress_,% f.Duration
        If (f.Image!="")
            GuiControl, % f.Update ":",_Image_,% f.Image
        If (f.Wallpaper!="")
            GuiControl, % f.Update ":",_Wallpaper_,% f.Image
        Return
    }

    If (f.Return!="")
        Return Notify[f.Return]



  wPW := ((PW!="") ? ("w" PW) : (""))    
  hPH := ((PH!="") ? ("h" PH) : (""))

  If GW !=
  {
   wGW = w%GW%
   wPW := "w" GW - 20
  }
  hGH := ((GH!="") ? ("h" GH) : (""))
  wGW_ := ((GW!="") ? ("w" GW - 20) : (""))
  hGH_ := ((GH!="") ? ("h" GH - 20) : (""))

Loop                ; within the defined range GF to GL
if !Notify[d:=A_Index]
   Break

Notify[d]:=f



If AC !=                ; saves the action to be used when clicked or timeout (or x-button is clicked)
  ACList .= "|" GN "=" AC            ; need to add different clicks for Title, Content, Image as well
If AT !=                ; saved internally in a list, then parsed by the timer or click routine
  ATList .= "|" GN "=" AT            ; to run the script-side subroutine/label "AC=LabelName"
If AX !=
  AXList .= "|" GN "=" AX


P_DHW := A_DetectHiddenWindows            ; start finding location based on what other Notify() windows are on the screen
P_TMM := A_TitleMatchMode            ; saved to restore these settings after changing them, so the calling script won't know
DetectHiddenWindows On            ; as they are needed to find all as they are being made as well... or hidden for some reason...
SetTitleMatchMode 1            ; and specific window title match is a little more failsafe
If (WinExist("_Notify()_GUI_"))              ;=== find all Notifications from ALL scripts, for placement
  WinGetPos, OtherX, OtherY                   ;=== change this to a loop for all open notifications and find the highest?
DetectHiddenWindows %P_DHW%            ;=== using the last Notify() made at this point, which may be better
SetTitleMatchMode %P_TMM%            ; and the global settings are restored for the calling thread


Gui, N%d%:New,-Caption +ToolWindow +AlwaysOnTop -Border  +hwndHGUI        ; 在这里开始创建窗口

Gui, N%d%:Color, % f.GC            ; 用逻辑来添加或不添加某些控制,壁纸,图片,标题,进度,信息
If FileExist(WP)                ; 并且如果使用它们或不一些放置逻辑视。 。 。肯定可以得到改善
{
  Gui, N%d%:Add, Picture, x0 y0 w0 h0 v_Wallpaper_, % WP    ; 壁纸添加第一,拉伸后的尺寸
  ImageOptions = x+8 y+4
}

f.hwnd:=HGUI
If (f.Image !=    "")            ; icon image added next, sized, and spacing added for whats next
{
  If FileExist(f.Image)
   Gui, N%d%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.IN " v_Image_ " ImageOptions, % f.Image
  Else
  Gui, N%d%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.Image " v_Image_ " ImageOptions, % A_WinDir "\system32\shell32.dll"

  ImageOptions = x+10
}

If (Title !="")            ; icon image added next, sized, and spacing added for whats next
{
  Gui, N%d%:Font, % "w" f.IW " s" f.TS " c" f.TC, % f.TF
  Gui, N%d%:Add, Text, %ImageOptions% BackgroundTrans v_Title_, % Title
}


If f.PG                ; 那么进度条,如果要求
  Gui, N%d%:Add, Progress, % "Range0-" PG " " wPW " " hPH " c" f.PC " Background" f.PB " v_Progress_"
Else
  If ((Title) && (Content))            ; some spacing tweaks if both used
   Gui, N%d%:Margin, , -5

If Content !=                ; and finally the Content text control if used
{
  Gui, N%d%:Font, % "w" f.MW " s" f.MS " c" f.MC, % f.MF
  Gui, N%d%:Add, Text, BackgroundTrans v_Content_, % Content
}

If ((Title) && (Content))            ; final spacing
  Gui, N%d%:Margin, , 8            
Gui, N%d%:Show, Hide %wGW% %hGH%, _Notify()_GUI_        ; final sizing
Gui  N%d%:+LastFound            ; would like to get rid of this to prevent calling script being affected
WinGetPos, GX, GY, GW, GH            ; final positioning
GuiControl, N%d%:, _Wallpaper_, % "*w" GW " *h" GH " " WP    ; stretch that wallpaper to size
GuiControl, N%d%:MoveDraw, _Title_,    % "w" GW-20 " h" GH-10    ; poor handling of text wrapping when gui has explicit size called
GuiControl, N%d%:MoveDraw, _Content_,  % "w" GW-20 " h" GH-10    ; needs improvement (and if image is used or not)
If AX !=                ; add the corner "X" for closing with a different action than otherwise clicked
{
  GW += 10
  Gui, N%d%:Font, % "w" f.XW " s" f.XS " c" f.XC, Arial Black          ; —(multiply) is the character used for the X-Button
  Gui, N%d%:Add, Text, % "x" GW-15 " y-2 Center w12 h20 g_Notify_Kill_" GN - GF + 1, % chr(0x00D7) ;鬃
}
Gui, N%d%:Add, Text, x0 y0 w%GW% h%GH% BackgroundTrans g_Notify_Action_Clicked_     ; to catch clicks anywhere on the gui
If (f.GR)                    ; 可能要在单独的标题/消息/等行动拆除
  WinSet, Region, % "0-0 w" GW " h" GH " R" f.GR "-" f.GR
If (f.GT)                    ; 非功能性的GT选项,因为边境GUI碍事
  WinSet, Transparent, % f.GT                ; will be addressed someday, leaving it in

SysGet, Workspace, MonitorWorkArea                ; positioning
NewX := WorkSpaceRight-GW-5
If (OtherY)
  NewY := OtherY-GH-2-f.BW*2
Else
  NewY := WorkspaceBottom-GH-5
If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

Gui, f%d%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20        ; border gui
Gui, f%d%:Color, % f.BC
Gui  f%d%:+LastFound

If (f.BR)
  WinSet, Region, % "0-0 w" GW+(f.BW*2) " h" GH+(f.BW*2) " R" f.BR "-" f.BR
If (f.BT)
  WinSet, Transparent, % f.BT

Gui, f%d%:Show, % "Hide x" NewX-f.BW " y" NewY-f.BW " w" GW+(f.BW*2) " h" GH+(f.BW*2), _Notify()_BGGUI_     ; actual creation of border gui! but still not shown
Gui, N%d%:Show,  % "Hide x" NewX " y" NewY " w" GW, _Notify()_GUI_            ; actual creation of Notify() gui! but still not shown
Gui  N%d%:+LastFound                    ; need to get rid of this so calling script isn't affected


If f.SI
  DllCall("AnimateWindow","UInt",WinExist(),"Int",f.SI,"UInt","0x00040008")        ; 动画中,如果使用Si
Else
  Gui, N%d%:Show, NA, _Notify()_GUI_                ; 否则,只显示

Gui, f%d%:Show, NA, _Notify()_BGGUI_                ; and the border shown
WinSet, AlwaysOnTop, On                    ; and set to Always on Top

If ((Duration < 0) OR (Duration = "-0"))                ; 保存在内部的ExitApp命令应该发生在这
  Exit := d                        ; 通知dissappears
If (Duration)    
{

Notify[d]:=SetTimerEx(- Abs(Duration) * 1000, "Notify", {d:d})
    

}        ; timer set depending on Duration parameter
Else
Notify[d]:=SetTimerEx(- Abs(Duration) * 1000, "Notify", {f:d})
                ; timer set to flash border if the Notify has 0 (infinite) duration

Return N%d%                    ; end of Notify(), returns Gui ID number used

;==========================================================================
;========================================== when a notification is clicked:

_Notify_Action_Clicked_:                ; option AC=Label means Label: subroutine will be called here when clicked
; Critical
ls:=A_Gui - GF + 1
Destroy.Remove(ls,"").stop
Gui, % A_Gui + GL - GF + 1 ":Destroy"
If SC
{    
  Gui, %A_Gui%:+LastFound
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
}
Gui, %A_Gui%:Destroy
If (ACList)
  Loop,Parse,ACList,|
   If ((Action := SubStr(A_LoopField,1,2)) = A_Gui)
   {
    Temp_Notify_Action:= SubStr(A_LoopField,4)
    StringReplace, ACList, ACList, % "|" A_Gui "=" Temp_Notify_Action, , All
    If IsLabel(_Notify_Action := Temp_Notify_Action)
     Gosub, %_Notify_Action%
    _Notify_Action =
    Break
   }
Notify.Remove(A_Gui,"")
Flash.Remove(ls,"").stop
If (Exit = A_Gui)
  ExitApp
Return
}

我现在都尽量使用H特性了,崩溃怕了
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 12 : 06
RE: Notify() 改造中
kongqir 提到:  我现在都尽量使用H特性了,崩溃怕了
说反了吧..不是H才崩溃的吗?
好久没用,H不就多了多线程特性吗?Huh

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 17 : 57
RE: Notify() 改造中
最后一个通用版本,其后都将是HY专用。
因为弃用了SetTimerEx(),这个定时器函数,只用了一个定时器,也就是从伪多线程意义说它只是单线程,只有执行完一个函数之后才会继续执行下一个。
而FTimer(),则每次调用都启用新的线程,也就是说它能最大化利用伪多线程。

------------
H的多线程崩溃我已经没什么好说的了。。


----------

代码: (全选)
[hy]
方式=
禁用=  
函数=
别名=ty_u_@r_a_l1
key=f2
内容=1
[c]



Notify("BBB","AAA",0,{GC:"0x062A48", border: 1, TC:"White", MC:"White", IW:49, IH:-1, Image: A_ScriptDir "\Attached\Icon\Quicktime-01.ico"})
Notify("BBB","AAA",4,{GC:"0x062A48", TC:"White", MC:"White", IW:29, IH:-1, Image: A_ScriptDir "\Attached\Icon\Timing.ico"})

Return


Notify(Title="Notify()",Content="",Duration="",Options=""){
    static Notify:=[],GNList:=[], ACList, ATList, AXList, Exit, _Wallpaper_, _Title_, _Content_, _Progress_, _Image_, Saved
        ,Default:={GC : "FFFFAA",GR : 9,GT : "Off",BC : "000000",BK : "Silver",BW : 2,BR : 13,BT : 105,BF : 500,TS : 10,TW : 625
            ,TC : "Default",TF : "Hiragino Sans GB W3",MS : 10,MW : "Default",MC : "Default",MF : "Default",SI : 0,SC : 0
            ,ST : 0,IW : 32,IH : 32,IN : 0,XF : "Arial Black",XC : "Default",XS : 12,XW : 800,PC : "Default",PB : "Default"}

    if IsObject(d:=Title)
    {
        if d.d
        {
            f:=Notify.Remove(d.d,"")
            f.ft.Stop()
            If (f.Duration = 0)
                Gui, % "f" d.d ":Destroy"
            d.A?DllCall("AnimateWindow","UInt",d.hwnd,"Int",d.A,"UInt", "0x00050001"):""
            f.AC AND IsLabel(f.AC)? Gosub(f.AC):""
            Gui, % "n" d.d ":Destroy"
            If (Exit = d.d)
                ExitApp
        }
        else if d.f
        {
            f:=Notify[d.f]
            Gui, % "f" d.f ":Color", % (f.Flash := !f.Flash) ? f.BK : f.BC
        }
        else
        {
            If f:=Notify[d.w].hwnd
            {
                WinWaitClose, % "ahk_id " f, , % Abs(d.t)
                If (ErrorLevel && d.t < 1)
                    Notify({d:d.w})
            }
        }
        Return
    }

    (Duration="")?Duration:=30:"",f:=Default.Clone()

    If Options        
    {
        if IsObject(Options)
        {
            for i,n in Options
                f[i]:=n
        }
        Else
        {
            for i,n in StrSplit(Options, " ")
                f[SubStr(n, 1,(s:=InStr(n, "="))-1)]:=SubStr(n, s+1)
        }
    }

    If (f.Wait!="")
    {
        If f.Wait Is Number
            Notify({w:f.w,t:Duration})
        Else            
            for i,n in Notify
                Notify({w:i,t:Duration})
        Return
    }

    If (f.Update!="")
    {            
        If (f.Title!="")
            GuiControl, % f.Update ":",_Title_,% f.Title
        If (f.Message!="")
            GuiControl, % f.Update ":",_Message_,% f.Message
        If (f.Duration!="")
            GuiControl, % f.Update ":",_Progress_,% f.Duration
        If (f.Image!="")
            GuiControl, % f.Update ":",_Image_,% f.Image
        If (f.Wallpaper!="")
            GuiControl, % f.Update ":",_Wallpaper_,% f.Image
        Return
    }

    If (f.Return!="")
        Return Notify[f.Return]



If (f.GW!="")

{
wGW := "w"  f.GW
wPW := "w" f.GW - 20
}
hGH := ((GH!="") ? ("h" GH) : (""))
wGW_ := ((GW!="") ? ("w" GW - 20) : (""))
hGH_ := ((GH!="") ? ("h" GH - 20) : (""))

    Loop                
        if !Notify[d:=A_Index]
            Break
    Notify[d]:=f

    If WinExist("__Notify")
        WinGetPos, OtherX, OtherY

    Gui, N%d%:New,-Caption +ToolWindow +AlwaysOnTop -Border +hwndHGUI +LastFound    
    Gui, N%d%:Color, % f.GC
    f.hwnd:=HGUI
    f.Duration := Duration
    f.Title := Title
    f.Content := Content    

    If FileExist(f.GW)
    {
        Gui, N%d%:Add, Picture, x0 y0 w0 h0 v_Wallpaper_, % f.GW
        ImageOptions := "x+8 y+4"
    }
    If (f.Image !=    "")
    {
        If FileExist(f.Image)
            Gui, N%d%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.IN " v_Image_ " ImageOptions, % f.Image
        Else
            Gui, N%d%:Add, Picture, % "w" f.IW  " h" f.IH " Icon" f.Image " v_Image_ " ImageOptions, % A_WinDir "\system32\shell32.dll"
        ImageOptions := "x+10"
    }
    If (Title !="")
    {
        Gui, N%d%:Font, % "w" f.IW " s" f.TS " c" f.TC, % f.TF
        Gui, N%d%:Add, Text, %ImageOptions% BackgroundTrans v_Title_, % Title
    }


    If f.PG
        Gui, N%d%:Add, Progress, % "Range0-" PG " w" f.PW " h"  f.PH " c" f.PC " Background" f.PB " v_Progress_"
    Else
        If ((Title) && (Content))
            Gui, N%d%:Margin, , -5

    
    If (Content !="")        
    {
        Gui, N%d%:Font, % "w" f.MW " s" f.MS " c" f.MC, % f.MF
        Gui, N%d%:Add, Text, BackgroundTrans v_Content_, % Content
    }

    If (Title && Content)
        Gui, N%d%:Margin, , 8
        
    Gui, N%d%:Show, Hide %wGW% %hGH%, __Notify
    WinGetPos, GX, GY, GW, GH
    GuiControl, N%d%:, _Wallpaper_, % "*w" GW " *h" GH " " WP
    GuiControl, N%d%:MoveDraw, _Title_,    % "w" GW-20 " h" GH-10
    GuiControl, N%d%:MoveDraw, _Content_,  % "w" GW-20 " h" GH-10

    If AX !=                ; add the corner "X" for closing with a different action than otherwise clicked
    {
        GW += 10
        Gui, N%d%:Font, % "w" f.XW " s" f.XS " c" f.XC, Arial Black          ; —(multiply) is the character used for the X-Button
        Gui, N%d%:Add, Text, % "x" GW-15 " y-2 Center w12 h20 g_Notify_Kill_" GN - GF + 1, % chr(0x00D7) ;鬃
    }

    Gui, N%d%:Add, Text, x0 y0 w%GW% h%GH% BackgroundTrans g__Notify     ; to catch clicks anywhere on the gui
    If (f.GR)
        WinSet, Region, % "0-0 w" GW " h" GH " R" f.GR "-" f.GR
    If (f.GT)
        WinSet, Transparent, % f.GT

    SysGet, Workspace, MonitorWorkArea
    NewX:=WorkSpaceRight-GW-5,(NewY:=OtherY?OtherY-GH-2-f.BW*2:WorkspaceBottom-GH-5)<WorkspaceTop?NewY:=WorkspaceBottom-GH-5:""

    If (Duration = 0)
    {
        Gui, f%d%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20  +LastFound
        Gui, f%d%:Color, % f.BC
        If (f.BR)
            WinSet, Region, % "0-0 w" GW+(f.BW*2) " h" GH+(f.BW*2) " R" f.BR "-" f.BR
        If (f.BT)
            WinSet, Transparent, % f.BT
        Gui, f%d%:Show, % "Hide x" NewX-f.BW " y" NewY-f.BW " w" GW+(f.BW*2) " h" GH+(f.BW*2), __BGNotify    
    }


    Gui, N%d%:Show,  % "Hide x" NewX " y" NewY " w" GW, __Notify
    If f.SI
        DllCall("AnimateWindow","UInt",HGUI,"Int",f.SI,"UInt","0x00040008")
    Else
        Gui, N%d%:Show, NA, __Notify
    
    If (Duration = 0)
        Gui, f%d%:Show, NA, __BGNotify

    WinSet, AlwaysOnTop, On, % "ahk_id " HGUI

    If ((Duration < 0) OR (Duration = "-0"))
        Exit := d
    If (Duration)
        f.FT:=SetTimerEx(- Abs(Duration) * 1000, "Notify", {d:d,A:f.st})
    Else
        f.FT:=SetTimerEx(f.BF, "Notify", {f:d})
Return d

__Notify:
    h:=Notify[b:=SubStr(A_Gui, 2)]
    Notify({d:b,A:h.SC})
Return
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 18 : 06 (这个帖子最后修改于: 2014-09-22 18 : 07 by robertL.)
RE: Notify() 改造中
  • SetTimerEx感觉多数情况伪多线程也够了,一般没有什么并行任务吧,好像也只有菜单啥的才会致使当前线程阻塞,其他线程暂停。
  • FTimer不是借助H版的多线程吗?算了,没弄懂你到底用啥版本...
  • 何况,你脚本里这么多东西,dllcall什么的最可怕了...,不一定H的问题吧?
    所以,像V2那样强制性报错,或者要求代码考虑容错,是正确的吧...

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 18 : 30 (这个帖子最后修改于: 2014-09-22 18 : 38 by kongqir.)
RE: Notify() 改造中
定时器的特点就是并行好吧。
下面的示例 SetTimerEx 只弹出一个。而正常的会弹出两个。
代码: (全选)
#Persistent
SetTimer a, -200
SetTimer b, -250

Return
a:
c(1)
Return

b:
c(2)
Return
c(d){
MsgBox % d
Sleep, 20000
}

SetTimerEx 完全是单线程,这点你都没搞清楚,你写的那个定时器可想而知了。

对了,帮我向L大反馈下。伪线程之类的词汇我不会翻译。
对比代码:
代码: (全选)
#Persistent

SetTimerEx(-200, "c", 1)
SetTimerEx(-250, "c", 2)
Return

a:
c(1)
Return

b:
c(2)
Return

c(d){
MsgBox % d
Sleep, 20000
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 19 : 08 (这个帖子最后修改于: 2014-09-22 19 : 31 by robertL.)
Smile RE: kongqir 动态定时器 并行化
  • 你那示例不准,偶尔也只弹出了一个(先第2个-250,关闭后,再第1个-200)..
    感觉和电脑速度有关,延长时间,效果又不一样了...
  • 即便是SetTimerEx,也可以做到等效于手动的SetTimer(即,不用等待前一个函数返回才开始后一个)
    使用主定时器触发辅定时器,使用定时器来执行动作,在定时器开始前变重设。
    在定时器执行标签中,执行函数前,完成重设定时器,则,函数执行后,定时器照常工作..
    你先参考这个思路改改看,SetTimerEx是类似的
    可能SetTimerEx没有考虑,我那个TimerL不确定有无考虑→未考虑,不过貌似交换两处代码就行了..
  • 这些词通过对照中-英帮助都能找到的..
    查了下,中文手册中就没搜到伪线程,谈不上对照了..
  • 空了我也看看这两个定时器..之前看的忘了..

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 19 : 30
RE: Notify() 改造中
= = 第一个示例一定都是弹出两个, 如果只弹出一个,你可以换电脑了。电脑速度或许不同,但你那电脑连时间都不准了。
至于“先第二个”。。。因为它后弹出,所以总在前面。是从这个角度出发的吗?

你先试试,多个SetTimer,运行同一个标签是什么效果再说吧。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 19 : 39 (这个帖子最后修改于: 2014-09-22 19 : 43 by robertL.)
RE: Notify() 改造中
我更正了下,是先弹出第2个,关闭后,等一阵(20000+200)后弹出第1个...
当然,我改时间了,Sleep 20000太长了= =。

尝试3个定时器SetTimer a, -200SetTimer b, -200SetTimer c, -200,最好的情况,同时弹出2个,关闭后,等一阵,弹出最后一个;仅弹出一个时,需要{关闭-等待}×2..

哦,用的V2,V1的话,只弹出来一个,关闭-等待-弹出-关闭-.....
↑也不准确,普遍只弹一个..

改时间-200-1000都这样,是不是我电脑太快了?...

太意外了,和预期不一样啊...算了,空了研究。

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 19 : 59
RE: Notify() 改造中
奇葩

帖子内容太短了, 请输入至少 5 个字符
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 20 : 06
RE: Notify() 改造中
如果改成大致
代码: (全选)
SetTimer a, -200
Sleep 100
SetTimer b, -250
我也能稳定弹两个了...奇怪...

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 20 : 35
RE: Notify() 改造中
换电脑吧。。。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-09-22, 20 : 38
RE: Notify() 改造中
kongqir 提到:  换电脑吧。。。
不用,电脑太快,加个延迟就好了...Big Grin

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
发表回复 


论坛跳转:


联系我们 | Autohotkey 中文站 | 回到顶部 | 回到正文区 | 精简(归档)模式 | RSS 聚合