Jump to content

DllCall, SetTimer, WM_TIMER and GUIRegisterMsg


Recommended Posts

Hi

I'm having two problems with the code below:

1.) According to the online MSDN documentation of SetTimer the parameter "uElapse" is of type UINT. However, when I pass that value to DllCall as an "uint" parameter DllCall will fail. If I pass it as "int" it works. Is this a problem with the MSDN documentation or with DllCall?

2.) According to the same documentation, if a WM_TIMER message is received, the wParam parameter/value should contain the value of nIDEvent (in my example: 50). However, if you run the code you can see, that is does not contain that value! Is this again a problem of the online documentation or something with GuiRegisterMsg??

Tested with 3.2.0.1!

#include <GUIConstants.au3>

Global Const $WM_TIMER = 0x0113
Global $nID = 50
Global $msg, $retval

Global $gui = GUICreate("test")
GUISetState ()
GUIRegisterMsg($WM_TIMER,"_TimerFunc")

$retval = DLLCall("user32.dll","int_ptr","SetTimer","hwnd",$gui,"int_ptr",$nID,"int",2000,"ptr",0)  ; <<== THIS WORKS
;$retval = DLLCall("user32.dll","int_ptr","SetTimer","hwnd",$gui,"int_ptr",$nID,"uint",2000,"ptr",0); <<== here ERROR
if @error then _error("DllCall failed")

do
until GUIGetMsg() = $GUI_EVENT_CLOSE

$retval = DLLCall("user32.dll","int","KillTimer","hwnd",$gui,"int_ptr",$nID)

Func _TimerFunc($hWndGUI, $MsgID, $WParam, $LParam)
    MsgBox(0,"TIMER","MsgID : " & $MsgID & " wParam: " & $WParam & " lParam: " & $LParam)
EndFunc

Func _error($msg)
    MsgBox(0,"ERROR", $msg)
    exit
EndFunc

Thanks

Kurt

Edited by /dev/null

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

I think this is what you want:

$retval = DllCall("User32.dll", "int", "SetTimer", "hwnd", $GUI, "int", $nID, "int", 2000, "int", 0)
PaulIA,

interesting... Using "int" instead of "int_ptr" for nIDEvent, solves half of the problem (although MSDN suggests to use UINT_PTR). Now, wParam contains the value of Event ID (nIDEvent).

However, the "problem" with DllCall is still there if I use "uint" instead of "int" for uElapse. Any idea if this is a documentation error in MSDN or a problem with DllCall? Looking at the defintion in the file winuser.h (Dev-C++) show the same definition for SetTimer

WINUSERAPI UINT WINAPI SetTimer(HWND,UINT,UINT,TIMERPROC);

So, I'm still not sure if this is a problem with DllCall or something else.

EDIT: Dumb error. There is simply NO "uint" for DllCall. I mistook the parameters of DllStructCreate and DllCall...

Thanks

Kurt

Edited by /dev/null

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

If you use the beta uint should work. I did a coherency matching between dllcall param and dllstructcreate ones. ;)

AutoIT "crashes" when I use "uint" with 3.2.1.13.

>Running:(3.2.1.13):C:\Program Files\AutoIt3\beta\autoit3.exe "C:\temp\autoit\37318.au3"

!>AutoIT3.exe ended.rc:-1073741819

>Exit code: -1073741819 Time: 3.945

Test Code:

#include <GUIConstants.au3>

MsgBox(0,"",@AutoItVersion)

Global Const $WM_TIMER = 0x0113
Global $nID = 50
Global $msg, $retval

Global $gui = GUICreate("test")
GUISetState ()
GUIRegisterMsg($WM_TIMER,"_TimerFunc")

$retval = DLLCall("user32.dll","uint","SetTimer","hwnd",$gui,"uint",$nID,"uint",2000,"ptr",0); <<== here ERROR
if @error then _error("DllCall failed")

do
until GUIGetMsg() = $GUI_EVENT_CLOSE

$retval = DLLCall("user32.dll","int","KillTimer","hwnd",$gui,"int_ptr",$nID)

Func _TimerFunc($hWndGUI, $MsgID, $WParam, $LParam)
    MsgBox(0,"TIMER","MsgID : " & $MsgID & " wParam: " & $WParam & " lParam: " & $LParam)
EndFunc

Func _error($msg)
    MsgBox(0,"ERROR", $msg)
    exit
EndFunc
[autoit]

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

After replyng I did a test a found the same thing.

But I don't know how to correct.

the Problem come from a bad conversion of a uint to an int64.

I need Valik assistance

case tuint:
                *pvTemp = CastToInt64<unsigned __int32>(lparg->uintVal);
;)
Link to comment
Share on other sites

After replyng I did a test a found the same thing.

But I don't know how to correct.

the Problem come from a bad conversion of a uint to an int64.

I need Valik assistance

case tuint:
                *pvTemp = CastToInt64<unsigned __int32>(lparg->uintVal);
;)
why is it cast to int64?? In DllStructCreate there is "uint" AND "uint64". Maybe just replace CastToInt64 with CastToInt ??

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

UINT_PTR SetTimer(    

    HWND hWnd,
    UINT_PTR nIDEvent,
    UINT uElapse,
    TIMERPROC lpTimerFunc
);

How come you are not using the "int_ptr" or does exist "uint_ptr" ?

Lar.

using a "*_ptr" is wrong here anyway. Seems to be a bug in the MSDN documentation. If you pass in a pointer, later in the "callback" function for WM_TIMER, wParam will contain the address of the variable and not its value, so you cannot check if the timer that was triggered is the correct one. That was my first "error" ...

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

Well, it can't be cast to 32-bit because AutoIt doesn't store things unsigned internally. That means an unsigned number will be turned int a signed number. However, by storing it in a 64-bit number, quite obvious the sign bit isn't touched.

As to why it crashes, that's a very good question.

Link to comment
Share on other sites

why is it cast to int64?? In DllStructCreate there is "uint" AND "uint64". Maybe just replace CastToInt64 with CastToInt ??

Cheers

Kurt

It is the process of returning the value, so it is intended to not loose precision if the leftmost bit is one as 0x80000000. not to confuse with negative number so a conversion to 64bit integer is done.
Link to comment
Share on other sites

It is the process of returning the value, so it is intended to not loose precision if the leftmost bit is one as 0x80000000. not to confuse with negative number so a conversion to 64bit integer is done.

O.K. I see...

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

By the way, regarding UINT_PTR, DO NOT MAKE ASSUMPTIONS. UINT_PTR is NOT unsigned int *. It's either a 64-bit or 32-bit unsigned int. The <TYPE>_PTR types are used when you need to be 64-bit compatible since the correctly sized type will be chosen by the compiler depending on whether the application is being built as 32-bit or 64-bit.

Link to comment
Share on other sites

As to why it crashes, that's a very good question.

O.K., do I have to open a bug report, or are looking anyway??

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

No, it's fixed already.

Nice! What has been the problem?

Thanks

Kurt

Edited by /dev/null

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

CastToInt64() expects an address but JP was giving it a variable, not the address of the variable.

JP, I've fixed the uint/ushort code in DllCall(). I also added a comment near CastToInt64() mentioning that the parameter must be an address. If you know of any other places where you used a variable instead of the address of that variable with a call to CastToInt64(), please change accordingly.

Link to comment
Share on other sites

CastToInt64() expects an address but JP was giving it a variable, not the address of the variable.

JP, I've fixed the uint/ushort code in DllCall(). I also added a comment near CastToInt64() mentioning that the parameter must be an address. If you know of any other places where you used a variable instead of the address of that variable with a call to CastToInt64(), please change accordingly.

Thanks Valik, ;)

I have to admit that the casting in not my cup of tea ...

Link to comment
Share on other sites

By the way, regarding UINT_PTR, DO NOT MAKE ASSUMPTIONS. UINT_PTR is NOT unsigned int *. It's either a 64-bit or 32-bit unsigned int. The <TYPE>_PTR types are used when you need to be 64-bit compatible since the correctly sized type will be chosen by the compiler depending on whether the application is being built as 32-bit or 64-bit.

Is it intended if you as for a Int_ptr, on return the variable contain the int value. Same for short_ptr.

That a difference with DLLStruct at least in thr way to pass and retrieve value.

Link to comment
Share on other sites

I don't understand what your concern is. Example?

Func _ProcessGetExitCode($h_Process)
    Local $aRet = DllCall("kernel32.dll", "int", "GetExitCodeProcess", "hwnd", $h_Process, "long_ptr", 0)
    If @error Then Return SetError(@error, @extended, 0x7FFFFFFF)
    SetExtended($aRet[0])
    Return $aRet[2]
EndFunc   ;==>_ProcessGetExitCode

I retrieve this code which look a little bit strange for returning in a "long_ptr" which is not defined. Very different from dllStruct... which really need to a real pointer pointing to a long.

I understand my confusion. I was thinking the variable was set. It is better that the return is done in the array return by DllCall.

Forget about my silly remark. I didn't understand that the value pointed by an internal allocated pointer was returned.

perhaps the doc is not too clear on this special mechanism. ;)

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...