Sign in to follow this  
Followers 0
marc0v

Mouse cursor changing when using Run() function

7 posts in this topic

Hi,

I've an autoit script that starts other autoit scripts

(or an autoit exe starting other autoit exe in the compiled version)

I would like the mouse cursor NOT to go in its 'start application' state

when starting these new scripts/exe

(usually the small hourglass, or the Vista blue circle, under the arrow)

I'm using the built-in function :

Run ( "filename" [, "workingdir" [, flag[, standard_i/o_flag]]] )

(I'm still with AutoIt 3.2.0.1 at the moment)

Maybe a Windows dll is able to start a process without the cursor changing ?

Also I need to know the PID of the started process, and if an error occured

(like with the Run function)

I seems possible since I sometimes see applications starting in the background

without the cursor changing... (under WinXP SP3)

Thanks for any help.

Share this post


Link to post
Share on other sites



I think you can use workaround:

Change system (hourglass) cursor for arrow for a while.

Look at

Func _SetStdCursor($i_idc_cursor, $i_cursor)
   Local $newhcurs, $lResult
   $newhcurs = DllCall("user32.dll", "hwnd", "LoadCursor", "hwnd", 0, 'int', $i_idc_cursor)
   If Not @error Then
      $lResult = DllCall("user32.dll", "int", "SetSystemCursor", "int", $newhcurs[0], "int", $i_cursor)
      If @error Then
         MsgBox(0, "Error", "Failed SetSystemCursor")
      EndIf
   Else
      MsgBox(0, "Error", "Failed LoadCursor")
   EndIf
EndFunc;==>_SetStdCursor

Original post is here:

http://www.autoitscript.com/forum/index.php?showtopic=45073&view=findpost&p=335882

Share this post


Link to post
Share on other sites

...

Thank you, since I'm a workarounder I should have thought of this solution...

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

(Post Edited)

I've unexpected behavior with LoadCursor and SetSystemCursor, however I can do what I want

with LoadCursorFromFile but I rely on the cursors files (to be found in the current theme in the registry)

I'll look the forum for SetSystemCursor usage...

The code that doesn't work...

AutoItSetOption("MustDeclareVars", 1)

Global Const $HUSER32DLL = DllOpen("user32.dll")

Global Const $I_IDC_ARROW = 32512
Global Const $I_IDC_IBEAM = 32513

Local $hCurBeam, $result

$hCurBeam = DllCall($HUSER32DLL, "hwnd", "LoadCursor", "hwnd", 0, 'int', $I_IDC_IBEAM)

$result = DllCall($HUSER32DLL, "int", "SetSystemCursor", "int", $hCurBeam[0], "int", $I_IDC_ARROW)

MsgBox(0, "", "beam and arrow are SWAPPED")
; whereas the arrow was just expected to show as a beam, not the beam as an arrow

$result = DllCall($HUSER32DLL, "int", "SetSystemCursor", "int", $hCurBeam[0], "int", $I_IDC_ARROW)

MsgBox(0, "", "beam and arrow are restored, swapped again ?")

DllClose($HUSER32DLL)

The code that works but full path to cursors files is needed

AutoItSetOption("MustDeclareVars", 1)

Global Const $HUSER32DLL = DllOpen("user32.dll")
Global Const $I_IDC_ARROW = 32512

Local $arrowfile, $beamfile

$arrowfile = "full_path_to_your_arrow.cur"
$beamfile = "full_path_to_your_beam.cur"

SETSTDCURSOR($I_IDC_ARROW, $arrowfile, $beamfile)

Func SETSTDCURSOR($target_cursor, $file_normal, $file_change)
    Local $hcursor, $dllerror

    $hcursor = DllCall($HUSER32DLL, "hwnd", "LoadCursorFromFile", "str", $file_change)
    If @Error <> 0 Then Return

    DllCall($HUSER32DLL, "int", "SetSystemCursor", "int", $hcursor[0], "int", $target_cursor)
    If @Error <> 0 Then Return

    MsgBox(0, "", "arrow changed to beam, beam is unchanged")

    $hcursor = DllCall($HUSER32DLL, "hwnd", "LoadCursorFromFile", "str", $file_normal)
    If @Error <> 0 Then Return

    DllCall($HUSER32DLL, "int", "SetSystemCursor", "int", $hcursor[0], "int", $target_cursor)
    If @Error <> 0 Then Return

    MsgBox(0, "", "arrow restored")
EndFunc
Edited by marc0v

Share this post


Link to post
Share on other sites

Here is example from WinAPIEx UDF

#Include <WinAPIEx.au3>

Global $hCursor, $hPrev = _WinAPI_DuplicateCursor(_WinAPI_LoadCursor(0, 32512)) ; IDC_ARROW

$hCursor = _WinAPI_DuplicateCursor(_WinAPI_LoadCursor(_WinAPI_GetModuleHandle(@SystemDir & '\shell32.dll'), 1004))
_WinAPI_SetSystemCursor($hCursor, 32512) ; OCR_NORMAL
Sleep(5000)
_WinAPI_SetSystemCursor($hPrev, 32512)

Share this post


Link to post
Share on other sites

Zedna

$hCursor = _WinAPI_DuplicateCursor(_WinAPI_LoadCursor(_WinAPI_GetModuleHandle(@SystemDir & '\shell32.dll'), 1004))

The problem is, I did not want to rely on a static file because the user can set any cursor as his 'arrow' and 'app start' cursors

And I wanted do avoid reading the cursors files in the registry and create a handle from these files

So, I tried to load from memory these two cursors, overwrite the 'app start' with the 'arrow', and, when done, restore the 'app start' to normal

After some test I managed to do it, but it is NOT a good idea because if two applications do this at the same moment

the second one will load from memory an 'app start' that has been changed into an 'arrow' and won't be able to restore the 'app start' cursor

So I'll keep my solution which is (with appropriate error checking)

Global Const $I_IDC_ARROW       = 32512
Global Const $I_IDC_APPSTARTING = 32650

; read current theme cursors in registry
$sArrowFile = RegRead("HKEY_CURRENT_USER\Control Panel\Cursors", "Arrow")
$sAppStartFile = RegRead("HKEY_CURRENT_USER\Control Panel\Cursors", "AppStarting")

; create two handles, $hArrowCur[0] & $hAppStartCur[0]
$hArrowCur = DllCall("user32.dll", "hwnd", "LoadCursorFromFile", "str", $sArrowFile)
$hAppStartCur= DllCall("user32.dll", "hwnd", "LoadCursorFromFile", "str", $sAppStartFile)

; change 'app start' cursor to an 'arrow'
DllCall("user32.dll", "int", "SetSystemCursor", "int", $hArrowCur[0], "int", $I_IDC_APPSTARTING)

; Run something, and wait ~150ms, here you have a msgbox instead
msgbox(0, "No more 'app start' cursor", "run something to see...")

; restore 'app start' cursor to normal
DllCall("user32.dll", "int", "SetSystemCursor", "int", $hAppStartCur[0], "int", $I_IDC_APPSTARTING)

; finished
msgbox(0, "Back to normal", "restored.")

Since the solution without handles from file works, UNLESS there is collision between two applications doing that,

I also give it (so don't use it :D)

story is over I think, thanks for the help

#Include <WinAPIEx.au3>
Global Const $I_IDC_ARROW       = 32512
Global Const $I_IDC_APPSTARTING = 32650

$hArr = _WinAPI_DuplicateCursor(_WinAPI_LoadCursor(0, $I_IDC_ARROW))
$hStart = _WinAPI_DuplicateCursor(_WinAPI_LoadCursor(0, $I_IDC_APPSTARTING))

_WinAPI_SetSystemCursor($hArr, $I_IDC_APPSTARTING)
MsgBox(0, "No more 'app start' cursor", _
"Start a program to see that the cursor" & @CR & _
"doesn't get into his 'app start' state..." & @CR & _
"(The 'busy' state is still showed, as expected)" & @CR & @CR & _
"DON'T START ANOTHER INSTANCE OF THIS SCRIPT" & @CR & _
"until you've closed this msgbox otherwise you'll loose" & @CR & _
"your 'app start' cursor (until reloaded from a file)" & @CR & @CR & _
"(you can log off or edit the code at the end to get it back)")

_WinAPI_SetSystemCursor($hStart, $I_IDC_APPSTARTING)
MsgBox(0, "Back to normal", "restored.")

; restore your app start cursor from file
;$hStart = DllCall("user32.dll", "hwnd", "LoadCursorFromFile", "str", "the_path_to_your_cursor_file_here")
;DllCall("user32.dll", "int", "SetSystemCursor", "int", $hStart[0], "int", $I_IDC_APPSTARTING)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0