Seite 1 von 2

RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 12:57
von pbsol
Ich habe ein kleines Tool geschrieben, das Text einliest, aufbereitet und diesen im RTF-Format ins Clipboard kopiert. Unter Windows gelingt das recht gut; da gab es auch ein schönes Beispiel (weiß nicht mehr wo).

Unter Linux gelingt mir das einfach nicht. Meine Programmierkenntnisse sind jetzt nicht so gut, dass ich GTK+ bis ins Letzte verstehen würde, schon gar nicht die Umsetzung nach Purebasic. Einen einfachen Text kann ich mit

Code: Alles auswählen

clipboard=gtk_clipboard_get_(GDK_SELECTION_PRIMARY)
gtk_clipboard_set_text_(clipboard,text.s,-1)
kopieren. Das ist aber recht sinnlos, da Purebasic entsprechende Funktionen anbietet.

Soweit ich weiß muss man erst einem entsprechende Targets definieren (da habe ich schon Probleme) und dann wahrscheinlich mit

Code: Alles auswählen

gtk_clipboard_set_with_data_(*clipboard,targets,n_targets,*get_func,*clear_func,*user_data)
übertragen. Hier weiß ich insbesondere nicht, wie ich get_func und clear_func in Purebasic ansprechen soll.

Selbst für C gibt es recht wenig Beispiele, wie man so etwas machen könnte. Etwas in der Art (html) findet man hier:
http://www.findthatzip-file.com/search- ... tar.gz.htm

Kann mir jemand einen Tipp oder einen Stückchen Code geben?

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 16:40
von walker
Wie machst du das unter Windows?

Es gibt doch

Code: Alles auswählen

SetClipboardText(Text$)
der ist crossplattform .. reicht der nicht? Oder verstehe ich hier etwas falsch?

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 16:50
von Bisonte
Es geht hier vermutlich nicht um einen gewöhnlichen String, sondern um einen Text im RTF Format. Im Grunde gleichbedeutend mit Speicherblock.
Also wie kopiert man einen SpeicherBlock in's ClipBoard und zurück ? Und das ganze crossplatform....

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 17:13
von pbsol
So wie Bisonte das schreibt. Unter Windows so (Funktion von Green Snake):

Code: Alles auswählen

Procedure.i CopyRichTextToClipboard(rtf.s)
  Protected format.i
  Protected *globalMemory
  Protected *lock
  Protected result.i
 
  format = RegisterClipboardFormat_("Rich Text Format")
  If Not format
    ProcedureReturn #False
  EndIf
 
  If Not OpenClipboard_(#Null)
    ProcedureReturn #False
  Else
    EmptyClipboard_()
      
    *globalMemory = GlobalAlloc_(#GMEM_MOVEABLE | #GMEM_DDESHARE, Len(rtf) + 1)
    If Not *globalMemory
      ProcedureReturn #False
    EndIf
   
    *lock = GlobalLock_(*globalMemory)
    If Not *lock
      GlobalFree_(*globalMemory)
      ProcedureReturn #False
    EndIf
    
    PokeS(*lock, rtf, -1, #PB_Ascii) ; Text in ASCII umwandeln (falls Unicode verwendet wird) und schreiben.
    GlobalUnlock_(*globalMemory)
   
    result = SetClipboardData_(format, *globalMemory)
   
    GlobalFree_(*globalMemory)
    CloseClipboard_()
   
    ProcedureReturn result
  EndIf
 
  ProcedureReturn #False
EndProcedure
http://www.development-lounge.de/viewtopic.php?t=5978

Ansonsten erhält man immer nur den reinen Text, ohne Formatierungen und mit rtf-Steueranweisungen.

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 20:18
von ts-soft

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 11.01.2014 20:52
von pbsol
Ja, kenne ich natürlich. Hilft mir leider nicht weiter.

Gibt es irgendwo Literatur, die einem bei der Umsetzung hilft? Die PB-Hilfe ist da eher schweigsam und verweist immer auf den fortgeschrittenen/professionellen Programmierer, der solche Funktionen benötigt. Zudem sind eher Windows-Beispiele als GTK-Beispiele zu finden, das macht es nicht unbedingt leichter.

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 12.01.2014 23:37
von pbsol
Also ich habe es jetzt hinbekommen. Hatte die Lösung eigentlich schon recht lange, habe aber immer eine Unicode Executable erstellt und damit funktioniert es nicht. Und hier bräuchte ich nochmal Hilfe. Erst einmal der Code:

Code: Alles auswählen

gtk_init_(0,0)

; Clipboard Targets
Enumeration
  #TARGET_STRING
  #TARGET_RTF
EndEnumeration

Global Dim targets.GtkTargetEntry(2)

targets(0)\target=@"STRING"
targets(0)\flags=0
targets(0)\info=#TARGET_STRING

targets(1)\target=@"text/rtf"
targets(1)\flags=0
targets(1)\info=#TARGET_RTF
; Ende Target-Definition

Global n_targets=ArraySize(targets()) ; Anzahl der Targets

Global clipboard=gtk_clipboard_get_(GDK_SELECTION_PRIMARY) ;Clipboard oeffnen

Global rtf.s = "{\rtf1\ansi\ansicpg1252\deff0\deflang3082{\fonttbl{\f0\fswiss\fcharset0 Verdana;}}"  ;rtf das kopiert wird
rtf.s + "{\colortbl ;\red255\green102\blue0;\red128\green128\blue128;}"
rtf.s + "\viewkind4\uc1\pard\qc\f0\fs20\par"
rtf.s + "\cf1\ul\b\i\fs28 RTF RTF \cf2\fs20\par"
rtf.s + "\cf0\ulnone\b0\i0\par"
rtf.s + "\cf2 geht fast alles \par"
rtf.s + "\par"
rtf.s + "\cf2 bis auf Umlaute \par"
rtf.s + "\par"
rtf.s + "}"

ProcedureC get_func(clipboard,selection_data,info,user_data) ;rtf ins Clipboard 
  length=Len(rtf)
  Select info
    Case #TARGET_STRING
      gtk_selection_data_set_text_(selection_data,rtf,length)
    Case #TARGET_RTF
      gtk_selection_data_set_(selection_data,gdk_atom_intern_("text/rtf", #False),8,rtf,length)
  EndSelect
EndProcedure

gtk_clipboard_set_with_data_(clipboard,targets(),n_targets,@get_func(),#Null,#Null) ;hier werden u.a. die Targets uebertragen targets()

; Dummy-Fenster, muss waehrend des Programmtests geoffnet bleiben

OpenWindow(0, 0, 0, 345, 105, "GTK clipboard test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Den Inhalt könnt Ihr z.B. in OpenOffice kopieren oder als Text in einen Editor.

Ein kleines Python-Skript zeigt schön die Targets und den Inhalt:

Code: Alles auswählen

#!/usr/bin/python

import glib, gtk

def test_clipboard():
    clipboard = gtk.Clipboard()
    targets = clipboard.wait_for_targets()
    print "Targets available:", ", ".join(map(str, targets))
    for target in targets:
        print "Trying '%s'..." % str(target)
        contents = clipboard.wait_for_contents(target)
        if contents:
            print contents.data

def main():
    mainloop = glib.MainLoop()
    def cb():
        test_clipboard()
        mainloop.quit()
    glib.idle_add(cb)
    mainloop.run()

if __name__ == "__main__":
    main()
Und hiermit kann man das Problem erkennen. Wenn ich Unicode Executable auswähle, stimmen die Targets nicht mehr, statt "text/rtf" steht nur noch "t" und statt "STRING" nur noch "S". Die Daten sind zwar im Clipboard, aber keine Anwendung kann mit "t" oder "S" etwas anfangen.

Hat jemand eine Idee, wie es mit Unicode klappen könnte?

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 13.01.2014 00:18
von NicTheQuick
Du hättest eigentlich nur die Bits ändern müssen. Mit '8 * SizeOf(Character)' bleibt es dynamisch und funktioniert mit und ohne Unicode. Mehr hab ich aber auch nicht getestet. Aber das Einfügen in OpenOffice klappt auch mit Umlauten.

Code: Alles auswählen

gtk_init_(0,0)

; Clipboard Targets
Enumeration
  #TARGET_STRING
  #TARGET_RTF
EndEnumeration

Global Dim targets.GtkTargetEntry(2)

targets(0)\target=@"STRING"
targets(0)\flags=0
targets(0)\info=#TARGET_STRING

targets(1)\target=@"text/rtf"
targets(1)\flags=0
targets(1)\info=#TARGET_RTF
; Ende Target-Definition

Global n_targets=ArraySize(targets()) ; Anzahl der Targets

Global clipboard=gtk_clipboard_get_(GDK_SELECTION_PRIMARY) ;Clipboard oeffnen

Global rtf.s = "{\rtf1\ansi\ansicpg1252\deff0\deflang3082{\fonttbl{\f0\fswiss\fcharset0 Verdana;}}" +  ;rtf das kopiert wird
               "{\colortbl ;\red255\green102\blue0;\red128\green128\blue128;}" +
               "\viewkind4\uc1\pard\qc\f0\fs20\par" +
               "\cf1\ul\b\i\fs28 RTF RTF \cf2\fs20\par" +
               "\cf0\ulnone\b0\i0\par" +
               "\cf2 geht fast alles \par" +
               "\par" +
               "\cf2 bis auf Umlaute \par" +
               "\par" +
               "\cf2 ÄÖÜäöüß \par" +
               "\par" +
               "}"

Global *rtf_Ascii = AllocateMemory(Len(rtf) + 1)
PokeS(*rtf_Ascii, rtf, #PB_Ascii)

ProcedureC get_func(clipboard,selection_data,info,user_data) ;rtf ins Clipboard
  length=Len(rtf)
  Select info
    Case #TARGET_STRING
      gtk_selection_data_set_text_(selection_data,rtf,length)
    Case #TARGET_RTF
      gtk_selection_data_set_(selection_data, gdk_atom_intern_("text/rtf", #False), 8 * SizeOf(Character), @rtf, length)
  EndSelect
EndProcedure

gtk_clipboard_set_with_data_(clipboard,targets(),n_targets,@get_func(),#Null,#Null) ;hier werden u.a. die Targets uebertragen targets()

; Dummy-Fenster, muss waehrend des Programmtests geoffnet bleiben

OpenWindow(0, 0, 0, 345, 105, "GTK clipboard test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 13.01.2014 00:35
von ts-soft
@NicTheQuick
Mit Deiner Änderung funktionieren zwar die Umlaute, aber nicht im Unicode-Mode (da geht gar nichts).
Mit Import der Funktionen mit Pseudotype hatte ich auch noch kein Glück. Und den
text als ASCII in einen Speicher poken will auch nicht so recht. Sehr empfindlich die
Sache, fehlt mir leider im moment die Zeit für.

Aber irgendwie so in dieser Richtung sollte es funktionieren.

Re: RTF ins Clipboard kopieren - wie?

Verfasst: 13.01.2014 00:43
von pbsol
Jep, ist mir auch gerade aufgefallen. Arbeite mit 32 Bit Ubuntu 12.04 LTS, daran wird es wohl nicht liegen, oder? Das mit den Umlauten geht jetzt jedenfalls. Vielen Dank!