Page 1 of 1

Help with DLLCall function (ImGui wrapper)

Posted: 25 Sep 2021, 12:12
by Noblish
Hello, i'm here because i've tried so much (1+ weeks) and I just don't understand how to pass it to DLLCall. I would really appreciate if someone explains it to me.

Code: Select all

Func _ImGui_CheckBox($text, ByRef $active)
	Local $b_active = DllStructCreate("boolean value;")
	$b_active.value = $active

	Local $result = DllCall($IMGUI_DLL, "boolean:cdecl", "Checkbox", "wstr", $text, "ptr", DllStructGetPtr($b_active))
	If @error Then Return SetError(1, 0, 0)
	$active = $b_active.value
	Return $result[0]
EndFunc
I know I have to mess with VarSetCapacity and NumGet/Numput. Or simpler, use a library…which I found some, but could not get it to work.

Btw I'm converting Imgui(c++) to ahk, it's nearly done, I'm just stuck with some functions.

It's a checkbox on Imgui, which will toggle a variable, ByRef $active refers to -> (b_show_demo_window = 1/0) (example)

Image

please help me out :)

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 03:40
by just me
Just a guess:

Code: Select all

B_Active := !!Active ; converts the contents of Active to 0/1
Result := DllCall(IMGUI_DLL . "\Checkbox", "WStr", Text, "UCharP", B_Active, "Cdecl UChar")
MsgBox, %Result% - %Active% - %B_Active%

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 09:07
by Noblish
just me wrote:
26 Sep 2021, 03:40
Just a guess:

Code: Select all

B_Active := !!Active ; converts the contents of Active to 0/1
Result := DllCall(IMGUI_DLL . "\Checkbox", "WStr", Text, "UCharP", B_Active, "Cdecl UChar")
MsgBox, %Result% - %Active% - %B_Active%
Thanks for the reply , but it doesnt work

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 09:15
by swagfag
then post the c++ function prototype

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 09:19
by Noblish
swagfag wrote:
26 Sep 2021, 09:15
then post the c++ function prototype

Code: Select all

bool ImGui::Checkbox(const char* label, bool* v)
{
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
        return false;

    ImGuiContext& g = *GImGui;
    const ImGuiStyle& style = g.Style;
    const ImGuiID id = window->GetID(label);
    const ImVec2 label_size = CalcTextSize(label, NULL, true);

    const float square_sz = GetFrameHeight();
    const ImVec2 pos = window->DC.CursorPos;
    const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
    ItemSize(total_bb, style.FramePadding.y);
    if (!ItemAdd(total_bb, id))
        return false;

    bool hovered, held;
    bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
    if (pressed)
    {
        *v = !(*v);
        MarkItemEdited(id);
    }

    const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
    RenderNavHighlight(total_bb, id);
    RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
    ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
    if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue)
    {
        // Undocumented tristate/mixed/indeterminate checkbox (#2644)
        ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
        window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
    }
    else if (*v)
    {
        const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
        RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
    }

    if (g.LogEnabled)
        LogRenderedText(&total_bb.Min, *v ? "[x]" : "[ ]");
    if (label_size.x > 0.0f)
        RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), label);

    IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
    return pressed;
}

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 09:28
by swagfag
const char* is an AStr
and what is ImGui::? a class or a namespace?
and what is the calling convention?

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 10:05
by Noblish
C++ struct:

Code: Select all

typedef checkbox {
	int value;
	} ;
Ahk struct:

Code: Select all

VarSetCapacity(struct, 4, 0)
value := NumGet(struct, 0, "Int")
NumPut(value, struct, 0, "Int")
My approach.. :

Code: Select all

    CheckBox(text, ByRef active){
        VarSetCapacity(struct, 4, 0)
        value := NumGet(struct, "Int")
 

        Result := DllCall("imgui\Checkbox", "WStr", value, "Ptr", &active, "Cdecl Int")
        active := active
        Return result
    }
I'm not sure if looking into c++ code rn is the right thing to do. I know I'm forgetting something , but I don't know what. I'm not an expert with structures or DllCall

Here my GitHub repo for this project: https://github.com/Noblishh/imguiahk

Re: Help translate a code from AutoIT to AHK

Posted: 26 Sep 2021, 10:27
by swagfag
Noblish wrote:
26 Sep 2021, 10:05
I'm not sure if looking into c++ code rn is the right thing to do.
how else would u know what DllCall types ure supposed to use?

Code: Select all

    CheckBox(text, ByRef active){
        VarSetCapacity(struct, 4, 0)
        value := NumGet(struct, "Int")
 

        Result := DllCall("imgui\Checkbox", "WStr", value, "Ptr", &active, "Cdecl Int")
        active := active
        Return result
    }
i cant even begin to imagine what u intended to write with this function.
  • text is an unused local param
  • u allocate and zero-init 4 bytes
  • u then cast that to an Int(which is of course 0)
  • u then pass that 0(value) to the WStr param(which if we assume the function prototype u showed previously is correct, should have been an AStr)
  • a Ptr-sized outparam is used for the bool*(wrong)
  • its still unclear if the calling convention is __cdecl(no dll source and no info on what project settings were used to compile it)
  • Int return type is used for a bool(wrong)
  • active := active, ????
  • based on the function prototype, its still unclear if ure trying to invoke a free function(in which case ImGUI:: will have been a namespace; possible) or an instance method(in which case ImGUI:: will have been a classname; impossible)

Re: Help with DLLCall function (ImGui wrapper)

Posted: 26 Sep 2021, 14:42
by Noblish
Main script Gui Loop:

Code: Select all

b_show_demo_window = false
;//------------------------------------------------------------------

While 1
{
    ImGui.BeginFrame()
    
    If Not ImGui.Begin("Test", True) Then Exit
    ;ImGui.ShowDemoWindow()
    If ImGui.CheckBox("Show demo window", b_show_demo_window) Then ImGui.EnableViewports(b_show_demo_window)
    
    If b_show_demo_window Then ImGui.ShowDemoWindow()
    ImGui.End()
    ImGui.EndFrame()
}
Checkbox func:

Code: Select all

    CheckBox(text, ByRef active){
                VarSetCapacity(struct, 4, 0)
        value := NumGet(struct, 0, "Int")
        
        Result := DllCall("imgui\Checkbox", "WStr", text, "Ptr", WHATtoINSERThere???, "Cdecl Int") ; "boolean:cdecl"
        Return result
    }
Yea, I know that I used *value* in the *text* zone, it meant for debug.
Bool translates to Int on AHK, you can't use *bool*.

Checkbox starts as default 0, whenever you click it turns to 1, that's how I open Other Gui's or toggle something. I just don't understand how to work out with "VarSetCapacity/NumGet/NumPut"

Re: Help with DLLCall function (ImGui wrapper)

Posted: 26 Sep 2021, 14:55
by swagfag
https://docs.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-160#sizes-of-built-in-types
no, bool is bool - ahk UChar

https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
typedef int BOOL; is int - ahk Int

Code: Select all

Result := DllCall("imgui\Checkbox", "AStr", text, "UChar*", &active, "Cdecl UChar") ; "boolean:cdecl"
whereby active is a variable with 1 or 0 already assigned to it

if that doesnt work, __cdecl may be the wrong calling convention

Re: Help with DLLCall function (ImGui wrapper)

Posted: 27 Sep 2021, 03:14
by teadrinker
Must be DllCall("imgui\Checkbox", "WStr", "My Checkbox", "UIntP", state, "Cdecl")
In the loop should look like this:

Code: Select all

currentState := newState := 1
while DllCall("imgui\PeekMsg", "Cdecl") {
   ...
   if DllCall("imgui\Checkbox", "WStr", "My Checkbox", "UIntP", newState, "Cdecl")
      currentState := newState := !currentState
   ...
}

Re: Help with DLLCall function (ImGui wrapper)

Posted: 27 Sep 2021, 12:25
by Noblish
teadrinker wrote:
27 Sep 2021, 03:14
Must be DllCall("imgui\Checkbox", "WStr", "My Checkbox", "UIntP", state, "Cdecl")
In the loop should look like this:

Code: Select all

currentState := newState := 1
while DllCall("imgui\PeekMsg", "Cdecl") {
   ...
   if DllCall("imgui\Checkbox", "WStr", "My Checkbox", "UIntP", newState, "Cdecl")
      currentState := newState := !currentState
   ...
}
Sorry, but it doesn't work, I'm out of ideas :/

Re: Help with DLLCall function (ImGui wrapper)

Posted: 27 Sep 2021, 12:53
by teadrinker

Code: Select all

if !hLib := DllCall("LoadLibrary", "Str", "imgui.dll", "Ptr")
   throw "Failed to load imgui.dll. Error: " . A_LastError

hWnd := DllCall("imgui\GUICreate", "WStr", "My Gui", "Int", 500, "Int", 400, "Int", 500, "Int", 200, "Cdecl Ptr")
WinShow, ahk_id %hWnd%

currentState := newState := 1
while DllCall("imgui\PeekMsg", "Cdecl") {
   DllCall("imgui\BeginFrame", "Cdecl")
   DllCall("imgui\Begin", "WStr", "New Window", "Int", 0, "Int", 0, "Cdecl")
   
   if DllCall("imgui\Checkbox", "WStr", " My Checkbox", "UIntP", newState, "Cdecl")
      currentState := newState := !currentState
   
   DllCall("imgui\End", "Cdecl")
   DllCall("imgui\EndFrame", "UInt", 0x004488, "Cdecl")
   Sleep, 10
}
DllCall("FreeLibrary", "Ptr", hLib)
For me it works.

Re: Help with DLLCall function (ImGui wrapper)

Posted: 27 Sep 2021, 16:18
by Noblish
teadrinker wrote:
27 Sep 2021, 12:53

Code: Select all

if !hLib := DllCall("LoadLibrary", "Str", "imgui.dll", "Ptr")
   throw "Failed to load imgui.dll. Error: " . A_LastError

hWnd := DllCall("imgui\GUICreate", "WStr", "My Gui", "Int", 500, "Int", 400, "Int", 500, "Int", 200, "Cdecl Ptr")
WinShow, ahk_id %hWnd%

currentState := newState := 1
while DllCall("imgui\PeekMsg", "Cdecl") {
   DllCall("imgui\BeginFrame", "Cdecl")
   DllCall("imgui\Begin", "WStr", "New Window", "Int", 0, "Int", 0, "Cdecl")
   
   if DllCall("imgui\Checkbox", "WStr", " My Checkbox", "UIntP", newState, "Cdecl")
      currentState := newState := !currentState
   
   DllCall("imgui\End", "Cdecl")
   DllCall("imgui\EndFrame", "UInt", 0x004488, "Cdecl")
   Sleep, 10
}
DllCall("FreeLibrary", "Ptr", hLib)
For me it works.
Thanks man, appreciate.

Could you tell me why this function doesn't work ? I'm trying directing calling it

Code: Select all

   CheckBox(text){
        currentState := newState := 0
        if DllCall("imgui\Checkbox", "WStr", text, "UIntP", newState, "Cdecl")
            currentState := newState := !currentState
    }

Re: Help with DLLCall function (ImGui wrapper)

Posted: 27 Sep 2021, 16:59
by teadrinker
Noblish wrote: why this function doesn't work ?
It doesn't make any sense. imgui::Checkbox can only work in the way I provided.

Re: Help with DLLCall function (ImGui wrapper)  Topic is solved

Posted: 27 Sep 2021, 17:48
by teadrinker
This variant will work:

Code: Select all

if !hLib := DllCall("LoadLibrary", "Str", "imgui.dll", "Ptr")
   throw "Failed to load imgui.dll. Error: " . A_LastError

hWnd := DllCall("imgui\GUICreate", "WStr", "My Gui", "Int", 500, "Int", 400, "Int", 500, "Int", 200, "Cdecl Ptr")
WinShow, ahk_id %hWnd%

while DllCall("imgui\PeekMsg", "Cdecl") {
   DllCall("imgui\BeginFrame", "Cdecl")
   DllCall("imgui\Begin", "WStr", "New Window", "Int", 0, "Int", 0, "Cdecl")
   
   state1 := Checkbox(" My Checkbox", 0)
   state2 := Checkbox(" Another Checkbox", 1)
   
   DllCall("imgui\End", "Cdecl")
   DllCall("imgui\EndFrame", "UInt", 0x004488, "Cdecl")
   Sleep, 10
}
DllCall("FreeLibrary", "Ptr", hLib)

Checkbox(text, initialState := 0) {
   static state := {}
   if !state.HasKey(text)
      state[text] := [initialState, initialState]
   s := state[text]
   if DllCall("imgui\Checkbox", "WStr", text, "UIntP", s[1], "Cdecl")
      s[1] := s[2] := !s[2]
   Return s[1]
}

Re: Help with DLLCall function (ImGui wrapper)

Posted: 28 Sep 2021, 08:44
by Noblish
teadrinker wrote:
27 Sep 2021, 17:48
This variant will work:

Code: Select all

if !hLib := DllCall("LoadLibrary", "Str", "imgui.dll", "Ptr")
   throw "Failed to load imgui.dll. Error: " . A_LastError

hWnd := DllCall("imgui\GUICreate", "WStr", "My Gui", "Int", 500, "Int", 400, "Int", 500, "Int", 200, "Cdecl Ptr")
WinShow, ahk_id %hWnd%

while DllCall("imgui\PeekMsg", "Cdecl") {
   DllCall("imgui\BeginFrame", "Cdecl")
   DllCall("imgui\Begin", "WStr", "New Window", "Int", 0, "Int", 0, "Cdecl")
   
   state1 := Checkbox(" My Checkbox", 0)
   state2 := Checkbox(" Another Checkbox", 1)
   
   DllCall("imgui\End", "Cdecl")
   DllCall("imgui\EndFrame", "UInt", 0x004488, "Cdecl")
   Sleep, 10
}
DllCall("FreeLibrary", "Ptr", hLib)

Checkbox(text, initialState := 0) {
   static state := {}
   if !state.HasKey(text)
      state[text] := [initialState, initialState]
   s := state[text]
   if DllCall("imgui\Checkbox", "WStr", text, "UIntP", s[1], "Cdecl")
      s[1] := s[2] := !s[2]
   Return s[1]
}
Thank you really much for your idea, works perfectly!
Do you know why we can't close the GUI? Whenever I press the X button nothing happens, it doesn't go to the End() func. If I need to stop the loop, how I do so?

Re: Help with DLLCall function (ImGui wrapper)

Posted: 28 Sep 2021, 09:21
by teadrinker
For me my code breaks the loop. When I press the close button on GUI, DllCall("imgui\PeekMsg", "Cdecl") returns 0 and the cycle breaks, and the script terminates. Are you sure you launch my code as it is?

Re: Help with DLLCall function (ImGui wrapper)

Posted: 29 Sep 2021, 11:52
by Noblish
teadrinker wrote:
28 Sep 2021, 09:21
For me my code breaks the loop. When I press the close button on GUI, DllCall("imgui\PeekMsg", "Cdecl") returns 0 and the cycle breaks, and the script terminates. Are you sure you launch my code as it is?
Yes it breaks the loop, but i mean click on the X on imgui, not ahk gui. Also , im not drawing with the gui. I could also just hide it , but the correct way is just to break the drawing loop and quit the current gui. im not sure if the error is coming from ImGui.Begin or ImGui.GUICreate. Or if i simply need to make some if states

Re: Help with DLLCall function (ImGui wrapper)

Posted: 29 Sep 2021, 13:16
by teadrinker
Noblish wrote: i mean click on the X on imgui, not ahk gui. Also , im not drawing with the gui.
I'm not sure I understand what you mean. GUI in my code is created by imgui, there is not any AHK GUI.
If you showed your code it would make things clearer.