Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Get the position of the text cursor (Caret)!

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1522

PostPosted: Mon Oct 14, 2024 9:06 pm    Post subject: Get the position of the text cursor (Caret)! Reply with quote

I tried this in many ways but the result always remained with the "LuaJIT" or "ffi" module.

Below is a sample code, it needs to print the position of the blinking cursor (caret) in the Windows window but I did not get the correct result.

User32.dll Caret:
Code:
<DllImport("user32.dll", ExactSpelling:=True)> _
Public Shared Function GetCaretPos(<Out> ByRef pt As Point) As BOOL
End Function


User32.dll POINT:
Code:
<Serializable, StructLayout(LayoutKind.Sequential), TypeConverter(GetType(PointConverter)), ComVisible(True)> _
Public Structure Point
    Public Shared ReadOnly Empty As Point
    Private x As Integer
    Private y As Integer
    Public Sub New(ByVal x As Integer, ByVal y As Integer)
        Me.x = x
        Me.y = y
    End Sub

    Public Sub New(ByVal sz As Size)
        Me.x = sz.Width
        Me.y = sz.Height
    End Sub

    Public Sub New(ByVal dw As Integer)
        Me.x = CShort(Point.LOWORD(dw))
        Me.y = CShort(Point.HIWORD(dw))
    End Sub

    <Browsable(False)> _
    Public ReadOnly Property IsEmpty As Boolean
        Get
            Return ((Me.x = 0) AndAlso (Me.y = 0))
        End Get
    End Property

    Public Property X As Integer
        Get
            Return Me.x
        End Get
        Set(ByVal value As Integer)
            Me.x = value
        End Set
    End Property

    Public Property Y As Integer
        Get
            Return Me.y
        End Get
        Set(ByVal value As Integer)
            Me.y = value
        End Set
    End Property

    Public Shared Widening Operator CType(ByVal p As Point) As PointF
        Return New PointF(CSng(p.X), CSng(p.Y))
    End Operator

    Public Shared Narrowing Operator CType(ByVal p As Point) As Size
        Return New Size(p.X, p.Y)
    End Operator

    Public Shared Operator +(ByVal pt As Point, ByVal sz As Size) As Point
        Return Point.Add(pt, sz)
    End Operator

    Public Shared Operator -(ByVal pt As Point, ByVal sz As Size) As Point
        Return Point.Subtract(pt, sz)
    End Operator

    Public Shared Operator =(ByVal left As Point, ByVal right As Point) As Boolean
        Return ((left.X = right.X) AndAlso (left.Y = right.Y))
    End Operator

    Public Shared Operator <>(ByVal left As Point, ByVal right As Point) As Boolean
        Return Not (left = right)
    End Operator

    Public Shared Function Add(ByVal pt As Point, ByVal sz As Size) As Point
        Return New Point((pt.X + sz.Width), (pt.Y + sz.Height))
    End Function

    Public Shared Function Subtract(ByVal pt As Point, ByVal sz As Size) As Point
        Return New Point((pt.X - sz.Width), (pt.Y - sz.Height))
    End Function

    Public Shared Function Ceiling(ByVal value As PointF) As Point
        Return New Point(CInt(Math.Ceiling(CDbl(value.X))), CInt(Math.Ceiling(CDbl(value.Y))))
    End Function

    Public Shared Function Truncate(ByVal value As PointF) As Point
        Return New Point(CInt(value.X), CInt(value.Y))
    End Function

    Public Shared Function Round(ByVal value As PointF) As Point
        Return New Point(CInt(Math.Round(CDbl(value.X))), CInt(Math.Round(CDbl(value.Y))))
    End Function

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        If Not TypeOf obj Is Point Then
            Return False
        End If
        Dim point As Point = DirectCast(obj, Point)
        Return ((point.X = Me.X) AndAlso (point.Y = Me.Y))
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return (Me.x Xor Me.y)
    End Function

    Public Sub Offset(ByVal dx As Integer, ByVal dy As Integer)
        Me.X = (Me.X + dx)
        Me.Y = (Me.Y + dy)
    End Sub

    Public Sub Offset(ByVal p As Point)
        Me.Offset(p.X, p.Y)
    End Sub

    Public Overrides Function ToString() As String
        Dim textArray1 As String() = New String() { "{X=", Me.X.ToString(CultureInfo.CurrentCulture), ",Y=", Me.Y.ToString(CultureInfo.CurrentCulture), "}" }
        Return String.Concat(textArray1)
    End Function

    Private Shared Function HIWORD(ByVal n As Integer) As Integer
        Return ((n >> &H10) And &HFFFF)
    End Function

    Private Shared Function LOWORD(ByVal n As Integer) As Integer
        Return (n And &HFFFF)
    End Function

    Shared Sub New()
    End Sub
End Structure


Code:
function GetCaretPos()
    local point = { x = 0, y = 0 }
    local result = executeCodeLocalEx("user32.GetCaretPos", point) -- nil
                    -- executeCodeLocalEx("user32.GetCaretPos", "") -- 1
    if result then
        return point.x, point.y
    else
        return nil, nil
    end
end

local function printCaretPosition()
    local x, y = GetCaretPos()
    if x and y then
        print(string.format("caret position: (%d, %d)", x, y))
    else
        print("Unable to get caret position")
    end
end

printCaretPosition()



As a result of my research, I learned that the "ffi" module can do this.

However, although I left the "ffi.dll" library in the "C:\Program Files\Cheat Engine 7.5\clibs64" folder, I got errors like "local ffi = require("ffi")" path not found.

My question is:
If there are multiple notebooks in a Windows window (Desktop), I want to print the blinking text cursor (Caret) in which one or its position.

Note: Please, do not suggest me to click somewhere all the time and get "getMousePos" or "getCursorPos".

I want to see the cursor's position (Position) at runtime (Write).

ChatGPT keeps telling me that the most effective method is the "ffi" module.

Code:
-- Define the necessary Windows API functions
local ffi = require("ffi")

ffi.cdef[[
typedef struct {
    int x;
    int y;
} POINT;

bool GetCaretPos(POINT* lpPoint);
]]

local user32 = ffi.load("user32.dll")

-- Function to get caret position
local function GetCaretPos()
    local point = ffi.new("POINT")
    if user32.GetCaretPos(point) then
        return point.x, point.y
    else
        return nil, nil
    end
end

-- Function to print caret position
local function printCaretPosition()
    local x, y = GetCaretPos()
    if x and y then
        print(string.format("caret position: (%d, %d)", x, y))
    else
        print("Unable to get caret position")
    end
end

-- Example usage: call printCaretPosition to print the caret position
printCaretPosition()


But if you have a workable solution, feel free to contribute to this project.
Thanks in advance.

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
xxhehe
Expert Cheater
Reputation: 0

Joined: 11 Mar 2015
Posts: 154

PostPosted: Fri Nov 15, 2024 5:40 am    Post subject: Re: Get the position of the text cursor (Caret)! Reply with quote

AylinCE wrote:
I tried this in many ways but the result always remained with the "LuaJIT" or "ffi" module.

Below is a sample code, it needs to print the position of the blinking cursor (caret) in the Windows window but I did not get the correct result.

User32.dll Caret:
Code:
<DllImport("user32.dll", ExactSpelling:=True)> _
Public Shared Function GetCaretPos(<Out> ByRef pt As Point) As BOOL
End Function


User32.dll POINT:
Code:
<Serializable, StructLayout(LayoutKind.Sequential), TypeConverter(GetType(PointConverter)), ComVisible(True)> _
Public Structure Point
    Public Shared ReadOnly Empty As Point
    Private x As Integer
    Private y As Integer
    Public Sub New(ByVal x As Integer, ByVal y As Integer)
        Me.x = x
        Me.y = y
    End Sub

    Public Sub New(ByVal sz As Size)
        Me.x = sz.Width
        Me.y = sz.Height
    End Sub

    Public Sub New(ByVal dw As Integer)
        Me.x = CShort(Point.LOWORD(dw))
        Me.y = CShort(Point.HIWORD(dw))
    End Sub

    <Browsable(False)> _
    Public ReadOnly Property IsEmpty As Boolean
        Get
            Return ((Me.x = 0) AndAlso (Me.y = 0))
        End Get
    End Property

    Public Property X As Integer
        Get
            Return Me.x
        End Get
        Set(ByVal value As Integer)
            Me.x = value
        End Set
    End Property

    Public Property Y As Integer
        Get
            Return Me.y
        End Get
        Set(ByVal value As Integer)
            Me.y = value
        End Set
    End Property

    Public Shared Widening Operator CType(ByVal p As Point) As PointF
        Return New PointF(CSng(p.X), CSng(p.Y))
    End Operator

    Public Shared Narrowing Operator CType(ByVal p As Point) As Size
        Return New Size(p.X, p.Y)
    End Operator

    Public Shared Operator +(ByVal pt As Point, ByVal sz As Size) As Point
        Return Point.Add(pt, sz)
    End Operator

    Public Shared Operator -(ByVal pt As Point, ByVal sz As Size) As Point
        Return Point.Subtract(pt, sz)
    End Operator

    Public Shared Operator =(ByVal left As Point, ByVal right As Point) As Boolean
        Return ((left.X = right.X) AndAlso (left.Y = right.Y))
    End Operator

    Public Shared Operator <>(ByVal left As Point, ByVal right As Point) As Boolean
        Return Not (left = right)
    End Operator

    Public Shared Function Add(ByVal pt As Point, ByVal sz As Size) As Point
        Return New Point((pt.X + sz.Width), (pt.Y + sz.Height))
    End Function

    Public Shared Function Subtract(ByVal pt As Point, ByVal sz As Size) As Point
        Return New Point((pt.X - sz.Width), (pt.Y - sz.Height))
    End Function

    Public Shared Function Ceiling(ByVal value As PointF) As Point
        Return New Point(CInt(Math.Ceiling(CDbl(value.X))), CInt(Math.Ceiling(CDbl(value.Y))))
    End Function

    Public Shared Function Truncate(ByVal value As PointF) As Point
        Return New Point(CInt(value.X), CInt(value.Y))
    End Function

    Public Shared Function Round(ByVal value As PointF) As Point
        Return New Point(CInt(Math.Round(CDbl(value.X))), CInt(Math.Round(CDbl(value.Y))))
    End Function

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        If Not TypeOf obj Is Point Then
            Return False
        End If
        Dim point As Point = DirectCast(obj, Point)
        Return ((point.X = Me.X) AndAlso (point.Y = Me.Y))
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return (Me.x Xor Me.y)
    End Function

    Public Sub Offset(ByVal dx As Integer, ByVal dy As Integer)
        Me.X = (Me.X + dx)
        Me.Y = (Me.Y + dy)
    End Sub

    Public Sub Offset(ByVal p As Point)
        Me.Offset(p.X, p.Y)
    End Sub

    Public Overrides Function ToString() As String
        Dim textArray1 As String() = New String() { "{X=", Me.X.ToString(CultureInfo.CurrentCulture), ",Y=", Me.Y.ToString(CultureInfo.CurrentCulture), "}" }
        Return String.Concat(textArray1)
    End Function

    Private Shared Function HIWORD(ByVal n As Integer) As Integer
        Return ((n >> &H10) And &HFFFF)
    End Function

    Private Shared Function LOWORD(ByVal n As Integer) As Integer
        Return (n And &HFFFF)
    End Function

    Shared Sub New()
    End Sub
End Structure


Code:
function GetCaretPos()
    local point = { x = 0, y = 0 }
    local result = executeCodeLocalEx("user32.GetCaretPos", point) -- nil
                    -- executeCodeLocalEx("user32.GetCaretPos", "") -- 1
    if result then
        return point.x, point.y
    else
        return nil, nil
    end
end

local function printCaretPosition()
    local x, y = GetCaretPos()
    if x and y then
        print(string.format("caret position: (%d, %d)", x, y))
    else
        print("Unable to get caret position")
    end
end

printCaretPosition()



As a result of my research, I learned that the "ffi" module can do this.

However, although I left the "ffi.dll" library in the "C:\Program Files\Cheat Engine 7.5\clibs64" folder, I got errors like "local ffi = require("ffi")" path not found.

My question is:
If there are multiple notebooks in a Windows window (Desktop), I want to print the blinking text cursor (Caret) in which one or its position.

Note: Please, do not suggest me to click somewhere all the time and get "getMousePos" or "getCursorPos".

I want to see the cursor's position (Position) at runtime (Write).

ChatGPT keeps telling me that the most effective method is the "ffi" module.

Code:
-- Define the necessary Windows API functions
local ffi = require("ffi")

ffi.cdef[[
typedef struct {
    int x;
    int y;
} POINT;

bool GetCaretPos(POINT* lpPoint);
]]

local user32 = ffi.load("user32.dll")

-- Function to get caret position
local function GetCaretPos()
    local point = ffi.new("POINT")
    if user32.GetCaretPos(point) then
        return point.x, point.y
    else
        return nil, nil
    end
end

-- Function to print caret position
local function printCaretPosition()
    local x, y = GetCaretPos()
    if x and y then
        print(string.format("caret position: (%d, %d)", x, y))
    else
        print("Unable to get caret position")
    end
end

-- Example usage: call printCaretPosition to print the caret position
printCaretPosition()


But if you have a workable solution, feel free to contribute to this project.
Thanks in advance.


Write an executable in C/C++/luajit to get the position of the text caret, and then use CE's executeCode/executeCodeEx to execute it.
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1522

PostPosted: Fri Nov 15, 2024 6:26 am    Post subject: Re: Get the position of the text cursor (Caret)! Reply with quote

xxhehe wrote:


Write an executable in C/C++/luajit to get the position of the text caret, and then use CE's executeCode/executeCodeEx to execute it.


Join the project only if you have a solution.
The advice you give requires other external coding and leads to more complex coding (probably in coding languages we do not know) instead of solving the problem in the current situation.

So which one do you recommend me to specialize in?
C? C++ ? luajit ? Smile

Note: Windows' "GetCursorPos()" (Mouse) function works and produces correct results.
However, "GetCaretPos()" always returns "0" or does not work.
This is a bit strange!

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
xxhehe
Expert Cheater
Reputation: 0

Joined: 11 Mar 2015
Posts: 154

PostPosted: Fri Nov 15, 2024 7:39 am    Post subject: Re: Get the position of the text cursor (Caret)! Reply with quote

AylinCE wrote:
xxhehe wrote:


Write an executable in C/C++/luajit to get the position of the text caret, and then use CE's executeCode/executeCodeEx to execute it.


Join the project only if you have a solution.
The advice you give requires other external coding and leads to more complex coding (probably in coding languages we do not know) instead of solving the problem in the current situation.

So which one do you recommend me to specialize in?
C? C++ ? luajit ? Smile

Note: Windows' "GetCursorPos()" (Mouse) function works and produces correct results.
However, "GetCaretPos()" always returns "0" or does not work.
This is a bit strange!

I don't care about your project..As a true LUA novice, I may indeed have underestimated the difficulty of implementation.
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1522

PostPosted: Fri Nov 15, 2024 8:32 am    Post subject: Reply with quote

By "project" I only meant this question topic.

The codes I gave at the beginning of the topic have already been used and tested, but no results were obtained.

Please only participate in this topic with code examples that have yielded positive results.

Otherwise, I do not intend to drag the topic into a discussion area.

Thanks for your feedback anyway.

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 958

PostPosted: Fri Nov 15, 2024 9:40 am    Post subject: This post has 2 review(s) Reply with quote

The <Out> parameter need to provide a memory address for the function to write to (as return results)

eg.
Code:

local function GetCaretPos()
    local ms = createMemoryStream()
    ms.writeQword(0x12345678) -- just allocate 2x 4 bytes
--    print(ms.Size)
    local ok = executeCodeLocalEx("user32.GetCaretPos", ms.Memory)
    ms.Position = 0 -- reset read from start
    local x = ms.readDword()-- read in sequence
    local y = ms.readDword()-- don't x,y = ms.readDword(), ms.readDword()
    ms.Destroy()
--    print(ok, x, y)
    return x,y
end

print(GetCaretPos())


I don't know what the numbers means (in pixel? chars?), tho.

_________________
- Retarded.
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1522

PostPosted: Fri Nov 15, 2024 10:22 am    Post subject: Reply with quote

panraven wrote:
The <Out> parameter need to provide a memory address for the function to write to (as return results)

eg.
Code:

local function GetCaretPos()
    local ms = createMemoryStream()
    ms.writeQword(0x12345678) -- just allocate 2x 4 bytes
--    print(ms.Size)
    local ok = executeCodeLocalEx("user32.GetCaretPos", ms.Memory)
    ms.Position = 0 -- reset read from start
    local x = ms.readDword()-- read in sequence
    local y = ms.readDword()-- don't x,y = ms.readDword(), ms.readDword()
    ms.Destroy()
--    print(ok, x, y)
    return x,y
end

print(GetCaretPos())


I don't know what the numbers means (in pixel? chars?), tho.


Perfect working example and thanks.

You are a secret weapon! You only focus on the right targets.

Thanks.

The code you created does the following:

It does not print the caret's location on the desktop.
It only prints the current location of the caret in the material (Notepad, Lua Script etc.) that is being written.
In other words, it takes focus from the material (Notepad.Width, Notepad.Height) and tells its location in it.

When there are 3 notebooks on the desktop, it does not tell which one "Caret" is in, but actually, this is the solution I wanted.

This code will save me the trouble of calculating "Left, Top, Height, Width" to get the cursor's focus.

Note: With the "Y" parameter (by clicking on the previous and next lines) we can calculate the height of the current font.

Similarly, the "x" parameter can calculate the "Width" covered by each letter.


I don't know why you joined so late, but thanks again for your effective solution. (+1 to be returned after the time limit).

***

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
xxhehe
Expert Cheater
Reputation: 0

Joined: 11 Mar 2015
Posts: 154

PostPosted: Fri Nov 15, 2024 8:50 pm    Post subject: Reply with quote

panraven wrote:
The <Out> parameter need to provide a memory address for the function to write to (as return results)

eg.
Code:

local function GetCaretPos()
    local ms = createMemoryStream()
    ms.writeQword(0x12345678) -- just allocate 2x 4 bytes
--    print(ms.Size)
    local ok = executeCodeLocalEx("user32.GetCaretPos", ms.Memory)
    ms.Position = 0 -- reset read from start
    local x = ms.readDword()-- read in sequence
    local y = ms.readDword()-- don't x,y = ms.readDword(), ms.readDword()
    ms.Destroy()
--    print(ok, x, y)
    return x,y
end

print(GetCaretPos())


I don't know what the numbers means (in pixel? chars?), tho.



Great code. Use executeCodeLocalEx to call external programs, such as exe/dll, to implement GetCaretPos.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites