You have to reload the script to make it work... (does not work the first time) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
wetware05
Posts: 750
Joined: 04 Dec 2020, 16:09

You have to reload the script to make it work... (does not work the first time)

06 Sep 2021, 18:55

Hi.

This script watches that the left mouse button is held down. If it exceeds a certain time, a small Gui is activated which gives the option to copy.

The problem is that when you open it for the first time it doesn't work and you have to reload it, as you can see in the video? Why?

(If the clipboard is not used, TrayTip does not emerge).

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
;#Persistent
CoordMode, Mouse, Screen

~LButton::
    time := A_TickCount
	KeyWait, LButton
    varTemp := A_TimeSinceThisHotkey
    if varTemp>1200
	Gosub, Select
    Else
return

Select:
MouseGetPos, xpos1, ypos1
Gui,1: color,EEAA99
Gui, Add, Button, x2 y2 w64 h15 gExitMenu, Exit
Gui, Add, Button, x2 y18 w64 h64 hwndIcon gButtonLabel
Gui, Show, x%xpos1% y%ypos1% w68 h84, Window-Title
Gui, -Caption ;+alwaysontop
GuiButtonIcon(Icon, "clipboard.ico", 1, "s90")
Return

ButtonLabel:
ClipTemp := Clipboard
clipboard := ""
Gui, Destroy
SetTimer, ActivateWinUM, 100
Send, ^c
;Gosub, OnClipboardChange
ClipWait
if Not Clipboard=ClipTemp
	{
	SoundPlay, Clipboard_Sound.mp3
	TrayTip, Timed TrayTip, %Clipboard%, 0x1, 0x10, 0x20
	SetTimer, HideTrayTip, -1500
	}
	Else
	{
	SoundPlay, ambiguity2.mp3
	TrayTip, Timed TrayTip, REPEATED CLIPBOARD!, 0x2, 0x10, 0x20
	SetTimer, HideTrayTip, -1500
	}
Return

ActivateWinUM:
MouseGetPos,,, WinUMID
WinActivate, ahk_id %WinUMID%
return

;^esc::
;Gui, Destroy
;Return

ExitMenu:
Gui, Destroy
Return

;GuiClose:
;ExitApp

HideTrayTip() {
    TrayTip
}
Return

GuiButtonIcon(Handle, File, Index := 1, Options := "")
{
	RegExMatch(Options, "i)w\K\d+", W), (W="") ? W := 16 :
	RegExMatch(Options, "i)h\K\d+", H), (H="") ? H := 16 :
	RegExMatch(Options, "i)s\K\d+", S), S ? W := H := S :
	RegExMatch(Options, "i)l\K\d+", L), (L="") ? L := 0 :
	RegExMatch(Options, "i)t\K\d+", T), (T="") ? T := 0 :
	RegExMatch(Options, "i)r\K\d+", R), (R="") ? R := 0 :
	RegExMatch(Options, "i)b\K\d+", B), (B="") ? B := 0 :
	RegExMatch(Options, "i)a\K\d+", A), (A="") ? A := 4 :
	Psz := A_PtrSize = "" ? 4 : A_PtrSize, DW := "UInt", Ptr := A_PtrSize = "" ? DW : "Ptr"
	VarSetCapacity( button_il, 20 + Psz, 0 )
	NumPut( normal_il := DllCall( "ImageList_Create", DW, W, DW, H, DW, 0x21, DW, 1, DW, 1 ), button_il, 0, Ptr )	; Width & Height
	NumPut( L, button_il, 0 + Psz, DW )		; Left Margin
	NumPut( T, button_il, 4 + Psz, DW )		; Top Margin
	NumPut( R, button_il, 8 + Psz, DW )		; Right Margin
	NumPut( B, button_il, 12 + Psz, DW )	; Bottom Margin	
	NumPut( A, button_il, 16 + Psz, DW )	; Alignment
	SendMessage, BCM_SETIMAGELIST := 5634, 0, &button_il,, AHK_ID %Handle%
	return IL_Add( normal_il, File, Index )
}
Return


Can it be improved, they have errors in their execution.

(I know the limits of this script. If you have done a mouse drag, without selecting text it does the same procedure, but that's why a gui comes out and it's not very annoying).
User avatar
mikeyww
Posts: 27191
Joined: 09 Sep 2014, 18:38

Re: You have to reload the script to make it work... (does not work the first time)

06 Sep 2021, 19:06

You probably wrote line 13 unintentionally. The "Else" now applies to the Return, so if the condition is actually true, then the script continues instead of returning.
wetware05
Posts: 750
Joined: 04 Dec 2020, 16:09

Re: You have to reload the script to make it work... (does not work the first time)

07 Sep 2021, 04:50

Thanks mikeyww.

I have thought that the first time it may be hindered by the antivirus, which tries to predict what the program does and "slows it down".

It's never clear to me when to use return. In some situations it is very obvious (end of a routine or subroutine). Other issues for which I have not found documentation. Do functions require a return? or it doesn't make sense either. Another one. How to order in a script the subroutines and functions, first the functions and then the subroutines or the other way around..., or it doesn't matter and it's just to give a visual order to the script.

In some situations I have found that the script becomes more erratic if ordered.
User avatar
mikeyww
Posts: 27191
Joined: 09 Sep 2014, 18:38

Re: You have to reload the script to make it work... (does not work the first time)

07 Sep 2021, 05:28

Good questions. Yes, your antivirus software can interfere, depending on circumstances. This happens most often with compiled scripts, but it could happen with AutoHotkey.exe, too.

Return ends a labeled subroutine including hotkey routines, and the auto-execute section. More precisely, it
returns from a subroutine to which execution had previously jumped via function-call, Gosub, Hotkey activation, GroupActivate, or other means.
If you want a function to end in the middle, or to return a value, Return is also used there; it is otherwise optional at the end of a function.

You can put your labeled routines and functions in any order, keeping in mind that consecutive subroutines with regular labels will execute in order, until Return is reached. I put my functions at the bottom of the script by convention; others may put them at the top. I usually group my hotkeys, but not always, depending on how I want looking at the script to remind me about certain related sections of code.

The auto-execute section must be at the top of the script. If followed by a hotkey, then the first hotkey has an implicit return before it. More precisely,
while the script's first hotkey/hotstring label has the same effect as return, other hotkeys and labels do not.
If your script changes according to your ordering, then it would usually mean that you are missing a Return; you have unreachable code, which is an unlabeled section following a Return; or you have consecutive labeled routines that are running in order without an intervening Return.

Finally,
if there is no caller to which to return, Return will do an Exit instead.
This also generally means that if your script is not persistent, the first Return will induce an Exit.

A simple way to think of Return is that you can use it to terminate each of your subroutines.

I saw that your script has functions that are then followed (after the closing brace) by Return. Those Return commands serve no role but are indeed executed but as if the function were located elsewhere in the script (but the Return stays in place). Two demos are below.

Code: Select all

MsgBox, 1
function() {
}
Return
MsgBox, 2

Code: Select all

MsgBox, 1
function() {
}
MsgBox, 2
Why? Because a closing brace terminates a function.

Of course, if the Return follows a Return, then the second one never executes (true even if the script were to persist).

Code: Select all

MsgBox, 1
Return
function() {
}
; MsgBox, 2
Return
MsgBox, 3
Now you know why I put functions at the bottom of my script.... :)
wetware05
Posts: 750
Joined: 04 Dec 2020, 16:09

Re: You have to reload the script to make it work... (does not work the first time)

07 Sep 2021, 09:21

mikeyww, I tried your suggestion, but the gui comes out when she wants to, even if it is closed in a subroutine, and is not "called". It seems that the "else, return" sequence makes a pseudo-loop that waits for the condition of the first lines to occur. Maybe there's a real loop to be made.

What I've learned better is that if a function is closed with } there is no need for return. :P

I tend to put extra return when I see the script leaks to do what it should not. I could put them one by one and check what the problem is, but it takes a lot of time. There is a saying that "it is better to have too much than too little". :lol:
User avatar
mikeyww
Posts: 27191
Joined: 09 Sep 2014, 18:38

Re: You have to reload the script to make it work... (does not work the first time)  Topic is solved

07 Sep 2021, 11:40

Not really. It's better to understand and debug your script than to insert Return randomly!

Ideas:

Code: Select all

Gui, -Caption
Gui, Color, EEAA99
Gui, Margin, 2, 2
Gui, Add, Button,     w64 h15                      , Exit
Gui, Add, Button, y+1 wp  h64 hwndIcon gButtonLabel

~LButton::start := A_TickCount
~LButton Up::
If (A_TickCount - start < 1200)
 Return
MouseGetPos, xpos1, ypos1
Gui, Show, x%xpos1% y%ypos1%
Return

ButtonLabel:
Gui, Submit
last := Clipboard, Clipboard := ""
Send ^c
ClipWait, 0
If ErrorLevel {
 MsgBox, 48, Error, An error occurred while waiting for the clipboard.
 Return
} Else If (Clipboard = last) {
 SoundPlay, ambiguity2.mp3
 TrayTip, Timed TrayTip, REPEATED CLIPBOARD!
} Else {
 SoundPlay, Clipboard_Sound.mp3
 TrayTip, Timed TrayTip, %Clipboard%
}
SetTimer, HideTrayTip, -1500
Return

GuiEscape:
GuiClose:
ButtonExit:
Gui, Hide
Return

HideTrayTip:
TrayTip
Return
wetware05
Posts: 750
Joined: 04 Dec 2020, 16:09

Re: You have to reload the script to make it work... (does not work the first time)

07 Sep 2021, 14:08

Much more reliable. It does what they need to do more safely and elegantly. Thank you very much mikeyww. :dance: A question. Having created the "HideTrayTip" subroutine. In my "HideTrayTip" script calls a function.

Code: Select all

SoundPlay, ambiguity2.mp3
	TrayTip, Timed TrayTip, REPEATED CLIPBOARD!, 0x2, 0x10, 0x20
	SetTimer, HideTrayTip, -1500
.......
.......
HideTrayTip() {
    TrayTip
}
Are they two ways of doing the same thing?

(I didn't know that subroutines could be concatenated.)

Code: Select all

GuiEscape:
GuiClose:
ButtonExit:
Gui, Hide
Return
User avatar
mikeyww
Posts: 27191
Joined: 09 Sep 2014, 18:38

Re: You have to reload the script to make it work... (does not work the first time)

07 Sep 2021, 14:12

Yes, labels can be stacked if needed.

Regarding the SetTimer label,
if not a valid label name, this parameter can be the name of a function, or a single variable reference containing a function object.
My own habit is to use subroutines instead of functions when I do not need local variables, do not have parameters, and do not return a value-- but in many cases, it does not really matter which you pick.
wetware05
Posts: 750
Joined: 04 Dec 2020, 16:09

Re: You have to reload the script to make it work... (does not work the first time)

08 Sep 2021, 16:31

I have finished this small utility. I intercluded the arrest of the application before making the mouse drag (line 26), which is activated on line 33 so that copying is more effective. Now almost 100% of the time it does it successfully (I gave me problems sometimes, that's why I added that extra lines).

I added an activated and deactivated button on the function. When it is activated, the glue window does not come out. To return it to Active, you have to go to the F6 key and the window will be released to activate the function again.

It looks like this:

Image

Sorry to Mikeyww, for having altered his script. I was complicated to adjust the buttons if I did not do it in my own way.

The function of activating and deactivating a button is from SKAN, and is on this page: https://autohotkey.com/board/topic/80584-how-to-simulate-a-graphical-button-in-a-gui/

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
;#Persistent
CoordMode, Mouse, Screen

Gui, -Caption
Gui, Color, EEAA99
Gui, Margin, 12, 12
Gui, Add, Button, x1 y1 w64 h15                      , Exit
Gui, Add, Button, x1 y17 w64 h65 hwndIcon gButtonLabel
Gui, Add, Picture, x66 y0 w12 h81 E0x200 vState0 icon1 gSubRoutine1, PauseOn.png
Gui, Add, Picture, x66 y0 w14 h83 Border vState1 icon1 gSubRoutine1, PauseOff.png
GuiButtonIcon(Icon, "clipboard.ico", 1, "s90")
GoSub, Toggle_Switch

*F6::
MouseGetPos, xpos1, ypos1
Gui, Show, x%xpos1% y%ypos1% W81 h84
Return

~LButton::start := A_TickCount
~LButton Up::
If (A_TickCount - start < 1200)
  Return
MouseGetPos,,, WinUMID
MouseGetPos, xpos1, ypos1
Gui, Show, x%xpos1% y%ypos1% W79 h87
Return

ButtonLabel:
Gui, Submit
WinActivate, ahk_id %WinUMID%
last := Clipboard, Clipboard := ""
Send ^c
ClipWait, 0
If ErrorLevel {
 MsgBox, 48, Error, An error occurred while waiting for the clipboard.
 Return
} Else If (Clipboard = last) {
 SoundPlay, ambiguity2.mp3
 TrayTip, Clipboard Message, REPEATED CLIPBOARD!, 0x2, 0x10, 0x20
} Else {
 SoundPlay, Clipboard_Sound.mp3
 TrayTip, Clipboard Message, %Clipboard%, 0x1, 0x10, 0x20
}
SetTimer, HideTrayTip, -1500
Return

GuiEscape:
GuiClose:
ButtonExit:
Gui, Hide
Return

Toggle_Switch:
If Toggle=0
  {
   GuiControl, Hide, State0
   GuiControl, Show, State1
   Toggle=1
  }
Else {
   GuiControl, Hide, State1
   GuiControl, Show, State0
   Toggle=0
  }
Return

SubRoutine1:
GoSub,Toggle_Switch
If Toggle=0
{
Hotkey, LButton Up, on
Return
}
If Toggle=1
{
Hotkey, LButton Up, off
Return
}

HideTrayTip:
TrayTip
Return

GuiButtonIcon(Handle, File, Index := 1, Options := "")
{
	RegExMatch(Options, "i)w\K\d+", W), (W="") ? W := 16 :
	RegExMatch(Options, "i)h\K\d+", H), (H="") ? H := 16 :
	RegExMatch(Options, "i)s\K\d+", S), S ? W := H := S :
	RegExMatch(Options, "i)l\K\d+", L), (L="") ? L := 0 :
	RegExMatch(Options, "i)t\K\d+", T), (T="") ? T := 0 :
	RegExMatch(Options, "i)r\K\d+", R), (R="") ? R := 0 :
	RegExMatch(Options, "i)b\K\d+", B), (B="") ? B := 0 :
	RegExMatch(Options, "i)a\K\d+", A), (A="") ? A := 4 :
	Psz := A_PtrSize = "" ? 4 : A_PtrSize, DW := "UInt", Ptr := A_PtrSize = "" ? DW : "Ptr"
	VarSetCapacity( button_il, 20 + Psz, 0 )
	NumPut( normal_il := DllCall( "ImageList_Create", DW, W, DW, H, DW, 0x21, DW, 1, DW, 1 ), button_il, 0, Ptr )	; Width & Height
	NumPut( L, button_il, 0 + Psz, DW )		; Left Margin
	NumPut( T, button_il, 4 + Psz, DW )		; Top Margin
	NumPut( R, button_il, 8 + Psz, DW )		; Right Margin
	NumPut( B, button_il, 12 + Psz, DW )	; Bottom Margin	
	NumPut( A, button_il, 16 + Psz, DW )	; Alignment
	SendMessage, BCM_SETIMAGELIST := 5634, 0, &button_il,, AHK_ID %Handle%
	return IL_Add( normal_il, File, Index )
}
If you are in Windows Explorer and you keep the left button pressed something more than one second, you copy the long path of the file, with this "file:///d:/utilities/autohotkey/scripts/multiclipboard preview/2.AHK clipboard button ", I had not devised that possibility, but it is an extra.

All the necessary files can be downloaded from here: https://mega.nz/file/VN5hkSgA#CYeLfUKZMZjBTrEmDG3Xiy5ROZ2cAMMAUAfXO7zecvc

I have made a small modification to make it more evident, with two colors of buttons (green and red). :lol:
New version: https://mega.nz/file/hIpmiaoZ#hHpC-Mcrb3LQxjPkXDRFxZ0mxXIEUVBAQOt5oilOJ8U

They have a small problem or complication. When it starts, the button variable is zero, which supposedly deactivates the function, but it is not like that. I do not know how to fix it.
Right now I'm tired to think. That function calls a routine that at the same time calls another, to see his status. Perhaps some more logical and with a more orderly mind solutions. Or I think about it tomorrow with more traquility. (The solution for now is to try what state it is and ambia it if it is not the desired, it can be done by calling the GUI with F6.)


Next day, more rested and solved. You had to swap the vState variable from the first button to the second, and change the state switch in the subroutine, named "SubRroutine1"

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], l6908lay and 93 guests