Automatisierung mit Abfangen von Tasten und Mausklicks. - Seite 11

 
DKeN:
cm=GetDlgItem(hdlg,ID_SYMBOL);
int pos=SendMessageA(cm,CB_GETCOUNT,0,0);//Nummer in der Liste ermitteln
//das Paar finden
string fs=";
for(int l=0;l<pos;l++){
int ll=SendMessageA(cm,CB_GETLBTEXT,l,fs);
Print(ll," ",fs);
}

Wie bekomme ich eine Liste der Werkzeuge im Auftragsfenster (F9)?

Ich erhalte die Anzahl der Elemente, kann aber nicht genau die Zeilen nach Anzahl erhalten, sondern gebe -1 zurück.

#define ID_SYMBOL 0x053E //Zeichenname zur Auswahl

cmhandle ComboBox

Bevor Sie einen Text empfangen können, müssen Sie zunächst einen Puffer vorbereiten, der groß genug für den Empfang des Textes ist. Und Ihre fs-Zeile hat überhaupt keine Länge. Es ist seltsam, dass Ihr Terminal wegen dieses Durcheinanders nicht abstürzt. Deshalb müssen Sie fs vorher mit einer ausreichend langen Zeichenkette initialisieren. Wenn wir den allgemeinen Fall betrachten, dass die Länge der empfangenen Zeichenkette beliebig sein kann, sollten wir diese Länge zunächst mit der Nachricht CB_GETLBTEXTLEN ermitteln, um zu wissen, welche Puffergröße erforderlich ist.
 
lasso:

Alexey, danke, die Funktion funktioniert, aber...


Es wird nur die Gewinde-ID benötigt, da ich zwei Terminals in Gebrauch habe.

Ich bin mit der Header-Identifikation aus der Sache herausgekommen, aber ich würde trotzdem gerne wissen, wie man die Thread-ID unter dem Tester bestimmt?

Die ID des aktuellen Threads kann mit der Funktion GetCurrentProcessId() ermittelt werden
 
Meat:
Bevor Sie einen Text empfangen, müssen Sie zunächst einen Puffer vorbereiten, der groß genug ist, um den Text zu empfangen........

TEXT!!!

Wenn Sie Ihre Funktion an meine Bedürfnisse anpassen

int FindWindow(string class, string caption, bool captionexactly=false)

stieß auf die Tatsache, dass der auf Funktionsebene lokal deklarierte Stringpuffer string textbuf nur einmal beim ersten Aufruf initialisiert wird,

und verhält sich dann wie eine statische Variable.

string textbuf="Абвгдежзийклмнопрсту";   // В_ЭТОЙ_СТРОКЕ_255_СИМВОЛОВ
Print("textbuf после инициализации =",textbuf);
Möchten Sie sich zu dieser Situation äußern?
 
lasso:

TEXT!!!

Wenn Sie Ihre Funktion an meine Bedürfnisse anpassen

stieß auf die Tatsache, dass der auf Funktionsebene lokal deklarierte Stringpuffer string textbuf nur einmal beim ersten Aufruf initialisiert wird,

und verhält sich dann wie eine statische Variable.

Können Sie sich zu dieser Situation äußern?

Ich verstehe, was ich meine. Sie meinen, der Puffer speichert den alten Wert, der von GetText abgerufen wurde. Ich erinnere mich, dass es mich früher auch überrascht hat. Aber es ist eine MMS-Funktion. Irgendwo im Forum sagten die Entwickler, dass alle auf Compilerebene definierten Konstanten an einem separaten Ort dauerhaft im Speicher abgelegt werden und beim Verlassen der Funktion nicht verloren gehen (überschrieben werden). Ihre Adresse ist zunächst bekannt und ändert sich während des Programmablaufs nicht. Daher wird beim erneuten Aufruf der Funktion dieselbe konstante Zeichenkette von derselben Adresse abgerufen, wenn auf sie zugegriffen wird. Aber wir haben dort einen anderen Text, der von der Funktion GetText platziert wurde.
Ebenso kann man einfach Print("Abvgdezijklmnostu") machen und erhält dort einen anderen Text :) Es geht also nicht um die Variable textbuf, sondern um eine konstante Zeichenkette. Bei der Kompilierung werden alle konstanten Zeichenfolgen geprüft und in die Datenbank aufgenommen, und zwar nur eindeutige Zeichenfolgen. Werden identische Zeichenfolgen erkannt, wird nur eine gemeinsame Datenbankinstanz für sie angelegt. Wenn Sie also diese Instanz während der Arbeit verpfuschen, werden alle Aufrufe einer solchen Zeichenkette von irgendeiner Stelle im Programm ebenfalls ein verpfuschtes Ergebnis liefern.

Wenn Ihnen das nicht gefällt, können Sie einen Puffer programmatisch erstellen:

string textbuf="";
for (int i=0; i<255; i++)
  textbuf=textbuf+" ";

Dann gibt es kein solches Problem mehr. Ich weiß nicht mehr, ob man das machen darf. Sie werden jedoch keinen Fehler beim Speicherzugriff erhalten. Versuchen Sie es doch einmal.

 
Meat:
Auf diese Weise würde ein solches Problem nicht auftreten. Aber ich weiß jetzt nicht mehr, ob man das so machen kann. Ich frage mich, ob es nicht einen Speicherzugriffsfehler geben wird... Probieren Sie es aus.

Sobald ich gelesen habe, dass "255 Zeichen nicht auf den Bildschirm passen und das Aussehen des Forums ruinieren", habe ich das getan.

Aber diese Option hat nicht funktioniert, die API-Funktion hat nichts zurückgegeben... Deshalb habe ich Ihre Variante verlassen.

......

Trotzdem vielen Dank für eine weitere ausführliche Antwort.

 
lasso:

Als ich las, dass "255 Zeichen nicht in den Bildschirm passen und das Aussehen des Forums beeinträchtigen", habe ich das sofort getan.

Aber diese Option hat nicht funktioniert, die API-Funktion hat nichts zurückgegeben... Deshalb habe ich Ihre Variante verlassen.

......

Trotzdem vielen Dank für eine weitere ausführliche Antwort.


Mit Vergnügen.

Soweit ich verstanden habe, ist der Grund dafür, dass in diesem Fall der Verweis auf den ursprünglichen Textpuffer, der zu der Variablen gehört, nicht an die Funktion übergeben wird, sondern an seine Kopie, d. h. einen temporären Puffer, der vor dem Aufruf der Funktion erstellt wird. Selbst wenn die Funktion den Text in diesem Puffer ändert, hat dies keine Auswirkungen, da der ursprüngliche Puffer unverändert bleibt. Und der Verweis auf den temporären Puffer geht verloren, wenn die Funktion beendet wird. Ich hatte einmal Probleme mit der Übergabe einer Zeichenkette an die DLL, weil das so ist. Aber es gibt eine Lösung. Sie müssen ein Element des String-Arrays an die Funktion übergeben. In diesem Fall wird kein Zwischenpuffer erstellt, und die Funktion erhält einen Verweis auf den ursprünglichen Puffer.

string buffer[1]={""};
for (int i=0; i<500; i++)
  buffer[0]=buffer[0]+" ";

GetWindowTextA(h,buffer[0],500);

Das sollte funktionieren.

 
void SetSymbol(int hdlg,string symbol,int len){
   int cm=GetDlgItem(hdlg,ID_SYMBOL);
   int pos=SendMessageA(cm,CB_GETCOUNT,0,0);//получим количество в списке
   string fs,ff;
   
   for(int l=0;l<pos;l++){
       //SendMessageA(cm,CB_SETCURSEL,l,0);
       int len_text=SendMessageA(cm,CB_GETLBTEXTLEN,l,0);
       fs=" ";
       for(int m=0;m<len_text+1;m++) fs=StringConcatenate(fs," ");
       int ll=SendMessageA(cm,CB_GETLBTEXT,l,fs);
       Print(len_text," = ",fs); //пусто!!! длину получает.

          
       ff=StringSubstr(fs,0,len);
      // Print(symbol);
       if(ff==symbol) {
            SendMessageA(cm,CB_SETCURSEL,l,0);
            break;
       }
   }
}

Ich kann die Länge normalerweise abrufen, aber ich kann den Text nicht abrufen :-(

Bitte erklären Sie, wie die Zeichenfolge korrekt zu initialisieren, und im Allgemeinen, ist es möglich, es ohne externe DLL zu implementieren?

müssen Sie ein Symbol in der Liste der Werkzeuge suchen und es auswählen.


 
DKeN:

Ich kann die Länge normal abrufen, aber ich kann den Text nicht abrufen :-(

Bitte erklären Sie, wie die Zeichenfolge korrekt zu initialisieren, und im Allgemeinen, ist es möglich, es ohne externe DLL zu implementieren?

müssen Sie ein Symbol in der Liste der Werkzeuge suchen und es auswählen.

Die Initialisierung der Zeichenkette habe ich gerade in einer früheren Nachricht an Genosse Lasso erklärt. Sie können entweder ein Element des String-Arrays verwenden oder die String-Variable einfach mit einer Konstante ausreichender Länge initialisieren. In Ihrem Fall ist es einfacher, eine Konstante zu verwenden, weil Sie im Voraus wissen, dass die Größe der resultierenden Zeichenkette 78 Bytes nicht überschreiten wird:

12 Bytes (Instrumententicker) + 2 Bytes (Komma und Leerzeichen) + 64 Bytes (vollständiger Instrumentenname) . Dies ist die maximal mögliche Länge der Zeichenkette. Nun, Sie können auf 80 aufrunden.

Wenn Sie aber nur ein bestimmtes Instrument in der Liste AUSWÄHLEN wollen, brauchen Sie dessen Namen nicht zu erfahren. Sie müssen nur die Nachricht CB_SELESTRING verwenden. Als String-Parameter brauchen Sie nur den Anfangsteil des Namens ("EURUSD") zu senden, und das Programm findet und wählt den entsprechenden Eintrag in der Liste von selbst aus.

 

Der Million Dollar Robot API-Berater der nahen Zukunft: Es zieht eine Menge profitabler Geschäfte im Terminal selbst an... :) und wenn in ein oder zwei Monaten ein frischgebackener Millionär versucht, seinen Gewinn vom Broker abzuheben, wird er feststellen, dass es nicht einen einzigen Handel gab... aber der Erstattungszeitraum für den Berater ist vorbei... :))))))))

 

Leute, bitte helft mir, den Griff der Kaufen/Verkaufen-Schaltflächen im Bestellfeld zu identifizieren. Ich habe den Griff der Auftragsbox gefunden:

int chart_handle = WindowHandle(Symbol(), Period());
int MT_handle = GetAncestor(chart_handle, GA_ROOT); // GA_ROOT 2
PostMessageA(MT_handle, WM_KEYDOWN, VK_F9, 0); // открываем окошко Ордер
Sleep(1000); // Wait. This is important!
int Order_handle = GetLastActivePopup(MT_handle); // хэндл от Ордер-а

Als Nächstes versuche ich, den Handle der Schaltfläche zu ermitteln (z. B. Kaufen), aber ich erhalte 0 als Antwort.

int Buy_handle = GetDlgItem(Order_handle, 0x40C); // 0x40C найдено с помощью WinSpy++

Das Interessanteste ist, dass ich im Feld "Sofortige Ausführung" den Handle eines Elements nicht finden kann. Ich kann auch keinen Handle für die Sofortige Ausführung selbst finden. WinSpy++ sieht es jedoch als separates Element und zeigt dafür die ID 0xFFFFFF an.

Bitte urteilen Sie nicht zu streng, ich bin ein Anfänger.