DonationCoder.com forum
 
Read-only archive. This is a static copy of the DonationCoder.com forum. Reading and searching work as before; logging in, posting and private messages do not.
Archive of 2026-10-21 · About this archive · Main site

Author Topic: AutoHotkey Programming Questions Megathread  (Read 8,722 times)

dnm

  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 25
AutoHotkey Programming Questions Megathread
« on: May 13, 2008, 11:01 PM »
I didn't see an existing thread for questions about AutoHotkey programming, so I thought I'd start a catch-all here. Mouser, feel free to move this wherever is more appropriate.

The idea is that since we have sterling AutoHotkey (AHK) programmers like skrommel and others, those of us on DonationCoder who have AHK programming questions can ask them of each other here. This isn't a replacement for the AutoHotkey Community forums, just a local thread for AHK programming questions. Deeper discussions can be taken offline, moved to another thread, or moved to the AutoHotkey Community forums.

Thanks for reading!

dnm

  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 25
Re: AutoHotkey Programming Questions Megathread
« Reply #1 on: May 13, 2008, 11:14 PM »
Here's a question to start off the thread.

Earlier today I was trying to get write some basic AHK functions which allow me to convert characters which I've copied to the clipboard to a different representation. For instance, my initial use case was something like this: I want to be able to copy a series of bytes from my hex editor (as hex bytes) and use a hotkey to trigger a function (or series of functions) which will bit-invert those bytes, then save them as hex bytes back to the clipboard. Once that's done, I can paste them back into my hex editor and see the ASCII representation of the inverted bytes.

The strategy I used to go about this was seemingly simple, but possibly too complex. I'm not sure. I assume up front that the bytes I'm copying are already valid hex bytes, 0-9 and A-F, regardless of case (uppercase everything internally), and ignore whitespace (SPC, TAB, and RET). Convert from hex to a binary value, invert the value, then convert from binary to hex and save to the clipboard.

I'm not terribly familiar with writing functions in AHK; mostly I use it for hotstrings and hotkeys only. I tried my hand at a couple different approaches, none of which worked fully. I also looked at the following code samples on the AHK Community Forums, which seemed really interesting, but also overkill for what I want.

http://www.autohotkey.com/forum/topic21172.html
http://www.autohotkey.com/forum/topic21172-105.html

I did find some code in AutoIt (v3) that I modified only slightly that works well (at least the one bit I've tested), but the problem is that I don't run AutoIt like I run AutoHotkey, i.e. running in my system tray, capturing key macros, replacing text, etc. I probably can run AutoIt that way (I'd have to look into it), but generally I run AutoIt scripts for specific tasks, and don't really use it the same way I use AutoHotkey. While I could just write hotkeys in AutoHotkey to call the AutoIt scripts, that gets rid of the idea of having this be self-contained in my standard AHK script, and complicates deployment.

Any ideas? I'm open to all approaches, as long as I can make sense of the code.

Thanks in advance!

Here's the edited AutoIt code (as it stands right now):

Code: (AutoIt)
; baseconv.au3 -- Base conversion functions for representative strings (binary
;                 strings, decimal values, hex values).

; ==============================================================================
; FUNCTIONS
; ==============================================================================
;
; Original code for functions by "ptrex" on AutoIt Forums
; http://www.autoitscript.com/forum/index.php?showtopic=70507

; --------------------------------------------------------------------------
; BinStr2Dec
; --------------------------------------------------------------------------
Func BinStr2Dec($strBin)
Local $Return
Local $lngResult
Local $intIndex

If StringRegExp($strBin,'[0-1]') then
$lngResult = 0
  For $intIndex = StringLen($strBin) to 1 step -1
    $strDigit = StringMid($strBin, $intIndex, 1)
    Select
      case $strDigit="0"
        ; do nothing
      case $strDigit="1"
        $lngResult = $lngResult + (2 ^ (StringLen($strBin)-$intIndex))
      case else
        ; invalid binary digit, so the whole thing is invalid
        $lngResult = 0
        $intIndex = 0 ; stop the loop
    EndSelect
  Next

  $Return = $lngResult
    Return $Return
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

; --------------------------------------------------------------------------
; Dec2BinStr
; --------------------------------------------------------------------------
Func Dec2BinStr($iDec)
Local $i, $sBinChar = ""

If StringRegExp($iDec,'[[:digit:]]') then
$i = 1

Do
 $x = 16^$i
 $i +=1
 ; Determine the Octects
Until $iDec < $x

For $n = 4*($i-1) To 1 Step -1
    If BitAND(2 ^ ($n-1), $iDec) Then
        $sBinChar &= "1"
    Else
        $sBinChar &= "0"
    EndIf
Next
 Return $sBinChar
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

; --------------------------------------------------------------------------
; Hex2Dec
; --------------------------------------------------------------------------
Func Hex2Dec($Input)
Local $Temp, $i, $Pos, $Ret, $Output

If StringRegExp($input,'[[:xdigit:]]') then
$Temp = StringSplit($Input,"")

For $i = 1 to $Temp[0]
    $Pos = $Temp[0] - $i
    $Ret =  Dec (Hex ("0x" & $temp[$i] )) * 16 ^ $Pos
    $Output = $Output + $Ret
Next
    return $Output
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

; --------------------------------------------------------------------------
; Dec2Hex
; --------------------------------------------------------------------------
Func Dec2Hex($Input)
local $Output, $Ret

If StringRegExp($input,'[[:digit:]]') then
Do
    $Ret = Int(mod($Input,16))
    $Input = $Input/16
    $Output = $Output & StringRight(Hex($Ret),1)
Until Int(mod($Ret,16))= 0

    Return StringMid(_StringReverse($Output),2)
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

; --------------------------------------------------------------------------
; BinStr2Hex
; --------------------------------------------------------------------------
Func BinStr2Hex($strBin)
    Local $test, $Result = '',$numbytes,$nb

If StringRegExp($strBin,'[0-1]') then

    if $strBin = '' Then
        SetError(-2)
        Return
    endif

    Local $bits = "0000|0001|0010|0011|0100|0101|0110|0111|1000|1001|1010|1011|1100|1101|1110|1111"
    $bits = stringsplit($bits,'|')
    #region check string is binary

    $test = stringreplace($strBin,'1','')
    $test = stringreplace($test,'0','')
    if $test <> '' Then
        SetError(-1);non binary character detected
        Return
    endif
    #endregion check string is binary

    #region make binary string an integral multiple of 4 characters
    While 1
        $nb = Mod(StringLen($strBin),4)
        if $nb = 0 then exitloop
        $strBin = '0' & $strBin
    WEnd
    #endregion make binary string an integral multiple of 4 characters

    $numbytes = Int(StringLen($strBin)/4);the number of bytes

    Dim $bytes[$numbytes],$Deci[$numbytes]
    For $j = 0 to $numbytes - 1;for each byte
    ;extract the next byte
        $bytes[$j] = StringMid($strBin,1+4*$j,4)

    ;find what the dec value of the byte is
        for $k = 0 to 15;for all the 16 possible hex values
            if $bytes[$j] = $bits[$k+1] Then
                $Deci[$j] = $k
                ExitLoop
            EndIf
        next
    Next

;now we have the decimal value for each byte, so stitch the string together again
    $Result = ''
    for $l = 0 to $numbytes - 1
        $Result &= Hex($Deci[$l],1)
    Next
    return $Result
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

; --------------------------------------------------------------------------
; Hex2BinStr
; --------------------------------------------------------------------------
Func Hex2BinStr($strHex)
    Local $Allowed = '0123456789ABCDEF'
    Local $Test,$n
    Local $Result = ''
    if $strHex = '' then
        SetError(-2)
        Return
    EndIf

    $strHex = StringSplit($strHex,'')
    for $n = 1 to $strHex[0]
        if not StringInStr($Allowed,$strHex[$n]) Then
            SetError(-1)
            return 0
        EndIf
    Next

    Local $bits = "0000|0001|0010|0011|0100|0101|0110|0111|1000|1001|1010|1011|1100|1101|1110|1111"
    $bits = stringsplit($bits,'|')
    for $n = 1 to $strHex[0]
        $Result &=  $bits[Dec($strHex[$n])+1]
    Next

    Return $Result
EndFunc


; ==============================================================================
; TEST CODE
; ==============================================================================

; Quick and drity, not good test code, but works for now.
; Currently only tests Hex2BinStr.

Dim $testVal1 = "DEAD"
Dim $returnVal1 = Hex2BinStr($testVal1)
MsgBox(0,"Results",$returnVal1)
; Expected value: 1101111010101101

Dim $testVal2 = "2152"
Dim $returnVal2 = Hex2BinStr($testVal2)
MsgBox(0,"Results",$returnVal2)
; Expected value: 0010000101010010

Dim $testVal3 = "b57b"
Dim $returnVal3 = Hex2BinStr($testVal3)
MsgBox(0,"Results",$returnVal3)
; Expected value: 1011010101111011
« Last Edit: May 13, 2008, 11:16 PM by dnm »

Original address: https://www.donationcoder.com/forum/index.php?topic=13344.0