Using a delay (w3_setTimeOut) with Visual Control Application - smart-mobile-studio

Using Smart Mobile Studio 2.2.0.4165 (Beta)
I am not sure if I am doing this right, and It may be that I just don't understand how to use the w3_TimeOut callback properly.
The following code locks up when i click the start button. My start button is stuck in the down position, and the program locks up. When I close the program, I then get an "External Exception". I have to restart SMS to do anything more. What have I done wrong?
procedure TForm1.StartClick(Sender: TObject);
var
i: integer;
begin
//initialize variable
fRunning:= true;
repeat
//get a random light (1-4) and add to array
fLights.Add(RandomInt(4)+1);
//step through lights array and light up each light
for i:= 0 to fLights.Count-1 do
begin
LightUp(fLights[i]);
//add a delay after each
w3_setTimeOut( procedure ()
begin
//shut down light
LightDwn(fLights[i]);
end, 200);
end; //for
until not fRunning;
end;
procedure TForm1.StopClick(Sender: TObject);
begin
//reset variable
fRunning:= false;
//clear all lights in array
fLights.Clear;
end;
I even tried
w3_callback( procedure ()
begin
LightDwn(fLights[i]);
end, 200);
If I do not use the delay, and instead, kinda delay it with a show message, it works exactly as I need it too (of course, I can't use the show messages though )
procedure TForm1.StartClick(Sender: TObject);
var
i: integer;
begin
//initialize variable
fRunning:= true;
repeat
//get a random light (1-4) and add to array
fLights.Add(RandomInt(4)+1);
//step through lights array and light up each light
for i:= 0 to fLights.Count-1 do
begin
LightUp(fLights[i]);
ShowMessage('Up: ' + intToStr(fLights[i]));
LightDwn(fLights[i]);
ShowMessage('Down: ' + intToStr(fLights[i]));
end; //for
until not fRunning;
end;
A simple test shows me that the the w3_TimeOut is not a blocking routine
e.g.
procedure TForm1.W3Button1Click(Sender: TObject);
var
I: Integer;
begin
for I:= 1 to 99 do
begin
w3_setTimeOut( procedure ()
begin
//shut down light
W3Label1.Caption:= IntToStr(I);
end, 1000);
end;
The label does not get updated until after the loop has completed
I even tried refreshing the form and the label
w3_setTimeOut( procedure ()
begin
//shut down light
W3Label1.Caption:= IntToStr(I);
W3Label1.Invalidate;
//self.Invalidate;
end, 1000);
But, I do not think i am even doing that properly
after some searching, I found the TW3EventRepeater in the SmartCL.Time.
However, it seems that it works exactly like both the w3_setTimeOut and w3_callback
How do i do a wait() after some code, then when the wait expires, do some more code. it must be a blocking wait?
thanx
ANSWER:
fTimer:= TW3Timer.Create;
fTimer.Delay:= 1000;
fTimer.OnTime:= HandleTimer;
fTimer.Enabled:= True;

JavaScript is single-threaded, therefore timers are only triggered when your program is not doing anything. Therefore, your event is never called as your program is waiting indefinitely in the repeat..until loop inside StartClick.
You should rewrite your program so that:
Clicking a button sets a timer.
Everyhing else is executed inside the timer event.

Related

AutoHotKey not finding image on a window

I recently discovered AutoHotKey, this scripting language seemed to be amazing !
Unfortunately, I can't manage to make my script find an image on a window (BlueStacks in my case).
Can someone please help me, my script is :
CoordMode, Pixel, screen
CoordMode, Mouse, screen
*ESC::ExitApp
ImgFound := false
while(ImgFound = false)
{
ImageSearch, ButtonX, ButtonY, 0, 0, A_ScreenWidth, A_ScreenHeight, *50 C:\Users\...\Documents\...\test.png
if (ErrorLevel = 2)
{
MsgBox Could not execute script.
ExitApp
}
else if (ErrorLevel = 1)
{
ImgFound := false
}
else
{
MsgBox Found.
click, %ButtonX%, %ButtonY%
ImgFound := true
}
}
Your while loop is unreachable code.
The code execution stops when the first hotkey label is encountered. This is called the Auto-execute Section.
Move your hotkey definition to be at the very bottom.
(All hotkeys always defined by hotkeys labels get always created regardless of being in the auto-execute section or not)

Multiple occurence of web notification

I want to show a web notification to the user if they left the page open for 10 seconds. I have already taken the notification permission.
Problem here is the notification occurs multiple times even if the user comes back to the page in less than 10 secs. Already use clearTimeout for flushing myVar value....but no luck.....any help!
var myVar;
window.onblur = function myFunction() {
myVar = setTimeout(function () {
var notification = new Notification("XXX page is open in background ");
}, 10000);
clearTimeout(myVar);
};
want to make in such a way that only if user goes out of the page multiple times the notification will trigger everytime....but if he comes back to the page it will not appear..
Well, it could be due to testing. You must realize that window.onblur is triggered each time you leave the page. So if you leave, enter, leave, enter, leave, you will get 3 popups; each event runs independantly.
What you should do is call clearTimeout() in your window.onfocus event; don't forget to clear your myVar variable in both your popup handling code and your onfocus event (and test for it being null or not).

Auto Clicker for AHK that clicks and holds down control, only while i press F9

I need a script in AHK that auto-clicks and holds down the control key at the same time for a software that I am using. I would love to be able to bind that action to like F9
I have found scripts that auto click, but they are toggles and I don't know how to add the function of holding down control at the same time.
This is a bit more compact. Note that this is also setup for using ctrl+F9 because once control is held down, F9 won't turn off the autoclicking since it thinks you're pressing ctrl+F9. It will click wherever your mouse is, but you can add coordinates if you want to click in a specific location. I put a sleep in there for 50ms, but modify to suit your needs.
f9::
^f9::
Send , % ( bT := !bT ) ? "{ctrl down}" : ""
While( bT )
{
Click ; Clicks wherever your mouse is. Add coordinates if you need a specific pos.
Sleep , 50
}
Send , {ctrl up}
Return
q::
auto = true
send, {CONTROL DOWN}
while(auto){
mouseclick, left, "X-Cord","Y-Cord"
if GetKeyState(q)
auto =true
}
send, {CONTROL UP}
return
As you cant run 2 commands at the literal same time this should work.
If you wanted to be more precise depending on what your using it for,
this would be better:
q::
x := ;place your desired coordinates in these two variables.
y :=
f1::
{
mousegetpos, start_x, start_y
auto = true
send, {CONTROL DOWN}
while(auto){
mouseclick, left, %x%, %y%, 1, 0
if GetKeyState(q)
auto =true
}
send, {CONTROL UP}
mousemove, %start_x%, %start_y%, 0
}
return
This will get your cursor position, move cursor to point as fast as possible, hold control down, left click, let go of control, return to original position.
Use 'q' to start and terminate

I'm looking for a solution for a loop with a array of images

so what i'm trying to do is to change the images that's stored in a array that contains 16 imgs, it's basically a animation for when you play a game (press forward character moves[moving imgs], release button character stops[stoped img]). The thing is that after the array reaches it's length max and the key is still being pressed it needs to reset the array to 15 (so this loop will give the illusion of the constant movement), but i think i'm not finding the right synthax or something.
Thanks in advance.
PImage p1;
PImage[] zeroArray = new PImage [16];
void setup() {
size(600,600);
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
}
}
void draw() {
background(255);
imageMode(CENTER);
if(keyPressed) {
i++;
} else if (i > zeroArray.length) {
zeroArray[] = zeroArray[15]; // <--this ain't right, how should i declare this??
}
image(zeroArray[i], 300, 300, 800, 800);
}
I think you're mixing a few ideas into one if statement. Let's take a look at this section of your code:
if(keyPressed){
i++;
}
else if (i > zeroArray.length){
zeroArray[] = zeroArray[15];
}
Run through this line-by-line and really think about what it's doing. If a key is pressed, it increments the i variable. If a key is not pressed, then it checks whether i is greater than the length of the zeroArray array variable. If it is, it attempts to reset the array, which is not valid syntax.
Take a step back and think about what you're trying to do. Forget about code for a second. Write down exactly what you're trying to do, in English. My guess is you're trying to do something like this:
Change the image being drawn whenever the key is pressed.
If we reach the end of the images, then start over at the first image.
When you have something like that written out, that's an algorithm that you can start thinking about implementing with code. Break your problem down into smaller steps and take those steps on one at a time.
For example, step 1 is to change the image whenver the key is pressed. You basically have that already:
if(keyPressed){
i++;
}
Then, step 1 is to reset the i variable whenever it reaches the end of the array. You might do that using an if statement like this:
if(i >= zeroArray.length){
i = 0;
}
Putting it all together, it would look like this:
if(keyPressed){
i++;
if(i >= zeroArray.length){
i = 0;
}
}
Now this code checks if a key is being pressed, and if so it increments the i variable. It then checks whether the i variable has gone past the end of the array, and if so it reset it back to the beginning.
If that's not exactly what you're looking for, then the process of solving your problem is still the same: you need to write down, in English, exactly what you're trying to do. You need to do that before you start hammering away at the code.
Are you sure you want to reset the array to 15? That's the last element. However, in general, the solution would be to change the line:
zeroArray[] = zeroArray[15];} // <--this ain't right, how should i declare this??
to
i = 15; //Just change the index pointer to 15 (or whichever frame you want to reset to)
Thank you all for the answers, they really gave me some light.
To Kevin Workman.
Writing down the path that i intended to take really helped out, your thinking was almost on point. Using your method i came up with this
1)Change character sprites if key is being pressed
2) Reset movement to a certain point in case it exceeded the animation sprites, and the key is still being pressed
3)Set to fist sprite if the key is released or not being pressed at all
To Sahil Jain
You were right about changing the index to [15], it didn't work so well
Here is the revised code:
PImage p1;
PImage[] zeroArray = new PImage [16];
void setup(){
size(600,600);
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
}
}
void draw(){
background(255);
imageMode(CENTER);
if (keyCode == RIGHT){
if(keyPressed){
i++;
} else {
i = 0;
}
if (i >= zeroArray.length){
i = 4;}
image(zeroArray[i], 300, 300, 800, 800);
}
}
Have you tried switching your else if to your main argument in the last If...Then statement? Also, don't forget to reset your variable i to 0 so it resets too and doesn't continue to always try to reset and end up in an infinite loop of sorts :)
As it is in your code in the question, it does the increment first and will never follow through to read into the second choice (the one you want it to do).

AutoHotkey - Perform action based on clicked menu item

I looked around the AHK forums, google, and here on stack overflow and could not find any method for pulling this off, so thanks BIG TIME in advance if you can figure this one out. I am using notepad in my examples, but I'm writing this script for a complicated Point Of Sale program.
I want to do something almost exactly like this, but using the application menus as described below instead of a button.
I would like to have a script that performs an action if a certain menu item is clicked. It does not matter whether that is determined by menu position, label or otherwise. Cursor position, however, is probably not viable for my needs.
A simple example of this would be to open a MsgBox when File-Open is selected with the mouse in notepad.
I have implemented a few techniques that enabled me to pull variables out of most control objects following a left click (buttons, drop-down menus, etc), but when I use the application menu (for example, in notepad: file-save or file-open) It returns a blank string. For example:
#z::
MouseGetPos,,,,Ctrl,2
ControlGetText, Text,,ahk_id %Ctrl%
MouseClick, left
Sleep 2500
MsgBox, %Text%
(Note that I used windows-z so as to not return a MsgBox after every left-click.)
Will return 'cancel' if the cancel button was pressed in the 'file-save as' dialogue of notepad, but returns nothing if I activate it while selecting anything from the application menus (file, edit, format, etc.)
I know that these menus are accessible to AHK, as you can do the following do activate 'File-Save' from the notepad menu:
WinMenuSelectItem, Untitled - Notepad,File,Save
But when I use window spy, I see the objects behind the menu, rather than strings that are actually in the menu.
Are these menus actually separate windows that I need to switch to active to read? Or am I trying to do something impossible?
Big thanks in advance, this is something that's been driving me crazy!
Menus are not that easy to get info from, at least not with autohotkeys built-in commands, you will need to use DllCall's to get the info you need.
I have made you an example that works with notepad for me on win7 64b
What i did in the example is look for notepad run it if its not there then get the ID (hWnd) of the notepad window
When you press ctrl + LButton a DllCall to GetMenu using the ID of the notepad window is used to get a menu handle.
After that more DllCall's are used to get things like GetMenuItemCount, GetSubMenu and GetMenuItemInfo.
What this does is it lets us loop over the menu items one by one and getting info about them, in this example we're getting the state of the items, specifically the highlight state.
When an item is found that has the highlight state the script stores the indexs of the item and breaks the loops.
As this is only an example all it does is display a string message with the index numbers and sends a LButton press
Example:
ifWinNotExist, ahk_class Notepad
{
Run, notepad.exe
WinWait, ahk_class Notepad
}
WinGet, hWnd, ID,
^Lbutton::
hMenu :=DllCall("GetMenu", "Uint", hWnd)
loop % (count := DllCall("GetMenuItemCount", "ptr", hMenu))
{
menu_index := A_index
; Note that menu item positions are zero-based.
hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", (A_index-1))
; Set the capacity of mii to sizeof(MENUITEMINFO)
VarSetCapacity(mii, A_PtrSize=8 ? (Size:=80) : (Size:=48), 0)
; Set the cbSize field to sizeof(MENUITEMINFO)
NumPut(Size, mii, 0)
; Set the mask to whatever you want to retrieve.
; In this case I set it to MIIM_STATE=1.
NumPut(1, mii, 4)
loop % (subCount := DllCall("GetMenuItemCount", "ptr", hSubMenu))
{
Sub_index := A_index
; Note that menu item positions are zero-based.
DllCall("GetMenuItemInfo", "UInt", hSubMenu, "UInt", (A_index-1), "UInt", 1, "UInt", &mii)
; Get the state field out of the struct.
fState := NumGet(mii, 12)
if (fState & 0x80) ; 0x80 MFS_HILITE | 0x8 MFS_CHECKED
{
MenuString := "Found in top #" menu_index " Sub pos #" Sub_index
break 2
}
}
}
if (MenuString)
{
Tooltip % MenuString
}
else
{
tooltip no menu item highlighted
}
send {Lbutton}
return
I hope that helps you get an idea of what is needed to do what your trying to do, other possible DllCalls to Look at are MenuItemFromPoint, GetMenuString.
This can take time to get right, but with the Dllcalls i have shown in this example, I hope that you can find other examples of how to use them with autohotkey on the forums.
This AutoHotkey script should do what you require.
It has been tested on Notepad (Windows 7), and should be readily adaptable to other programs that use the standard context menus still used in the vast majority of software. Although many programs use custom menu bars, the context menus are often still standard context menus.
I have provided two scripts, one will show a ToolTip and block triggering a menu item, whenever any menu item is pressed, which is useful for understanding and for diagnostic purposes.
The second script will show a ToolTip and block triggering any menu item if its text string starts with 'Open'.
Note: the text of the Notepad menu item is
Open... Ctrl+O (Open...[tab]Ctrl+O) and not simply 'Open'.
-
;==================================================
;tested on Notepad (Windows 7)
;block any clicks on any menu items when notepad is the active window
;note: to bypass this and click an item anyway, use ctrl+click
;note: requires Acc.ahk library in AutoHotkey\Lib folder
;https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/Libraries/Acc.ahk
;on right of screen right-click Raw, Save target as...
#IfWinActive, ahk_class Notepad
;LButton::
CoordMode, Mouse, Screen
MouseGetPos, , , hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
SendInput {LButton Down}
KeyWait, LButton
MouseGetPos, vPosX, vPosY, hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
ControlSend, Dummy, {Click, 0, 0}, ahk_class Notepad
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
SendInput {LButton Up}
Return
#IfWinActive
;==================================================
;tested on Notepad (Windows 7)
;block any clicks on the 'open' menu item when notepad is the active window
;note: to bypass this and click an item anyway, use ctrl+click
;note: requires Acc.ahk library in AutoHotkey\Lib folder
;https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/Libraries/Acc.ahk
;on right of screen right-click Raw, Save target as...
#IfWinActive, ahk_class Notepad
LButton::
CoordMode, Mouse, Screen
MouseGetPos, , , hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
vItemText := ""
oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
Loop, % oAcc.accChildCount
if (oAcc.accState(A_Index) & 0x80) ;MF_HILITE := 0x80
if (1, vItemText := oAcc.accName(A_Index))
break
if (SubStr(vItemText, 1, 4) = "Open")
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
}
SendInput {LButton Down}
KeyWait, LButton
MouseGetPos, vPosX, vPosY, hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
ControlSend, Dummy, {Click, 0, 0}, ahk_class Notepad
vItemText := ""
oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
Loop, % oAcc.accChildCount
if (oAcc.accState(A_Index) & 0x80) ;MF_HILITE := 0x80
if (1, vItemText := oAcc.accName(A_Index))
break
if (SubStr(vItemText, 1, 4) = "Open")
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
}
SendInput {LButton Up}
Return
#IfWinActive
;==================================================
Note:
The code samples posted in the two links below, achieve related goals.
Is it possible to catch the close button and minimize the window instead? AutoHotKey
AutoHotKey: Run code on Window Event (Close)
Note:
The function JEE_MenuIsActive, link below, can be used to check whether
the menu bar/sysmenu bar is active
in order to distinguish title bar menus from right-click context menus.
GUI COMMANDS: COMPLETE RETHINK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=25893