Programming plugins
An Introduction to Project Dogwaffle’s Simple and Flexible Plugin Architecture.
This document includes the following subjects:
Plugin example (VB 5/6)
Plugin Interface Function Reference (Alphabetical)
Other Documents
Plugin Interface Function Examples Lots of examples of common functions. (VB 5/6)
Download the Visual Basic source code for the plugins |
Plugin_Examples.zip These plugins are open source and may be used for any purpose. |
Barebone projects Projects with and without an interface. For the quickest start, start here. |
“It only requires one line of code to get things going!”
Are you interested in the exciting field of computer graphics programming, but don’t have the time or resources to develop your own high end application? Wouldn’t you like to have a way to build and test your own routines without the hassle of low end hardware abstractions and archaic programming structures? Wouldn’t you like to work in a friendly, high end environment that still lets you write fast, flexible code? Well, you can do that, and contribute your own functionality to a powerful and growing graphics workhorse at the same time!
Project Dogwaffle plugins are standard executable programs that can be written in almost any language that supports ActiveX under Microsoft Windows, however here we will concentrate on Visual Basic Professional or Enterprise edition 5 or 6, and VB net. 'Standard Editions’ of Visual Basic may be viable, but are not supported in this document.
The plugin interface uses ActiveX automation that is built into Visual Basic. It only requires one line of code to get things going! A naming convention is provided so Dogwaffle can neatly categorize it's plugins.
Executables names are appended with "_pf" for a filters, "_pi" for importers, "_px" for exporters, "_pb" for plugins that act on brushes, and "_pm" for plugins that don't fall into any of the other categories.
To get additional information about all available functions and their descriptions, create a reference to dogwaffle in Visual Basic (Project menu/References...) and use the Object Browser (View menu).
The Dogwaffle Object
To access the plugin interface functions, you create a dogwaffle object. It sounds scary but it's really quite simple - only one line (or two if you count the dim statement for the object) After that everything works the way you are used to in Visual Basic.
'create a dogwaffle object
Dim Dogwaffle As Object
Set Dogwaffle = CreateObject("Dogwaffle.Dogwaffle_Class")
'now you can use any dogwaffle method (or function) like this
'Dogwaffle.Refresh 'refreshes the buffers imagery, as an example
Controls used by Project Dogwaffle
Note, these components are not required for any plugin, but may be used without the requirement of an installer, because they are installed by Project Dogwaffle.
To avoid complications with installing your plugin on other systems, consider only using these controls. You can add or remove components and references from the Project/Component... and Project/References... menu items in the Visual Basic editor.
Microsoft Common Dialog Control 6.0 (SP3)
Microsoft Flexgrid Control 6.0 (sp3)
Microsoft Rich Textbox Control 6.0
Microsoft Windows Common Controls 5.0 (SP2)
Bevel Box
Button Gadget
Horizontal Prop Gadget
Lens Flare Rendering and More...Eventually
Mutually Exclusive Button Gadget
To begin a new plugin, open a standard
exe project.
|
Create a new module
that will contain your
plugins code. In the
case of a plugin with an
interface, this will be
startup code.
|
If your plugin does not require an
interface, just remove the default
form from the project.
|
Be sure to set the Startup Object to Sub Main. This causes program execution to begin with your own custom startup code |
Now add a ‘sub main’ procedure: Sub Main 'create a dogwaffle object Dim Dogwaffle As Object ‘if you want to use the Dogwaffle object outside of this procedure, declare it at the top (outside of the procedure) like this: Public Dogwaffle as object Set Dogwaffle = CreateObject("Dogwaffle.Dogwaffle_Class") ‘Add your own code here End sub Go on to the plugin examples |
Creating a Plugin with an Interface
Often, a plugin will require input from the user. If you know you will need an interface for your project, don’t remove the form in the previous step, or simply add a new one. Design your form as you would normally in Visual Basic. It might look something like the illustration. When ready to open the form, remember that we have changed the startup option to run our custom startup code, so the form doesn’t get open by default. Therefore, we are required to open the form ourselves. We could open it like normal like this:
Form1.show
This would open the form, but since plugins are independent executable programs, it would open up outside of Project Dogwaffle’s main window. To compensate for this, we send a copy of the form to the plugin interface like this:
Dim NewWindow As Form
Dim showmode As Integer
Set NewWindow = Form1
showmode = 0
Call Dogwaffle.Dog_SendFormObject(NewWindow, showmode)
The first parameter is the form itself, and the second parameter is 0 for modal, and 1 for non-modal operation.
“The result was a programming interface that couldn’t be simpler or more powerful!”
It was the goal of the plugin interface was to be fully asynchronous, so the method of linking with dlls used by other graphics software wasn’t the best solution. Microsoft Windows contains a number of communication port types, unfortunately, none of them where particularly simple or appropriate for the application. Also, passing memory pointers between applications is not supported under Windows without marshaling, because of the memory protection scheme. A scripting language approach was also considered, but it turned out to be too slow.
Then, it was determined to make the program an ActiveX host. It was something of a trade off, but the result was a programming interface that couldn’t be simpler or more powerfull! The ActiveX technology is transparent to Visual Basic programmers, and with a little know-how, Visual Basic can be pretty fast.
Optimizing
Performance in Visual Basic.
Note, these examples refer to Visual Basic 5 and 6, Professional or Enterprise Editions with Native Code Compiler. Visual Basic Net will have slightly different requirements.
A lot of people don't realize that Visual Basic is actually pretty fast. The reason for this is likely that it defaults to being ‘safe’. Here's how to make you code run faster in Visual Basic in three easy steps...
Always declare variables. If not declared, variables default to 'variant.' Variants are very slow. Dim variables as integer or long if possible. Don't let this happen to you..."
Dim x,y,z,r,g,b as long
It should be...
Dim X as long, y as long, z as long, r as long, g as long, b as long
If the first syntax were used, only the last variable would be declared as long and the rest as the default, variants, which are slow!
Turn on all optimizing options when compiling an application. That's what they're there for.
Write good code. Ok, this one isn't necessarily as simple as the other two. Generally try to reduce the amount of work being done in the inner loop. Volumes could be written on the subject and probably have, but not by me.
VB has another neat optimizing trick with division. There are two division operators, the “/” and “\” operators. The one your are probably most familiar with is “/”, which seems like a normal division sign, and it is. The catch is that “/” is meant for floating point math, and anytime you use it, even with integer and long variables, everything has to be coerced to floating point. Using the integer division operator “\” lets you do division on integers, which can be much faster if it’s all you need.
Reference of plugin interface methods (alphabetical):
*Visual Basic’s Object browser will let you browse these from the IDE.
* Note, VB.Net will require a change in data types. VB5/6 uses 32 bit longs, and 16 bit Integers. VB.Net uses 64 bit longs, and 32 bit integers. Usage of VB5/6 is assumed in this document except where specified. See your VB.net migration documentation for full details.
Contact the developer.
Sub Dog_ActivateCustomBrush() Activates the custom brush tool |
Sub Dog_AlphaOff() Turns off the alpha channel (while still keeping the alpha in memory) |
Sub Dog_AlphaOn() Turns on the alpha channel |
Function Dog_Animbrush_Currentframe() As Long Gets the current frame of the animbrush |
Sub Dog_Animbrush_Next() Goes to the next frame in an animbrush, depending on the play direction. |
Property Dog_BufferHeight As Integer read-only The hight of the main buffer in pixels |
Property Dog_BufferWidth As Integer read-only The width of the main buffer in pixels |
Sub Dog_ChangeBarImage(filename As String) Changes the image of the status bar. The image is a bmp or jpeg at 160 x 15. |
Sub Dog_ChangePointer(Number As Long) Changes the mouse pointer. |
Sub Dog_CopyBrush() Causes the current custom brush to be copied to the clipboard |
Sub Dog_CreateAnim(frames As Long) Creates an anim with the specified number of frames |
Sub Dog_CreateAnimAdv(frames As Long, Flags As Long) Creates a new animation with some ‘advanced’ flag settings. Flags 'bit 1 not set=don't copy first frame. Set=all frames get copy of first frame. 'bit 2 set=clear current animation if one exists. |
Function Dog_CreateEmptyBrush(BrushWidth, BrushHeight) Creates a new empty custom brush of the given size. Returns -1 if could not be created. |
Sub Dog_CreateNewAnBr(frames As Long) Creates a new animbrush with the specified number of frames. A custom brush must have previously been created. |
Sub Dog_DeleteFrame(Frame As Long) Deletes the specified frame |
Sub Dog_FreeAnim() Frees the current animation and its resources. |
Function Dog_Get_InternalBrushID() As Long Returns the numeric ID of the current internal brush |
Function Dog_GetABuffer() Gets a copy of the alpha channel in a variant |
Function Dog_GetAlphabits() As Byte Returns a value that indicates the activation state of the alpha channel |
Sub Dog_GetAlphaBounds(x1 As Long, y1 As Long, x2 As Long, y2 As Long) Returns the bounds of the current alpha 'selection' in x1,y1,x2,y2 which should be long supplied by the user. |
Function Dog_GetAltitude() As Single Returns the altitude of a tablets stylus. |
Function Dog_GetAnimbrush_A() Returns the alpha channel of an animbrush. |
Function Dog_GetAnimbrush_B() Returns the blur channel of an animbrush. |
Function Dog_GetAnimbrush_G() Returns the green channel of an animbrush. |
Function Dog_GetAnimbrush_R() Returns the red channel of an animbrush. |
Function Dog_GetAnimbrush_Totalframes() As Long Gets the total frames in an animbrush. |
Function Dog_GetAzimuth() As Single Returns the pens azimuth. |
Function Dog_GetB(X As Integer, Y As Integer) As Long returns the blue attribute of the specified pixel. |
Function Dog_GetBBuffer() Gets a copy of the main green buffer in a variant |
Function Dog_GetBFrame(Frame As Long) Returns the blue channel of a frame from the animation |
Function Dog_GetBrushABuffer() Gets a copy of the current working custom brush alpha buffer. |
Function Dog_GetBrushBBuffer() Gets a copy of the working custom brush blue buffer |
Function Dog_GetBrushGBuffer() Gets a copy of the working custom brush green buffer. |
Function Dog_GetBrushHeight() As Integer Gets the height in pixels of the current working custom brush. |
Function Dog_GetBrushMode() As String Returns the paint mode of the internal brush. Not to be confused with the fill mode used by fill tools. (See Dog_GetPaintMode) |
Function Dog_GetBrushOpacity() As Long Returns the internal brush opacity |
Function Dog_GetBrushRBuffer() Gets a copy of the working custom brush red buffer. |
Function Dog_GetBrushSettings() As String Returns the filename of a file containing a BrushSettings structure that contains all of the current settings from the brush settings panel. (not including Brush type) |
Function Dog_GetBrushSize() As Long Returns the size of the internal brush |
Function Dog_GetBrushSteps() As Long Returns the steps of the internal brush |
Function Dog_GetBrushType() As Long Gets the current brush type 0=aa brush, 1=internal brush, 2=custom brush. |
Function Dog_GetBrushWidth() As Integer Gets the width in pixels of the current working custom brush. |
Function Dog_GetBump() Gets a copy of the current paper (bump) texture in an array |
Function Dog_GetCurrentFrame() As Long Returns the current frame number in the animation (frame numbers start at 0) |
Function Dog_GetFillMode() As Long Gets the current fill mode used by fill tools. |
Sub Dog_GetFrame() Causes the current frame of the animation to be stored into the RGB buffers. |
Function Dog_GetG(X As Integer, Y As Integer) As Long returns the green attribute of the specified pixel. |
Function Dog_GetGBuffer() Gets a copy of the main green buffer in a variant |
Function Dog_GetGFrame(Frame As Long) Returns the green channel of a frame from the animation |
Function Dog_GetGradient(Index As Integer) Gets a copy of the gradient There are 8 indexes altogether. Use Dog_GetGradientIndex to get the one currently selected by the user. |
Function Dog_GetGradientIndex() As Integer Returns the index of the currently selected gradient. |
Function Dog_GetGridState() As Boolean Returns the on/off state of the grid |
Function Dog_GetGridX() As Long Returns the x size of the grid |
Function Dog_GetGridY() As Long Gets the y size of the grid |
Function Dog_GetMediaPreview() Returns an image of what the current media might look like in use. |
Function Dog_GetPaper() Returns the paper texture currenly in use |
Function Dog_GetPaperHeight() As Long Returns the height of the current paper texture |
Function Dog_GetPaperWidth() As Long Returns the width of the current paper |
Function Dog_GetPitch() As Single Returns the pens pitch |
Function Dog_GetPressure() As Single Returns the current tablet pressure as a value between 0 and 1 |
Function Dog_GetPrimaryColor() As Long Gets the primary pen color that is used for drawing with the left mouse button. |
Function Dog_GetR(X As Integer, Y As Integer) As Long Returns the red attribute of the specified pixel. |
Function Dog_GetRBuffer() Gets a copy of the main red buffer in a variant |
Function Dog_GetRFrame(Frame As Long) |
Function Dog_GetRGB(X As Integer, Y As Integer) As Long Returns the RGB attributes of the specified pixel in long word format. |
Function Dog_GetRoll() As Single Returns the pens roll |
Function Dog_GetSecondaryColor() As Long Gets the secondar pen color that is used for drawing with t the right mouse button. |
Function Dog_GetSwapBBuffer() Returns the Swap blue buffer in a variant |
Function Dog_GetSwapGBuffer() Returns the Swap green buffer in a variant |
Function Dog_GetSwapRBuffer() Returns the swap red buffer in a variant |
Function Dog_GetTempDir() As String Gets the directory for storing temp files |
Function Dog_GetTotalFrames() As Long Returns the total number of frames in an animation. (Returns actual number of frames, not starting at 0) |
Function Dog_GetTwist() As Single Returns the pens twist |
Function Dog_GetWells() Gets an array in a variant containing every well entry. |
Function Dog_GetYaw() As Single Returns the pens Yaw |
Sub Dog_GotoFrame(Frame As Long) Goes to the specified frame |
Sub Dog_GotoFrameAdv(Frame As Long, Flags As Long) Goes to the specified frame, with options... |
Sub Dog_InitMarquee() Initializes the marquis with whatever's in the alpha channel |
Sub Dog_InsertFrame(Frame As Long) Inserts a new frame at the specified frame. |
Function Dog_IsTabletActive() As Boolean Returns TRUE if the tablet is active |
Sub Dog_Load_IM(filename As String) Loads an new buffer through the external IM loader (Image Magic) |
Sub Dog_Lock() Locks the buffers to prevent them from being accessed you're using them. |
Sub Dog_Lock() Locks the buffer to prevent the user from making changes while a plugin is accessing it. Pair with Dog_Unlock |
Sub Dog_MessageBox(message) Displays the supplied message to the user |
Sub Dog_NewBrushFilename(Path As String) |
Sub Dog_NewBuffer(Width As Integer, Height As Integer) Creates a new dogwaffle buffer (currently erasing the old one) |
Sub Dog_NewFilename(Path As String) Changes the internal pathname that dogwaffle uses when saving a buffer |
Sub Dog_NewPaper(filename As String) Sets a new paper texture. Supports BMP and Jpg |
Sub Dog_PasteBrush() |
Sub Dog_PlayAnimation() Plays the current animation. |
Function Dog_QuestionBox(message) As Integer Prompts the user with a OK/Cancel requester. Result is 1 for ok and 2 for cancel. |
Sub Dog_Refresh() Refreshes the display after you've made changes. |
Sub Dog_Refresh_BrushDisplays() Refreshes various thumbnail images inside dogwaffle that display the current custom brush. For example, the brush keyer,the current brush icon, etc. |
Sub Dog_RenameBuffer(Name As String) Changes the name of the buffer displayed in the windows title bar. |
Sub Dog_ReplaceInternalBrush(filename As String, Index As Long) Replaces internal brush images |
Function Dog_RequestFile_Open(Title As String, filename As String, Pattern As String) As String Displays an Open file requester. Result is a filename or "" |
Function Dog_RequestFile_Save(Title As String, filename As String, Pattern As String) As String Displays a Save file requester. Result is a filename or "" |
Sub Dog_RestorePointer() Returns the mouse pointer to normal |
Sub Dog_SaveUndo() Saves an undo |
Sub Dog_SeAnimtBrush_A(abuf) 'yes, with the typo SetAnimBrush Sets the alpha channel of an animbrush |
Sub Dog_SeAnimtBrush_B(bbuf) Sets the blue channel of an animbrush |
Sub Dog_SeAnimtBrush_G(Gbuff) Sets the green channel of an animbrush. |
Sub Dog_SeAnimtBrush_R(Rbuff) Sets the red channel of an animbrush. |
Sub Dog_SendFormObject(NewObject As Object, showmode As Integer) Displays a copy of a form inside the application. |
Sub Dog_SetABuffer(abuf) Sets the alpha buffer with the supplied array. |
Sub Dog_SetBBuffer(bbuf) Sets the blue buffer with the supplied array. |
Sub Dog_SetBrushABuffer(abuf) Sets the alpha buffer of the current custom brush with the supplied array. Brush should be initialized first. |
Sub Dog_SetBrushBBuffer(bbuf) Sets the blue buffer with the supplied array. |
Sub Dog_SetBrushGBuffer(gbuf) Sets the green buffer of the current custom brush with the supplied array. Brush should be initialized first. |
Sub Dog_SetBrushMode(mode As String) Sets the paint mode of the internal brush. Not to be confused with the fill mode used by fill tools. (See Dog_SetPaintMode) |
Sub Dog_SetBrushOpacity(opacity As Long) Sets the opacity slider on the tool panel. |
Sub Dog_SetBrushRBuffer(rbuf) Sets the red buffer of the current custom brush with the supplied array. Brush should be initialized first. |
Sub Dog_SetBrushSettings(SettingsFile As String) Reads a BrushSettings file that contains all of the settings for the brush settings panel. (not including Brush type) |
Sub Dog_SetBrushSize(Size As Long) Sets the brush size slider on the tool panel. |
Sub Dog_SetBrushSteps(Steps As Long) |
Function Dog_SetBrushType(BrushType As Long) As Long Sets the brush type. 0=aa brush, 1-internal brush, 2=custom brush. |
Sub Dog_SetFillMode(mode As Long) Sets the paint mode used by fill tools |
Sub Dog_SetGBuffer(gbuf) Sets the green buffer with the supplied array. |
Sub Dog_SetGradient(NewGradient, Index As Integer) copies an array to the gradient of index. |
Sub Dog_SetGrid(Active As Boolean, X As Long, Y As Long) Sets the size of the grid and the on/off state. |
Sub Dog_SetInternalBrush(Index As Long) Selects a new internal brush image by index. |
Function Dog_SetMousePointer(PointerNumer As Integer) As Integer Sets the mouse pointer to one of several predifined images such as the hourglass. Returns the number of the current pointer. |
Sub Dog_SetPaper(Buffer, pwidth As Long, pheight As Long) creates a new paper texture and sets its image. |
Sub Dog_SetPrimaryColor(r As Byte, g As Byte, b As Byte) Sets the primary pen color that is used for drawing with the left mouse button. |
Sub Dog_SetProgress(progress As Single) Sets a value to the visible progress bar on the plugin interface. value is between 0 and 100. |
Sub Dog_SetRbuffer(rbuf) Sets the red buffer with the supplied array. |
Sub Dog_SetRGB(X As Integer, Y As Integer, r As Byte, g As Byte, b As Byte) Sets the specified pixel in the main buffers to the value r,g,b. |
Sub Dog_SetSecondaryColor(r As Byte, g As Byte, b As Byte) Sets the secondary pen color that is used for drawing with the right mouse button. |
Sub Dog_SetSwapBBuffer(jbbuf) Sets the blue buffer for the swap image with the specified array. |
Sub Dog_SetSwapGBuffer(jgbuf) Sets the green buffer for the swap image with the specified array. |
Sub Dog_SetSwapRBuffer(jrbuf) Sets the red buffer for the swap image with the specified array. |
Sub Dog_SetWells(NewWells) sets dogwaffles well colors using a variant array |
Sub Dog_ShowScrub(CurrentFrame As Long, TotalFrames As Long) Shows the animation control panel. |
Sub Dog_StopAnimation() Stops playing an animation. |
Sub Dog_StoreFrame() Causes the RGB buffers to be stored into the current frame of the animation. |
Sub Dog_Unlock() Unlocks the buffers for use by the user (if no other plugin still holds a lock) |
Sub Dog_UnlockHard() Unlocks the buffer even if another plugin holds a lock. |
Function Dog_ValueBox(Title As String, Min As Integer, max As Integer) As Integer Prompts the user for a value within a specific range. Result is the value or -1 if canel. |
Function Dog_ValueBox2(Title As String, Caption As String, Min As Long, max As Long, Default As Long) As Long Replacement for the valuebox requester. Now allows a default value and window title. |
Function Dog_WallpaperFilename() As String Retunrs the filename of the current wallpaper image displayed in the backdrop (MDI) window. |
Here is a very simple example of a plugin. The following is the complete program. Just paste it into an empty project with no forms, and one module. That's it.
This example is for Visual Basic 5 and 6. See below for a VB.net example.
Sub Main
'*** NEGATIVE FILTER EXAMPLE ***
'to use this example, create a visual basic project with no forms
'and one empty module and paste this code into it. that's it.
'dogwaffle should be running when this code is executed.
Dim x As Integer, y As Integer
Dim r As Byte, g As Byte, b As Byte
'allocate the main buffers
Dim MainRBuffer() As Byte
Dim MainGBuffer() As Byte
Dim MainBBuffer() As Byte
'create a dogwaffle object
Dim Dogwaffle As Object
Set Dogwaffle = CreateObject("Dogwaffle.Dogwaffle_Class")
'get the width and height of the buffer
th = Dogwaffle.Dog_BufferHeight
tw = Dogwaffle.Dog_BufferWidth
'get the buffers
MainRBuffer() = Dogwaffle.Dog_GetRBuffer
MainGBuffer() = Dogwaffle.Dog_GetGBuffer
MainBBuffer() = Dogwaffle.Dog_GetBBuffer
'process the buffers.
'in this case, a negative effect.
For y = 0 To th-1
For x = 0 To tw-1
r = MainRBuffer(x, y)
g = MainGBuffer(x, y)
b = MainBBuffer(x, y)
MainRBuffer(x, y) = 255-r
MainGBuffer(x, y) = 255-g
MainBBuffer(x, y) = 255-b
Next
Next
'send the buffers back to dogwaffle.
Dogwaffle.Dog_SetRbuffer MainRBuffer()
Dogwaffle.Dog_SetGbuffer MainGBuffer()
Dogwaffle.Dog_SetBbuffer MainBBuffer()
'and refresh the screen
Dogwaffle.Dog_Refresh
End Sub
These plugin examples may be freely modified and distributed. That's what it's there for.
'the main difference is the way arrays are declared. They used to be dim (lower bound, upper bound)
'now now, lower bound is alwyas 0, and the parameter is the number of array elements, and not the upper bound.
'also Integers are now 32 bit and Longs are now 64 bit, so we use integers instead of longs.
Sub Main()
'*** NEGATIVE FILTER EXAMPLE ***
'to use this example, create a visual basic project with no
forms
'and one empty module and paste this code into it.
'Set the startup entry point to Sub Main in the project
properties
'that's it.
'dogwaffle should be running when this code is executed.
Dim x As Integer, y As Integer
Dim r As Byte, g As Byte, b As Byte
Dim tw As Long, th As Long
'create a dogwaffle object
Dim Dogwaffle As Object
Dogwaffle = CreateObject("Dogwaffle.Dogwaffle_Class")
'get the width and height of the buffer
th = Dogwaffle.Dog_BufferHeight
tw = Dogwaffle.Dog_BufferWidth
'allocate the main buffers
Dim MainRBuffer(tw, th) As Byte
Dim MainGBuffer(tw, th) As Byte
Dim MainBBuffer(tw, th) As Byte
'get the buffers
MainRBuffer = Dogwaffle.Dog_GetRBuffer
MainGBuffer = Dogwaffle.Dog_GetGBuffer
MainBBuffer = Dogwaffle.Dog_GetBBuffer
'process the buffers.
'in this case, a negative effect.
For y = 0 To th - 1
For x = 0 To tw - 1
r = MainRBuffer(x, y)
g = MainGBuffer(x, y)
b = MainBBuffer(x, y)
MainRBuffer(x, y) = 255 - r
MainGBuffer(x, y) = 255 - g
MainBBuffer(x, y) = 255 - b
Next
Next
'send the buffers back to dogwaffle.
Dogwaffle.Dog_SetRbuffer(MainRBuffer)
Dogwaffle.Dog_SetGbuffer(MainGBuffer)
Dogwaffle.Dog_SetBbuffer(MainBBuffer)
'and refresh the screen
Dogwaffle.Dog_Refresh()
End Sub
Information and code on this page is provided without warenty of any kind. Use
at your own risk.