sendMessage to monthcall

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
GRUWEZ
Posts: 14
Joined: 16 Nov 2021, 10:20

sendMessage to monthcall

Post by GRUWEZ » 01 Dec 2021, 04:52

Hello Everyone,

i'm trying to select a date in a monthcal with the sendmessage cmd from AHK. Unfortunately, this is not working and i don't know where is my mistake or my misunderstanding. Anyone could help ? Here's what i already try.

Code: Select all

   ConvertNormalDateToSystemTime(YYYYMMDD)
; this return a  SystemTime format date from a normal date
{
    YYYYMMDD.=000000
    YYYYMMDDHHMISS:=YYYYMMDD
    
    
    VarSetCapacity(SystemTime, 16, 0)  ; This struct consists of 8 UShorts (i.e. 8*2=16).
    Int := SubStr(YYYYMMDDHHMISS, 1, 4)  ; YYYY (year)
    NumPut(Int, SystemTime, 0, "UShort")
    Int := SubStr(YYYYMMDDHHMISS, 5, 2)  ; MM (month of year, 1-12)
    NumPut(Int, SystemTime, 2, "UShort")
    Int := SubStr(YYYYMMDDHHMISS, 7, 2)  ; DD (day of month)
    NumPut(Int, SystemTime, 6, "UShort")
    Int := SubStr(YYYYMMDDHHMISS, 9, 2)  ; HH (hour in 24-hour time)
    NumPut(Int, SystemTime, 8, "UShort")
    Int := SubStr(YYYYMMDDHHMISS, 11, 2) ; MI (minute)
    NumPut(Int, SystemTime, 10, "UShort")
    Int := SubStr(YYYYMMDDHHMISS, 13, 2) ; SS (second)
    NumPut(Int, SystemTime, 12, "UShort")
    
    return % &SystemTime
    
}


MCM_FIRST:= 0x1000 
MCM_SETCURSEL:= MCM_FIRST + 2
MyDate:= 20211115
WinActivate ahk_class AutoHotkeyGUI, ExempleCalendrier.ahk

dateASelectionnerDansCalendrier := ConvertNormalDateToSystemTime(20211115)



try
{
            SendMessage MCM_SETCURSEL , ,  &dateASelectionnerDansCalendrier, SysMonthCal321, ahk_class AutoHotkeyGUI ; THIRD TRIAL  
            MsgBox % ErrorLevel
}
catch e
{
    MsgBox % ErrorLevel
}
        

. I already try to compile the script and run it as admin. I know that there is no multiselected option on my monthcal. Someone on Discord suggest me that MCM_SETCURSEL lparam was pointing to a systemtime. So how could i send my date to my monthcal ? Should i convert my actual date into a systemTime in an other way ? (speaking as a noob). When i run this, the external program is crashing. A debug window is comming. I tried to send the message with windowspy ++ but it says that the message is not valid (no more info). I have not the code of my external program so guicontrol is not an option.
Thanks for any help !

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: sendMessage to monthcall

Post by just me » 01 Dec 2021, 05:49

In your code SystemTime is defined as a local function variable which is cleared when the function finishes. Also, you return the address of the local variable and pass the address of the receiving variable to SendMessage.

You might try the following:

Code: Select all

   ConvertNormalDateToSystemTime(YYYYMMDD, ByRef SystemTime)
; this return a  SystemTime format date from a normal date
{
	...
}
...
ConvertNormalDateToSystemTime(20211115, dateASelectionnerDansCalendrier)
...
But since SystemTime is a structure of 16 bytes and can't be passed in a pointer sized message parameter you might need to reserve memory in the address space of the remote process.

GRUWEZ
Posts: 14
Joined: 16 Nov 2021, 10:20

Re: sendMessage to monthcall

Post by GRUWEZ » 01 Dec 2021, 17:29

Hey,
Thanks a lot for your quick answer, which is verry interesting.
If i'd like to reserve memory in the address space of the remote process, should i use smth like this comming from github ?
https://github.com/Ixiko/AHK-libs-and-classes-collection/blob/master/libs/o-z/RMO.ahk

Code: Select all

; ==================================================================================================================================
; Stores the content of a local variable into the remote memory block.
; Parameters:   LocalVar   -  Local variable
;               Offset     -  Offset within the remote memory block
;                             Default: 0
;               Size       -  Size of the local variable in bytes
;                             Default: 0 -> size of the local variable returned by VarSetCapacity()
; Return value: True, if successful; otherwise False.
; ==================================================================================================================================
RMO_Put(RMO, ByRef LocalVar, Offset := 0, Size := 0) {
   If RMO_CheckParams(RMO, Offset, Size = 0 ? (Size := VarSetCapacity(LocalVar)) : Size)
      Return DllCall("WriteProcessMemory", "Ptr", RMO.HPROC, "Ptr", RMO.Addr + Offset, "Ptr", &LocalVar, "UPtr", Size, "Ptr", 0)
   Return False
}
And so with a bit of adaptation, the function in my code would be:

Code: Select all

RMO_Put(RMO, dateASelectionnerDansCalendrier  , Offset := 0, 16)
; followed by the precedently function 
ConvertNormalDateToSystemTime(20211115, dateASelectionnerDansCalendrier)
Is this making sense or should i create an RMO object first ?

Creating an RMO object should be with smth like this ?

Code: Select all

RMO_Create(Proc, Size, CheckBitness := True) {
   ; PROCESS_QUERY_INFORMATION = 0x0400, PROCESS_VM_WRITE = 0x20, PROCESS_VM_READ = 0x10, PROCESS_VM_OPERATION = 0x8
   ; READ_WRITE_ACCESS = 0x0438, MEM_COMMIT = 0x1000, PAGE_READWRITE = 4
   Static Dummy := Func("RMO_Dummy")
   Static RMOBase := {__New: Dummy, __Delete: Func("RMO_Free"), __Get: Dummy, __Set: Dummy}
   ; If a window/control handle is passed, get the PID
   If DllCall("IsWindow", "Ptr", Proc, "UInt")
      DllCall("GetWindowThreadProcessId", "Ptr", Proc, "UIntP", Proc)
   ; Open the process for allocating/reading/writing memory.
   If !(HPROC := DllCall("OpenProcess", "UInt", 0x0438, "Int", False, "UInt", Proc, "Ptr"))
      Return False
   ; Check if both processes are running in the same 32/64-bit environment (THX, Lexikos)
   If (CheckBitness) && (A_Is64bitOS) {
      If !DllCall("IsWow64Process", "Ptr", HPROC, "UIntP", WOW64) || (WOW64 && (A_PtrSize = 8)) || (!WOW64 && (A_PtrSize = 4))
         Return (DllCall("CloseHandle", "Ptr", HPROC) & 0) ; False
   }
   ; Allocate a buffer in the (presumably) remote process.
   If !(Addr := DllCall("VirtualAllocEx", "Ptr", HPROC, "Ptr", 0, "UPtr", Size, "UInt", 0x1000, "UInt", 4, "UPtr"))
      Return False
   ; All right, return the RMO object
   Return {HPROC: HPROC, Addr: Addr, Size: Size, Get: Func("RMO_Get"), Init: Func("RMO_Init"), Put: Func("RMO_Put"), Base: RMOBase}
}


Thanks a lot for your help bc i 'm not so strong that i thought in informatics ;)

GRUWEZ
Posts: 14
Joined: 16 Nov 2021, 10:20

Re: sendMessage to monthcall

Post by GRUWEZ » 02 Dec 2021, 05:55

Or maybe juste with varsetcapacity() can be the job done ?
Thanks

Post Reply

Return to “Ask for Help (v1)”