Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Syntax aus delphi7 für DLL-call in AHK übersetzen



  • Please log in to reply
18 replies to this topic
pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013
Hallo,
ich habe ein Problem mit der Umsetzung eines Programm von Delphi7 in AHK. Es geht darum, daß ich ein USB-Relais-Modul via Hotkey's schalten möchte. Dazu muß eine Dll ins Programm eingebunden, und auf bestimmte Werte zugegriffen bzw. geschrieben werden. Wie muß ich es umschreiben, das es funktioniert? Wie muß ich die Variablen richtig deklarieren?
 
Vielen Dank
 
Hier mein AHK-Prog.:
#InstallKeybdHook
LControl & RAlt::
Relais1und2 = 7
Relais3und4 = 8
bO_Mask = 0
FT_LIST_NUMBER_ONLY = $80000000
FT_Result := DllCall("ftd2xx.dll\FT_ListDevices",pvArg1,pvArg2,dwFlags)
FT_Result := DllCall("ftd2xx.dll\FT_Open",iDevice,ftHandle)
FT_Result := DllCall("ftd2xx.dll\FT_SetBaudRate",ftHandle,BaudRate)
FT_Result := DllCall("ftd2xx.dll\FT_SetBitMode",ftHandle,ucMaske,ucEnable)
FT_Result := DllCall("ftd2xx.dll\FT_Write,ftHandle",FTOutBuf,BufferSize,ResultPtr)
FT_Result := DllCall("ftd2xx.dll\FT_Close",ftHandle)

Input, Ausgabevariable, L1
If Ausgabevariable = %Relais1und2%
  Result = FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)
  Result = FT_Open(0,@FT_hd)
  bIO_Mask = 255
  Result = FT_SetBitMode(FT_hd, bIO_Mask, $01)
  bO_Mask = 3
  Result = FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten)
 MsgBox AltGr+%Ausgabevariable% = Sie haben Relais1und2 Ein gedrückt.  ;  richtig angezeigt      
 MsgBox Nummer =  + %dwDevCount% + FT_hd =  + %FT_hd%                     ; Variable sind leer
If Ausgabevariable = %Relais3und4%
           MsgBox AltGr+%Ausgabevariable% + Sie haben Relais3und4 Ein gedrückt.
  Result = FT_ListDevices(@dwDevCount, NIL , FT_LIST_NUMBER_ONLY)
  Result = FT_Open(0,@FT_hd)
  bIO_Mask = 255
  Result = FT_SetBitMode(FT_hd, bIO_Mask, $01)
  bO_Mask = 12
  Result = FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten)
Return


Hier das Delphi-Prog.: (nur das wesentliche)
type
   FT_Result = Integer;
   FT_Handle = Dword;
 
var
  FRM_Main: TFRM_Main;
  FT_hd: FT_Handle;
//USB-Gerät suchen & öffnen
  dwDevCount: DWord;
  Result: FT_Result;
//USB SetBitMode
  bIO_Mask: byte;
//Relais schalten
  bO_Mask: byte;
  iWritten: integer;
 
const
   FT_LIST_NUMBER_ONLY = $80000000;
 
implementation
{$R *.dfm}
 
   function FT_ListDevices(pvArg1:Pointer; pvArg2:Pointer; dwFlags:Dword):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_ListDevices';
   function FT_Open(iDevice: integer; ftHandle:Pointer):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Open';
   function FT_SetBaudRate(ftHandle:DWord; BaudRate:DWord):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_SetBaudRate';
   function FT_SetBitMode(ftHandle:DWord; ucMaske, ucEnable: Byte):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_SetBitMode';
   function FT_Write(ftHandle:DWord; FTOutBuf: Pointer; BufferSize: LongInt; ResultPtr: Pointer):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Write';
   function FT_Close(ftHandle:DWord):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Close';

procedure TFRM_Main.Button1Click(Sender: TObject);
begin    //suchen & öffnen
  Result := FT_ListDevices(@dwDevCount, NIL , FT_LIST_NUMBER_ONLY);
  Result := FT_Open(0,@FT_hd);
  bIO_Mask := 255;
  Result := FT_SetBitMode(FT_hd, bIO_Mask, $01);
  //schalten Relais 1+2 ein 
  bO_Mask := 3;
  Result := FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten);
  if (Result = 0) then
    if (dwDevCount <> 0) then
      ShowMessage('Nummer = ' + IntToStr(dwDevCount) + '  |   FT_hd = ' + IntToStr(FT_hd))
    else
      ShowMessage('Fehler -  Es keine USB-Relais vorhanden.')
end;
... usw.

nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012

Sry ich bin nicht so gut in Delphi als das ich den Code in einwandfreies AHK übersetzten könnte.

Aber ich kann ein Paar Fehler bennenen.

 

FT_LIST_NUMBER_ONLY = $80000000

Ergibt keinen Sinn. Zum benutzten von Hex-Werten wird der Präfix 0x benutzt und nicht $. Also:

FT_LIST_NUMBER_ONLY = 0x80000000

Generell würde ich = durch := ersetzten, da bei dir sonst Fehler entstehen. Also:

FT_LIST_NUMBER_ONLY := 0x80000000

 

FT_Result := DllCall("ftd2xx.dll\FT_ListDevices",pvArg1,pvArg2,dwFlags)

Bei DLLCalls in AHK muss vor jedem Argument der Typ dieses Arguments angegeben werden z.B.

FT_Result := DllCall("ftd2xx.dll\FT_ListDevices","Pointer",pvArg1,"Pointer",pvArg2,"UInt",dwFlags)

Ich finde Ausserdem keine Definition von pvArg1, pvArg2 und dwFlags. Also übergibst du leere Werte?

 

If Ausgabevariable = %Relais1und2%
  Result = FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)
  Result = FT_Open(0,@FT_hd)
  bIO_Mask = 255
  Result = FT_SetBitMode(FT_hd, bIO_Mask, $01)
  bO_Mask = 3
  Result = FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten)

Ich nehme an das das alles nur ausgeführt werden soll wenn Ausgabevariable = %Relais1und2%.

Dazu musst du aber die entsprechende Passage in eckige Kammern setzten.Also:

If Ausgabevariable = %Relais1und2%

{
  Result = FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)
  Result = FT_Open(0,@FT_hd)
  bIO_Mask = 255
  Result = FT_SetBitMode(FT_hd, bIO_Mask, $01)
  bO_Mask = 3
  Result = FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten)

}

Weiterhin wird If Ausgabevariable = %Relais1und2% als schlechter Stil angesehen.

Die Passage sollte geändert werden , da dies in AHKv2 nicht mehr möglich sein wird.Also:

If (Ausgabevariable=Relais1und2)

 

Result = FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)

Wieder = durch := ersetzten sonst wird der Befehl nicht ausgeführt.

Result wäre dann "FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)" und nicht das Ergebnis des Funktionsaufrufs.

Result := FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)

Ich finde nirgendwo eine Definition für FT_ListDevices. Sie müsste so aussehen:

FT_ListDevices(pvArg1,pvArg2,dwFlags)

{

return DllCall("ftd2xx.dll\FT_ListDevices","Pointer",pvArg1,"Pointer",pvArg2,"UInt",dwFlags)

}

Das gleiche gilt für alle Funktionen die du im Skript benutzt.

Result := FT_ListDevices("@dwDevCount", NIL , FT_LIST_NUMBER_ONLY)

Was bedeutet "@dwDevCount" ? Da du bei der DLL einen Pointer übergibst macht ein String wenig Sinn.

 

FT_Result := DllCall("ftd2xx.dll\FT_ListDevices",pvArg1,pvArg2,dwFlags)
FT_Result := DllCall("ftd2xx.dll\FT_Open",iDevice,ftHandle)
FT_Result := DllCall("ftd2xx.dll\FT_SetBaudRate",ftHandle,BaudRate)
FT_Result := DllCall("ftd2xx.dll\FT_SetBitMode",ftHandle,ucMaske,ucEnable)
FT_Result := DllCall("ftd2xx.dll\FT_Write,ftHandle",FTOutBuf,BufferSize,ResultPtr)
FT_Result := DllCall("ftd2xx.dll\FT_Close",ftHandle)

Das sieht aus als wäre das eine Passage die du direkt von Delphi übernommen hast.

Ist in AHK unnötig, da der DllCall dann tatsächlich ausgeführt wird und weder Ergebnis hat.

Dazu wird das ganze noch Fehlerhaft aufgerufen.

 

Ich hoffe Ich konnte dir helfen.icon_mrgreen.gif


Visit the new forum ahkscript.org.

http://ahkscript.org


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

Vielen Dank für Deine Fehlerkorrekturen, sie helfen mir die AHK Syntax zu verstehen.
Aber ich blicke noch nicht richtig durch.
Ich hatte geglaubt, dass Du über das Delphi-script verstehst was ich in AHK programmieren will.
Ok, das klappt so nicht. Ich setze zurück auf Anfang.
Grundlage für alles ist diese Anleitung des Herstellers:

ftdichip.com/Support/Documents/ProgramGuides/D2XX_Programmer's_Guide(FT_000071).pdf

Bitte geh auf den Link und lad Dir das pdf herunter.(830kb)
Unter Punkt 3.6 (Seite 12)  ist die erste Funktion beschrieben die ich brauche um die Relaiskarte anzusprechen.
Wenn Du mir an dieser Funktion erläutern kanns, wie ich mit AHK vorgehen muß um z.B. die Nummer vom Gerät "numDevs" in MsgBox angezeigt zubekommen, dann wäre ich einen großen Schritt weiter.

 

Vielen Dank für Deine Mühe



IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007

Hallo pebe54,

 

Was du mal sicher benötigst sind Definitionen für all die Konstanten und Structs. Die gibt es normalerweise in Form von Header Dateien bei C/C++ wären dies (*.h)

 

Dann wäre es auch gut zu wissen was dein Know-How stand ist, damit wir dir entsprechende Hilfe geben können.

 

 

Grüsse



nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012

du musst noch @ urch & ersetzten.

Allerdings kommen wir, wie IsNul gesagt hat,ohne die Header Datei kein Stück weiter.

Das Ergebnis wird auch nicht in einer Msgbox Sichtbar gemacht werden können, ohne Numput und Numget zu verwenden.


Visit the new forum ahkscript.org.

http://ahkscript.org


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

Hallo IsNull, hallo nnnik,
danke, das Ihr mir helfen wollt. Zuerst der Stand meiner Kenntnisse. Ich habe vor mehr als 30 Jahren mit Basic angefangen, mich dann mit html, asp , SQL-Datenbankanbindungen  Access 2000 beschäftigt.
Soweit so gut. Ich habe also ein 8 Kanal USB-Relais welches von einem FTDI-Chip FT245R gesteuert wird. Neben dem Relais hat mir der Hersteller zum einen ein Driver-setup.exe und ein D2XX_Programmer's_Guide(FT_000071).pdf zur Verfügung gestellt.
 
Nun zu der Header-Datei. Was meint Ihr? Das ist doch eine "Definitionsdatei" bei C++,oder? ch habe keine weitere Datei zur Verfügung, außer die ftd2xx.dll und die PDF-Beschreibungen.
 
Ich habe versucht die erforderlichen Deklarationen der Variablen und Befehle in AHK nochmal umzusetzen, so funktioniert es aber noch nicht. Das Relais will einfach nicht klicken, bzw. ich bekomme schon den BitModus nicht gesetzt.sad.png
 

;***********Steuerung USB-Relais**********
; ***********Deklaration der Variablen laut Programmers Guide, Beispiele
; FT_HANDLE ftHandle
; FT_STATUS ftStatus
; DWORD numDevs
; UCHAR bIO_Mask = 0xff                                     1+2+4+8+16+32+64+128 = 255 setzt für alle Ausgänge(Relais) den BitModus
; UCHAR Mode = 1; // Set asynchronous bit-bang mode UChar
; DWORD BytesWritten       
; char  bO_Mask[256]  // Contains data to write to device   1=Relais1|2=Relais2|4=Relais3|8=Relais4|....|128=Relais8|   => 255 = alle ein  => 0 = alle aus  => 3 = R1+R2 ein
 
SetFormat,integer,hex
H := A_ScreenHeight-100
ftHandle := "Ptr"
ftStatus := "Ptr"
FT_LIST_NUMBER_ONLY := 0x80000000
VarSetCapacity(a, A_PtrSize*2 )
numDevs := NumGet(a,A_PtrSize*2,"Char")
BytesWritten := NumGet(a,A_PtrSize,"Char")

ftStatus := DLLCall("ftd2xx.dll\FT_ListDevices","Ptr", &numDevs, "UInt", 0,"UInt", FT_LIST_NUMBER_ONLY)
        numDevs := Asc(numDevs)
 StatusListDevices := ftStatus                                                       ; ftStatus=0 - ok.                                  
ftStatus := DLLCall("ftd2xx.dll\FT_Open","UInt",0, "Ptr", &ftHandle)                                                          
 StatusOpen := ftStatus                                                              ; ftStatus=0 - ok. 
 Transform, StatusftHandle, Asc, %ftHandle%
 
 VarSetCapacity(bIO_Mask,1,0)
 NumPut(0xff, bIO_Mask, 0, "Uchar" )
;bIO_Mask := NumGet(bIO_Mask,0,"Uchar")
 VarSetCapacity(Mode,1,0)
 NumPut(1,Mode, 0,"Uchar")
;Mode := NumGet(Mode,0,"Uchar")
 
;FT_SetBitMode(ftHandle, bIO_Mask, $01) = Delphi
 
ftStatus := DLLCall("ftd2xx.dll\FT_SetBitMode","Ptr",ftHandle, "Uchar", bIO_Mask, "Uchar", Mode)
 StatusBitMode := ftStatus                                                           ; ftStatus=1 - BitMode nicht gesetzt

 
Volume_Up::
;Volume_Down::
;while GetKeyState("Volume_Down")
Esc::                                                                                       ; nur wegen der Tastatur am 2.Rechner
while GetKeyState("Esc")
{
   ; hier stehen die Befehle für Relais 1-2 ein                      -   auskommentiert weil Bitmode nicht gesetzt!
;listvars
; VarSetCapacity(bO_Mask,1,0)
; NumPut(0x3, bO_Mask, 0, "Uchar" )                              

 
;FT_Write(ftHandle, @bO_Mask, sizeof(bO_Mask), @BytesWritten) = Delphi  @bO_Mask = Pointer | sizeof(bO_Mask) definiert den Zeiger in Array von ganzen Zahlen

 
;ftStatus := DLLCall("ftd2xx.dll\FT_Write","Ptr",ftHandle ,"Ptr", bIO_Mask ,"Ptr", bIO_Mask , "Ptr", BytesWritten )   
 StatusWrite := ftStatus

 
   ; ab hier funktionieren die Befehle 
 Gui, +AlwaysOnTop +Disabled -Caption
 Gui, Font, s24, Verdana
 Gui, Color, EEAA99
 Gui +LastFound  ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
 WinSet, TransColor, EEAA99
 Gui, Add, Text,, - Volumen -`nStatusListDevices = %StatusListDevices%  numDevs = %numDevs% `nStatusOpen = %StatusOpen%  ftHandle = %StatusftHandle% `nStatusBitMode = %StatusBitMode% `nStatusWrite = %StatusWrite%
 ;Gui, Show, xCenter y%H%, NoActivate, Volumen
 Gui, Show
}
while GetKeyState("Volume_UP")
{
   ; ab hier sollen die Befehle für Relais 3-4 ein stehen - bO_Mask := 12
 Gui, +AlwaysOnTop +Disabled -Caption 
 Gui, Font, s24, Verdana 
 Gui, Color, EEAA99
 Gui +LastFound  ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
 WinSet, TransColor, EEAA99
 Gui, Add, Text,, + Volumen +
 Gui, Show, xCenter y%H%, NoActivate, Volumen
}
 Gui, Destroy
   ; ab hier sollen die Befehle für alle Relais aus  stehen - bO_Mask := 0
Return 

 

 

 
Vieleicht schaut Ihr noch mal drüber.
 
 
Danke und beste Grüße


Edited by IsNull, 29 January 2013 - 08:54 PM.


IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007
Hi,

Die Funktion FT_SetBitMode hat keine komplexen Paremeter (Structs), d.h. du benötigst VarSetCapacy und Numput mal sicher nicht. Ganz so kompliziert ist AHK also auch nicht happy.png

Unter deinen funktionierenden Code:
ftStatus := DLLCall("ftd2xx.dll\FT_ListDevices","Ptr", &numDevs, "UInt", 0,"UInt", FT_LIST_NUMBER_ONLY)        
numDevs := Asc(numDevs) 
StatusListDevices := ftStatus                                 ;// ftStatus=0 - ok.                                 
ftStatus := DLLCall("ftd2xx.dll\FT_Open","UInt",0, "Ptr", &ftHandle)                              StatusOpen := ftStatus
Kommt nun also für FT_SetBitMode:
bIO_Mask := 0xFF
mode := 1 
ftStatus := DLLCall("ftd2xx.dll\FT_SetBitMode","Ptr",ftHandle, "Uchar", bIO_Mask, "Uchar", mode) 
StatusBitMode := ftStatus                               ;// ftStatus=1 - BitMode nicht gesetzt
MsgBox % "BitMode set? " ftStatus


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

Hallo,

gut, so einfach hatte ich es mir dann auch vorgestellt, aber es klappt so nicht. Ich bekomme für ftstatus eine 1 zurück, also Bitmodus nicht gesetzt. Die zu erwartenden Werte für ftstatus habe ich den funktionierenden Delphi-Scrip entnommen. Deren Interpretation sollte also auch in AHK so zutreffen. Aus reiner Neugier habe ich mir im Delphi den Wert für ftHandle, nach ft_Open, via Msgbox anzeigen lassen. Als String gewandelt wird 3809680 angezeigt. Bei AHK wird durch die Zuweisung auf StatusftHandle und Asc-Wandlung für ftHandle 8592 ausgegeben. Was hat das zu bedeuten, ist das von Bedeutung?

Hast Du noch eine Idee?



IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007
Dein Problem kann entweder durch falsche AHK Syntax bedingt sein, oder durch falsche Verwendung der API (Wenn Vorbedingungen für die FT_SetBitMode Funktion nicht erfüllt sind)
 
Ein Handle ist eine Zahl, und es ist zu erwarten, dass ein Handle bei jedem Programm-Aufruf einen anderen Wert annimmt. Ein Transform für das Handle scheint mir unnötig.

Ich würde nach jedem DLLCall(In der AHK Help zum Thema DLLCall findest du eine Beschreibung zu Errorlevel.) mit einem "if" den ErrorLevel abfragen, und wenn dieser nicht i.O. ist ausgeben. Das gibt Aufschluss über die falsche Verwendung von Funktionen, d.h. ob Parameter, Typen Namen etc. korrekt verwendet wurden.
 
DllCall(xyz) ;// irgend ein DllCall

if(!ErrorLevel) ;// Wenn ErrorLevel ungleich 0 ist (0 impliziert Erfolg)
{
 msgbox % "Fehler: " ErrorLevel
}


just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Schau Dir das mal an, ist natürlich ungetestet:

; type
; FT_Result = Integer -> Int
; FT_Handle = Dword   -> UInt

; var
; FRM_Main: TFRM_Main;
FT_hd := 0        ; DWORD (FT_Handle)     -> UInt
; USB-Gerät suchen & öffnen
dwDevCount := 0   ; DWORD                 -> UInt
Result := 0       ; Integer (FT_Result)   -> Int
;USB SetBitMode
bIO_Mask := 0     ; Byte                  -> UChar
;Relais schalten
bO_Mask := 0      ; Byte                  -> UChar
iWritten := 0     ; Integer               -> Int

; const
FT_LIST_NUMBER_ONLY := 0x80000000

; procedure TFRM_Main.Button1Click(Sender: TObject);
; begin    //suchen & öffnen
; Result := FT_ListDevices(@dwDevCount, NIL , FT_LIST_NUMBER_ONLY);
Result := DllCall("ftd2xx.dll\FT_ListDevices", "UIntP", dwDevCount, "Ptr", 0, "UInt", FT_LIST_NUMBER_ONLY, "Int")
; Result := FT_Open(0,@FT_hd);
Result := DllCall("ftd2xx.dll\FT_Open", "Int", 0, "UIntP", FT_hd, "Int")
bIO_Mask := 255
; Result := FT_SetBitMode(FT_hd, bIO_Mask, $01);
Result := DllCall("ftd2xx.dll\FT_SetBitMode", "UInt", FT_hd, "UChar", bIO_Mask, "UChar", 0x01, "Int")
; schalten Relais 1+2 ein
bO_Mask := Chr(3) ; hier muss wahrscheinlich ein Zeichen genutzt werden, das den ASCII-Wert 0x03 repräsentiert
; Result := FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten);
Result := DllCall("ftd2xx.dll\FT_Write", "UInt", FT_hd, "Ptr", &bO_Mask, "Int", 1, "IntP", iWritten, "Int")
If (Result = 0) ; then
   If (dwDevCount <> 0) ; then
      MsgBox, 0, Ergebnis, Nummer = %dwDevCount%   |   FT_hd = %FT_hd%
   Else
      MsgBox, 0, Fehler, Keine USB-Relais vorhanden!
; end;
/*
implementation
{$R *.dfm}

   function FT_ListDevices(pvArg1:Pointer; pvArg2:Pointer; dwFlags:Dword):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_ListDevices';
   function FT_Open(iDevice: integer; ftHandle:Pointer):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Open';
   function FT_SetBaudRate(ftHandle:DWord; BaudRate:DWord):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_SetBaudRate';
   function FT_SetBitMode(ftHandle:DWord; ucMaske, ucEnable: Byte):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_SetBitMode';
   function FT_Write(ftHandle:DWord; FTOutBuf: Pointer; BufferSize: LongInt; ResultPtr: Pointer):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Write';
   function FT_Close(ftHandle:DWord):
      FT_Result; stdcall; External 'ftd2xx.dll' name 'FT_Close';
*/


Prefer ahkscript.org for the time being.


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

Hier das geänderte Script:

 

;***********Steuerung USB-Relais**********

; ***********Deklaration der Variablen laut Programmer's Guide, Beispiele
; FT_HANDLE ftHandle
; FT_STATUS ftStatus
; DWORD numDevs
; UCHAR bIO_Mask = 0xff 1+2+4+8+16+32+64+128 = 255
; UCHAR Mode = 1; // Set asynchronous bit-bang mode UChar
; DWORD BytesWritten
; char bO_Mask[256] // Contains data to write to device 1=Relais1|2=Relais2|4=Relais3|8=Relais4|....|128=Relais8| => 255 = alle ein => 0 = alle aus => 3 = R1+R2 ein

;SetFormat,integer,hex
H := A_ScreenHeight-100
ftHandle := "Ptr"
ftStatus := "Ptr"
FT_LIST_NUMBER_ONLY := 0x80000000
VarSetCapacity(a, A_PtrSize*2 )
numDevs := NumGet(a,A_PtrSize*2,"Char")
BytesWritten := NumGet(a,A_PtrSize,"Char")


ftStatus := DLLCall("ftd2xx.dll\FT_ListDevices","Ptr", &numDevs, "UInt", 0,"UInt", FT_LIST_NUMBER_ONLY)
numDevs := Asc(numDevs)
StatusListDevices := ftStatus ; ftStatus=0 - ok.
ftStatus := DLLCall("ftd2xx.dll\FT_Open","UInt",0, "Ptr", &ftHandle)
StatusOpen := ftStatus ; ftStatus=0 - ok.
;StatusftHandle := Asc(ftHandle)
Transform, StatusftHandle, Asc, %ftHandle%

if(!ErrorLevel) ;// Wenn ErrorLevel ungleich 0 ist (0 impliziert Erfolg)
{
OpenErrorLevel := ErrorLevel
}
bIO_Mask := 0xFF
mode := 1
ftStatus := DLLCall("ftd2xx.dll\FT_SetBitMode","Ptr",ftHandle, "Uchar", bIO_Mask, "Uchar", mode)
StatusBitMode := ftStatus

if(!ErrorLevel) ;// Wenn ErrorLevel ungleich 0 ist (0 impliziert Erfolg)
{
BitModeErrorLevel := ErrorLevel
}

Volume_Up::
;Volume_Down::
;while GetKeyState("Volume_Down")
Esc:: ; nur wegen der Tastatur am 2.Rechner
while GetKeyState("Esc")
{
; hier stehen die Befehle für Relais 1-2 ein
;listvars

bO_Mask := 3
;FT_Write(ftHandle, @bO_Mask, sizeof(bO_Mask), @BytesWritten) = Delphi @bO_Mask = Pointer | sizeof(bO_Mask) definiert den Zeiger in Array von ganzen Zahlen

ftStatus := DLLCall("ftd2xx.dll\FT_Write","Ptr",ftHandle ,"Ptr", &bIO_Mask ,"Ptr", bIO_Mask , "Ptr", &BytesWritten )
StatusWrite := ftStatus
if(!ErrorLevel) ;// Wenn ErrorLevel ungleich 0 ist (0 impliziert Erfolg)
{
WriteErrorLevel := ErrorLevel
}
; ab hier funktionieren die Befehle
Gui, +AlwaysOnTop +Disabled -Caption
Gui, Font, s24, Verdana
Gui, Color, EEAA99
Gui +LastFound ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
WinSet, TransColor, EEAA99
Gui, Add, Text,, - Volumen -`nStatusListDevices = %StatusListDevices% numDevs = %numDevs% `nStatusOpen = %StatusOpen% OpenErrorLevel= %OpenErrorLevel% ftHandle = %StatusftHandle% `nStatusBitMode = %StatusBitMode% BitModeErrorLevel=%BitModeErrorLevel%`nStatusWrite = %StatusWrite% WriteErrorLevel=%WriteErrorLevel%
;Gui, Show, xCenter y%H%, NoActivate, Volumen
Gui, Show
}
while GetKeyState("Volume_UP")
{
; ab hier sollen die Befehle für Relais 3-4 ein stehen - bO_Mask := 12
Gui, +AlwaysOnTop +Disabled -Caption
Gui, Font, s24, Verdana
Gui, Color, EEAA99
Gui +LastFound ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
WinSet, TransColor, EEAA99
Gui, Add, Text,, + Volumen +
Gui, Show, xCenter y%H%, NoActivate, Volumen
}
Gui, Destroy
; ab hier sollen die Befehle für alle Relais aus stehen - bO_Mask := 0
Return

Leider bring uns ErrorLevel nicht wirklich weiter.  sad.png

 

Das Ergebnis der Änderungsvorschlägen von just me, auf Anhieb ohne Fehler - Respekt, aber das Relais will trotzdem nicht klicken sad.png
 



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Du darfst die Rückgabewerte wie dwDevCount und TH_hd nach dem DllCall nicht verändern.

"UIntP", dwDevCount bewirkt z.B. Folgendes:

  • Ein temporärer Speicherbereich in der Größe einer UInt (4 Bytes) wird angelegt.
  • Ein Pointer auf diesen Bereich wird an die aufgerufene Funktion übergeben.
  • Den UInt Wert aus dem temporären Speicher wird nach Rückkehr auslesen und in dwDevCount abgelegt.

Der Wert in dwDevCount ist damit nach dem DllCall korrekt.

Edit: Probiere mal das:

VarSetCapacity(bO_Mask, 4, 0)
NumPut(0x03, bO_Mask, 0, "UChar")
; Result := FT_Write(FT_hd, @bO_Mask, sizeof(bO_Mask), @iWritten);
Result := DllCall("ftd2xx.dll\FT_Write", "UInt", FT_hd, "Ptr", &bO_Mask, "Int", 1, "IntP", iWritten, "Int")

 

 


Edited by just me, 30 January 2013 - 04:58 PM.

Prefer ahkscript.org for the time being.


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

OK, mein Fehler. Ich wollte die Werte von dwDevCount und FT_hd jeweils einer Variablen StatusdwDevCount und StatusFT_hd zuweisen, um sie am Ende angezeigt zu bekommen. Das sollte doch kein Problem sein, Oder?

Ich hab den Fehler und auch die anderen Asc-Umwandlungen beseitigt. Ich gehe davon aus das die Ergebnisse der jeweiligen Result auch im AHK richtig wären. Demnach müßten die Ergebnisse für Result = 0, für StatusdwDevCount=1 und für StatusdFT_hd = eine Zahl sein. Stimmt bei diesen Script nicht für alle Werte.

 

;***********Steuerung USB-Relais**********
;Vorschlag von just me
; var
; FRM_Main: TFRM_Main;
FT_hd := 0        ; DWORD (FT_Handle)     -> UInt
; USB-Gerät suchen & öffnen
dwDevCount := 0   ; DWORD                 -> UInt
Result := 0       ; Integer (FT_Result)   -> Int
;USB SetBitMode
bIO_Mask := 0     ; Byte                  -> UChar
;Relais schalten
bO_Mask := 0      ; Byte                  -> UChar
iWritten := 0     ; Integer               -> Int
H := A_ScreenHeight-100


 

Result := DllCall("ftd2xx.dll\FT_ListDevices", "UIntP", dwDevCount, "Ptr", 0, "UInt", FT_LIST_NUMBER_ONLY, "Int")
 StatusListDevices := Result
        StatusdwDevCount := dwDevCount


 

if(!ErrorLevel)
{
ListDevicesErrorLevel := ErrorLevel
}                                                                                   
Result := DllCall("ftd2xx.dll\FT_Open", "Int", 0, "UIntP", FT_hd, "Int")
 StatusOpen := Result                                                           
 StatusFT_hd := FT_hd


 

if(!ErrorLevel)
{
OpenErrorLevel := ErrorLevel
}
 bIO_Mask := 0xFF
Result := DllCall("ftd2xx.dll\FT_SetBitMode", "UInt", FT_hd, "UChar", bIO_Mask, "UChar", 0x01, "Int")
 StatusBitMode := Result                             


 

if(!ErrorLevel)
{
BitModeErrorLevel := ErrorLevel
}


 

Volume_Up::
;Volume_Down::
;while GetKeyState("Volume_Down")
Esc::                                                                                       ; nur wegen der Tastatur am 2.Rechner
while GetKeyState("Esc")
{
   ; hier stehen die Befehle für Relais 1-2 ein  
 ;listvars


 

bO_Mask := Chr(3)
Result := DllCall("ftd2xx.dll\FT_Write", "UInt", FT_hd, "Ptr", &bO_Mask, "Int", 1, "IntP", iWritten, "Int")
 StatusWrite := Result
if(!ErrorLevel)
{
WriteErrorLevel := ErrorLevel
}
   ; ab hier funktionieren die Befehle 
 Gui, +AlwaysOnTop +Disabled -Caption
 Gui, Font, s24, Verdana
 Gui, Color, EEAA99
 Gui +LastFound  ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
 WinSet, TransColor, EEAA99
 Gui, Add, Text,, - Volumen -`nStatusListDevices = %StatusListDevices%  ListDevicesErrorLevel=%ListDevicesErrorLevel% StatusdwDevCount = %StatusdwDevCount% `nStatusOpen = %StatusOpen% OpenErrorLevel= %OpenErrorLevel% StatusFT_hd = %StatusFT_hd% `nStatusBitMode = %StatusBitMode% BitModeErrorLevel=%BitModeErrorLevel%`nStatusWrite = %StatusWrite% WriteErrorLevel=%WriteErrorLevel%
 ;Gui, Show, xCenter y%H%, NoActivate, Volumen
 Gui, Show
}
while GetKeyState("Volume_UP")
{
   ; ab hier sollen die Befehle für Relais 3-4 ein stehen - bO_Mask := 12
 Gui, +AlwaysOnTop +Disabled -Caption 
 Gui, Font, s24, Verdana 
 Gui, Color, EEAA99
 Gui +LastFound  ; Macht das GUI-Fenster zum zuletzt gefundenen Fenster.
 WinSet, TransColor, EEAA99
 Gui, Add, Text,, + Volumen +
 Gui, Show, xCenter y%H%, NoActivate, Volumen
}
 Gui, Destroy
   ; ab hier sollen die Befehle für alle Relais aus  stehen - bO_Mask := 0
Return 


 

 


 


 



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Zu spät (s.o.) 


Prefer ahkscript.org for the time being.


pebe54
  • Members
  • 17 posts
  • Last active: Jan 24 2014 05:26 PM
  • Joined: 16 Jan 2013

Hallo, da bin ich wieder,

just me, die Definition mit VarSetCapacity .... habe ich vorher auch schon probiert. Klappt auch nicht.

Auf der Suche nach einer Lösung habe ich hier einen Beitrag im englischen Forum gefunden. Unter "dllcall parameter issues" hatte einer bereits 2007 das gleiche Problem. Wenn ich es (mit meinen sehr schlechtem Englisch) richtig verstanden habe, konnten die damals das Problem lösen. Offensichtlich durch das vorhergehende Laden der gesamten Dll. So ähnlich funktioniert ja auch das Delphi-Programm, erst werden die Funktionen "definiert" und später im Programm verwendet. Was haltet Ihr davon?