Jump to content

DllCalls Win API and AutoIt standards, measurements and internals


AXLE
 Share

Recommended Posts

Hello to all  =)

I am currently creating some Functions UDFs and examples using DllCall and other methods that interact with MS C runtime and Windows API.

Many of the MSDN documents can be a little ambiguous and more so when converting to an AutoIt3 context, so for correctness or when I can't find conformation from within the forum or other documentation I would like to ask a number of questions with regards to the above topic. Even though some questions may not appear to relate to the same topic, they are all related to the same set of UDFs I am creating.

The main purpose of the Function library is exemplify the use of Dll Calls from within AutoIt3 for other users and obviously a good learning and practice exercise for myself. Some Functions may resemble functions already supplied within the UDF library, and is purely a mater of process and coincidence to have arrived at a similar place. Where a UDF function already exists I will provide an example of the same method using the standard UDF , as the standard AutoIt UDFs will be more appropriate for most Users.

The second purpose is to extend some of the current UDFs relating to AutoIt/Windows Dialog Metrics and Device Context. Although this is intended mostly for my own purposes It will offer a reasonable context for DllCall examples and hopefully a few additional functions that others may benefit from.

Before posting any code or examples I would like to ensure that I am using the correct AutoIt and Win API measurements and methods so I will begin with those questions.

(Mods, I would like to keep future code examples at the top of this thread, but if that is not convenient I can begin another thread. Basic layout top to bottom 1. Code examples with explanations  2.Standards, Measurements and Metrics 3.Questions and general discussions)

For members who may feel that I am an unknown quantity, I am a very happy, easy going person and always approachable for questions or suggestions =)

I do have a lot going on in the background most days between indentured study, Software Dev Startup, assisting local students with fundamental coding and robotics, time with my family etc.

So If I don't reply to a question straight away, its just that I am busy elsewhere with other commitments.

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

My first question relates to Windows ANSI and WIDE functions, although any Windows API function applies. ( Example: SendMessage(), SendMessageA(), SendMessageW() )

SendMessage appears to be a 'Legacy' Function from early windows and in 'Compiled C code' would translate to SendMessageA/W according to to compile time definitions. In most instances in AutoIt3 I would be inclined to use SendMessageW() as this would appear to be  native to both AutoIt and Win API ( UCS-2 ).

AuoIt DllCall Help states "By default, AutoIt tries to use the ANSI version of a function name, i.e. MessageBoxA is attempted when MessageBox is given as the function name. To call the unicode version use MessageBoxW." This is confirmed if I use SendMessage() in DllCall().

Many of the UDF functions that I have looked at use the non-specific function name for a Win API function (ie. _SendMessage() ). From the above help file I may have expected this to translate to SendMessageA(), but the reverse is true.

My Question is, If creating  Functions for a UDF using 'DllCall', Should I use:

_MyWinAPIFunctionW() where DllCall translates to the Win API WinAPIFunctionW()

_MyWinAPIFunctionA() where DllCall translates to the Win API WinAPIFunctionA() and

_MyWinAPIFunction() where DllCall translates to the Win API WinAPIFunctionA() unless otherwise selected from within _MyWinAPIFunction() or

The Current UDF method:

_MyWinAPIFunction() where DllCall translates to the Win API WinAPIFunctionW() unless otherwise selected from within _MyWinAPIFunction()

 

I would be inclined to follow the first three naming examples, what do you think?

P.S. I am often working between C, Win-API and AutoIt code which will become confusing for me if I begin reversing naming conventions.

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

Hello. 

I think the better way to go is  using UNICODE all time, at least you use a custom dll that does not support unicode.

So you will end with functions like this:

_MyWinAPIFunction() where DllCall translates to the Win API WinAPIFunctionW()

 

Saludos

 

Link to comment
Share on other sites

Thanks Danyfirex, I appreciate the input =)

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

Hi, I was looking at the StringFormat() Funct https://www.autoitscript.com/autoit3/docs/functions/StringFormat.htm

And all of the examples are PrintFormat()

Is this a 'Typo' and meaning StringFormat(), or is there an undocumented PrintFormat() for Console?

AXLE

P.S.

The definition at the top is 'printf()' group, the examples are 'sprintf' using PrintFormat() as the Func Name.

Edited by AXLE
Additional information

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

  • Moderators

AXLE,

PrintFormat is a function at the end of the example script which deals with the actual printing of the formatted string to the console.

M23

Edited by Melba23
Corrected English!

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 comment
Share on other sites

Hi Melba23, I can't find any reference to PrintFormat anywhere. Is this an undocumented Func, or where is meant to be used?

P.S. Thanks for the fast reply

AXLE

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

8 minutes ago, AXLE said:

I can't find any reference to PrintFormat anywhere.

You need to read what he wrote more carefully. Plus you need to LOOK at the example script you're talking about, the function PrintFormat  is in the script.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • Moderators

AXLE,

This is the StringFormat example script from the Help file:

Example()

Func Example()
    Local $iInt_Unsigned = 43951789
    Local $iInt_Negative = -43951789

    ConsoleWrite(@CRLF & "Numeric Formats" & @CRLF)

    PrintFormat($iInt_Unsigned, "%d", "standard positive integer with no sign", 1) ; 43951789
    PrintFormat($iInt_Negative, "%d", "standard negative integer with sign", 1) ; -43951789
    PrintFormat($iInt_Unsigned, "%i", "standard integer", 1) ; 43951789
    PrintFormat($iInt_Unsigned, "%09i", "9 digits with leading zero", 1) ; 043951789
    PrintFormat($iInt_Unsigned, "%e", "scientific notation") ; 4.395179e+007
    PrintFormat($iInt_Unsigned, "%u", "unsigned integer with positive integer", 1) ; 43951789
    PrintFormat($iInt_Negative, "%u", "unsigned integer with negative integer", 1) ; 4251015507
    PrintFormat($iInt_Unsigned, "%f", "floating point") ; 43951789.000000
    PrintFormat($iInt_Unsigned, "%.2f", "floating point with 2 digits after decimal point", 1) ; 43951789.00
    PrintFormat($iInt_Unsigned, "%o", "octal", 1) ; 247523255
    PrintFormat($iInt_Unsigned, "%s", "string", 1) ; 43951789
    PrintFormat($iInt_Unsigned, "%x", "hexadecimal (lower-case)", 1) ; 29ea6ad
    PrintFormat($iInt_Unsigned, "%X", "hexadecimal (upper-case)", 1) ; 29EA6AD
    PrintFormat($iInt_Unsigned, "%+d", "sign specifier on a positive integer", 1) ; +43951789
    PrintFormat($iInt_Negative, "%+d", "sign specifier on a negative integer", 1) ; -43951789

    Local $sString = "string"
    Local $sString_Long = "longstring"

    ConsoleWrite(@CRLF & "String Formats - [ ] used to show beginning/end of string" & @CRLF)

    PrintFormat($sString, "[%s]", "standard string", 1) ; [string]
    PrintFormat($sString, "[%10s]", "10 chars right justified with added spaces") ; [    string]
    PrintFormat($sString, "[%-10s]", "10 chars left justified with added spaces") ; [string    ]
    PrintFormat($sString_Long, "[%10.8s]", "right justified but precision 8 so truncated") ; [  longer s]
    PrintFormat($sString_Long, "[%-10.8s]", "left justifed but precision 8 so truncated") ; [longer s  ]
    PrintFormat($sString, "[%010s]", "10 chars with leading zero") ; [0000string]

    ConsoleWrite(@CRLF & "Date Format - each % uses a new parameter" & @CRLF)
    ConsoleWrite('"%02i\%02i\%04i" 0n (1, 9, 2013) => ' & StringFormat("%02i\%02i\%04i", 1, 9, 2013) & @CRLF)

    ConsoleWrite(@CRLF & "Just string to format  without Vars" & @CRLF)
    ConsoleWrite('"Some \texample text\n" => ' & StringFormat('Some \texample text\n'))
EndFunc   ;==>Example

Func PrintFormat($vVar, $sFormat, $sExplan, $iTab = 0)
    ConsoleWrite('"' & $sFormat & '" on ' & $vVar & @TAB & ' => ' & StringFormat($sFormat, $vVar))
    If $iTab Then ConsoleWrite(@TAB)
    ConsoleWrite(@TAB & " ; " & $sExplan & @CRLF)
EndFunc   ;==>PrintFormat

Scroll to the bottom of the code and you will see this line:

Func PrintFormat($vVar, $sFormat, $sExplan, $iTab = 0)

THAT is where you find the function - as I said above:

Quote

PrintFormat is a function at the end of the example script

Clear now? If not, may I suggest a trip to the opticians?

M23

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 comment
Share on other sites

No need to be rude, I just don't understand what PrintFormat() is. And yes now I see the additional Func.. So my appologies..

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

  • Moderators

AXLE,

I was not being rude - merely trying (and obviously failing) to add a little levity to my response. I am tempted to do so again, but as you appear to be in snowflake mode I will desist*.

M23

* I just could not resist.....:P

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 comment
Share on other sites

Sorry I read so much code and documentation between Au and C and WinAPI it sends my eyes and head blurry :)

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

Trying to nut out the returns for GetCharABCWidthsFloatW maybe it's time for sleep lol.

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

  • Moderators

AXLE,

No problem - we have all been there.

M23

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 comment
Share on other sites

Yes I know, I stumbled over your footsteps a fair bit along the way so far ;) If I cont to hit my head on the wall I will post what I have and you can dice me up for lunch :D

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

OK, got GetCharABCWidthsFloatW sorted(ish) Getting return 95 pixel wide 1lead,93font,1trail on default 'W' font at size 72pts @(96)100%. <-means nothing but screen ruler says yes =)

aka A=1,B=93,C=1 and screen rule says yes. Small win for me:) I'll tidy it up and get a demo up when my eyes aren't falling out of my head.

 

Alpha Demo of GetCharABCWidthsFloatW

The following is a barely functional demo of GetCharABCWidthsFloatW. At current I am only retrieving the 'Advance Width' for a single Font.

The Func is nowhere near complete, and I have a long way to go with it yet. It has twisted my brain over the last two days before finally getting a win. I want to put it up for comments and guidance with regards to the $tagABCFLOAT_ALT, the pointer to $tABCFLOAT in GetCharABCWidthsFloatW and the correct use of the pointer for the return values from the structure. I have encountered numerous segfaults whist trying to get pointers to tABCFLOAT to 'Play Nice', so Please proceed with caution. The $cChar, $iFirst and $iLast must be the same character or segfault is pretty much guaranteed. If you want to change the font, change all Three.

Some forum members have had extensive experience with many similar functions and I welcome any constructive guidance.

;****************************************************************************************
;* AutoIt Version : 3.3.14.1                                                            *
;* App Title .....: GetCharABCWidthsFloatW Func Demo                                    *
;* App Version ...: 0.0.0.1 Alpha (11/01/2019) xx:xxpm                                  *
;* Author ........: AXLE                                                                *
;* WWW ...........:                                                                     *
;* Email .........:                                                                     *
;* Description:-                                                                        *
;* Alpha demonstration of the basic functionalty of GetCharABCWidthsFloatW to retrieve  *
;* the Width and cursor 'Advance Width' for any font (Incomplete)                       *
;*                                                                                      *
;* This Function is incomplete!!!!                                                      *
;*                                                                                      *
;* Provided as is. Use at your own risk.                                                *
;****************************************************************************************
;* TODO:                                                                                *
;* Too much to list.                                                                    *
;*                                                                                      *
;* Debug and test                                                                       *
;****************************************************************************************

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIGdiDC.au3>

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

Global Const $cChar = "W"
Global Const $iFontSize = 72 ; Set Font size for demo tests (If this value is changed then also $iFirst & $iLast must match)
;Global Const $iFirst = 87 ; 'A' == Dec 65 | 'g' == Dec 103 | 'W' == Dec 87 | '|' == Dec 124
;Global Const $iLast = 87 ;==> Comment out Local defines to use Globals
GUIMain()

Func GUIMain()
    Local $hGui = GUICreate("Winows Metrics Examples", 600, 400) ;Measurments in pixels
    GUISetState(@SW_SHOW, $hGui)

    Local $idLabel1 = GUICtrlCreateLabel($cChar, 10, 40, 150, 130) ; Shift off the window canvas. Prob not neccesary.
    ;'A' == Dec 65 | 'g' == Dec 103 | 'W' == Dec 87 | '|' == Dec 124
    GUICtrlSetFont($idLabel1, $iFontSize) ;72
    GUICtrlSetBkColor($idLabel1, 0x80FF80)
    ;GUICtrlSetState($idLabel1, BitOR($GUI_HIDE, $GUI_DISABLE)) ;$GUI_HIDE | $GUI_DISABLE (Hide the control, and disable it); Auto resizing of labels only works for small fonts
    ;Local $hLabel1 = GUICtrlGetHandle($idLabel1) ; Send $hLabel1 as HANDLE , instead of $idLabel1 as ControlID

    Ozz_GetCharABCWidthsFloat($idLabel1)

    ;Do
    ;Until GUIGetMsg() = $GUI_EVENT_CLOSE
    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete($hGui)
    Return 0
EndFunc   ;==>GUIMain


Func Ozz_GetCharABCWidthsFloat($idCtrl)

    ;==>Test if $idCtrl is a HANDLE, If Not Get HANDLE from Control ID
    ; Using MM_TEXT mapping mode
    If Not IsHWnd($idCtrl) Then $idCtrl = GUICtrlGetHandle($idCtrl) ; Need to set defualt input and error handler for when the $idCtrl, handle, or font is unkown and will need to defualt to system defualt font.
    If Not IsHWnd($idCtrl) Then Return SetError(1, 0, 0) ; Maybe I can create label here to ensure a valid Control handle, or better after DllCall?
    Local $hCtrl = $idCtrl ; This step is not required. It is only shown here to highlight that we will use the Control Handle ($hCtrl), NOT the Control ID ($idCtrl)
    ;   MsgBox(-1, "DEBUG Control Handle $hCtrl ..........", $hCtrl) ; HEX 0x... seams OK
    ;OK, we have our Control HANDLE

    ;==>Create Struct tagABCFLOAT; Local Const $tagSTRUCT1
    ;https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-_abcfloat
    ;####==> I am still uncertain if this structure is being created in the correct way <==####
    Local $tagABCFLOAT_ALT = "struct;FLOAT abcfA;FLOAT abcfB;FLOAT abcfC;endstruct" ;Const
    Local $tABCFLOAT = DllStructCreate($tagABCFLOAT_ALT)
    If @error Then MsgBox($MB_SYSTEMMODAL, "Debug", "DllStructCreate Error: " & @error)

    ;initiate struct to {0}; This step may not be required
    ;DllStructSetData($tABCFLOAT, "abcfA", 0) ;0.0; ### This is part of the Unhandled expeption (Pointer)
    ;DllStructSetData($tABCFLOAT, "abcfB", 0) ;0.0
    ;DllStructSetData($tABCFLOAT, "abcfB", 0) ;0.0

    ;If IsDllStruct($tABCFLOAT) Then MsgBox(-1, "DEBUG is $tABCFLOAT a struct ....", "The variable is a dll structure")
    ;MsgBox($MB_SYSTEMMODAL, "", "Struct Size: " & DllStructGetSize($tABCFLOAT) & @CRLF & "Handle: " & DllStructGetPtr($tABCFLOAT)); 3*4=12( 3*4(UINT/4 bytes) = 12 | Looks correct
    ;OK, we have our structure for the return data...

    ;==>Get Font handle from the Control
    ;Local Const $iMsg = 49 ;
    Dim $WM_GETFONT = 49 ; Declare $WM_GETFONT if it is not already in Constants includes

    Local $hFont
    ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessagew
    ;Local $aFont = DllCall("user32.dll", "LRESULT", "SendMessageA", "HWND", $hCtrl, "UINT", $iMsg, "WPARAM", 0, "LPARAM", 0)
    Local $aFont = DllCall("user32.dll", "LRESULT", "SendMessageW", "HWND", $hCtrl, "UINT", $WM_GETFONT, "WPARAM", 0, "LPARAM", 0) ;0x0031,$WM_GETFONT | not supported by rich edit controls, The EM_GETCHARFORMAT message is used instead
    If @error Then Return SetError(@error, @extended, "")
    If $aFont[0] = Null Then ; Can I move this to top of Func?
        $idCtrl = GUICtrlCreateLabel($cChar, 10, -5) ;, 150, 130) ; Shift off the window canvas. Prob not neccesary.
        GUICtrlSetFont($idCtrl, $iFontSize) ;72
        ;GUICtrlSetBkColor($idLabel1, 0x80FF80)
        GUICtrlSetState($idCtrl, BitOR($GUI_HIDE, $GUI_DISABLE)) ;$GUI_HIDE | $GUI_DISABLE (Hide the control, and disable it); Auto resizing of labels only works for small fonts
        ;Local $hLabel1 = GUICtrlGetHandle($idLabel1) ; Send $hLabel1 as HANDLE , instead of $idLabel1 as ControlID
        $hCtrl = $idCtrl
        $aFont = DllCall("user32.dll", "LRESULT", "SendMessageW", "HWND", $hCtrl, "UINT", $WM_GETFONT, "WPARAM", 0, "LPARAM", 0) ;0x0031,$WM_GETFONT | not supported by rich edit controls, The EM_GETCHARFORMAT message is used instead
        If @error Then Return SetError(@error, @extended, "")
        MsgBox(-1, "DEBUG Msg ........", "Used Default System Font!")
    EndIf
    $hFont = $aFont[0] ;Debug variable
    ;MsgBox(-1, "DEBUG FONT Handle $hFont ........", $hFont) ; int32 Pointer, seams OK
    ;OK, we have our Handle for the Font

    ;==> Get handle to DC
    ;HDC GetDC(HWND hWnd);typedef HANDLE HDC;;typedef PVOID HANDLE;
    ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getdc
    Local $hDC
    Local $ahDC = DllCall("user32.dll", "HANDLE", "GetDC", "HWND", $hCtrl)
    If @error Then Return SetError(@error, @extended, 0) ;### betst error check routines
    ;If Not IsHWnd($hDC) Or ($hDC = Null) Then Return SetError(0, 0, 0)
    If $ahDC[0] Then
        $hDC = $ahDC[0]
    Else
        Return 1 ; There was an error or Null return
    EndIf
    ;MsgBox(-1, "DEBUG hDC $hCtrl ........", $hDC) ; int32 Pointer, seams OK
    ;OK, we have our Handle for the DC

    #cs
        NO, FAILS
        ;HDC GetDC(HWND hWnd);typedef HANDLE HDC;;typedef PVOID HANDLE;
        Local $ahDCfnt = DllCall("user32.dll", "HANDLE", "GetDC", "HWND", $hFont)
        If @error Then Return SetError(@error, @extended, 0) ;### betst error check routines
        ;If Not IsHWnd($hDC) Or ($hDC = Null) Then Return SetError(0, 0, 0)
        If $ahDCfnt[0] Then
        $hDCfnt = $ahDCfnt[0]
        Else
        Return 1 ; There was an error or Null return
        EndIf
        MsgBox(-1, "Test hDCfnt $hFont ........", $hDCfnt) ; int32 Pointer, seams OK
    #ce

    ;-->Select the font into hDC (This routine is required even though the return is not used as in the C example method.)
    ;(Need to look closer at this Func!)
    Local $hDCfnt
    ;HGDIOBJ SelectObject(HDC hdc,HGDIOBJ h);typedef HANDLE HGDIOBJ;typedef HANDLE HDC;
    ;https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-selectobject
    ;SelectObject(hDC,hFont);//???? (Not Required, or diiferent method)
    Local $ahDCfnt = DllCall("gdi32.dll", "HANDLE", "SelectObject", "HANDLE", $hDC, "HANDLE", $hFont)
    If @error Then
        MsgBox(-1, "Test hDCfnt $hFont ........", "Error: " & @CRLF & @error & @CRLF & @extended)
        Return SetError(@error, @extended, 0) ;### betst error check routines
    EndIf

    ;If Not IsHWnd($hDC) Or ($hDC = Null) Then Return SetError(0, 0, 0)
    If $ahDCfnt[0] Then
        $hDCfnt = $ahDCfnt[0] ; Should I be selecting it into current $hDC ??????????????????
    Else
        Return 1 ; There was an error or Null return
    EndIf
    ;MsgBox(-1, "Test hDCfnt $hFont ........", $hDCfnt) ; int32 Pointer, seams OK
    ;OK, we have our Font into current DC

    ;==> Our DllCall to GetCharABCWidthsFloatW()
    $iFirst = 87 ; 'A' == Dec 65 | 'g' == Dec 103 | 'W' == Dec 87 | '|' == Dec 124
    $iLast = 87 ; 'W' == 87 ## In some tests I am getting an Unhandled exeption from pointer if not equal to $iFirst == 87 ?? Testing with differnt values fail, undefined behavoir.
    ; Please note that I have left these two variable here on purpose. You can comment them out and set as Global after $iFontSize for convenience.
    ; They must both match the 'char' used, currently 'W'

    ;GetCharABCWidthsFloat(hDC,'X','X', &lpxABCFLOAT);//(LPABCFLOAT)&lpxABCFLOAT
    ;https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-getcharabcwidthsfloatw
    ;####==> I have tried many methods to populate the structure correctly. This I am still uncertain of... <==####
    ;Local $aRetFntX = DllCall('gdi32.dll', 'BOOL', 'GetCharABCWidthsFloatW', 'HANDLE', $hDC, "UINT", $iFirst, "UINT", $iLast, 'struct*', $tABCFLOAT) ;#FAIL
    Local $aRetFntX = DllCall('gdi32.dll', 'BOOL', 'GetCharABCWidthsFloatW', 'HANDLE', $hDC, "UINT", $iFirst, "UINT", $iLast, 'struct*', DllStructGetPtr($tABCFLOAT)) ;##Returns pointer but segfaults
    ;Local $aRetFntX = DllCall('gdi32.dll', 'BOOL', 'GetCharABCWidthsFloatW', 'HANDLE', $hDC, "UINT", $iFirst, "UINT", $iLast, 'ptr', $tABCFLOAT) ;FAIL
    ;Local $aRetFntX = DllCall('gdi32.dll', 'BOOL', 'GetCharABCWidthsFloatW', 'HANDLE', $hDC, "UINT", $iFirst, "UINT", $iLast, 'ptr', DllStructGetPtr($tABCFLOAT)) ;##

    ;MsgBox($MB_SYSTEMMODAL, "DEBUG DllCall Return", "Error: " & @error & @CRLF & "Extended: " & @extended)
    If @error Or Not $aRetFntX[0] Then Return SetError(@error, @extended, 0) ;jps method
    ;OK, we have our $tABCFLOAT populated from GetCharABCWidthsFloatW... I hope =)

    _ArrayDisplay($aRetFntX) ; DEBUG, Display DllCall return values.

    _WinAPI_DisplayStruct($tABCFLOAT, $tagABCFLOAT_ALT) ; DEBUG, Display the contents of structure $tABCFLOAT
    ;MsgBox(-1, "_WinAPI_DisplayStruct ........", "Error: " & @CRLF & @error & @CRLF & @extended)
    ;MsgBox(-1, "DEBUG FIND", "DEBUG FIND") ; Had, Have issue with unhandle exeption.. Pointer ???

    Local $fabcfA = DllStructGetData($tABCFLOAT, 'abcfA') ; Get results from structure
    Local $fabcfB = DllStructGetData($tABCFLOAT, 'abcfB') ;DllStructGetData(DllStructGetPtr($tABCFLOAT), 'abcfB')
    Local $fabcfC = DllStructGetData($tABCFLOAT, 'abcfC') ;We could populate an array here $aArray[3]

    MsgBox(-1, "DEBUG DllStructGetData ...........", "A: " & $fabcfA & @CRLF & "B: " & $fabcfB & @CRLF & "C: " & $fabcfC)

    Local $fWidth = 0.0
    $fWidth = $fabcfA + $fabcfB + $fabcfC ; Add A+B+C (Note: This should relate to the "Advance Width", but I have not tested or confirmed as yet. )

    MsgBox(-1, "Results - Font Width...............", $fWidth)

    ;**********************************************************************************************
    ; I have had many unhandled exeptions trying to get the pointers to $tABCFLOAT to 'Play Nice'.
    ; Changing the values of $iFirst and $iLast to different chars (e.g. $iFirst = 65 'A' | $iLast = 87 'W'
    ; will cause the pointer to read from protected memory and fault every time. I am still working actively
    ; with this functoin and it is nowhere near complete. At best this just demonstrates the return for the
    ; width of a single character for the moment.
    ;
    ; I am open to sugestions with the correct creation and use of ABCFLOAT struct with GetCharABCWidthsFloatW,
    ; and return values. AXLE
    ;**********************************************************************************************


    $tABCFLOAT = 0
    ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-releasedc
    ;int ReleaseDC(HWND hWnd, HDC  hDC);
    Local $iReturnRelDC
    $aReturnRelDC = DllCall("user32.dll", "INT", "ReleaseDC", "HWND", $hCtrl, "HANDLE", $hDC) ;?? Font??
    If @error Then Return SetError(@error, @extended, 0) ;### best error check routines?

    $aReturnRelDC = DllCall("user32.dll", "INT", "ReleaseDC", "HWND", $hCtrl, "HANDLE", $hDCfnt) ;?? Font??
    If @error Then Return SetError(@error, @extended, 0) ;### best error check routines?

    ;Return 0; Value or array from GetCharABCWidthsFloatW
EndFunc   ;==>Ozz_GetCharABCWidthsFloat

 

 

 

That came out awful sigh. Sorry for that being unreadable. I really don't know whats happened :(

Ok, fixed... Sorry for the delay :)

Edited by AXLE
Corrections

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

  • Moderators

AXLE,

There is an "edit" post function available on this forum - please use it in future.

M23

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 comment
Share on other sites

I'm aware of the 'edit', I just can't see why the latter part shows as commented out. When I used the code tag it was unreadable too. I tried to upload /copy past 5 times with the same result.. Any ideas where I am going wrong so that I can correct it ?

Update:Found it, #CS in caps, and some ' and  " messing with comments. Don't know what language the Caps #CS crept in from lol

Edited by AXLE
correct update

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Link to comment
Share on other sites

This brings back to this one:


This might come as an exercise:

Try to determine how many count of Spaces (pixels * 1 space in the Edit control ) should equal to a given string so in turns its easy to calculate the extra padding for the given string (as proposed in the OP)

* May not be possible to do with rich edit controls as you have noted

Deye
 

Link to comment
Share on other sites

Hi Deye, Forgive me if I get this wrong, I am bit tired atm. You are attempting to align different lengths of text using space chrs ' ' in a similar way to 'Text Align Left', 'Center', 'Right' in a Rich Edit? Or are you looking for adding a margin in pixels or Logical Units?

The above snippet is my current progress for GetCharABCWidthsFloat function which according to MS will return character widths individually and in context to its placement within a string (aka Font Kerning). As the return values are transparent floating point values it offers the opportunity to obtain more accurate measurements before rounding to Abs(INT) occurs. Many of these group of functions (i.e. GetTextExtentPoint32) will determine the text extent and rectangle (Overall length) and in some cases a close approximation of characters. Hopefully when completed it will allow some more flexibility when dealing with text and font alignments.

https://docs.microsoft.com/en-us/windows/desktop/gdi/character-widths

csftx-02.png

I am putting together a UDF library which will include many of the current methods for measuring text sizes and GetCharABCWidthsFloat is just one of many. Ultimately I don't see why we cannot achieve 'text aligning' as part of that.

P.S. You may find the 'GUICtrlCreateListView' Controls useful by placing your "OK" in the second column. Just an idea :)

Edited by AXLE
Additional information

"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

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

×
×
  • Create New...