Jump to content
Sign in to follow this  
Ejoc

DllStruct Dev

Recommended Posts

Valik

Thats one of those C++ thingies

<{POST_SNAPBACK}>

Yes, yes it is. Re-read my post for an example.

Share this post


Link to post
Share on other sites
Ejoc

What's the advantage of using the template vs a macro?

I setup 2 macros to make it easier to read:

#define GetFromCast(s,p,v)  v = (__int64)*((s *)(p))
#define SetFromCast(s,p,v)  *((s *)(p)) = (s)v

SetFromCast(__int32,(iBaseAddr+iOffset),vParams[2].n64Value());
GetFromCast(__int32,(iBaseAddr+iOffset),vResult);
Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
Valik

The advantages are that its type-safe and that it uses the language features instead of the pre-processor which can sometimes be a dirty hack. Your solution is perfectly acceptable in a C environment, but their are more eloquent solutions in a C++ environment. However, so long as the code works correctly, its probably more a matter of taste than anything else. I prefer the C++ way of doing things including the more verbose casts.

In this particular case, I would definitely not use something like your code because it looks a bit weird seeing standard function call notation but instead of passing a variable, a type is passed for the first parameter. With templates, the type is passed as a template parameter which looks more natural, or at least provides a more logical distinction between types and variables.

Share this post


Link to post
Share on other sites
Ejoc

Thanks to JdeB, I was able to get a beta w/ DllStruct* included, and... it worked!! I want to make more tests, but it looks good :(


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
Ejoc

Probably the most important test, I've called it "The Larry Test" works :(

$hwnd   = WinGetHandle("")
$coor   = WinGetPos($hwnd)

$rect   = DllStructCreate("int;int;int;int")
DLLCall("user32.dll","int","GetWindowRect",_
        "hwnd",$hwnd,_
        "ptr",DllStructPtr($rect))

$l = DllStructGet($rect,1)
$t = DllStructGet($rect,2)
$r = DllStructGet($rect,3)
$b = DllStructGet($rect,4)
DllStructFree($rect)

MsgBox(0,"The Larry Test :)","WinGetPos(): (" & $coor[0] & "," & $coor[1] &_
        ") (" & $coor[2] + $coor[0] & "," & $coor[3] + $coor[1] & ")" & @CRLF&_
        "GetWindowRect(): (" & $l & "," & $t & ") (" & $r & "," & $b & ")")

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
Ejoc

While writing the help files I realized that I dont support floating point numbers atm. Can anyone else suggest basic data types that "have" to be supported, Currently you can use:

byte 8bit(1byte) signed char

ubyte 8bit(1byte) unsigned char

char 8bit(1byte) ASCII char

short 16bit(2byte) signed integer

ushort 16bit(2byte) unsigned integer

int 32bit(4byte) signed integer

uint 32bit(4byte) unsinged integer

dword 32bit(4byte) signed integer

udword 32bit(4byte) unsinged integer

ptr 32bit(4byte) integer

int64 64(8byte) signed integer

uint64 64bit(8byte) unsinged integer


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
SumTingWong

While writing the help files I realized that I dont support floating point numbers atm.  Can anyone else suggest basic data types that "have" to be supported, Currently you can use:

byte 8bit(1byte) signed char

ubyte 8bit(1byte) unsigned char

char 8bit(1byte) ASCII char

short 16bit(2byte) signed integer

ushort 16bit(2byte) unsigned integer

int 32bit(4byte) signed integer

uint 32bit(4byte) unsinged integer

dword 32bit(4byte) signed integer

udword 32bit(4byte) unsinged integer

ptr 32bit(4byte) integer

int64 64(8byte) signed integer

uint64 64bit(8byte) unsinged integer

<{POST_SNAPBACK}>

List of basic Windows types supported by DllCall is posted here.

Would you be able to provide support for the Windows type names as well as the C names?

Share this post


Link to post
Share on other sites
SumTingWong

I am trying to use SHFileOperation with the following struct:

typedef struct _SHFILEOPSTRUCT {
    HWND hwnd;
    UINT wFunc;
    LPCTSTR pFrom;
    LPCTSTR pTo;
    FILEOP_FLAGS fFlags;
    BOOL fAnyOperationsAborted;
    LPVOID hNameMappings;
    LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT

I have tried:

"ptr;uint;char[" & sizeofprfrom & "];char[" & sizeofpto & "];uint;int;ptr;char[" & sizeoftitle & "]"

and various other combinations, including using byte instead of char

How would you translate the struct above?

Thanks

Share this post


Link to post
Share on other sites
Ejoc

I am trying to use SHFileOperation with the following struct:

typedef struct _SHFILEOPSTRUCT {
    HWND hwnd;
    UINT wFunc;
    LPCTSTR pFrom;
    LPCTSTR pTo;
    FILEOP_FLAGS fFlags;
    BOOL fAnyOperationsAborted;
    LPVOID hNameMappings;
    LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT

I have tried:

"ptr;uint;char[" & sizeofprfrom & "];char[" & sizeofpto & "];uint;int;ptr;char[" & sizeoftitle & "]"

and various other combinations, including using byte instead of char

How would you translate the struct above?

Thanks

<{POST_SNAPBACK}>

This will be tricky

$pFrom = DllStructCreate("char[256]")
$pTo - DllStructCreate("char[256]")
$lpszProgressTitle = DllStructCreate("char[256]");could be more or less then 256

$SHFILEOPSTRUCT = DllStructCreate("int;uint;ptr;ptr;int;int;ptr;ptr")
DllStructSet($SHFILEOPSTRUCT,1,$HWND)
DllStructSet($SHFILEOPSTRUCT,2,0);no idea what it should be
DllStructSet($SHFILEOPSTRUCT,3,DllStructPtr($pFrom))
DllStructSet($SHFILEOPSTRUCT,4,DllStructPtr($pTo))
DllStructSet($SHFILEOPSTRUCT,5,0);unsure of value
DllStructSet($SHFILEOPSTRUCT,6,0);unsure of value
DllStructSet($SHFILEOPSTRUCT,7,0);If you need something other then NULL do like $pTo
DllStructSet($SHFILEOPSTRUCT,8,DllStructPtr($lpszProgressTitle))

One thing people need to remember is if the Data Type starts with LP (Long Pointer) it is always a "ptr" and you have to create the space for it using another struct and setting its value using DllStructPtr()

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
SumTingWong

Thanks....I tried that earlier as well but couldn't get it work. Here's what I have so far.

Global Const $FO_MOVE               = 0x0001
Global Const $FO_COPY               = 0x0002
Global Const $FO_DELETE             = 0x0003
Global Const $FO_RENAME                 = 0x0004

Global Const $FOF_MULTIDESTFILES        = 0x0001
Global Const $FOF_CONFIRMMOUSE        = 0x0002
Global Const $FOF_SILENT                = 0x0004
Global Const $FOF_RENAMEONCOLLISION  = 0x0008
Global Const $FOF_NOCONFIRMATION        = 0x0010
Global Const $FOF_WANTMAPPINGHANDLE  = 0x0020
Global Const $FOF_ALLOWUNDO          = 0x0040
Global Const $FOF_FILESONLY          = 0x0080
Global Const $FOF_SIMPLEPROGRESS        = 0x0100
Global Const $FOF_NOCONFIRMMKDIR        = 0x0200
Global Const $FOF_NOERRORUI          = 0x0400
Global Const $FOF_NOCOPYSECURITYATTRIBS = 0x0800
Global Const $FOF_NORECURSION          = 0x1000
Global Const $FOF_NO_CONNECTED_ELEMENTS = 0x2000
Global Const $FOF_WANTNUKEWARNING      = 0x4000
Global Const $FOF_NORECURSEREPARSE    = 0x8000

Dim $n

$n = _CopyWithProgress("C:\Temp\au3src\*.*", "C:\Temp\Test")
ConsoleWrite(@error & @LF)
ConsoleWrite($n & @LF)

Func _CopyWithProgress($sFrom, $sTo, $sTitle = "")
#cs
typedef struct _SHFILEOPSTRUCT {
    HWND hwnd;
    UINT wFunc;
    LPCTSTR pFrom;
    LPCTSTR pTo;
    FILEOP_FLAGS fFlags;
    BOOL fAnyOperationsAborted;
    LPVOID hNameMappings;
    LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT
#ce
    Local $SHFILEOPSTRUCT
    Local $pFrom
    Local $pTo
    Local $pTitle
    Local $aDllRet
    Local $nError = 0
    
    $SHFILEOPSTRUCT = DllStructCreate("int;uint;ptr;ptr;uint;int;ptr;ptr")
    If @error Then Return False     
; hwnd
    DllStructSet($SHFILEOPSTRUCT, 1, 0)
; wFunc
    DllStructSet($SHFILEOPSTRUCT, 2, $FO_COPY)
; pFrom
    $pFrom = DllStructCreate("char[" & StringLen($sFrom)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sFrom)+1
    DllStructSet($pFrom, 1, $sFrom)
; We need a second null at the end
    DllStructSet($pFrom, 1, 0, StringLen($sFrom)+2)
    DllStructSet($SHFILEOPSTRUCT, 3, $pFrom)
; pTo
    $pTo = DllStructCreate("char[" & StringLen($sTo)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sTo)+1
    DllStructSet($pTo, 1, $sTo)
; We need a second null at the end
    DllStructSet($pTo, 1, 0, StringLen($sTo)+2)
    DllStructSet($SHFILEOPSTRUCT, 4, $pTo)
; fFlags
    DllStructSet($SHFILEOPSTRUCT, 5, BitOR($FOF_SIMPLEPROGRESS, _ 
                                           $FOF_NOCONFIRMMKDIR, _ 
                                           $FOF_NOCONFIRMATION, _ 
                                           $FOF_NOERRORUI))
; fAnyOperationsAborted
    DllStructSet($SHFILEOPSTRUCT, 6, 0)
; hNameMappings
    DllStructSet($SHFILEOPSTRUCT, 7, 0)
    $pTitle = DllStructCreate("char[" & StringLen($sTitle)+1 & "]")
    If $sTitle <> "" Then   
        DllStructSet($pTitle, 1, $sTitle)
        DllStructSet($SHFILEOPSTRUCT, 3, $pTitle)
    Else
        DllStructSet($SHFILEOPSTRUCT, 8, 0)
    EndIf
    $aDllRet = DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructPtr($SHFILEOPSTRUCT))
    If @error Or $aDllRet[0] <> 0 Then
        $aDllRet = DllCall("kernel32.dll", "long", "GetLastError")
        If Not @error Then $nError = $aDllRet[0]
    EndIf
    DllStructFree($pFrom)
    DllStructFree($pTo)
    DllStructFree($pTitle)
    DllStructFree($SHFILEOPSTRUCT)
    If $nError <> 0 Then 
        SetError($nError)
        Return False
    EndIf
    Return True
EndFunc

pFrom and pTo need to be double-null terminated. This is what I did to add the second null.

; pFrom
$pFrom = DllStructCreate("char[" & StringLen($sFrom)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sFrom)+1
DllStructSet($pFrom, 1, $sFrom)
; We need a second null at the end
DllStructSet($pFrom, 1, 0, StringLen($sFrom)+2)
DllStructSet($SHFILEOPSTRUCT, 3, $pFrom)

Share this post


Link to post
Share on other sites
Ejoc

Thanks....I tried that earlier as well but couldn't get it work. Here's what I have so far.

Global Const $FO_MOVE                  = 0x0001
Global Const $FO_COPY                  = 0x0002
Global Const $FO_DELETE              = 0x0003
Global Const $FO_RENAME                 = 0x0004

Global Const $FOF_MULTIDESTFILES        = 0x0001
Global Const $FOF_CONFIRMMOUSE        = 0x0002
Global Const $FOF_SILENT                = 0x0004
Global Const $FOF_RENAMEONCOLLISION  = 0x0008
Global Const $FOF_NOCONFIRMATION        = 0x0010
Global Const $FOF_WANTMAPPINGHANDLE  = 0x0020
Global Const $FOF_ALLOWUNDO          = 0x0040
Global Const $FOF_FILESONLY          = 0x0080
Global Const $FOF_SIMPLEPROGRESS        = 0x0100
Global Const $FOF_NOCONFIRMMKDIR        = 0x0200
Global Const $FOF_NOERRORUI          = 0x0400
Global Const $FOF_NOCOPYSECURITYATTRIBS = 0x0800
Global Const $FOF_NORECURSION          = 0x1000
Global Const $FOF_NO_CONNECTED_ELEMENTS = 0x2000
Global Const $FOF_WANTNUKEWARNING      = 0x4000
Global Const $FOF_NORECURSEREPARSE    = 0x8000

Dim $n

$n = _CopyWithProgress("C:\Temp\au3src\*.*", "C:\Temp\Test")
ConsoleWrite(@error & @LF)
ConsoleWrite($n & @LF)

Func _CopyWithProgress($sFrom, $sTo, $sTitle = "")
#cs
typedef struct _SHFILEOPSTRUCT {
    HWND hwnd;
    UINT wFunc;
    LPCTSTR pFrom;
    LPCTSTR pTo;
    FILEOP_FLAGS fFlags;
    BOOL fAnyOperationsAborted;
    LPVOID hNameMappings;
    LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT
#ce
    Local $SHFILEOPSTRUCT
    Local $pFrom
    Local $pTo
    Local $pTitle
    Local $aDllRet
    Local $nError = 0
    
    $SHFILEOPSTRUCT = DllStructCreate("int;uint;ptr;ptr;uint;int;ptr;ptr")
    If @error Then Return False     
; hwnd
    DllStructSet($SHFILEOPSTRUCT, 1, 0)
; wFunc
    DllStructSet($SHFILEOPSTRUCT, 2, $FO_COPY)
; pFrom
    $pFrom = DllStructCreate("char[" & StringLen($sFrom)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sFrom)+1
    DllStructSet($pFrom, 1, $sFrom)
; We need a second null at the end
    DllStructSet($pFrom, 1, 0, StringLen($sFrom)+2)
    DllStructSet($SHFILEOPSTRUCT, 3, $pFrom)
; pTo
    $pTo = DllStructCreate("char[" & StringLen($sTo)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sTo)+1
    DllStructSet($pTo, 1, $sTo)
; We need a second null at the end
    DllStructSet($pTo, 1, 0, StringLen($sTo)+2)
    DllStructSet($SHFILEOPSTRUCT, 4, $pTo)
; fFlags
    DllStructSet($SHFILEOPSTRUCT, 5, BitOR($FOF_SIMPLEPROGRESS, _ 
                                           $FOF_NOCONFIRMMKDIR, _ 
                                           $FOF_NOCONFIRMATION, _ 
                                           $FOF_NOERRORUI))
; fAnyOperationsAborted
    DllStructSet($SHFILEOPSTRUCT, 6, 0)
; hNameMappings
    DllStructSet($SHFILEOPSTRUCT, 7, 0)
    $pTitle = DllStructCreate("char[" & StringLen($sTitle)+1 & "]")
    If $sTitle <> "" Then    
        DllStructSet($pTitle, 1, $sTitle)
        DllStructSet($SHFILEOPSTRUCT, 3, $pTitle)
    Else
        DllStructSet($SHFILEOPSTRUCT, 8, 0)
    EndIf
    $aDllRet = DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructPtr($SHFILEOPSTRUCT))
    If @error Or $aDllRet[0] <> 0 Then
        $aDllRet = DllCall("kernel32.dll", "long", "GetLastError")
        If Not @error Then $nError = $aDllRet[0]
    EndIf
    DllStructFree($pFrom)
    DllStructFree($pTo)
    DllStructFree($pTitle)
    DllStructFree($SHFILEOPSTRUCT)
    If $nError <> 0 Then 
        SetError($nError)
        Return False
    EndIf
    Return True
EndFunc

pFrom and pTo need to be double-null terminated. This is what I did to add the second null.

; pFrom
$pFrom = DllStructCreate("char[" & StringLen($sFrom)+2 & "]")
; Hopefully, the string will now be null-terminated at StringLen($sFrom)+1
DllStructSet($pFrom, 1, $sFrom)
; We need a second null at the end
DllStructSet($pFrom, 1, 0, StringLen($sFrom)+2)
DllStructSet($SHFILEOPSTRUCT, 3, $pFrom)

<{POST_SNAPBACK}>

Forgot to use DllStructPtr

DllStructSet($SHFILEOPSTRUCT, 3, DllStructPtr($pFrom))

DllStructSet($SHFILEOPSTRUCT, 4, DllStructPtr($pTo))

DllStructSet($SHFILEOPSTRUCT, 3, DllStructPtr($pTitle)) *This should be 8 not 3

Glad you got the Double NULL, I noticed that when looking on MSDN

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
SumTingWong

Forgot to use DllStructPtr

DllStructSet($SHFILEOPSTRUCT, 3, DllStructPtr($pFrom))

DllStructSet($SHFILEOPSTRUCT, 4, DllStructPtr($pTo))

DllStructSet($SHFILEOPSTRUCT, 3, DllStructPtr($pTitle)) *This should be 8 not 3

Glad you got the Double NULL, I noticed that when looking on MSDN

<{POST_SNAPBACK}>

Doh!....that's what burning the midnight candle will do to you. :(

Thanks

Share this post


Link to post
Share on other sites
Ejoc

Since I see some common problems I thought I'd try to make some UDFs to help people out. This is my first UDF for it, feed this one your string you are using to create a struct and It will give you info about it.

structbuilder.au3

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
SumTingWong

OK, here's an interesting one.

I am trying to get QueryServiceConfig to work with 3 different methods in the attached script.

The problem is that I can get the addresses of string params but not the actual content.

Any ideas?

EDIT: sorry wrong link and function name

ServiceTest.au3

Edited by SumTingWong

Share this post


Link to post
Share on other sites
Smed

How should arrays of structures be handled?

It seems to me that this is somewhat less than elegant:

$baseStructure = "int;dword;byte"
$arrayOfStructures = $baseStructure
$arraySize = 8
For $i = 1 To $arraySize
  $arrayOfStructures &= ";" & $baseStructure
Next

601DisengageEnd Program

Share this post


Link to post
Share on other sites
Smed

Ow Larry, I'm getting stabbing pains in my chest now. I was just concerned about simple arrays and you had to go float the tree concept. Little Steps.. One at a time.. Rome wasn't built in a day.


601DisengageEnd Program

Share this post


Link to post
Share on other sites
Ejoc

Bleh I was hoping to avoid dealing w/ structs in structs but it doesnt look like I can. I could almost do this "easily" with a UDF but there's 1 problem. Anyways here are some idea's I had on how to handle it:

1:

$p = DllStructCreate("ptr;byte[16];ptr"); problem is here, need to know the size of the sub struct
$sub = _DllStructSubStruct($p,2,"int;int;int;int");$p=struct,2=element 2 of that struct,"the sub struct"
$value1 = DllStructGet($sub,1)
DllStructFree($p);dont call it on $sub

2:(I'm leaning towards this method, no change to the DllStruct... Functions)

$RECT = "int;int;int;int"
$p = DllStructCreate("ptr;" & $RECT & ";ptr");seperate the sub struct so it's more clear
$sub = _DllStructSubStruct($p,2,5);this would then change $p to have 3 elements, 1=the first ptr; 2=the substruct but you wouldn't access it from $p anymore; 3=the second ptr
;or
$sub = _DllStructSubStruct($p,2,$RECT)
$value1 = DllStructGet($sub,1)
DllStructFree($p);dont call on $sub

3:

Dim $sub
$p = DllStructCreate("ptr;param;ptr","int;int;int;int",$sub);param would tell it to take the next param passed to DllStructCreate
$value1 = DllStructGet($sub,1)
DllStructFree($p)

Hmmm...


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
Ejoc

would it be a pointer array?

$a = DLLStructCreate("int;int;int")

$b = DLLStructCreate("int;int;int")

$c = DLLStructCreate("int;int;int")

$d = DLLStructCreate("int;int;int")

$e = DLLStructCreate("int;int;int")

$f = DLLStructCreate("int;ptr[5]")

DLLStructSet($f,2,DLLStructPtr($a),1)

DLLStructSet($f,2,DLLStructPtr($:(,2)

DLLStructSet($f,2,DLLStructPtr($c),3)

DLLStructSet($f,2,DLLStructPtr($d),4)

DLLStructSet($f,2,DLLStructPtr($e),5)

I don't know about useful, but hypothetical?

Also... Is there a way to get a piece of a struct pointer? DLLStructGetMem?

Lar.

<{POST_SNAPBACK}>

That's how you'd do an array of pointers.

Not sure exactly what you mean by piece of a struct pointer.


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
Ejoc

So based on my #2 method here is a UDF for sub structs:

;=====================================================
;   _DllStructSubStruct(ByRef $p, $iElement, $szStruct)
;   $p          The return from DllStructCreate()
;   $iElement   The element where the sub struct is located
;   $szStruct   The String representing the Sub Struct
;   Returns a new struct for use in DllStructGet/DllStructSet
;   Sets @Error to -1 if $iElement is outside, -2 sub struct
;       would go outside the bounds of the struct
;   $p's elements are decreased as the substruct elements are removed
;
;   $RECT_STR   = "int;int;int;int"
;   $POINT_STR  = "int;int"
;   $p          = DllStructCreate("ptr;" & $RECT_STR & ";" & $POINT_STR)
;   $rect       = _DllStructSubStruct($p,2,$RECT_STR)
;   $point      = _DllStructSubStruct($p,3,$POINT_STR)
;   DllCall("some.dll","int","func","ptr",DllStructPtr($p))
;   $point_x    = DllStructGet($point,1)
;   $point_y    = DllStructGet($point,2)
;   $left       = DllStructGet($rect,1)
;   $top        = DllStructGet($rect,2)
;   $right      = DllStructGet($rect,3)
;   $bottom     = DllStructGet($rect,4)
;   DllStructFree($p)
;=====================================================

SubStruct.au3

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites
GaryFrost

Haven't had a chance to try the substruct stuff yet, but thought you might find the next bit of code interesting.

#include <GuiConstants.au3>

GUICreate("Sample", 220, 210, -1, -1)
$color = _ChooseColor()
If(@error)Then
    MsgBox(0,"","Error _ChooseColor: " & @error)
Else
    ConsoleWrite($color & @LF)
EndIf
$a_font = _ChooseFont()
If(IsArray($a_font)) Then
    MsgBox(0,"","Font Name: " & $a_font[2] & @LF & "Size: " & $a_font[3] & @LF & "Weight: " & $a_font[4])
Else
    MsgBox(0,"","Error _ChooseFont: " & $a_font)
EndIf

Func _ChooseFont()
;~ typedef struct {
;~   DWORD lStructSize;
;~   HWND hwndOwner;
;~   HDC hDC;
;~   LPLOGFONT lpLogFont;
;~   INT iPointSize;
;~   DWORD Flags;
;~   COLORREF rgbColors;
;~   LPARAM lCustData;
;~   LPCFHOOKPROC lpfnHook;
;~   LPCTSTR lpTemplateName;
;~   HINSTANCE hInstance;
;~   LPTSTR lpszStyle;
;~   WORD nFontType;
;~   INT nSizeMin;
;~   INT nSizeMax;
;~ } CHOOSEFONT, *LPCHOOSEFONT;

Global Const $CF_EFFECTS = 0x100
;~  Causes the dialog box to display the controls that allow the user to specify strikeout, underline, and text color options.
;~      If this flag is set, you can use the rgbColors member to specify the initial text color.
;~      You can use the lfStrikeOut and lfUnderline members of the structure pointed to by lpLogFont to specify the initial settings of the strikeout and underline check boxes.
;~      ChooseFont can use these members to return the user's selections.
Global Const $CF_PRINTERFONTS = 0x2
;~ CF_PRINTERFONTS
;~  Causes the dialog box to list only the fonts supported by the printer associated with the device context (or information context) identified by the hDC member.
Global Const $CF_SCREENFONTS = 0x1
;~  Causes the dialog box to list only the screen fonts supported by the system.
Global Const $CF_SHOWHELP = 0x4
;~  Causes the dialog box to display the Help button.
;~      The hwndOwner member must specify the window to receive the HELPMSGSTRING registered messages that the dialog box sends when the user clicks the Help button.
;~ typedef struct tagLOGFONT { 
;~   LONG lfHeight; 
;~   LONG lfWidth; 
;~   LONG lfEscapement; 
;~   LONG lfOrientation; 
;~   LONG lfWeight; 
;~   BYTE lfItalic; 
;~   BYTE lfUnderline; 
;~   BYTE lfStrikeOut; 
;~   BYTE lfCharSet; 
;~   BYTE lfOutPrecision; 
;~   BYTE lfClipPrecision; 
;~   BYTE lfQuality; 
;~   BYTE lfPitchAndFamily; 
;~   TCHAR lfFaceName[LF_FACESIZE]; 32 chars max
;~ } LOGFONT, *PLOGFONT; 
$logfont = "int;int;int;int;int;byte;byte;byte;byte;byte;byte;byte;byte;char[32]"
$struct  = "dword;int;int;ptr;int;dword;int;int;ptr;ptr;int;ptr;dword;int;int"
Local $p = DllStructCreate($struct)
if @error Then
  ;MsgBox(0,"","Error in DllStructCreate " & @error);
    SetError(-1)
   Return -1
endif
Local $lf = DllStructCreate($logfont)
if @error Then
  ; MsgBox(0,"","Error in DllStructCreate " & @error);
    DllStructFree($p)
    SetError(-2)
    Return -2
endif
DllStructSet($p,1,DllStructSize($p))
DllStructSet($p,2,WinGetHandle(WinGetTitle("")))
DllStructSet($p,4,DllStructPtr($lf))
DllStructSet($p,6,BitOR($CF_SCREENFONTS,$CF_PRINTERFONTS,$CF_EFFECTS))
$ret = DllCall("comdlg32.dll","long","ChooseFont","ptr",DllStructPtr($p))
If ($ret[0] == 0) Then
; user selected cancel or struct settings incorrect
    DllStructFree($p)
    DllStructFree($lf)
    SetError(-3)
   Return -3
EndIf
$fontname = DllStructGet($lf,14)
$italic = 0
$underline = 0
$strikeout = 0
If(DllStructGet($lf,6)) Then
    $italic = 2
EndIf
If(DllStructGet($lf,7)) Then
    $underline = 4
EndIf
If(DllStructGet($lf,8)) Then
    $strikeout = 8
EndIf
$attributes = BitOR($italic,$underline,$strikeout)
$size = DllStructGet($p,5) / 10
$weight = DllStructGet($lf,5)
DllStructFree($p)
DllStructFree($lf)
Return StringSplit($attributes & "," & $fontname & "," & $size & "," & $weight,",")
EndFunc

Func _ChooseColor()
;~ typedef struct {
;~   DWORD lStructSize;
;~   HWND hwndOwner;
;~   HWND hInstance;
;~   COLORREF rgbResult;
;~   COLORREF *lpCustColors;
;~   DWORD Flags;
;~   LPARAM lCustData;
;~   LPCCHOOKPROC lpfnHook;
;~   LPCTSTR lpTemplateName;
;~ } CHOOSECOLOR, *LPCHOOSECOLOR;
Global Const $CC_ANYCOLOR = 0x100 
;~  Causes the dialog box to display all available colors in the set of basic colors. 
Global Const $CC_FULLOPEN = 0x2
;~  Causes the dialog box to display the additional controls that allow the user to create custom colors.
;~  If this flag is not set, the user must click the Define Custom Color button to display the custom color controls.
Global Const $CC_SHOWHELP = 0x8
;~  Causes the dialog box to display the Help button. The hwndOwner member must specify the window to receive the HELPMSGSTRING registered messages that the dialog box sends when the user clicks the Help button.

$custcolors = "int[16]"
$struct = "dword;int;int;int;ptr;dword;int;ptr;ptr"
Local $p = DllStructCreate($struct)
if @error Then
  ;MsgBox(0,"","Error in DllStructCreate " & @error);
    SetError(-1)
   Return -1
endif
Local $cc = DllStructCreate($custcolors)
if @error Then
  ; MsgBox(0,"","Error in DllStructCreate " & @error);
    DllStructFree($p)
    SetError(-2)
    Return -1
endif
DllStructSet($p,1,DllStructSize($p))
DllStructSet($p,2,WinGetHandle(WinGetTitle("")))
DllStructSet($p,5,DllStructPtr($cc))
DllStructSet($p,6,BitOR($CC_ANYCOLOR,$CC_FULLOPEN))

$ret = DllCall("comdlg32.dll","long","ChooseColor","ptr",DllStructPtr($p))
If ($ret[0] == 0) Then
; user selected cancel or struct settings incorrect
    DllStructFree($p)
    DllStructFree($cc)
    SetError(-3)
   Return -1
EndIf
Local $color_picked = Hex(String(DllStructGet($p,4)), 6)
DllStructFree($p)
DllStructFree($cc)
; return Hex RGB Color
Return '0x' & StringMid($color_picked, 5, 2) & StringMid($color_picked, 3, 2) & StringMid($color_picked, 1, 2)
EndFunc

Edit: added _ChooseFont

Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


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
Sign in to follow this  

×