IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

[Tutoriel] Envoyer des chaînes et structures par PostMessage


Sujet :

Delphi

  1. #1
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut [Tutoriel] Envoyer des chaînes et structures par PostMessage
    Bonjour à tous !

    Je vous propose aujourd'hui un nouveau tutoriel sur l'envoi de chaînes ou de structures par PostMessage en utilisant la table d'atomes.

    N'hésitez pas à faire part de vos réactions

    Bonne lecture !

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Bonjour,

    Personnellement j'utilise un autre approche que je trouve bcp plus simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    type
      TMessageData = class
        UnEntier: Integer;
        UneChaine: string;
        UnStream: TStream;
        NImporteQuoi: TNImportQuoi;
      end;
     
      TDataMessage = record
        Msg: Integer;
        Null: Integer;
        Data: TMessageData;
       Result : Integer;
      end;
     
    procedure SendInfos(HWnd, Msg: Integer; UnEntier, UneChaine...);
    var
      data: TMessageData;
    begin
      data := TMessageData.Create;
      data.UnEntier := UnEntier;
      data.UneChaine := UneChaine;
      ...
      PostMessage(HWnd, Msg, 0, Integer(@data));
    end;
    le destinataire du message est responsable de la suppression de "data", mais il est possible d'ajouter ces objets à une ThreadList globale qu'on purge le cas échéant quand c'est nécessaire.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    C'est possible en effet

    Par record, il faudra prendre soin de faire appel à GetMem/FreeMem (New/Dispose) et pas simplement déclarer une variable locale à la fonction !
    Mon approche se veut cependant plus universelle et autorise l'envoi entre processus

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    J'ai jamais eu le temps de m'occuper de [QR] Comment passer une string dans un message Windows ? qui utilise WM_COPYDATA qui fonctionnee en inter-processus
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    ...mais qui est obligatoirement synchrone par SendMessage

  6. #6
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    @AndNotY,

    Salut, j'ai parcouru tout ton article, et à la fin je me suis demandé à quoi cela peut servir en cas réel ? (je préfère passer pour un idiot, mais je pose quand même la question...)

    Est-ce un moyen de transmettre des données (tableau, chaîne, nombre) entre 2 applications ?


  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Tu peux envoyer tout ce que tu veux, entre threads ou entre processus

    Voici deux exemples.

    Rediriger la sortie d'une application console.
    Admettons que cycliquement, tu lances en tâche de fond une application console invisible pour de la maintenance (backup, mise à jour...). Tu aimerais cependant que l'utilisateur soit informé de l'avancement ou d'une éventuelle erreur. Tu pourrais bien sûr :
    • utiliser CreateProcess et rediriger la sortie sur un Pipe. Un travail conséquent ;
    • lancer ShellExecuteEx depuis un thread et attendre la fin pour contrôler le code de sortie (ExitCode), mais pas de notification d'avancement ;
    • envoyer WM_COPYDATA mais SendMessage est bloquant et dû à la structure de taille fixe, le texte risque d'être tronqué (ou alors il faut surdimentionner le buffer).

    Ici, rien de tout cela ! Il suffit de redéfinir WriteLn et d'envoyer PostTextMessage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    program Project1;
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    uses
      SysUtils, Windows, Messages, MessagesEx;
     
    procedure WriteLn(aText :string);
    begin
      PostTextMessage(FindWindow('ClassName', 'WindowName'), WM_USER, aText);
    end;
     
    begin
      ClearTableOnExit := FALSE;
     
      try
        WriteLn('BlaBla');
        WriteLn('BlaBla');
     
      except
        on E: Exception do
          WriteLn(E.Message);
      end;
    end.

    Hook.
    Tu aimerais intercepter le retour de traitement d'un message par une fenêtre quelconque. Tu vas pour cela injecter une DLL dans les processus par SetWindowsHookEx. Mais un hook peut être très pénalisant pour le système et le ralentir considérablement si le traitement à effectuer est long.
    Jusqu'à Windows XP, on privilégiait le passage d'info par fichier mappé. Les lectures et écritures devant bien sûr être synchronisées par mutex. Depuis Vista et l'UAC, C'est fini ! La DLL injectée dans une application de niveau d'intégrité inférieur (par exemple Internet Explorer en mode protégé) n'aura pas accès au fichier mappé. Une violation est générée et c'est le deadlock assuré de l'application cible.
    On pourrait à nouveau utiliser WM_COPYDATA, mais il faudra que notre application soit très réactive. Imagine un hook souris tellement pénalisant que le curseur avance par saccade !
    Router simplement les informations par PostMessage ? Bien sûr si peu d'informations nous intéressent et tiennent dans WParam/LParam. Mais il ne faut pas espérer en récupérer plus par la suite par AttachThreadInput (UAC quand tu nous tiens...).

    Intercepter le retour d'un message se fait en plaçant un hook de type WH_CALLWNDPROCRET. Un pointeur est passé dans LParam correspondant à la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type
      TCwpRetStruct = record
        lResult :LRESULT;
        lParam  :LPARAM;
        wParam  :WPARAM;
        message :UINT;
        hwnd    :HWND;
      end;
    Nous n'aurons donc plus qu'à faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function CWPRetProc(aCode: integer; aWParam: WPARAM; aLParam: LPARAM):LRESULT; stdcall;
    begin
      if (aCode = HC_ACTION) then
        PostBufferMessage(FindWindow('ClassName', 'WindowName'), WM_USER, aLParam, SizeOf(TCwpRetStruct));
     
      Result := CallNextHookEx(0, aCode, aWParam, aLParam);
    end;
    Est-ce plus clair ?

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    envoyer WM_COPYDATA mais SendMessage est bloquant et dû à la structure de taille fixe, le texte risque d'être tronqué (ou alors il faut surdimentionner le buffer).
    WM_COPYDATA est bloquant, cela a un avantage car son retour permet de vérifier la bonne reception\compréhension du message par le receveur

    Sinon WM_COPYDATA utilise une structure COPYDATASTRUCT de taille fixe mais permet justement de gérer un buffer de longueur variable via se membres cbData et lpData
    On peut donc strictement définir un buffer de la taille exacte de la donnée devant être envoyé

    Sinon, pourquoi ne pas avoir utiliser BinToHex qui aurait fait le travail de conversion en Hexa bien plus rapidement que les nombreuses réallocation\concaténation de Data.Bytes même si FastMM le gère bien mieux que l'ancien gestionnaire de mémoire

    Tient, j'ai fait un petit dev hier que l'on m'a réclamé pour simplifier la vie de l'utilisateur
    un programme A doit lancer un programme B
    A étant déjà loggué, B est lancé en mode "AutoLogin" pour que l'utilisateur n'est pas retapé son Login+PW
    Dans d'autres programmes qui font la même chose, le login est passé sur la ligne de commande, en clair pour certaines et d'autres en chiffré
    Cela reste une jolie faille de sécurité puisque cela permet un login sans PW
    Mon prédecesseur n'avait pas du tout conscience de la sécurité !

    Je passe un HWND qui servirait ensuite pour un échange entre A et B d'un GUID servant d'ID de session qui aboutit à l'authentification, c'est déjà plus difficile à choper (un hook)

    je viens d'en extraire une petite classe plus générique, on voit tout de suite qu'avec un peu d'effort que l'on pourrait hériter d'un TStream et utiliser un TBinaryReader\TBinaryWriter dessus

    la Version C++, si j'ai le temps, je la tenterais en Delphi

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    //---------------------------------------------------------------------------
    typedef bool __fastcall (__closure *TShaiCopyDataMessagerReadEvent)(TObject* Sender, HWND DataSender, void *Data, int DataLen);
     
    //---------------------------------------------------------------------------
    //                          TShaiCopyDataMessager                           -
    //---------------------------------------------------------------------------
    class TShaiCopyDataMessager : public TObject
    {
    private:
      // Membres Privés
      HWND FSenderHandle;
      HWND FRecipientHandle;
      COPYDATASTRUCT FRawData;
      TShaiCopyDataMessagerReadEvent FOnRead;
     
      // Accesseurs
      HWND __fastcall GetSenderHandle();
     
      // Méthodes Privées
      void __fastcall WndProc(Messages::TMessage &Message);
      bool DoRead(HWND DataSender, void *Data, int DataLen);
     
    public:
      // Constructeurs Publiques
      /*constructor*/__fastcall TShaiCopyDataMessager();
      /*destructor*/virtual __fastcall ~TShaiCopyDataMessager();
     
      // Méthodes Publiques
      void BeginWrite();
      void WriteInteger(int Value);
      void WriteString(String Value);
      void WriteBuffer(void *Data, int DataLen);
      bool EndWrite();
      void CancelWrite();
     
      int ReadInteger(void *Data, /*out*/int &Value);
      int ReadString(void *Data, /*out*/String &Value);
     
      // Propriétés Publiques
      __property HWND SenderHandle = {read=GetSenderHandle};
      __property HWND RecipientHandle = {read=FRecipientHandle, write=FRecipientHandle};
      __property TShaiCopyDataMessagerReadEvent OnRead = {read=FOnRead, write=FOnRead};
    };

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    //---------------------------------------------------------------------------
    //                          TShaiCopyDataMessager                           -
    //---------------------------------------------------------------------------
    /*constructor*/__fastcall TShaiCopyDataMessager::TShaiCopyDataMessager()
    {
     
    }
     
    //---------------------------------------------------------------------------
    /*destructor*/__fastcall TShaiCopyDataMessager::~TShaiCopyDataMessager()
    {
      CancelWrite();
     
      if (FSenderHandle != 0)
      {
        DeallocateHWnd(FSenderHandle);
        FSenderHandle = 0;
      }
    }
     
    //---------------------------------------------------------------------------
    HWND __fastcall TShaiCopyDataMessager::GetSenderHandle()
    {
      if ( ! FSenderHandle)
        FSenderHandle = AllocateHWnd(WndProc);
     
      return FSenderHandle;
    }
     
    //---------------------------------------------------------------------------
    void TShaiCopyDataMessager::BeginWrite()
    {
      CancelWrite();
    }
     
    //---------------------------------------------------------------------------
    void TShaiCopyDataMessager::WriteInteger(int Value)
    {
      WriteBuffer(&Value, sizeof(Value));
    }
     
    //---------------------------------------------------------------------------
    void TShaiCopyDataMessager::WriteString(String Value)
    {
      int Len = Value.Length();
      WriteInteger(Len);
     
      if (Len > 0)
      {
        int Size = Len * sizeof(Char); // gère que la table BMP de UTF-16
        WriteBuffer(Value.c_str(), Size);
      }
    }
     
    //---------------------------------------------------------------------------
    void TShaiCopyDataMessager::WriteBuffer(void *Data, int DataLen)
    {
      int Position = FRawData.cbData;
      FRawData.cbData += DataLen;
      if (Position > 0)
        ReallocMemory(FRawData.lpData, FRawData.cbData);
      else
        FRawData.lpData = GetMemory(FRawData.cbData);
      CopyMemory((Byte*)FRawData.lpData + Position, Data, DataLen);
    }
     
    //---------------------------------------------------------------------------
    bool TShaiCopyDataMessager::EndWrite()
    {
      bool Result = SendMessage(FRecipientHandle, WM_COPYDATA, (WPARAM)FSenderHandle, (LPARAM)&FRawData);
      CancelWrite();
      return Result;
    }
     
    //---------------------------------------------------------------------------
    void TShaiCopyDataMessager::CancelWrite()
    {
      FreeMemory(FRawData.lpData);
      ZeroMemory(&FRawData, sizeof(FRawData));
    }
     
    //---------------------------------------------------------------------------
    int TShaiCopyDataMessager::ReadInteger(void *Data, /*out*/int &Value)
    {
      int Result = -1;
      if ( ! IsBadReadPtr(Data, sizeof(Value)))
      {
        Value = *(int*)Data;
        Result = sizeof(Value);
      }
      return Result;
    }
     
    //---------------------------------------------------------------------------
    int TShaiCopyDataMessager::ReadString(void *Data, /*out*/String &Value)
    {
      int Result = -1;
      int Len = 0;
      int TmpResult = ReadInteger(Data, Len);
      if (TmpResult > 0)
      {
        Result = TmpResult;
        if (Len > 0)
        {
          Value = UnicodeString((WideChar*)((Byte*)Data + TmpResult), Len);
          int Size = Len * sizeof(Char); // gère que la table BMP de UTF-16
          Result += Size;
        }
        else
          Value = "";
      }
      return Result;
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TShaiCopyDataMessager::WndProc(Messages::TMessage &Message)
    {
      if (Message.Msg == WM_COPYDATA)
      {
        PCOPYDATASTRUCT PRawData = (PCOPYDATASTRUCT)Message.LParam;
        if (PRawData && PRawData->cbData)
          Message.Result = DoRead((HWND)Message.WParam, PRawData->lpData, PRawData->cbData);
        else
          Message.Result = false;
      }
      else
        Message.Result = DefWindowProc(FSenderHandle, Message.Msg, Message.WParam, Message.LParam);
    }
     
    //---------------------------------------------------------------------------
    bool TShaiCopyDataMessager::DoRead(HWND DataSender, void *Data, int DataLen)
    {
      bool Result = false;
      if (FOnRead)
        Result = FOnRead(this, DataSender, Data, DataLen);
     
      return Result;
    }

    //---------------------------------------------------------------------------

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    void __fastcall TSystemManipForm::BtnCopyDataWhoIAmClick(TObject *Sender)
    {
      if ( ! FCopyDataMessager)
      {
        FCopyDataMessager = new TShaiCopyDataMessager();
        FCopyDataMessager->OnRead = CopyDataMessagerReadEventHandler;
      }
     
      EditCopyDataWhoIAm->Text = UIntToStr((unsigned)FCopyDataMessager->SenderHandle);
    }
     
    //---------------------------------------------------------------------------
    bool __fastcall TSystemManipForm::CopyDataMessagerReadEventHandler(TObject *Sender, HWND DataSender, void *Data, int DataLen)
    {
      bool Result = false;
     
      TShaiCopyDataMessager* Messager = dynamic_cast<TShaiCopyDataMessager*>(Sender);
      if (Messager)
      {
        String S1, S2, S3;
     
        int OffSet = Messager->ReadString(Data, S1);
        Data = (Byte*)Data + OffSet;
        OffSet = Messager->ReadString(Data, S2);
        Data = (Byte*)Data + OffSet;
        OffSet = Messager->ReadString(Data, S3);
     
        MemoCopyDataRecv->Lines->Add(S1 + S2 + S3);
        Result = Pos("bad", S2) <= 0;
      }
     
      return Result;
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TSystemManipForm::BtnCopyDataSendToClick(TObject *Sender)
    {
      if ( ! FCopyDataMessager)
      {
        FCopyDataMessager = new TShaiCopyDataMessager();
        FCopyDataMessager->OnRead = CopyDataMessagerReadEventHandler;
      }
     
      FCopyDataMessager->RecipientHandle = (HWND)StrToInt(EditCopyDataSendTo->Text);
      FCopyDataMessager->BeginWrite();
      FCopyDataMessager->WriteString("La Chaine est : \"");
      FCopyDataMessager->WriteString(EditCopyDataSendToText->Text);
      FCopyDataMessager->WriteString("\" !");
      if ( ! FCopyDataMessager->EndWrite())
        MemoCopyDataRecv->Lines->Add("bad est refusé");
    }
    //---------------------------------------------------------------------------

    Code dfm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    object BtnCopyDataWhoIAm: TButton
      Left = 3
      Top = 3
      Width = 75
      Height = 25
      Caption = 'Who I Am ?'
      TabOrder = 0
      OnClick = BtnCopyDataWhoIAmClick
    end
    object EditCopyDataWhoIAm: TEdit
      Left = 84
      Top = 5
      Width = 121
      Height = 21
      Alignment = taRightJustify
      NumbersOnly = True
      ReadOnly = True
      TabOrder = 1
      Text = '?'
    end
    object BtnCopyDataSendTo: TButton
      Left = 3
      Top = 34
      Width = 75
      Height = 25
      Caption = 'Send To'
      TabOrder = 2
      OnClick = BtnCopyDataSendToClick
    end
    object EditCopyDataSendTo: TEdit
      Left = 84
      Top = 36
      Width = 121
      Height = 21
      Alignment = taRightJustify
      NumbersOnly = True
      TabOrder = 3
      Text = '?'
    end
    object EditCopyDataSendToText: TEdit
      Left = 211
      Top = 36
      Width = 121
      Height = 21
      TabOrder = 4
      Text = 'Bonjour !'
    end
    object MemoCopyDataRecv: TMemo
      Left = 3
      Top = 65
      Width = 329
      Height = 274
      Lines.Strings = (
        'Receive :')
      ReadOnly = True
      ScrollBars = ssBoth
      TabOrder = 5
    end
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    WM_COPYDATA est bloquant, cela a un avantage car son retour permet de vérifier la bonne reception\compréhension du message par le receveur
    C'est clair qu'à partir du moment où un dialogue est nécessaire, cette technique n'est pas applicable. Ce n'est pas pour rien que j'ai pris l'exemple de WH_CALLWNDPROCRET dont la donnée ne peut être modifiée

    Maintenant, mon but était vraiment de faire de l'asynchrone...

    Citation Envoyé par ShaiLeTroll Voir le message
    Sinon, pourquoi ne pas avoir utiliser BinToHex qui aurait fait le travail de conversion en Hexa bien plus rapidement que les nombreuses réallocation\concaténation de Data.Bytes
    J'aurais pu Comme j'aurais pu aussi définir une chaîne de 2x la taille de la donnée et travailler sur l'index du caractère.
    Mais je suis un pervers et au départ je comptais convertir un octet sur 10 bits (actuellement 16 bits) pour utiliser au mieux les 255 octets à disposition. Puisqu'une des contraintes est : pas de byte à "0" son codage aurait été 1000010000 (en ajoutant toujours "1"). Mais ça devenait un peu compliqué et le tuto n'aurait plus été "Confirmé", mais "Expert"

    Mais j'aurais dû plus simplifier !

    Citation Envoyé par ShaiLeTroll Voir le message
    Je passe un HWND qui servirait ensuite pour un échange entre A et B d'un GUID servant d'ID de session qui aboutit à l'authentification, c'est déjà plus difficile à choper (un hook)
    J'ai aussi utiliser ce genre de technique en envoyant un message que l'application ne sait pas gérer (RegisterWindowMessage, donc inconnu par la cible)
    mais récupéré par hook pour exécuter du code dans le processus cible

  10. #10
    Membre habitué
    Inscrit en
    Mars 2007
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 191
    Points : 132
    Points
    132
    Par défaut
    c'est Noël
    Dans l'endroit et au bon moment que ce tutoriel car je passais des heures pour apprendre quelques choses sur les HOOK(s).

    Merci pour ce tutoriel et les interventions des chères membres

  11. #11
    Membre à l'essai
    Homme Profil pro
    Cyberdocumentaliste
    Inscrit en
    Décembre 2021
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Cyberdocumentaliste
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2021
    Messages : 11
    Points : 13
    Points
    13
    Par défaut
    salut, j'ai vu le tuto, mais j'avoue c'est quand il faut envoyer ou recevoir je ne sais pas quoi mettre dans la commande : PostTextMessage(aWnd :hWnd; aMessage :cardinal; aText :string) :integer;

    si quelqu'un connais bien cette commande, je suis preneur car ca corresponds bien a ce que je voudrais faire, j'ai bien récuperer le fichier MessagesEx je l'ai intégrer a mon application, mais pas plus.

Discussions similaires

  1. Réponses: 6
    Dernier message: 20/08/2013, 22h37
  2. Réponses: 4
    Dernier message: 20/04/2007, 14h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo