For Windows, this question is quickly answered: HWND. Pretty much everything is of this basic “window”-type and most API commands that deal with windows can be used on most GUI objects. You can also find many code examples on the forums that deal with a lot of common API tasks. The situation is different for Linux and OSX. Here, different Gadgets may have different underlying objects and so it is not entirely clear what functions can be used. There are also a lot less examples around for these systems. Of course when developing programs that run on multiple OS, you will need solutions for all of them.

To help this situation a bit, i have compiled a list of what are the underlying objects behind the PB gadgets and other GUI objects. You can get access to these using functions such as GadgetID(), WindowID(), etc.

Disclaimer:

This information is internal stuff. While many of these things haven’t changed in many years, it is still possible that we decide to change something in the future. Also some Gadgets are heavily modified for PB with custom subclasses or callbacks which also may change in the future and break your code. So as usual: Feel free to use this information, but if it breaks, its not our problem.

So here it goes:

Windows

Linux

OSX

WindowID()

HWND

GtkWindow

WindowRef

MenuID()

HMENU

GtkMenuBar / GtkMenu

MenuRef

StatusBarID()

HWND

GtkHBox

ControlRef (UserPane)

ToolBarID()

HWND

GtkToolbar

HIToolbarRef

FontID()

HFONT

PangoFontDescription

PB internal pointer

ImageID()

HBITMAP

GdkPixbuf

CGImageRef

GadgetID()

HWND

GtkWidget

ControlRef

ButtonGadget

“Button”

GtkButton / GtkToggleButton

PushButton / BevelButton

ButtonImageGadget

“Button”

GtkButton / GtkToggleButton

PushButton / BevekButton

CalendarGadget

“SysMonthCal32”

GtkCalendar

HIView

CheckBoxGadget

“Button”

GtkCheckButton

CheckBox

ComboBoxGadget

“ComboBox” / WC_COMBOBOXEX

GtkComboBox / GtkComboBoxEntry

PopupButton / HIComboBox

ContainerGadget

custom class

GtkFixed

UserPane

DateGadget

DATETIMEPICK_CLASS

GtkEntry

UserPane

EditorGadget

RICHEDIT_CLASS

GtkTextView

UserPane (rendering a TNXObject)

ExplorerComboGadget

WC_COMBOBOXEX

GekComboBoxEntry

HIComboBox

ExplorerListGadget

WC_LISTVIEW

GtkTreeView

DataBrowser

ExplorerTreeGadget

WC_TREEVIEW

GtkTreeView

DataBrowser

Frame3DGadget

“Button” / “Static”

GtkFrame

GroupBox / UserPane / Separator

HyperLinkGadget

“Static”

GtkButton

UserPane

IPAddressGadget

WC_IPADDRESS

GtkEntry

EditUnicodeText

ImageGadget

“Static”

GtkImage

UserPane

ListIconGadget

WC_LISTVIEW

GtkTreeView

DataBrowser

ListIconGadget

“ListBox”

GtkTreeView

DataBrowser

MDIGadget

“MDICLIENT”

–

–

OptionGadget

“Button”

GtkRadioButton

RadioButton

PanelGadget

“SysTabControl32”

GtkNotebook

Tabs

ProgressBarGadget

PROGRESS_CLASS

GtkProgressBar

ProgressBar

ScrollAreaGadget

custom class

GtkScrolledWindow

UserPane

ScrollBarGadget

“SCROLLBAR”

GtkVScrollBar / GtkHScrollBar

ScrollBar

ShortcutGadget

HOTKEY_CLASS

GtkEntry

EditUnicodeText

SpinGadget

UPDOWN_CLASS + “Edit”

GtkHBox containing others

UserPane containing others

SplitterGadget

custom class

GtkVPaned / GtkHPaned

UserPane

StringGadget

“Edit”

GtkEntry

EditUnicodeText

TextGadget

“Static”

GtkLabel

StaticText

TrackBarGadget

TRACKBAR_CLASS

GtkVScale / GtkHScale

Slider

TreeGadget

WC_TREEVIEW

GtkTreeView

DataBrowser

WebGadget

custom class + ActiveX control

GtkMozEmbed

HIWebView

Notes:

Gadgets all have the same basic type noted in the GadgetID() row. However, Gadgets are devided into “window classes” on Windows, or subclasses of the general GtkWidget on Linux.

For Gadgets on Windows: If the entry is noted in “” then this is the class name, if it is not then this is the symbolic constant for the class name. You’ll have to look up the text value in the appropriate header files.

On OSX, there are no classes for the controls, its all a ControlRef. The names i noted here are derived from the control creation functions (ie CreateTabsControl()). If you are looking for information, you should start there.

Gadgets may have multiple classes depending on the flags on creation.

On Linux, many gadgets are placed inside their own container to add a frame or catch events. (GtkFrame, GtkEventBox). The GadgetID() command returns the real gadget in this case, not the container.

On OSX, the UserPane controls are drawn by PB itself, so you don’t have much ways to modify them other than the PB commands.

Thats it. I hope this information is useful to some people, and hopefully we will see some more cross-platform API examples on the forum in the future 🙂

A lot changed in the 2DDrawing library with the v4.40 version. In fact, it basically underwent a complete rewrite. Only very few code parts remain from the previous version. Since it has come up in various questions and bug reports on the forum i am going to explain the new design a little bit and what consequences it has on stuff like mixing API and PB commands for drawing.

Lets start off with what the 4.31 library looked like:

The Windows version of the library was based entirely on GDI (the Windows drawing API). GDI allows output on a window, image, printer, sprites and the screen with the same commands so for the most part only the code that set up the drawing needed to be specific and the rest was shared (hence the separation of the output functions like ImageOutput() from StartDrawing()). One detail that a lot of users relied on was the fact that the GDI handle to the drawing context (HDC) was returned for StartDrawing() which allowed to easily mix API and PB commands in the drawing operation even without much knowledge of GDI. The internal data structure of the library was published a long time ago in the PB Library SDK and since the library didn’t change much over time there is still some code that relies on them.

Linux was a different story. Here every output requires its own API (Gtk for window an image, libgnomeprint for printer and some pixel based routines for SDL output). So the Linux library had a plugin like system just like some other PB libraries have to select the right command depending on the output. The Mac OSX version basically had only one output for images. The printer library created a temporary image and sent it to the printer when drawing was done. There was no drawing for windows, sprites or the screen on OSX. The drawing functions shared the pixel based drawing code we used for SDL on Linux.

Why the library was rewritten:

The reason was the alphachannel. As explained in a previous entry, i worked on improving the capabilities of PB when it comes to displaying alphachannel images. After that was finished i felt that at least some support for 2DDrawing was needed in addition to the DrawAlphaImage() command as well. The problem here is that GDI does not support the alphachannel even though it can handle 32bit images. Since Windows 98 you can load images with alphachannel and display them with the AlphaBlend() API but that is pretty much it. Any manipulation of the image with GDI will cause the alpha information to be lost. The same problem exists with Gdk on Linux. The ony drawing functions that exist work on GdkDrawable objects and these do not support the alphachannel. GDI+ is the Windows replacement for GDI which can deal with the alphachannel, but we needed a crossplatform solution to this problem. So we made the decision to create our own drawing functions similar to the pixel based ones for SDL and OSX which could handle the alphachannel in all drawing commands. As you can see from the result i went a step further and added the gradient drawing support (which also would not be possible with the API functions).

The new design:

Since our pixel based routines can only draw on images we now need separate “subsystems” for drawing even on Windows. So now we have this plugin-architecture on all OS. The real drawing functions are called through pointers which are set when the drawing is started so the speed impact is minimal. For those concerned about executable sizes: A drawing subsystem is only linked when the corresponding output function is used in the code. So if you do not use ImageOutput() none of the image drawing code will be linked.

So there is now a GDI subsystem on Windows and the new “PixelBuffer” one. The PixelBuffer subsystem does all its drawing directly on the memory of the output image with no API involvement. The only exception is the drawing of text. We did not want to add the overhead and license troubles by including an external font rendering engine like freetype so DrawText() uses GDI to render the text to a special device context from which the text is then drawn to to the real output with the alphachannel and gradients taken into account. It works in a similar way on the other OS where the native API is used to render the text and then it is copied to the real output. There is of course a speed penalty from this, but it cannot be avoided and it is questionable how much faster a separate rendering engine would be with this task.

Things to watch out for for on Windows:

I tried my best to keep the library backward compatible. If you use PB drawing commands only then there should be no difference at all. If you mix them with API then there are some things to watch out for:

As the “HDC result from StartDrawing()” is very commonly used i kept that behavior the same. So even though the PB commands do not use it for the drawing, there is still a device context created and returned from StartDrawing() which you can use to draw on the image with API.

You can still mix API drawing functions with PB functions on the same output without problems. The only thing that changed here is that GDI functions that change the global state of the device context no longer affect the PB drawing functions like they used to because the PB functions do not actually used that device context. So a function like SetWorldTransform() will not cause DrawImage() to draw a rotated image anymore. However it should still work if you use the BitBlt() API.

You have to be aware that GDI functions will erase the alphachannel. So if you draw on a 32bit PB image and use a GDI function, the modified area will look transparent after that. The best way to avoid this problem is to use 24bit images as output when API commands are involved. (We changed the default image depth to 24bit in 4.40 beta2 to make the transition easier)

PB Images are now always DIBs (device independent bitmap) to allow for the pixel based drawing. The #PB_Image_DisplayFormat flag used to create a DDB (device dependent bitmap), but this is no longer supported. #PB_Image_DisplayFormat now has the value 32 to create a 32bit image instead. Some GDI functions (like GetDIBits()) expect a DDB, so you may get trouble there.

DrawImage() can still draw API created images (including DDBs and icons). Again you have to be aware that a 32bit API created bitmap will probably have all alpha values as 0 which PB will interpret as fully transparent. Using 24bit is the solution here as well. Also DrawImage() expects DIBs to be bottom-up (the default on Windows). If you use top-down DIBs then they will be drawn upside down. There is no way to avoid that as Windows does not provide a way to find out the pixel orientation of a DIB.

If you relied on the library’s internal data structures then you are out of luck. Nothing is as it was before on the library’s internals.

To sum it up: Stick to 24bit images and in most cases mixing PB drawing with API drawing should work just as it did before.

Things to watch out for on Linux:

I am not aware of code that mixed 2DDrawing with API on Linux. StartDrawing() used to return the GdkDrawable handle for Image+WindowOutput() before. It now returns that only for the WindowOutput() as there is no more drawable when drawing on an image. Backward compatibility wasn’t possible here.

One thing to note in general is that PB images are now GdkPixbuf objects and no longer GdkPixmap. This is a big improvement as many Gtk functions expect GdkPixbuf nowadays, so it is actually easier to use PB images with Gtk functions.

Things to watch out for on OSX:

Nothing to say here. Since the 2DDrawing support was so poor before, it only got better with this release. There is now a separate QuickDraw based subsystem for WindowOutput(). Yes i know that QuickDraw is deprecated, but it was much easier to implement this way than to go for a full Quartz based one. I have plans to do a Quartz subsystem one day to have better PrinterOutput() (for the moment, it still works with images as an intermediate).

One thing to note is the new output for sprites and the screen with OpenGL (this applies to all OS): There is no way to modify the data in video memory, so if you call StartDrawing() the whole sprite data or the entire screen content is transferred to main memory for the drawing. This is very slow. So doing 2DDrawing everytime you refresh the screen is too costly. The better way is to draw on sprites just once and then display them over and over. Still, this is better than having no 2DDrawing for sprite/screen at all.

Future plans:

There is still room for optimisation in the new 2DDrawing code. For now the focus was on getting a stable implementation. Also the plan is to eventually have the alpha drawing routines also for SpriteOutput() and ScreenOutput() but this will need some more work to support all possible pixel formats for the screen. Stay tuned…

This one is for all those who are quick to complain when a new feature is added that they themselves don’t need. As it turns out, sometimes changes made in areas you may not care about at all can trigger changes in places that you may find useful after all. One of these areas is the IDE.

It all started very small and insignificant: Inspired by the recently reanimated thread here, i decided to add the ability to easily switch out the IDE provided icon set for a custom icon theme. How hard could this be? It was a rather small thing really, and quite quickly implemented in the IDE code. Here is where you would say: “Why do i need themes? Better focus on something else!”, well better read on…

Of course i had to test this, and for that purpose i created a theme with the Silk icons also mentioned in that thread (the result is quite nice btw, and will be included in the PB package). They use a lot of semi-transparency and converting them to icons (non 32bit, for older Windows versions) just didn’t look good. So i tried loading and using the png files directly. Well ups, the PB ImageMenu doesn’t support the alpha-channel. In fact, it doesn’t even support non-icon images at all. So i’ll just change the drawing code to support alpha-channel images, how hard could this be?

Those who know me a little closer know that i tend to think way too far ahead with these kinds of things. What good is alpha-channel support in the menu when not even the ImageGadget can properly display alpha-channel images? So lets just add it there as well, and then there is the ButtonImageGadget too. Seriously, how hard could this be? 🙂 (turns out this one was actually a tough one. The nice solution i had worked up for Vista/XP just didn’t want to work on the older Windows versions)

Alpha-channel improvements on Linux

The line doesn’t end there though. There is also the Linux version. The Image lib on Linux didn’t support the full alpha-channel so far, it only supported full transparent pixels through a 1-bit mask. And there i am, right back at the beginning with a set of ugly looking icons in the menu. So, lets just add the full alpha-channel to the Linux Image lib. How hard… well, this really is a bigger deal. It means a rewrite of the entire lib, plus large parts of the 2DDrawing lib and every other command that deals with images. We had this one on our list for quite a while already though because the lib still uses a GdkPixmap to represent an image and not a GdkPixbuf which is the much better choice. So i went ahead and rewrote these commands as well, and it was worth it. The lib can now use the full alpha-channel and since the Gtk widgets all bring support for GdkPixbu’s, every Gadget that deals with images can use it too. (for example ListIcon, Tree etc). Oh and while i was at it, i dived a bit into SDL and implemented DrawAlphaImage() for Linux too. 🙂

This brings a new “problem”. With Linux supporting the alpha-channel in every GUI element, the Windows version is lacking behind again because it still requires Icon files for some GUI things. That cannot stand! XP and Vista actually solve this quite well with their 32bit icon support so this wasn’t so hard to do. Older versions however don’t support that, so to get the best possible result an alpha-channel image is converted to an icon with a mask to get at least some transparency. You can now pass non-icon images to all functions that take an Image on Windows too and it will be converted to an icon as needed.

For once, the Mac version was the easy target in all this because it already came with full alpha-channel support from the start. It only lacked the ImageMenu, but i added that as well.

So, with v4.40 you will be able to use alpha-channel images for all GUI elements and it will look good on all OS. No more converting to ico to get transparency on Windows! If you plan to target Windows versions older than XP, you might want to avoid semi-transparent pixels though for things like toolbars so it will look good also without the 32bit icon support. If you plan to target Windows 95 or NT4, you are out of luck as they don’t have alpha-channel support at all. 😛