Jump to content

Help on using DLLs and creating a function _WinAPI_GetTitleBarRect (help & collaborate) - (Moved)


Go to solution Solved by Nine,

Recommended Posts

Hello more experienced people! Forgive me if this is not the correct forum to post this in. I am looking into DLLs to get more practice with them, and maybe find a way to solve a small issue I'm having. I am in NO WAY anything more than a novice when it comes to coding in general (I have like 2 months of experience). I've had all of today's experience with DLLS. That said, I've set out to make a function that will return the rectangle to a window's title bar. This is the C++ syntax from the MSDN reference: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-gettitlebarinfo

BOOL GetTitleBarInfo(
  [in]      HWND          hwnd,
  [in, out] PTITLEBARINFO pti
);

This is the code I started with. I'm uncertain of the proper function building format as it pertains to AutoIt, so forgive my liberty in doing so:

#Include <StructureConstants.au3>

Func _WinAPI_GetTitleBarRect( $hWnd)
    Local $tRECT = DllStructCreate( $tagRECT)
    Local $aCall = DllCall( "user32.dll", "bool", "GetTitleBarInfo", "hwnd", $hWnd, "ptr*", $pTITLEBARINFO)
    If @error Or Not $aCall[0] Then Return SetError( @error, @extended, 0)

    Return $tRECT
EndFunc   ;==>_WinAPI_GetTitleBarRect

The MSDN reference says in parameter 2, that I need a pointer to a 'TITLEBARINFO structure', the member 'cbSize' must be set to the size of 'TITLEBARINFO' whatever that means... https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-titlebarinfo The C++ syntax here is:

typedef struct tagTITLEBARINFO {
  DWORD cbSize;
  RECT  rcTitleBar;
  DWORD rgstate[CCHILDREN_TITLEBAR + 1];
} TITLEBARINFO, *PTITLEBARINFO, *LPTITLEBARINFO;

So using the reference, I did:

#Include <StructureConstants.au3>
Global Const $tagTITLEBARINFO = "struct;dword cbSize;rect rcTitleBar;dword rgstate[6];endstruct"

Func _WinAPI_GetTitleBarRect( $hWnd)
    Local $tRECT = DllStructCreate( $tagRECT)
    
    Local $tTITLEBARINFO = DllStructCreate( $tagTITLEBARINFO)
    Local $iTITLEBARINFO = DllStructGetSize( $tTITLEBARINFO)
    DLLStructSetData( $tTITLEBARINFO, "cbSize", $iTITLEBARINFO)
    Local $pTITLEBARINFO = DllStructGetPtr( $tTITLEBARINFO)
    
    Local $aCall = DllCall( "user32.dll", "bool", "GetTitleBarInfo", "hwnd", $hWnd, "ptr*", $pTITLEBARINFO)
    If @error Or Not $aCall[0] Then Return SetError( @error, @extended, 0)

    Return $tRECT
EndFunc   ;==>_WinAPI_GetTitleBarRect

So now I have 2 structures. One ready to receive a rectangle, and the other ready to receive title bar information... I think. I really have no idea what I'm doing, also I'm starting to think that what I'm trying to do just isn't possible. Anyway, finally, here is the test code that I'm running with now:

#Include <StructureConstants.au3>
Global Const $tagTITLEBARINFO = "struct;dword cbSize;rect rcTitleBar;dword rgstate[6];endstruct"

$hWndStay = WinGetHandle( "[CLASS:CabinetWClass]")

$tagTitleRECT = _WinAPI_GetTitleBarRect( $hWndStay)
If @error Then
    ConsoleWrite( "Error " & @TAB & "( " & @error & ", " & @extended & ", " & $tagTitleRECT & ")" & @CRLF)
Else
    ConsoleWrite( "Left" & @TAB & @TAB & DllStructGetData( $tagTitleRECT, "Left") & @CRLF)
    ConsoleWrite( "Right" & @TAB & @TAB & DllStructGetData( $tagTitleRECT, "Right") & @CRLF)
    ConsoleWrite( "Top" & @TAB & @TAB & DllStructGetData( $tagTitleRECT, "Top") & @CRLF)
    ConsoleWrite( "Bottom" & @TAB & DllStructGetData( $tagTitleRECT, "Bottom") & @CRLF)
EndIf

Func _WinAPI_GetTitleBarRect( $hWnd)
    Local $tRECT = DllStructCreate( $tagRECT)
    If @error Then Return SetError( @error, @extended, 0)
    Local $tTITLEBARINFO = DllStructCreate( $tagTITLEBARINFO)
    If @error Then Return SetError( @error, @extended, -1)
    Local $iTITLEBARINFO = DllStructGetSize( $tTITLEBARINFO)
    If @error Then Return SetError( @error, @extended, -2)
    DLLStructSetData( $tTITLEBARINFO, "cbSize", $iTITLEBARINFO)
    If @error Then Return SetError( @error, @extended, -3)
    Local $pTITLEBARINFO = DllStructGetPtr( $tTITLEBARINFO)
    If @error Then Return SetError( @error, @extended, -4)
    Local $aCall = DllCall( "user32.dll", "bool", "GetTitleBarInfo", "hwnd", $hWnd, "ptr*", $pTITLEBARINFO)
    If @error Or Not $aCall[0] Then Return SetError( @error, @extended, -5)

    Return $aCall
EndFunc   ;==>_WinAPI_GetTitleBarRect

I'm getting error ( 2, 0, -1) which means 'There is an unknown Data Type in the string passed.' It's probably that ';rect rcTitleBar;' I thought it was suspect to begin with. I'm also unsure of that rgstate[6] one that I derived from the constants defined by windows. Namely the [CCHILDREN_TITLEBAR+1], CCHILDREN_TITLEBAR = 5 apparently..

If you are going to run my test code, make sure to have FileExplorer open, as I was using that as an example title bar to grab.

Like I said, I have no idea what I'm doing, but if someone does know what to do, I'd appreciate being taken along this function building exercise, so as to learn how to correct the issue, and gain sovereignty in being able to do these things :)

P.S. I know of another roundabout way to get the title bar rectangle using client and window rectangles, but it'll be unreliable as some windows have their title bar within the client rectangle, which is where my little problem originated. I've since updated my working project to go around having to get the title bar size, but getting title bar size is still something I really want to do, as my next milestone requires knowing the title bar size. So for those of you who like having tough problems to try to fix, I imagine this could be one! No issue if this is impossible, I might just start trying to learn C++ :D

TL:DR I'm trying to get the title bar size of any given window, I'm new to DLLs. I'm trying to reference MSDN and I'm failing at it.

Edited by D3fr0s7
Clarification
Link to post
Share on other sites
  • Moderators

Moved to the appropriate forum.

Moderation Team

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites
  • Solution

Try this :

#include <Array.au3>
#include <WinAPIDiag.au3>

$hWnd = WinGetHandle("[CLASS:CabinetWClass]")
ConsoleWrite($hWnd & @CRLF)

Global Const $tagTITLEBARINFO = "dword cbsize;long Left;long Top;long Right;long Bottom;dword rgstate[6];"

Local $tTitleBarInfo = DllStructCreate($tagTITLEBARINFO)
$tTitleBarInfo.cbsize = DllStructGetSize($tTitleBarInfo)

Local $aRet = DllCall("user32.dll", "bool", "GetTitleBarInfo", "hwnd", $hWnd, "struct*", $tTitleBarInfo)
ConsoleWrite(@error & @CRLF)
_ArrayDisplay($aRet)
_WinAPI_DisplayStruct($tTitleBarInfo, $tagTITLEBARINFO)

 

Link to post
Share on other sites

Thank you for your response @Nine! That did the trick! That solved the reason for opening this thread. 

Sadly it didn't solve the problem I was having... The height of the rectangle it returned wasn't representative of the title bar size as it returned the same thing as the windows constant $SM_CYCAPTION.. It is really looking like there is absolutely no way of getting the title bar height of a given non-AutoIt window. Thanks for your help with the DLL though! I appreciate it

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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...