Autor |
Beitrag |
Tony-S
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Mo 19.07.10 16:31
Hallo Forum, ich möchte aus meiner Zwischenablage eine Bitmap in ein anderes Programm (Paint oder Word) einfügen.
Als erstes suche ich nach dem "Paint" Fenster, was auch anscheinend eintritt, da Window > 0 ist. Dann simuliere ich Strg + V, also einfügen.
Delphi-Quelltext 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:
| procedure SendBMPtoPaint(BMP: TBitmap); var Window: HWND; begin Window := FindWindowEx(FindWindow('Paint', nil), 0, 0, nil); if Window > 0 then begin PostMessage(Window, wm_KeyDown, vk_Control,0); PostMessage(Window, wm_KeyDown, Ord('V'),0); PostMessage(Window, wm_Keyup, vk_Control,0); PostMessage(Window, wm_Keyup, Ord('V'),0); end; end;
Diese Prozedur rufe ich dann auf:
procedure TForm1.btnPaintExportClick(Sender: TObject); begin Clipboard.Assign(imgBMP.Picture.Bitmap); Try ShellExecute(Application.Handle,'open', pchar('mspaint.exe'),nil, Nil, SW_Show); Finally SendBMPtoPaint(imgBMP.Picture.Bitmap); end; end; |
Was mach ich da falsch, oder was kann ich da anders machen? Bin für jede Hilfe dankbar.
Moderiert von Narses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Moderiert von Narses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 19.07.2010 um 16:33
Zuletzt bearbeitet von Tony-S am Di 20.07.10 00:15, insgesamt 1-mal bearbeitet
|
|
Tastaro
      
Beiträge: 414
Erhaltene Danke: 23
|
Verfasst: Mo 19.07.10 17:32
Probier mal
Delphi-Quelltext 1: 2: 3: 4:
| PostMessage(Window, wm_KeyDown, vk_Control,0); PostMessage(Window, wm_KeyDown, Ord('V'),0); PostMessage(Window, wm_Keyup, Ord('V'),0); PostMessage(Window, wm_Keyup, vk_Control,0); |
Beste Grüße
|
|
glotzer
      
Beiträge: 393
Erhaltene Danke: 49
Win 7
Lazarus
|
Verfasst: Mo 19.07.10 17:37
eventuell auch ein sleep(1000) einfügen befor der tastendruck simuliert wird, ich vermute mal paint ist noch nicht ganz gestartet...
|
|
MaPsTaR
      
Beiträge: 90
Erhaltene Danke: 4
Win XP
Delphi 7 Enterprise
|
Verfasst: Mo 19.07.10 18:30
Hast du schonmal geprüft, was dir FindWindow('Paint', nil) zurück gibt?
Ich wette mit dir, da sollte 0 herauskommen.
Wer weiß welches Fenster du mit deinem Code ansprichst...
Wenn du dir die Parameter von FindWindow ansiehst wirst du auch merken warum:
HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name --> PChar('MSPaintAPP')
LPCTSTR lpWindowName // pointer to window name --> klappt mit nil
);
Versuch mal das:
Delphi-Quelltext 1:
| FindWindow(PChar('MSPaintAPP'), nil); |
damit solltest du das richtige Handle von dem Fenster bekommen.
_________________ Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Mo 19.07.10 20:21
Vielen Dank schon mal, man muss also die Tasten in der entgegen gesetzten Richtung "loslassen".
Sleep sowie der Tipp von Mapstar haben leider nicht so ganz geklappt - Window.
Ergänzt hab ich noch:
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:
| procedure TForm1.FormCreate(Sender: TObject); begin BMP:= TBitmap.Create; BMP.Width := imgBMP.Width; BMP.Height := imgBMP.Height; BMP := imgBMP.Picture.Bitmap; end;
procedure TForm1.btnPaintExportClick(Sender: TObject); begin Clipboard.Assign(imgBMP.Picture.Bitmap); Try ShellExecute(Application.Handle,'open', pchar('mspaint.exe'),nil, Nil, SW_Show); Finally SendBMPtoPaint(BMP); end; end;
procedure SendBMPtoPaint(BMP: TBitmap); var Window: HWND; begin Window := FindWindow(PChar('MSPaintAPP'), nil); <--
if Window > 0 then begin sleep(2000); PostMessage(Window, wm_KeyDown, vk_Control,0); PostMessage(Window, wm_KeyDown, Ord('V'),0); PostMessage(Window, wm_Keyup, Ord('V'),0); PostMessage(Window, wm_Keyup, vk_Control,0); end; end; |
Ich hab btw Win7, aber das wird wohl nix ausmachen.
|
|
MaPsTaR
      
Beiträge: 90
Erhaltene Danke: 4
Win XP
Delphi 7 Enterprise
|
Verfasst: Mo 19.07.10 21:21
Lad dir mal dieses Programm runter, damit kannst die Fenster einer Anwendung auswerten, dort erhältst du z.B. auch den Klassennamen von dem Fenster.
MSPaintApp ist der KlassenName für das Fenster von Paint unter XP, vielleicht liegt es daran.
Unter XP kommst du so zu der Zeichenfläche, hab das mit dem oben genannten Programm getestet, ob die Handle stimmen.
Delphi-Quelltext 1: 2: 3:
| Window1 := FindWindow(PChar('MSPaintAPP'), nil); Window2 := FindWindowEx(Window1, 0, PChar('AfxFrameOrView42u'), PChar('')); Window3 := FindWindowEx(Window2, 0, PChar('Afx:1000000:8'), PChar('')); |
Deinen Code habe ich mal ausprobiert. Im Paint funktioniert das bei mir auch nicht, dafür aber in Edit-Feldern, wenn ich es so mache:
Delphi-Quelltext 1: 2: 3: 4: 5:
| PostMessage(Window, WM_KEYDOWN, vk_Control, 0); PostMessage(Window, WM_KEYDOWN, Ord('V'), 0); PostMessage(Window, WM_CHAR, 22, 0); PostMessage(Window, WM_KEYUP, Ord('V'), LongInt($C0000001)); PostMessage(Window, WM_KEYUP, vk_Control, LongInt($C0000001)); |
Vielleicht will Paint noch eine spezielle Message, um Strg+V zu verwerten??
_________________ Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Mo 19.07.10 23:36
Danke für das Programm, hatte auch mal sowas ähnliches. Also an 7 liegt es nicht, hier heißt es auch MSPaintApp.
Das Programm gibt mir ja auch ein Handle als Hexwert(?) zurück und zwar 1061A, was Dezimal 67098. Wenn ich mein Programm jetzt starte und nachschaue welchen Wert das Handle des Paint-Fensters hat, so wird mir da 263568 als Wert zurückgegeben :/
Das mit Edit-Feldern funktioniert heißt ja nur, das Paint anscheinend wirklich noch was zusätzliches braucht, nur was?! Davon mal abgesehen, gibt es nicht noch eine andere (unkomplizierte) Lösung für mein Problem? Wobei ich ja schon der Meinung bin es so richtig zu lösen wäre  .
Ist ja auch für das forum interessant wenn wir eine Lösung finden, aber vorallem für mich.
|
|
MaPsTaR
      
Beiträge: 90
Erhaltene Danke: 4
Win XP
Delphi 7 Enterprise
|
Verfasst: Di 20.07.10 00:22
Wieso das mit dem Handle nicht klappt kann ich nicht sagen, evtl. deinen aktuellen Code nochmal posten?
Wenn du das Bild nur in Paint öffnen willst, könntest du das Bild über dein Programm speichern und dann mit Paint öffnen lassen...
_________________ Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Di 20.07.10 00:49
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:
| procedure TForm1.FormCreate(Sender: TObject); begin BMP:= TBitmap.Create; BMP.Width := imgBMP.Width; BMP.Height := imgBMP.Height; BMP := imgBMP.Picture.Bitmap; end;
procedure SendBMPtoPaint(BMP: TBitmap); var Window: HWND; begin Window := FindWindow(PChar('MSPaintApp'), nil);
if Window > 0 then begin sleep(2000); PostMessage(Window, wm_KeyDown, vk_Control,0); PostMessage(Window, wm_KeyDown, Ord('V'),0); PostMessage(Window, wm_Keyup, Ord('V'),0); PostMessage(Window, wm_Keyup, vk_Control,0); end; end;
procedure TForm1.btnPaintExportClick(Sender: TObject); begin Clipboard.Assign(imgBMP.Picture.Bitmap); Try ShellExecute(Application.Handle,'open', pchar('mspaint.exe'),nil, Nil, SW_Show); Finally SendBMPtoPaint(BMP); end; end; |
Nee das mit dem erst speichern macht sich in dem Programm in dem ich das brauche nicht wirklich gut.
´Vielleicht is ja auch das, was ich in der Prozedur mache Blödsinn, also das die eine bmp erwartet hmmm.
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Di 20.07.10 09:22
Bist du dir sicher das es einfach reicht das Bitmap zur Zwischenablage zu "Assignen"? Ich habe bisher noch nie was brauchbares gefunden um Bilder in die Zwischenablage einzufügen, aber soweit ich weis muss das Bild im Metafile Format sein.
Wenn du dazu Informationen gefunden hast wäre ich für die Quelle dankbar.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 20.07.10 10:58
kontrolliere mal, was in der Zwischenablage steht. Ich vermute dass es nur der pointer (also das objekt) auf die bitmap ist
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Di 20.07.10 11:52
hi, ich weiss nicht ob Du es schon gemacht hast. Aber soviel ich weiss must Du dafür ein Handle erstellen wenn Du die Zwischenablage global verwenden willst.
Alles ander was man inerhalb von Delphi macht, bleibt auch in Delphi selbst.
Musste ich bei mir auch machen, allerdings ging es bei mir um dragdrop von Files aus meinem Programm herraus. Also strg+c dann strg+v z.B.
Bei Dir währe es BitMap was Du ja einfügen tust. Ist aber vom Prinzip her das gleiche, lediglich der Aufruf würde sich ändern!
Delphi-Quelltext 1:
| Clipboard.SetAsHandle(CF_HDROP, hGlobal); |
für CF_HDROP gibt es CF_BITMAP glaube ich!
Hoffentlich habe ich es richtig erklärt!
Gruss Alf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Di 20.07.10 12:10
@Sinspin, klappen tut das aufjeden Fall, denn wenn ich das mal so ausprobiere,
Paint öffne und dann (selbser) Strg + V drücke wird das Bild eingefügt, sprich es war auch in der Zwischenablage.
Auf der Suche nach einer Quelle hab ich noch das hier gefunden:
www.swissdelphicente...showcode.php?id=1981
Da gibt es die Prozedur "PasteBitmap32FromClipboard" als Ziel erwartet die auch ne Bitmap..
@Flamefire hm wie überprüft man das  ? Ich mein es scheint ja "da" zu sein.
Ist wohl doch alles komplizierter als ich dachte ;D.
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Di 20.07.10 12:26
Hi
Wenn es jetzt nicht um den allgemeinen Fall, sondern konkret um Paint geht: Kannst du die Datei nicht von deinem Programm abspeichern(TBitmap.SaveToFile/Stream), und dann per Parameter mit Paint öffnen?
lg,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Di 20.07.10 12:27
@ ALF
Hm nein das habe ich nicht.
Ich hab zumindestens verstanden wormu es geht  ,
der erste Paramater ist der Dateityp das dürfte auch CF_Bitmap sein,
der zweite ist dann wie darauf zugegriffen werden soll?
Sprich das sieht dann so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TimgBMP.btnPaintExportClick(Sender: TObject); begin Clipboard.SetAsHandle(CF_BITMAP, hGlobal);
Clipboard.Assign(imgBMP.Picture.Bitmap); Try ShellExecute(Application.Handle,'open', pchar('mspaint.exe'),nil, Nil, SW_Show); Finally SendBMPtoPaint(imgBMP.Picture.Bitmap); end; end; |
Siehe Zeile mit Pfeil
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Di 20.07.10 12:47
hglobel ist der Handler dafür!
Delphi-Quelltext 1: 2: 3: 4:
| var hGlobal: THandle; begin hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, |
der allerdings dannn Deiner Bitmap noch zugewiessen werden muss.
Ich weiss zwar nicht ob der Umweg nötig is,t da Du ja selber sagst, mit STRG+V kannst Du die Bitmap ja schon in MSPAINT einfügen.
Ansonsten empfehle ich es so wie Hidden es vorgeschlagen hat.Speichern musst Du sie sicherlich irgendwan!
Denn, entweder Du hängst die Datei beim Aufruf von MSPAINT mit ran, oder Du must sowieso mit STRG+V das BitMap in MSPAINT einfügen!!! Und dies funktioniert ja schon, wie Du sagst. Ich glaube nicht das es da noch andere Möglichkeiten gibt!
Gruss Alf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
MaPsTaR
      
Beiträge: 90
Erhaltene Danke: 4
Win XP
Delphi 7 Enterprise
|
Verfasst: Di 20.07.10 12:49
Hallo, ich glaube, das Problem liegt nicht bei der Zuweisung zur Zwischenablage, sondern bei der Übergabe der Tastenkombination an Paint.
Probier mal das:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.SendBMPtoPaint; var Window: HWND; begin Application.ProcessMessages; Sleep(500); Window := FindWindow(PChar('MSPaintAPP'), nil); if Window > 0 then begin Sleep(500); SetForegroundWindow(Window); Sleep(500); keybd_event(vk_Control, MapVirtualKey(vk_Control, 0), 0, 0); keybd_event(vkKeyScan('V'), MapVirtualKey(vkKeyScan('V'), 0), 0, 0); keybd_event(vkKeyScan('V'), MapVirtualKey(vkKeyScan('V'), 0), KEYEVENTF_KEYUP, 0); keybd_event(vk_Control, MapVirtualKey(vk_Control, 0), KEYEVENTF_KEYUP, 0); end; end; |
Bei mir läuft es so, eventuell musst du die sleep's noch etwas anpassen.
Gruß MaPsTaR
_________________ Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Di 20.07.10 12:57
MaPsTaR hat folgendes geschrieben : | Hallo, ich glaube, das Problem liegt nicht bei der Zuweisung zur Zwischenablage, sondern bei der Übergabe der Tastenkombination an Paint. |
Das vermute ich auch!
Wobei ich mich frage was das Sleep soll!
Die Procedure muss sowie so komplet durchlaufen werden bevor irgend etwas passiert!
Wenn dann müssten es zwei Aufrufe sein!
Der erste öffnet Paint!
Der zweite übergibt an das Handle von Paint die Tasten!!
Gruss ALf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
MaPsTaR
      
Beiträge: 90
Erhaltene Danke: 4
Win XP
Delphi 7 Enterprise
|
Verfasst: Di 20.07.10 12:59
Das würde natürlich auch gehen, aber so wie Tony-S es angefangen hat habe ich es ohne Sleep probiert und da ist gar nichts passiert.
EDIT:
Die Werte für Sleep lassen sich bestimmt auch noch runtersetzen, das sollte von dem jeweiligen System abhängen, wie lange Paint braucht, um die Eingabe empfangen zu können.
Hatte jetzt bloß keine Lust das auch noch auszuprobieren. 
_________________ Liebe Kinder, es stimmt ... solnage auch nur der ertse und lezte Bchutsabe rihctig ist und alle andreen Bcuhsatben irgendwie vorahnden sind,
dann knan man es dennonch lesen, also macht nur weiter so, wir verstehen euch schon
|
|
Tony-S 
      
Beiträge: 184
Erhaltene Danke: 6
Windows 7, XP, Ubtuntu
Delphi 7, Visual Basic.net
|
Verfasst: Di 20.07.10 13:08
Danke Mapstar das läuft!
Aber da ich nicht kopieren will, naja gut mach ich jetzt eh ^^, wäre es noch nett wenn du mir bissl was erklärst:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure TForm1.SendBMPtoPaint; var Window: HWND; begin Application.ProcessMessages; Sleep(500); Window := FindWindow(PChar('MSPaintAPP'), nil); if Window > 0 then begin Sleep(500); SetForegroundWindow(Window); Sleep(500); wo ist der Unterschied mit MapVirtualKey? keybd_event(vk_Control, MapVirtualKey(vk_Control, 0), 0, 0); keybd_event(vkKeyScan('V'), MapVirtualKey(vkKeyScan('V'), 0), 0, 0); keybd_event(vkKeyScan('V'), MapVirtualKey(vkKeyScan('V'), 0), KEYEVENTF_KEYUP, 0); keybd_event(vk_Control, MapVirtualKey(vk_Control, 0), KEYEVENTF_KEYUP, 0); end; end; |
Ansonsten Vielen Dank an alle hier die dazu beigetragen haben, das Problem zu lösen.
Schönen Tag noch.
|
|
|