Automatisation avec interception des boutons et des clics de souris. - page 11

 
DKeN:
cm=GetDlgItem(hdlg,ID_SYMBOL) ;
int pos=SendMessageA(cm,CB_GETCOUNT,0,0);//obtient le numéro dans la liste
//trouver la paire
string fs=" ;
for(int l=0;l<pos;l++){
int ll=SendMessageA(cm,CB_GETLBTEXT,l,fs) ;
Print(ll," ",fs) ;
}

Veuillez m'indiquer comment obtenir correctement une liste d'outils dans la fenêtre de commande (F9).

J'obtiens le nombre d'éléments, mais je n'arrive pas à obtenir exactement les rangées par numéro, cela renvoie -1.

#define ID_SYMBOL 0x053E //nom du caractère à sélectionner

cmhandle ComboBox

Avant de pouvoir recevoir un texte, vous devez d'abord préparer un tampon suffisamment grand pour recevoir le texte. Et votre ligne fs n'a pas de longueur du tout. C'est étrange que votre terminal ne se plante pas à cause de ce désordre. C'est pourquoi vous devez initialiser fs au préalable avec une chaîne suffisamment longue. Si nous considérons le cas général, lorsque la longueur de la chaîne reçue peut être n'importe quelle longueur, nous devons d'abord connaître cette longueur avec le message CB_GETLBTEXTLEN pour savoir quelle taille de tampon est nécessaire.
 
lasso:

Alexey, merci, la fonction fonctionne, mais...


Je n'ai besoin que de l'identifiant du fil, car j'ai deux terminaux en service.

Je m'en suis sorti avec l'identification de l'en-tête, mais j'aimerais quand même savoir comment déterminer l'ID du fil sous le testeur ?

L'ID du thread actuel peut être obtenu avec la fonction GetCurrentProcessId()
 
Meat:
Avant de recevoir un texte, vous devez d'abord préparer un tampon suffisamment grand pour recevoir le texte........

TEXTE ! !!

En adaptant votre fonction à mes besoins

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

est tombé sur le fait que le tampon de chaîne de caractères textbuf, déclaré localement au niveau de la fonction, n'est initialisé qu'une seule fois lors du premier appel,

et se comporte alors comme une variable statique.

string textbuf="Абвгдежзийклмнопрсту";   // В_ЭТОЙ_СТРОКЕ_255_СИМВОЛОВ
Print("textbuf после инициализации =",textbuf);
Pourriez-vous commenter cette situation ?
 
lasso:

TEXTE ! !!

En adaptant votre fonction à mes besoins

est tombé sur le fait que le tampon de chaîne de caractères textbuf, déclaré localement au niveau de la fonction, n'est initialisé qu'une seule fois lors du premier appel,

et se comporte alors comme une variable statique.

Pourriez-vous commenter cette situation ?

Je vois ce que vous voulez dire. Vous voulez dire que le tampon stocke l'ancienne valeur récupérée par GetText. Je me souviens que ça me surprenait aussi. Mais c'est une fonctionnalité MQL. Quelque part sur le forum, les développeurs ont dit que toutes les chaînes constantes définies au niveau du compilateur sont stockées en permanence en mémoire dans un endroit séparé et ne sont pas perdues (écrasées) lorsqu'on quitte la fonction. Leur adresse est initialement connue et ne change pas pendant l'opération de programmation. Par conséquent, lors d'un nouvel appel de la fonction, lorsque la même chaîne constante est accédée, elle est prise à la même adresse. Mais nous avons un texte différent qui a été placé par la fonction GetText.
De même, vous pouvez faire simplement Print("Abvgdezijklmnostu") et obtenir un texte différent :) Donc, il ne s'agit pas d'une variable textbuf, mais d'une chaîne constante. Au moment de la compilation, toutes les chaînes constantes sont vérifiées et placées dans la base de données, et seulement les chaînes uniques. Si des chaînes identiques sont détectées, une seule instance de base de données commune est créée pour elles. Par conséquent, si vous perturbez cette instance pendant que vous travaillez, tous les appels à cette chaîne de caractères à partir de n'importe quel endroit du programme renverront également un résultat erroné.

Si vous ne l'aimez pas, vous pouvez créer un tampon de manière programmatique :

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

Alors il n'y aura pas de problème de ce genre. Je ne me souviens pas si c'est bien de faire ça. Vous n'obtiendrez pas d'erreur d'accès à la mémoire, cependant. Vous devriez essayer.

 
Meat:
De cette façon, un tel problème ne se produirait pas. Mais je ne me souviens pas maintenant si c'est possible de le faire de cette façon. Je me demande s'il n'y aura pas une erreur d'accès à la mémoire... Essayez-le.

Dès que j'ai lu que "255 caractères ne rentrent pas dans l'écran et gâchent l'aspect du forum", je l'ai fait.

Mais cette option n'a pas fonctionné, la fonction API n'a rien retourné... J'ai donc quitté votre variante.

......

En tout cas, je vous remercie beaucoup pour cette nouvelle réponse détaillée.

 
lasso:

Dès que j'ai lu que "255 caractères ne rentrent pas dans l'écran et gâchent l'aspect du forum", je l'ai fait.

Mais cette option n'a pas fonctionné, la fonction API n'a rien retourné... C'est pourquoi j'ai quitté votre variante.

......

En tout cas, je vous remercie beaucoup pour cette nouvelle réponse détaillée.


Tout le plaisir est pour moi.

D'après ce que j'ai compris, la raison en est que dans ce cas, la référence au tampon de texte original appartenant à la variable n'est pas transmise à la fonction, mais à sa copie, c'est-à-dire un tampon temporaire créé avant l'appel de la fonction. Par conséquent, même si la fonction modifie le texte dans ce tampon, cela n'a aucun effet, car le tampon d'origine reste inchangé. Et la référence au tampon temporaire est perdue lorsque la fonction se termine. J'ai déjà eu du mal à passer une chaîne de caractères dans une DLL à cause de cela. Mais il existe une solution. Vous devez passer un élément du tableau de chaînes dans la fonction. Dans ce cas, aucun tampon intermédiaire n'est créé, et la fonction obtient une référence au tampon d'origine.

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

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

Cela devrait fonctionner.

 
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;
       }
   }
}

Je peux obtenir la longueur normalement, mais je ne peux pas obtenir le texte :-(

Veuillez expliquer comment initialiser la chaîne correctement, et en général, est-il possible de l'implémenter sans dll externe ?

il est nécessaire de trouver un symbole dans la liste des outils et de le sélectionner.


 
DKeN:

Je peux obtenir la longueur normalement, mais je ne peux pas obtenir le texte :-(

Veuillez expliquer comment initialiser la chaîne correctement, et en général, est-il possible de l'implémenter sans dll externe ?

il est nécessaire de trouver un symbole dans la liste des outils et de le sélectionner.

A propos de l'initialisation de la chaîne, je viens de l'expliquer dans un message précédent au camarade lasso. Vous pouvez soit utiliser un élément du tableau de chaînes, soit simplement initialiser la variable chaîne avec une constante de longueur suffisante. Dans votre cas, il est plus facile d'utiliser une constante, car vous savez d'avance que la taille de la chaîne résultante ne dépassera pas 78 octets :

12 octets (ticker de l'instrument) + 2 octets (virgule et espace) + 64 octets (nom complet de l'instrument) . Il s'agit de la longueur maximale possible de la chaîne. Eh bien, vous pouvez arrondir à 80.

Mais si vous voulez simplement SÉLECTIONNER un instrument spécifique dans la liste, vous n'avez pas besoin d'obtenir son nom. Il suffit d'utiliser le message CB_SELESTRING. En tant que paramètre de type chaîne, il suffit d'envoyer la partie initiale du nom ("EURUSD,") pour qu'il trouve et sélectionne lui-même l'élément approprié dans la liste.

 

Le conseiller API du Million Dollar Robot du futur proche : Il attire beaucoup d'affaires rentables dans le terminal lui-même... :) et quand, dans un mois ou deux, un nouveau millionnaire essaiera de retirer ses bénéfices auprès du courtier, il découvrira qu'il n'y a pas eu une seule transaction... mais la période de remboursement pour le conseiller est terminée... :))))))))

 

Les gars, s'il vous plaît, aidez-moi à identifier la poignée des boutons Acheter/Vendre dans la boîte de commande. J'ai trouvé la poignée de la boîte de commande :

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); // хэндл от Ордер-а

Ensuite, j'essaie de déterminer la poignée du bouton (par exemple, Acheter), mais j'obtiens 0 en réponse.

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

La chose la plus intéressante est que je ne peux pas trouver la poignée d'un quelconque élément dans la caseExécution immédiate. Je ne trouve pas non plus de poignée pour l'exécution immédiate elle-même. Bien que WinSpy++ le considère comme un élément séparé et affiche l'ID 0xFFFFFF pour lui.

S'il vous plaît, ne jugez pas strictement, je suis un débutant.

Raison: