Seite 3 von 3

Re: Simpler WYSIWYG HTML Editor. Wie?

Verfasst: 20.06.2011 12:52
von ts-soft
Kukulkan hat geschrieben:und auch ohne RTF Konvertierungen meinerseits.
Das wäre aber IMHO die simpelste Lösung, die zudem Dein Programm nicht aufbläht.

Da würde ich an Deiner Stelle nochmals drüber Nachdenken :wink:

Gruß
Thomas

Re: Simpler WYSIWYG HTML Editor. Wie?

Verfasst: 20.06.2011 13:57
von Kiffi
hier mal ein WYSIWYG-Beispiel auf WebGadget-Basis.

Als WYSIWYG-Komponente kommt hier das dojotoolkit zum Einsatz

Code: Alles auswählen

Enumeration
  #frmWYSIWYG
EndEnumeration
Enumeration
  #frmWYSIWYG_cmdTest
  #frmWYSIWYG_Browser
EndEnumeration

Enumeration   ; VARENUM
  #VT_EMPTY = 0
  #VT_NULL = 1
  #VT_I2 = 2
  #VT_I4 = 3
  #VT_R4 = 4
  #VT_R8 = 5
  #VT_CY = 6
  #VT_DATE = 7
  #VT_BSTR = 8
  #VT_DISPATCH = 9
  #VT_ERROR = 10
  #VT_BOOL = 11
  #VT_VARIANT = 12
  #VT_UNKNOWN = 13
  #VT_DECIMAL = 14
  #VT_I1 = 16
  #VT_UI1 = 17
  #VT_UI2 = 18
  #VT_UI4 = 19
  #VT_I8 = 20
  #VT_UI8 = 21
  #VT_INT = 22
  #VT_UINT = 23
  #VT_VOID = 24
  #VT_HRESULT = 25
  #VT_PTR = 26
  #VT_SAFEARRAY = 27
  #VT_CARRAY = 28
  #VT_USERDEFINED = 29
  #VT_LPSTR = 30
  #VT_LPWSTR = 31
  #VT_RECORD = 36
  #VT_INT_PTR = 37
  #VT_UINT_PTR = 38
  #VT_FILETIME = 64
  #VT_BLOB = 65
  #VT_STREAM = 66
  #VT_STORAGE = 67
  #VT_STREAMED_OBJECT = 68
  #VT_STORED_OBJECT = 69
  #VT_BLOB_OBJECT = 70
  #VT_CF = 71
  #VT_CLSID = 72
  #VT_VERSIONED_STREAM = 73
  #VT_BSTR_BLOB = $fff
  #VT_VECTOR = $1000
  #VT_ARRAY = $2000
  #VT_BYREF = $4000
  #VT_RESERVED = $8000
  #VT_ILLEGAL = $ffff
  #VT_ILLEGALMASKED = $fff
  #VT_TYPEMASK = $fff
EndEnumeration

#DISPATCH_METHOD = $1
#DISPATCH_PROPERTYGET = $2
#DISPATCH_PROPERTYPUT = $4
#DISPATCH_PROPERTYPUTREF = $8

DataSection

  IID_IHTMLDocument: ; {626FC520-A41E-11CF-A731-00A0C9082637}
    Data.l $626FC520
    Data.w $A41E, $11CF
    Data.b $A7, $31, $00, $A0, $C9, $08, $26, $37
    
  IID_NULL: ; {00000000-0000-0000-0000-000000000000}
    Data.l $00000000
    Data.w $0000, $0000
    Data.b $00, $00, $00, $00, $00, $00, $00, $00       

EndDataSection

Procedure MakeBSTR(String$)
  Unicode$ = Space(Len(String$)*2+2)
  MultiByteToWideChar_(#CP_ACP, 0, @String$, -1, @Unicode$, Len(String$)*2+2)
  ProcedureReturn SysAllocString_(@Unicode$)
EndProcedure

Procedure.s ReadBSTR(bstr)
  length = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0)
  Text$ = Space(length)
  WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @Text$, length, 0, 0)   
  ProcedureReturn Text$
EndProcedure

Procedure.s StringFromVARIANT(*var.VARIANT)

  If VariantChangeType_(*var, *var, $2, #VT_BSTR) = #S_OK
    Result$ = ReadBSTR(*var\bstrVal)
    SysFreeString_(*var\bstrVal)
  Else
    Result$ = "ERROR : Cannot convert VARIANT to String!"
  EndIf
  
  ProcedureReturn Result$
EndProcedure

Procedure.s ExecuteJavaScript(Gadget, Function$, Arguments$, Separator$)
  Result$ = "ERROR" 

  Browser.IWebBrowser2 = GetWindowLong_(GadgetID(Gadget), #GWL_USERDATA)
  If Browser\get_Document(@DocumentDispatch.IDispatch) = #S_OK
    If DocumentDispatch\QueryInterface(?IID_IHTMLDocument, @Document.IHTMLDocument) = #S_OK
      If Document\get_Script(@Script.IDispatch) = #S_OK
        
        bstr_command = MakeBSTR(Function$)
        result = Script\GetIDsOfNames(?IID_NULL, @bstr_command, 1, 0, @dispID.l)
        If result = #S_OK
          
          ; parse the arguments          
          ;
          If Trim(Arguments$) = ""
            Count = 0
            *Arguments = 0
          Else            
            Count = CountString(Arguments$, Separator$)+1
            *Arguments = AllocateMemory(SizeOf(VARIANT)*Count)       
            *Arg.VARIANT = *Arguments
            
            For i = 1 To Count            
              *Arg\vt = #VT_BSTR
              *Arg\bstrVal = MakeBSTR(StringField(Arguments$, i, Separator$))
              *Arg + SizeOf(VARIANT)
            Next i
          EndIf
          
          params.DISPPARAMS\cArgs = Count
          params\cNamedArgs = 0
          params\rgvarg = *Arguments
          
          result = Script\Invoke(dispID, ?IID_NULL, 0, #DISPATCH_METHOD, @params, @varResult.VARIANT, 0, 0)
          If result = #S_OK
            Result$ = StringFromVARIANT(@varResult)
          Else
            Message$ = Space(3000)
            FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, result, 0, @Message$, 3000, 0)          
            Result$ = "ERROR: Invoke() "+Message$            
          EndIf
          
          If *Arguments
            *Arg.VARIANT = *Arguments
            For i = 1 To Count
              SysFreeString_(*Arg\bstrVal)
              *Arg + SizeOf(VARIANT)
            Next i          
            FreeMemory(*Arguments)
          EndIf
          
        Else
          Message$ = Space(3000)
          FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, result, 0, @Message$, 3000, 0)          
          Result$ = "ERROR: GetIDsOfNames() "+Message$          
          
        EndIf
        SysFreeString_(bstr_command)
                      
        Script\Release()
      EndIf
      Document\Release()
    EndIf
    DocumentDispatch\Release()
  EndIf

  ProcedureReturn Result$
EndProcedure

; Hier geht's lo-hos...

Define.s HTML

OpenWindow(#frmWYSIWYG, #PB_Ignore, #PB_Ignore, 600, 400, "WYSIWYG-Demo")
ButtonGadget(#frmWYSIWYG_cmdTest, 10, 5, 120, 25, "Get editor content...")
WebGadget(#frmWYSIWYG_Browser, 0, 30, 600, 360, "")

HTML + "<!DOCTYPE HTML PUBLIC ''-//W3C//DTD HTML 4.01//EN'' ''http://www.w3.org/TR/html4/strict.dtd''>"
HTML + "<html dir=''ltr''>"
HTML + "    <head>"
HTML + "        <style type=''text/css''>"
HTML + "            body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }"
HTML + "        </style>"
HTML + "        <script src=''http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js'' djConfig=''parseOnLoad: true''>"
HTML + "        </script>"
HTML + "        <script type=''text/javascript''>"
HTML + "            dojo.require(''dijit.Editor'');"

HTML + "  function GetEditorContent() { return dijit.byId(''editor1'').attr(''value'') };"

HTML + "        </script>"
HTML + "        <link rel=''stylesheet'' type=''text/css'' href=''http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css'' />"
HTML + "    </head>"
HTML + "    <body class='' claro ''>"
HTML + "        <div dojoType=''dijit.Editor'' id=''editor1''>"
HTML + "            <p>"
HTML + "                This instance is created from a div directly with default toolbar and"
HTML + "                plugins"
HTML + "            </p>"
HTML + "        </div>"
HTML + "    </body>"
HTML + "</html>"

HTML = ReplaceString(HTML, "''", Chr(34))

SetGadgetItemText(#frmWYSIWYG_Browser, #PB_Web_HtmlCode, HTML)

Repeat
  WWE=WaitWindowEvent()
  Select WWE
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #frmWYSIWYG_cmdTest
          MessageRequester("", ExecuteJavaScript(#frmWYSIWYG_Browser, "GetEditorContent", "", ""))
      EndSelect
    Case #PB_Event_CloseWindow
      Break 
  EndSelect
ForEver
ExecuteJavaScript() und der Klimbim drumherum habe ich von freak geklaut:
http://www.purebasic.fr/english/viewtop ... 94#p104594

Das Beispiel ist aufgrund der API-Aufrufe Win-only. Eine
Crossplattformlösung gibt es IMO nicht.

Grüße ... Kiffi

Re: Simpler WYSIWYG HTML Editor. Wie?

Verfasst: 20.06.2011 18:57
von Kiffi
Kiffi hat geschrieben:Eine Crossplattformlösung gibt es IMO nicht.
ups! Posting von DarkDragon übersehen...

// Edit: Jetzt auch crossplattformfähig (Danke an DD für den Trick):

Code: Alles auswählen

Enumeration
  #frmWYSIWYG
EndEnumeration
Enumeration
  #frmWYSIWYG_cmdTest
  #frmWYSIWYG_Browser
EndEnumeration

Define.s HTML

OpenWindow(#frmWYSIWYG, #PB_Ignore, #PB_Ignore, 600, 400, "WYSIWYG-Demo")
ButtonGadget(#frmWYSIWYG_cmdTest, 10, 5, 120, 25, "Get editor content...")
WebGadget(#frmWYSIWYG_Browser, 0, 30, 600, 360, "")

HTML + "<!DOCTYPE HTML PUBLIC ''-//W3C//DTD HTML 4.01//EN'' ''http://www.w3.org/TR/html4/strict.dtd''>"
HTML + "<html dir=''ltr''>"
HTML + "    <head>"
HTML + "        <style type=''text/css''>"
HTML + "            body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }"
HTML + "        </style>"
HTML + "        <script src=''http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js'' djConfig=''parseOnLoad: true''>"
HTML + "        </script>"
HTML + "        <script type=''text/javascript''>"
HTML + "            dojo.require(''dijit.Editor'');"

HTML + "  function SetDocumentTitle() { document.title=dijit.byId(''editor1'').attr(''value'') };"

HTML + "        </script>"
HTML + "        <link rel=''stylesheet'' type=''text/css'' href=''http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css'' />"
HTML + "    </head>"
HTML + "    <body class='' claro ''>"
HTML + "        <div dojoType=''dijit.Editor'' id=''editor1'' onDisplayChanged=''SetDocumentTitle();''>"
HTML + "            <p>"
HTML + "                This instance is created from a div directly with default toolbar and"
HTML + "                plugins"
HTML + "            </p>"
HTML + "        </div>"
HTML + "    </body>"
HTML + "</html>"

HTML = ReplaceString(HTML, "''", Chr(34))

SetGadgetItemText(#frmWYSIWYG_Browser, #PB_Web_HtmlCode, HTML)

Repeat
  WWE=WaitWindowEvent()
  Select WWE
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #frmWYSIWYG_cmdTest
          MessageRequester("", GetGadgetItemText(#frmWYSIWYG_Browser, #PB_Web_PageTitle))
      EndSelect
    Case #PB_Event_CloseWindow
      Break 
  EndSelect
ForEver
Weitere Infos zum Editor: http://docs.dojocampus.org/dijit/Editor

Grüße ... Kiffi

Re: Simpler WYSIWYG HTML Editor. Wie?

Verfasst: 21.06.2011 13:33
von Danilo
Kukulkan hat geschrieben:@Danilo
Ja, im Prinzip will ich nur rudimentäres. Allerdings ohne HTML Kenntnisse der Nutzer und auch ohne RTF Konvertierungen meinerseits. Kann Scintilla denn als WYSIWYG Editor funktionieren? Ich dachte, Scintilla macht nur Syntax-Highlighting (nehme ich heute für den HTML Editor-Part)?
Ich kenne mich mit Scintilla nicht aus, kann also nicht sagen ob es als
wirklicher WYSIWYG-Editor arbeiten kann.
Aber sowas wie Wordpad sollte man damit sicherlich machen können,
wenn man sich bissl einliest.

Nach kurzer Boardsuche (http://forums.purebasic.com/german/view ... 16&t=24132)
konnte ich dieses Beispiel erstellen:

Code: Alles auswählen

#font     = "Arial"
#fontsize = 14

Enumeration
  #DEFAULT   = 0
  #BOLD      = 1
  #ITALIC    = 4
  #UNDERLINE = 8
EndEnumeration

Procedure SetStyle(style,font$,fontsize,fontcolor,flag)
    ScintillaSendMessage(0,#SCI_STYLESETFONT, style, @font$)
    ScintillaSendMessage(0,#SCI_STYLESETSIZE, style, fontsize)
    ScintillaSendMessage(0,#SCI_STYLESETFORE ,style, fontcolor)
    If flag&#BOLD
        ScintillaSendMessage(0,#SCI_STYLESETBOLD     ,style, 1)
    EndIf
    If flag&#ITALIC
        ScintillaSendMessage(0,#SCI_STYLESETITALIC   ,style, 1)
    EndIf
    If flag&#UNDERLINE
        ScintillaSendMessage(0,#SCI_STYLESETUNDERLINE,style, 1)
    EndIf
EndProcedure

Procedure InitStyles()
    SetStyle(#DEFAULT                   ,#font,#fontsize  ,RGB($00,$00,$00),#DEFAULT)
    SetStyle(#BOLD                      ,#font,#fontsize  ,RGB($FF,$00,$00),#BOLD)
    SetStyle(#ITALIC                    ,#font,#fontsize-6,RGB($80,$80,$80),#ITALIC)
    SetStyle(#UNDERLINE                 ,#font,#fontsize  ,RGB($00,$00,$FF),#UNDERLINE)
    SetStyle(#BOLD|#UNDERLINE           ,#font,#fontsize  ,RGB($00,$00,$00),#BOLD|#UNDERLINE)
    SetStyle(#BOLD|#ITALIC              ,#font,#fontsize  ,RGB($00,$00,$00),#BOLD|#ITALIC)
    SetStyle(#BOLD|#ITALIC|#UNDERLINE   ,#font,#fontsize-4,RGB($00,$00,$00),#BOLD|#ITALIC|#UNDERLINE)
EndProcedure

Procedure StyleChars(start,length,style)
    ScintillaSendMessage(0,#SCI_STARTSTYLING,start,255)
    ScintillaSendMessage(0,#SCI_SETSTYLING,length,style)
EndProcedure

Procedure AddLine(text$)
    text$+Chr(10)
    len = Len(text$)
    text2$=Space(len*4)
    PokeS(@text2$,text$,len,#PB_UTF8) ; convert to UTF8
    ScintillaSendMessage(0, #SCI_APPENDTEXT, MemoryStringLength(@text2$,#PB_UTF8), @text2$)
EndProcedure


If OpenWindow(0, 0, 0, 500, 300, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If InitScintilla()
        ScintillaGadget(0, 0, 0, 500, 300, #Null)

        ScintillaSendMessage(0,#SCI_SETMARGINWIDTHN,1,0)        ; margin
        ScintillaSendMessage(0,#SCI_SETCODEPAGE,#SC_CP_UTF8,0)  ; UTF8 mode

        InitStyles()
        
        AddLine("Hallo Kukulkan!")
        AddLine("Das ist ein Scintilla-Gadget")
        AddLine("mit Styles")
        AddLine("")
        AddLine("Ä Ö Ü ä ö ü ß")

        StyleChars(0 ,15,#BOLD)
        StyleChars(16,28,#ITALIC)
        StyleChars(45,3 ,#UNDERLINE)
        StyleChars(49,6 ,#BOLD|#UNDERLINE|#ITALIC)
        
    EndIf
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf 
Bold, Italic, Underline, versch. Fonts und Fontgrößen gehen also
auf jeden Fall mit Scintilla.

EDIT: UTF8 bei Scintilla eingeschalten, geht nun auch mit Unicode.

Re: Simpler WYSIWYG HTML Editor. Wie?

Verfasst: 22.06.2011 14:20
von Kukulkan
Hallo Danilo, Kiffi und andere,

vielen Dank für die super Hilfe. Ich werde mir das mal in Ruhe ansehen und dann für den nächsten Release eine der Varianten einbauen.

DANKE!!!! :allright:

Kukulkan