AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Text in ein DBRichEdit einfügen per SendMessage()

Text in ein DBRichEdit einfügen per SendMessage()

Offene Frage von "himitsu"
Ein Thema von juergen · begonnen am 31. Jan 2021 · letzter Beitrag vom 6. Feb 2021
Antwort Antwort
Seite 2 von 2     12
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.017 Beiträge
 
Delphi 10.3 Rio
 
#11

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 1. Feb 2021, 19:40
Hallo Holger,
vielen Dank, lieb gemeint. U. a. hatte ich es auch so probiert wie in deinem Source. Aber es funktioniert einfach nicht.
Es muss an der Fremd-Anwendung liegen.
Ich habe zig Varianten durch probiert und es klappt einfach nicht. Mit anderen Anwendungen hatte ich kein Problem. Das Handle ist auch immer korrekt, das DBRichEdit ist im Editmodus, es wird aber kein Text übernommen.
WinSpy zeigt mir auch an, dass es wohl eine Midi-Anwendung ist. Ob es damit was zu tun haben könnte? Ich bin da echt ratlos.
Lt. Debugger wird alles korrekt ausgeführt.

@himitsu,
leider war mein Code-Ausschnitt unvollständig. Ich hatte das alles ausprobiert, auch mit WM_KEYUP. In Zukunft muss ich da etwas genauer den Code-Ausschnitt aufbereiten.

Was meintest du mit
Zitat:
Rate mal, warum es mehrere Versuche von SndKey/SendKey/... gibt.
Miniaturansicht angehängter Grafiken
winspy-ermittlung-der-handle-id.jpg  
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 1. Feb 2021, 20:12
Wie gesagt, siehe Bei Google suchenDelphi SendKeys / Hier im Forum suchenSendKeys
oder eben MSDN-Library durchsuchenEM_REPLACESEL ala RichEdit.SelText := '...'; .


Hat das Programm, bzw. das RichEdit den Eingabefocus?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 1. Feb 2021 um 22:08 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.017 Beiträge
 
Delphi 10.3 Rio
 
#13

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 1. Feb 2021, 21:55
@himitsu,
dank dir für deine Mühe!
Ich habe deine Tipps auch probiert, aber selbes Ergebnis: Die Showmessage wird aufgerufen und zeigt das richtige Handle an, aber im DBRichEdit der Fremdanwendung passiert absolut nichts.
Das DBRichEdit im Fremdprogramm hat immer den Fokus (Cursor blinkt im DBRichEdit), jeweils einmal im Editiermodus getestet und einmal ohne.

Wie kann ich denn in einem Fremdprogramm
Zitat:
RichEdit.SelText :=
setzen?


Hier mal einer meiner Tests:

Delphi-Quellcode:
PROCEDURE Tfrm_Main.WMHotKey( VAR Msg: TWMHotKey );
VAR
  s: STRING;
  copyDataStruct: TCopyDataStruct;
BEGIN
  gc_my_DBRichEdit_Handle := Handle_DBRichEdit_ermitteln { Return Handle-ID };
  TRY
    IF ( Msg.HotKey = Hotkey_id ) AND ( gc_my_DBRichEdit_Handle > 0 ) THEN
    BEGIN
      s := 'Das ist ein Test';
      copyDataStruct.cbData := 1 + ( Length( s ) * SizeOf( Char ) ); // !!!
      copyDataStruct.lpData := PChar( s );

      Keybd_Event( VK_RETURN, 0, 0, 0 ); // Taste drücken
      Keybd_Event( VK_RETURN, 0, KEYEVENTF_KEYUP, 0 ); // Taste loslassen

      SendMessage( gc_my_DBRichEdit_Handle, EM_REPLACESEL, 0, LPARAM( @copyDataStruct ) );
      Sleep( 2000 );

      ShowMessage( s + ' Handle-ID=' + IntToStr( gc_my_DBRichEdit_Handle ) );
    END;
  FINALLY
    // gc_my_DBRichEdit_Handle := 0; { TODO 2 -oJS -cnoch zu erledigen : Nach den Tests ist das zu aktivieren, damit die Variable nach jedem Aufruf auch initialisiert ist }
  END;
END;
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#14

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 1. Feb 2021, 22:21
Ein CopyDataStruct für was Anderes verwenden zu wollen, als für WM_COPYDATA ... naja

Hier bissl Was zum Abgucken und Ideenholen:
Delphi-Quellcode:
procedure TCustomEdit.SetSelTextBuf(Buffer: PChar);
begin
  SendMessage(Handle, EM_REPLACESEL, 0, LPARAM(Buffer));
end;

// oder besser
procedure TCustomEdit.DoSetTextHint(const Value: string);
begin
  ...
  SendTextMessage(Handle, EM_SETCUEBANNER, 0, Value);
end;
Und natürlich auch beim Hersteller nachzulesen.
MSDN-Library durchsuchenEM_REPLACESEL : https://docs.microsoft.com/en-us/win.../em-replacesel


PS, auch wenn es hier keine Lösung werden wird:
Selbst wenn es so funktioniert hätte, dann wäre aber die Größe dennoch falsch geworden.
Zitat:
1 + ( Length( s ) * SizeOf( Char ) )
Die abschließende #0 hätte natürlich auch 2 Byte groß sein wollen.
Erst (Length+1) und dann das *.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 1. Feb 2021 um 22:28 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.017 Beiträge
 
Delphi 10.3 Rio
 
#15

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 1. Feb 2021, 22:55
@himitsu,

danke für die Hinweise. Es hilft alles nichts, noch nie hat das DBRichEdit aus der Fremdanwendung überhaupt mal reagiert. Es scheint keine Messages von "außen" anzunehmen. Da bin ich mir ziemlich sicher. Da kann man wohl nichts machen.
Was als Q&D ginge, wäre den Text über Clipboard einzufügen, das funktioniert. Aber das will ich nicht. Ich mach da jetzt nichts mehr.

Gute N8!
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.017 Beiträge
 
Delphi 10.3 Rio
 
#16

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 5. Feb 2021, 22:48
Hallo zusammen,
also, ich weiß inzwischen, dass es nicht so einfach ist einen Text an ein RichEdit zu senden.
Ich taste mich nun so langsam ran, erst mal mit dem RichEdit von WordPad.
Das Handle zu ermitteln wenn Wordpad im Vordergrund ist, ist kein Problem.
Ich habe folgenden Source der prinzipiell einen Text an ein RichEdit innerhalb meiner eigenen Anwendung sendet:

Delphi-Quellcode:
// Source von Dr. Peter Below
TYPE
  TMyRichEdit = TRichEdit;

TYPE
  TEditStreamCallBack = FUNCTION( dwCookie: Longint; pbBuff: PByte;
    cb: Longint; VAR pcb: Longint ): DWORD; STDCALL;

  TEditStream = RECORD
    dwCookie: Longint;
    dwError: Longint;
    pfnCallback: TEditStreamCallBack;
  END;


FUNCTION EditStreamInCallback( dwCookie: Longint; pbBuff: PByte;
  cb: Longint; VAR pcb: Longint ): DWORD; STDCALL;
VAR
  theStream: TStream;
  dataAvail: LongInt;
BEGIN
  theStream := TStream( dwCookie );
  WITH theStream DO
  BEGIN
    dataAvail := Size - Position;
    Result := 0; { assume everything is ok }
    IF dataAvail <= cb THEN
    BEGIN
      pcb := READ( pbBuff^, dataAvail );
      IF pcb <> dataAvail THEN // couldn't read req. amount of bytes
          result := 0; // E_FAIL;
    END
    ELSE BEGIN
      pcb := READ( pbBuff^, cb );
      IF pcb <> cb THEN
          result := 0; // E_FAIL;
    END;
  END;
END;

FUNCTION EditStreamOutCallback( dwCookie: Longint; pbBuff: PByte;
  cb: Longint; VAR pcb: Longint ): DWORD; STDCALL;
VAR
  theStream: TStream;
BEGIN
  theStream := TStream( dwCookie );

  WITH theStream DO
  BEGIN
    IF cb > 0 THEN
        pcb := WRITE( pbBuff^, cb );
    Result := 0;
  END;
END;

PROCEDURE GetRTFSelection( aRichEdit: TRichEdit; intoStream: TStream );
VAR
  editstream: TEditStream;
BEGIN
  WITH editstream DO
  BEGIN
    dwCookie := Longint( intoStream );
    dwError := 0;
    pfnCallback := EditStreamOutCallBack;
  END;
  aRichedit.Perform( EM_STREAMOUT, SF_RTF OR SFF_SELECTION, longint( @editstream ) );
END;

PROCEDURE PutRTFSelection( aRichEdit: TRichEdit; sourceStream: TStream );
VAR
  editstream: TEditStream;
BEGIN
  WITH editstream DO
  BEGIN
    dwCookie := Longint( sourceStream );
    dwError := 0;
    pfnCallback := EditStreamInCallBack;
  END;
  aRichedit.Perform( EM_STREAMIN, SF_RTF OR SFF_SELECTION, longint( @editstream ) );
END;
Ich weiß nun nicht, wie ich es hinbekomme, dass ich einen Text an ein RichEdit einer Fremd-Anwendung (Wordpad) gesendet bekomme.
Die Frage ist, wie ich das Control in der Fremd-Anwendung ansprechen kann. Das was ich habe ist das Handle dieses Controls. Die Procedure PutRTFSelection erwartet ein RichEdit.

Delphi-Quellcode:
PROCEDURE Tfrm_Main.WMHotKey( VAR Msg: TWMHotKey );
VAR
  SS: TStringStream;

  FUNCTION WORDPAD_finden_TEST: THandle;
  VAR
    Len: LongInt;
    Title: STRING;
    Main_Wnd, wndChild: THandle;
  BEGIN
    Result := 0;
    Main_Wnd := GetForegroundWindow;
    IF Main_Wnd <> 0 THEN
    BEGIN
      Len := GetWindowTextLength( Main_Wnd ) + 1;
      SetLength( Title, Len );
      GetWindowText( Main_Wnd, PChar( Title ), Len );
      IF ( Pos( 'wordpad', LowerCase( Title ) ) > 0 ) THEN
      BEGIN
        IF Main_Wnd <> 0 THEN
        BEGIN
          wndChild := FindWindowEx( Main_Wnd, 0, 'RICHEDIT50W', NIL );
          IF wndChild <> 0 THEN
          BEGIN
            Result := wndChild;
          END;
        END;
      END;
    END;
  END;

BEGIN
  TRY
    gc_my_DBRichEdit_Handle := WORDPAD_finden_TEST;
    IF ( Msg.HotKey = Hotkey_id ) AND ( gc_my_DBRichEdit_Handle > 0 ) THEN
    BEGIN
      SS := TStringStream.Create
        ( '{\rtf1\ansi\ansicpg1252\deff0\deflang2055{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}{\f1\fnil MS Sans Serif;}}\viewkind4\uc1\pard\ul\b\f0\fs24 Test\ulnone\b0\f1\fs16\par}' );
      TRY
        PutRTFSelection( RICHEDIT1, SS ); // <==== wie komme ich hier das Control von Wordpad angesprochen (RICHEDIT50W), anstelle meinem RichEdit1
      FINALLY
        SS.Free;
      END;

      ShowMessage( 'Handle-ID=' + IntToStr( gc_my_DBRichEdit_Handle ) );
    END;
  FINALLY
    //
  END;
END;

Vielen Dank für Hinweise!
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)

Geändert von juergen ( 5. Feb 2021 um 22:57 Uhr) Grund: Text deutlicher formuliert...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#17

AW: Text in ein DBRichEdit einfügen per SendMessage()

  Alt 6. Feb 2021, 05:16
Ich bin mir fast sicher, dass du EM_STREAMIN nur innerhalb deiner Anwendung nutzen darfst.

Um es an einen anderen Prozeess schicken zu können,
müsstest du deinen Code von EditStreamInCallback/EditStreamOutCallback erst in diesen Prozess injizieren,
denn was will das andere Programm mit einem Pointer für deinen Speicher, wenn es seinen eigenen Speicher hat und an jener Stelle nichts oder sonstwas liegen wird.


Zitat:
 dwCookie := Longint( intoStream );
Wen sollen wir dafür steinigen?

UIntPtr oder NativeUInt
bzw.
IntPtr oder NativeInt

Aber auch TEditStream, TEditStreamCallBack, EditStreamInCallback und EditStreamOutCallback sind falsch deklariert.
DWORD_PTR -> https://docs.microsoft.com/en-us/win...streamcallback


Es gibt nur eine Message, welche "irgendeinen" Speicher selbstständig in den Zielprozess kopiert. (WM_COPYDATA)
Zusätzlich machen das auch noch die bekannten Text-Messages ala WM_SETTEXT.

Selbst wenn EM_STREAMIN/EM_STREAMOUT den Speicher von EDITSTREAM/TEditStream rüberkopiert, dann bleibt dennoch deine Funktion, und das von ihr Verwendete, bei dir.
Hast mal geschaut, ob es eine Variante mit IStream gibt? (z.B. beim Clippboard gibt es Schnittstellen, welche damit auch prozesssübergreifend funktionieren)

https://www.quickmacros.com/forum/sh...t=em_streamout
Zitat:
To get RTF from other process, would need to create dll file, for example in C language, and inject it into that process, for example with a hook.
k.A. ob das mit dem FileHandle hier funktioniert, aber vermutlich wird EM_STREAMIN/EM_STREAMOUT kein DuplicateHandle benutzen, womit "dein" Handle drüben ungültig wäre.
https://www.codeproject.com/Question...icateHandle-fu
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 6. Feb 2021 um 05:36 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 06:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf