Text an notepad senden und unter bestehendem Text einfügen ?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von Tommy »

auser hat geschrieben:BlockInput_() wiederum ...das sowohl für SendInput_() als auch für keybd_event_() nett gewesen wäre funktioniert in neueren Windows-Versionen nur noch mit Adminrechten. Was sich MS dabei gedacht hat ist mir ehrlich gesagt schleierhaft
Na Gott sei dank. Stell dir vor dein Programm stürzt ab während BlockInput_() benutz wird. :shock: Dann kannst du den PC nur noch resetten. :freak:
PB 5.41 x64
auser
Beiträge: 58
Registriert: 17.05.2011 10:56

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von auser »

Tommy hat geschrieben: Stell dir vor dein Programm stürzt ab
Das würde mich total nerven... echt... >_<

während BlockInput_()
Oh nein... dann würde das Input ja prompt wieder funktionieren (ich wär aber trotzdem noch voll genervt daß es überhaupt abgeschmiert ist).

Dann kannst du den PC nur noch resetten. :freak:
Sagte der Windows-User... /:-> ...und der doofe Admin macht das so wie so ständig also lass den mal? Nene. Mal davon abgesehen daß das BlockInput nicht mehr blockt wenn dein Program nicht mehr läuft (selbst wenn du zu faul warst und das BlockInput(0) nicht mehr reinschreibst) und die Problematik ja ned besser würde wenn's ein anderer User ist kannst du einfach STRL+ALT+ENTF machen daß alles wieder gut ist.
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von TWELVE »

Ich habe mit meiner zuletztgenannten Methode ein Problem: auf dem W7 Rechner, auf dem ich auch programmiere, läuft es wunderbar.Aber auf einem anderen W7 System
erscheint oft oder meistens mein mit

Code: Alles auswählen

SendMessage_(FindWindowEx_(Prog_hWnd, 0, "Edit", 0),#WM_PASTE,0,0)
ans Notepad gesendeter Text NICHT im Notepad.Der mit

Code: Alles auswählen

Delay(1000) : SendKeys(Prog_hWnd,"",#CRLF$) ; text to send
gesendete Linefeed funktioniert dagegen immer.Der Window Handle muß also stimmen, schlußfolgere ich daraus
( da ich den gleichen hWnd für Paste und SendKeys verwende...).

Wie gesagt, auf meinem Programmiersystem habe ich 100% Trefferquote und so könnte ich die exe herausgeben,
aber da es auf dem anderen System sehr unzuverlässig ist, muß ich das erst fixen, bevor ich einen User
mit sowas verärgere.

Woran könnte dieses Verhalten liegen ? Wenn der hWnd stimmt, warum pastet das Paste dann den Text
nicht oder meistens nicht rein ?

Als ich statt dem hWnd den Namen des Windows übergeben hab, hatte ich dieses Phänomen allerdings nicht
( was ich aber nicht will, die Gründe dafür sind oben nachzulesen...).
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von Kiffi »

<meinSenf>

mit Verlaub, TWELVE, aber wie lange quälst Du Dich jetzt mit diesem Problem herum? In der Zwischenzeit hättest Du locker eine saubere Lösung mit einem separaten eigenen Fenster (wie von mehreren Leuten hier vorgeschlagen) programmieren können.

</meinSenf>

NixFürUngut ... Peter
Hygge
matbal
Beiträge: 246
Registriert: 30.03.2011 20:53

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von matbal »

@TWELVE

1. Deine Prozedur ProcID2hWnd arbeitet bei mir unzuverlässig. Das heißt, sie liefert manchmal ein falsches Handle zurück. Noch schlimmer wird es, wenn ich in deinem Code noch ein Delay(1000) vor die Repeat-Schleife setze. Dann bekomme ich nie das richtige Handle.

Die Lösung von auser funktioniert bei mir dagegen zuverlässig. Da bekomme ich immer das richtige Handle zurück.

2. Im Editor kannst du einen Text anhängen, wenn du #EM_SETSEL und #EM_REPLACESEL verwendest. Im Prinzip setzt du im Editor die Selektion so, daß der Cursor am Ende Textes steht, und ersetzt dann die Selektion mit dem neuen Text:

Code: Alles auswählen

   hEdit = FindWindowEx_(Prog_hWnd, 0, "Edit", 0)
   SendMessage_(hEdit,#EM_SETSEL, $fffffff, $fffffff)  
   SendMessage_(hEdit,#EM_REPLACESEL, 0, text$ + #CRLF$) 
oder

Code: Alles auswählen

   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_SETSEL, $fffffff, $fffffff)  
   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_REPLACESEL, 0, text$ + #CRLF$) 
Zuletzt geändert von matbal am 08.05.2015 20:42, insgesamt 1-mal geändert.
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von TWELVE »

@matbal

Danke für den Super Tip !

Werde es nachher mal probieren.

Dass ProcID2hWnd nicht zuverlässig funktioniert, hatte ich weiter oben schon angemerkt.Es funktioniert allerdings bei mir
jetzt in der Form zuverlässig, dass ich es nur einmal nach RunProgram() aufrufe und dann den hWnd abspeichere.
Nachfolgende Aufrufe lieferten immer falsches Handle zurück, wie Du richtig anmerkst.Aber diese eine erste Mal liefert
bei mir den richtigen Window Handle.
TWELVE hat geschrieben:aber mich würde trotzdem interessieren, warum das o.g. ProcID2hWnd(ProcID.l) beim weiteren Aufrufen die hwnd nicht zuverlässig ermittelt.
Ich hatte jetzt nur zuletzt das Phänomen, dass der Code auf einem Rechner zuverlässig funktioniert, auf einem anderen nur sporadisch.

Danke ebenfalls an auser für den alternativen Code um den hWnd zu ermitteln !
Werde ich ebenfalls mal testen.Obwohl ich den Code nicht komplett verstehe, da
schon zuviel WinAPI Style drin ;-)

Das Einfügen meines Texts in Notepad geht auch über SendKeys, wie ich jetzt getestet habe.Und zwar auf allen Rechnern.
Einziger Nachteil gegenüber WM_PASTE ist, dass der Text etwas langsamer ins Notepad "geschrieben" wird.Damit könnte ich
aber leben, da es immer noch schnell genug geht, um nicht zu stören ( außer bei längeren Textblöcken vielleicht).
Die Applikation wird nicht behindert, wenn im Hintergrund noch der Text ins Notepad über sendkeys reinläuft.



@Kiffi:

Die Gründe dafür habe ich schon weiter oben aufgezählt.Ein eigenes Editor Window ist nur auf den ersten Blick einfach, damit
es Grundfunktionen wie ein Notepad hat, muß man da schon ordentlich WinAPI Code reinfummeln und da gibt es dann wieder
andere Schwächen.Mit Notepad sind viele User vertraut, es wird oft benutzt, um sich eine Notiz zu machen oder etwas Text
zwischenzulagern ( z.B. weil Webformulare beim Absenden hin und wieder abschmieren und dann der Text weg ist).
Und Notepad ist schon da !
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von TWELVE »

Der Code von ausen funktioniert bei mir nicht.

Code: Alles auswählen

Structure cb_inout
  pid.q
  handle.l
EndStructure 
Procedure EnumWindowsCallback(handle.l, *h.cb_inout)
    Protected pid.q = 0
    GetWindowThreadProcessId_(handle, @pid)
    If *h\pid = pid And IsWindowVisible_(handle)
      *h\handle = handle
      ProcedureReturn(0)  
    Else
      ProcedureReturn(1)
    EndIf 
EndProcedure 
Procedure FindWindowHopefully(pid.q)
  Protected h.cb_inout 
  h\pid = pid
  
  EnumWindows_(@EnumWindowsCallback(), @h)
  ProcedureReturn(h\handle)
EndProcedure 
FindWindowHopefully(pid.q) gibt immer "0" zurück.

Jemand eine Idee ?
matbal
Beiträge: 246
Registriert: 30.03.2011 20:53

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von matbal »

Nachdem deine Prozedur nicht immer erfolgreich war, hatte ich im Internet gesucht und einen C-Code gefunden. Den habe ich nach PB Übertragen und hinterher festgestellt, daß der Code von auser im Prinzip genauso arbeitet. Ausprobiert habe ich ihn nicht.

Denke daran, daß es einige Millisekunden dauert, bis Notepad das Fenster erstellt hat. Solange das Fenster nicht geöffnet ist, bekommst du kein Handle. Daher habe ich auch eine Schleife verwendet...

Hier mein Test-Code:

Code: Alles auswählen

EnableExplicit

Define Prog_ID
Define Prog_PID
Global Prog_hWnd


Procedure EnumWindowsCallback(hwnd, lParam)
   Protected ProcessId
   
   GetWindowThreadProcessId_(hwnd, @ProcessId)
   If (ProcessId = lParam)
      Prog_hWnd = hwnd
      ProcedureReturn #False
   EndIf
   ProcedureReturn #True
EndProcedure

Procedure Button_Click()
   Protected text$ = GetGadgetText(1)

   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_SETSEL, $fffffff, $fffffff)  
   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_REPLACESEL, 0, text$ + #CRLF$) 
EndProcedure



Prog_ID = RunProgram("notepad.exe", "", "", #PB_Program_Open)

If Prog_ID 
   Prog_PID = ProgramID(Prog_ID)
   
   Repeat
      Delay(100)
      EnumWindows_(@EnumWindowsCallback(),Prog_pID)
   Until Prog_hWnd 
   
   Debug "Prog_ID: "  + Str(Prog_ID)
   Debug "Prog_PID: " + Str(Prog_PID)
   Debug "Prog_hWnd: " + Str(Prog_hWnd)
   
      
   ; Demo-Fenster
   OpenWindow(0, 100, 100, 220, 80, "Fenster")
   StringGadget(1, 10, 10, 200, 20, "Textzeile")
   ButtonGadget(2, 10, 40, 100, 25, "Senden")
   BindGadgetEvent(2, @Button_Click())
   
   Repeat
   Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von TWELVE »

matbal hat geschrieben:Denke daran, daß es einige Millisekunden dauert, bis Notepad das Fenster erstellt hat.
Das war der entscheidende Hinweis ! Bei mir reicht ein einzelnes Delay(100), damit der hWnd korrekt befüllt ist.

Ich hatte verdrängt, dass auch meine bestehende Prozedur ProcID2hWnd() solange loopt, bis die ID ungleich 0 ist:

Code: Alles auswählen

  Repeat
      notepad_hWnd = ProcID2hWnd(notepadPID)
        If notepad_hWnd : Break : EndIf 
   ForEver

Danke für den Hinweis !

Die Ermittlung des Windows Handles ist mit dem Code von ausen tatsächlich zuverlässig und reproduzierbar.Da ich mit ProcID2hWnd()
aber beim ersten Aufruf immer Erfolg habe und dann hWnd in eine Variable speichere, ist das für mich in diesem Fall nicht ganz so
wichtig, ob bei einem weiteren Aufruf der hWnd zuverlässig ermittelt würde.

Dein Code:

Code: Alles auswählen

 
   hEdit = FindWindowEx_(Prog_hWnd, 0, "Edit", 0)
   SendMessage_(hEdit,#EM_SETSEL, $fffffff, $fffffff)  
   SendMessage_(hEdit,#EM_REPLACESEL, 0, text$ + #CRLF$) 
funktioniert...aber:

Der Text aus dem Editor wird ohne Linefeeds in das Notepad geklatscht, obwohl der Text welche enthält.
Das ist natürlich nicht im Sinne des Erfinders.

Die andere Variante macht es genauso, also kein Unterschied zu sehen:

Code: Alles auswählen

   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_SETSEL, $fffffff, $fffffff)  
   SendMessage_(GetDlgItem_(Prog_hWnd, 15),#EM_REPLACESEL, 0, text$ + #CRLF$)
Somit fallen beide Varianten aus, da ich den Text natürlich so ins Notepad übernehmen will, wie er ist, also mit Zeilenvorschüben am Ende jeder Zeile.
Weitere Test auf dem anderen W7 System bezüglich Zuverlässigkeit habe ich mir dann auch gespart.

Bleibt also im Moment nur #WM_PASTE und SendKeys().Schade, die Lösung mit #EM_REPLACESEL wäre eigentlich genau das, wonach ich gesucht hab.

Am Window Handle kann es meiner Meinung nicht liegen, dass der Text auf dem anderen PC per #WM_PASTE manchmal / oft / meist nicht im Notepad erscheint,
da der Linefeed per SendKeys ins gleiche Window Handle stets funktioniert.Außerdem funktioniert es auf dem anderen PC ja nicht generell nicht, und da ich
den hWnd abspeichere nachdem notepad geöffnet wurde, ändert dieser sich nicht mehr, solange dieses notepad geöffnet bleibt.
matbal
Beiträge: 246
Registriert: 30.03.2011 20:53

Re: Text an notepad senden und unter bestehendem Text einfüg

Beitrag von matbal »

TWELVE hat geschrieben: Der Text aus dem Editor wird ohne Linefeeds in das Notepad geklatscht, obwohl der Text welche enthält.
Das ist natürlich nicht im Sinne des Erfinders.
Ich vermute mal, daß es nur mit dem Format der Zeilenumbrüche zu tun hat. Verwendet der Text #CRLF$ für die Zeilenumbrüche, wird er auch mit Zeilenumbrüchen in Notepad geschrieben.

Wenn der Zeilenumbruch nur aus einem #CR$ oder #LF$ besteht, kommt der Text als eine Zeile an. Aber das ließe sich ja mit ReplaceString() vor dem senden korrigieren.
Antworten