Plug-Ins für Paint.Net

  • Allgemein

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Sederic Enders.

    Plug-Ins für Paint.Net

    Hi, ich will für Paint.net Plugins machen, finde aber fast nix, wos erklärt wird, außer: entwickler-forum.de/showthread…4323-Paint-NET-Plugin-Tut

    Das schaut schonmal gut aus, aber iwie findet mein Paint.net die Dll nicht, wenn ich sie ins Effects-Verzeichnis kopiere. Oder zumindest erscheint die Erweiterung dann nicht unter den Effekten.

    Hat jemand damit Erfahrung, oder weiß jemand, woran das liegt?

    Danke
    Ich bin gerade dabei, ein Bisschen was zu testen.
    Mit 2.0 funktioniert's nicht. Anscheinend funktioniert's mit 3.5.
    Aber ich bin noch am Testen.

    Edit: Im Tutorial findet man diesen Code:

    VB.NET-Quellcode

    1. Try
    2. Dim F As New Font("Arial", 12) ' Die Schriftart + Größe
    3. '..........
    4. Catch ex As Exception
    5. 'Ignoriere die Fehler!
    6. End Try


    [VB.NET] TryCatch ist ein heißes Eisen
    [Allgemein] [Sammlung] Sinnvolle Verwendungen für Try-Catch
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()

    Also mit 3.5 erscheint's bei mir in der Liste.
    Nur bekomme ich beim Rendern eine Exception: Das Objekt wird bereits verwendet.
    Mal sehen. Mitm Visual Studio kann man den Debugger ja an einen laufenden Prozess ranhängen. Vielleicht finde ich da noch was heraus.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Also bei mir wird aus irgendeinem Grund per Threading auf die Render-Methode zugegriffen. Und da kommt's zu 'ner Race-Condition und dann verabschiedet sich das Graphics-Objekt.

    Mit SyncLock funktioniert's:

    VB.NET-Quellcode

    1. Dim Lock As New Object
    2. Public Overrides Sub Render(...)
    3. SyncLock Lock
    4. dstArgs.Graphics.DrawString("Das ist ein Test!", New System.Drawing.Font("Consolas", 12), Drawing.Brushes.Red, 100, 100)
    5. End SyncLock
    6. End Sub


    Also anhängen geht in der Express-Version nur mit einem Workaround. Das könnte für Dich aber sogar ein besseres Workaround sein, als das richtige Anhängen im Visual Studio.

    Schließe Visual Studio.
    Gehe in den Projektordner. Da gibt's eine Projektmappenname.sln-Datei und für jedes Projekt einen Unterordner. Gehe in den Unterordner des Projektes.
    Öffne dort die Projektname.vbproj per "Rechtsklick" -> "Öffnen mit" mit dem Editor (oder Notepad++).
    Das Ganze ist vom Prinzip her eine XML-Datei.
    Direkt unter dem Knoten <Project ...> fügst Du folgenden Code ein:

    XML-Quellcode

    1. <PropertyGroup>
    2. <StartAction>Program</StartAction>
    3. <StartProgram>C:\Program Files\Paint.NET\PaintDotNet.exe</StartProgram>
    4. </PropertyGroup>

    Und bei StartProgram musst Du halt den Pfad zu Deiner PaintDotNet.exe angeben.

    Jetzt öffnest Du wieder das Projekt. Wenn Du jetzt auf Debuggen klickst, wird Paint.Net gestartet und der Debugger ist angehängt.

    Anmerkung:
    Wenn Du Haltepunkte gesetzt hast, sind diese nicht aktiv, bis Du das PlugIn einmal verwendest. Das liegt an der .Net-Runtime, weil Assemblies erst geladen werden, wenn sie gebraucht werden. Und Haltepunkte in Quellcodedateien von ungeladenen Assemblies werden im VisualStudio als deaktiviert angezeigt.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Also um 'ne einfache MessageBox aufscheinen zu lassen, müsstest Du nur MessageBox.Show() aufrufen.
    War das so gemeint? Oder gibt's da eigene Dialoge?
    Ich hab mal nach "paint.net plugin dialog" gegoogelt. Da scheinen Themen dabei zu sein, die interessant sein könnten. Ich weiß nur nicht genau, was Du brauchst.
    Zur Not scheinst Du immer noch eine eigene Windows Form verwenden zu können (wahrscheinlich einfach im Konstruktor der Effekt-Klasse instanzieren und als Dialog anzeigen).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ähm also ich mein halt diese Dialoge zum Einstellen der Effenkteigenschaften, dies sonst auch immer gibt.
    So scheint es nicht zu gehen, da dann der Dialog öfters erscheint (beim Start, beim Klicken auf Effekte und nach dem Rendern, ...)

    ich hab den Code von einem Effekt mal runtergeladen (BlendModesPlus) Das scheint aber ein spezielles Plugin zu sein - ich habs nicht durchblickt ;)
    Aber da hab ich was gelesen, dass man iwo das braucht:

    VB.NET-Quellcode

    1. Public Overrides Function CreateConfigDialog() As EffectConfigDialog
    2. Return New GUIDialog() 'Oder wie der halt heißen soll
    3. End Function


    und der Dialog erbt iwie von PaintDotNet.Effects.EffectConfigDialog

    Aber ich versteh des net...
    So. Ich hab mich da mal durchgewühlt. Es ist eigentlich ganz einfach.

    Du musst Deinem Projekt eine neue Form hinzufügen. Das ist Dein Einstellungsdialog.
    Dann klickst Du im Projektmappenexplorer ganz oben auf "Alle Dateien anzeigen". Klappe die Form auf und klicke auf <DeineForm>.Designer.vb doppelt.
    Irgendwo am Anfang des Codes steht eine Zeile Inherits System.Windows.Forms. Diese änderst Du auf Inherits PaintDotNet.Effects.EffectConfigDialog. Dadurch ist Dein Dialog ein für Paint.Net verwendbarer Dialog.

    PaintDotNet.Effects.EffectConfigDialog erbt von PaintDotNet.PdnBaseForm erbt von System.Windows.Forms.Form.
    Also kann Visual Studio jetzt Deinen Dialog im Designer öffnen. Also rechtsklick in den Code -> Ansicht-Designer.
    Da klickst Du Dir Deinen Dialog zusammen. Als Beispiel verwende ich hier mal ein NumericUpDown mit dem Standardwert 12.

    Eine Property, damit der Wert schön zugreifbar ist:

    VB.NET-Quellcode

    1. Public ReadOnly Property FontSize As Single
    2. Get
    3. Return NumericUpDown_FontSize.Value
    4. End Get
    5. End Property

    Und noch das ValueChanged-Event behandeln:

    VB.NET-Quellcode

    1. Private Sub OnFontSizeChanged() Handles NumericUpDown_FontSize.ValueChanged
    2. MyBase.OnEffectTokenChanged()
    3. End Sub

    Hier ist das MyBase.OnEffectTokenChanged() wichtig. Dadurch teilst Du Paint.Net mit, dass sich die Einstellungen geändert haben und Paint.Net leitet dann automatisch das Rendern ein.

    Den Dialog verwendest Du dann im PlugIn.
    In der PlugIn-Klasse deklarierst Du eine globale Variable vom Typ Deines Dialoges. Bei mir im Beispiel sieht das so aus:

    VB.NET-Quellcode

    1. Dim SettingsDlg As SettingsDialog02

    Ganz wichtig: Kein New-Schlüsselwort! Die Instanz wird nämlich hier erstellt:

    VB.NET-Quellcode

    1. Public Overrides Function CreateConfigDialog() As PaintDotNet.Effects.EffectConfigDialog
    2. SettingsDlg = New SettingsDialog02
    3. Return SettingsDlg
    4. End Function


    Jetzt muss nur noch der Konstruktor geändert werden. Man muss angeben, dass der Effekt konfigurierbar ist.

    VB.NET-Quellcode

    1. Public Sub New()
    2. MyBase.New("TestPlugIn01", New System.Drawing.Bitmap(16, 16), "Foto", PaintDotNet.Effects.EffectFlags.Configurable)
    3. End Sub


    Das war's.
    Jetzt kann gezeichnet werden:

    VB.NET-Quellcode

    1. Dim Lock As New Object
    2. Public Overrides Sub Render(parameters As PaintDotNet.Effects.EffectConfigToken, dstArgs As PaintDotNet.RenderArgs, srcArgs As PaintDotNet.RenderArgs, rois() As System.Drawing.Rectangle, startIndex As Integer, length As Integer)
    3. SyncLock Lock
    4. dstArgs.Graphics.DrawString("Das ist ein Test!", New System.Drawing.Font("Consolas", SettingsDlg.FontSize), Drawing.Brushes.Red, 100, 100)
    5. End SyncLock
    6. End Sub

    Hier wird einfach die Schriftgröße aus dem Dialog verwendet.

    In meinem Beispiel gibt's noch das Problem, dass das vorher gezeichnete nicht verschwindet. Ist für Effekte wahrscheinlich auch nicht nötig.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ok danke!!!

    Etz hab ich aber noch ein paar Probleme:

    Niko Ortner schrieb:

    Hier ist das MyBase.OnEffectTokenChanged() wichtig. Dadurch teilst Du Paint.Net mit, dass sich die Einstellungen geändert haben und Paint.Net leitet dann automatisch das Rendern ein.

    Jetzt rendert Paint.Net zwar neu, aber irgendwie werden die Einstellungen net übernommen und es rendert das selbe Bild wie vorher...

    Und dann noch ne Frage: Zu nem Dialog gehören ja Button (Ok, Abbrechen), also hab ich auch welche draufgeklickt... (bzw nen Dialog genommen)
    Aber die anderen Effectdialoge haben ja unten immer so nen Glas-Effekt, wo die Buttons sind und die haben immer das gleiche Design. haben da die Entwickler sich alle die Mühe gemacht und das selber eingebaut, oder gibt es da irgendwo was, wo man Paint.Net das machen lässt, also dass es selber die Dialog-Buttons drauf baut...

    Noch dazu bekomm ich ne Fehlermeldung von Paint.net, wenn ich einen AcceptButton einbau und den Click:

    Quellcode

    1. Datei: C:\Program Files\Paint.NET\Effects\HelloWorld.dll
    2. Effektname: HelloWorld.Class1
    3. Vollständige Fehlermeldung: System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
    4. bei PaintDotNet.Menus.EffectMenuBase.RunEffectImpl(Type effectType) in D:\src\pdn\pdn_35x\src\PaintDotNet\Menus\EffectMenuBase.cs:Zeile 896.

    und wenn ich keinen drauf mach, kann ich ja nirgendwo sagen, dass es den Effect übernehmen soll, weil wenn ich die Form schließ, dann verschwindet das gerenderte Zeug wieder und es schaut aus wie vorher...

    Aber danke schonmal für das kleine Tut ;) Ich hab nirgendwo was besseres gefunden :thumbup:
    Dass die Werte nicht übernommen werden ist komisch.
    Hast Du den Debugger wie in Post #8 erklärt angehängt?
    Dann kannst Du einen Haltepunkt in die Render-Methode setzen und Dir ansehen, was denn so für Werte vorhanden sind.

    Was Du jetzt mit dem Glas-Effekt meinst, verstehe ich nicht. Bei mir sieht mein eigener Dialog genau gleich aus wie ein vorgefertigter.
    Kannst Du da mal einen Screenshot machen, wo der Unterschied zu erkennen ist?
    (Nebenbei: Paint.Net hat einige eigene Controls, aber die sind als Friend deklariert, also nur in der eigenen Assembly erreichbar. Wenn Du ganz hardcore drauf bist, kommst Du an die Controls via Reflection dran.)

    Zur Exception:
    Ich hab's mal getestet. Die Exception kommt bei mir auch. Ich habe aber leider keine Ahnung woran das liegt.
    Vielleicht findest Du bei Google was. Ich mach mich auch mal auf die Suche, aber ich kann nicht garantieren, dass ich was finde.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Also irgendwie ändert es die Werte schon, aber es entsteht kein neues Bild. Ich hab mal getestet, dass es die aktuelle Zeit drauf druckt und beim Start kommt die richtige Zeit und danach, wenn ich nen Wert ändere, dann rendert es neu (der Ladebalken unten in Paint.net läuft durch) aber es entsteht kein neues Bild, sondern die vorherige Zeit bleibt stehn, obwohl beim Debuggen mit Haltepunkt bei Date.Now das eigentlich richtige Datum drin steht...
    Der debugger ist genauso eingehängt, wie du gesagt hast...

    Wg. Glaseffect: ich hab nen Screenshot gemacht (im Anhang, weil ich net weiß, wie ich des direkt einbinden kann ;)


    Dabei hab ich mir nur gedacht, ob es iwas gibt, dass Paint.Net die 2 Buttons selbst noch einbaut und die Click-Events und so weiter selber behandelt, oder ob ich die wie sonst auch selber eibauen muss (also wahrscheinlich schon)

    Wg Exception hab ich noch nix gefunden ;)
    Bilder
    • PaintDotNetEffektDialog.png

      18,96 kB, 449×521, 256 mal angesehen
    @Sederic Enders:
    Ich hab mir mal angesehen, was da für ein Dialog erstellt wird.
    Du musst Dir die IndirectUI ansehen. Die ist extra so gemacht, dass man sich nicht um Bindings und so kümmern muss.
    Die ist im Namespace PaintDotNet.IndirectUI in der Assembly PaintDotNet.Core.
    Da findest Du sicher auch Tutorials bei Google. Ich jedenfalls bin da ausgestiegen.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Checken ist wahrscheinlich nicht so das Problem.
    Nur dauert es eine Weile, sich in das Thema einzulesen. Und Paint.Net habe ich nie verwendet und so wie's aussieht werde ich das auch in Zukunft nicht verwenden. Deshalb will ich mich da nicht für Dich einlesen und Dir das dann erklären.

    Edit: ... Klang das jetzt hochnäsig?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils