| 1 | \section{The wxWindows resource system}\label{resourceformats} |
| 2 | |
| 3 | From version 1.61, wxWindows has an optional {\it resource file} facility, |
| 4 | which allows separation of dialog, menu, bitmap and icon specifications |
| 5 | from the application code. |
| 6 | |
| 7 | It is similar in principle to the Windows resource file (whose ASCII form is |
| 8 | suffixed .RC and whose binary form is suffixed .RES). The wxWindows resource |
| 9 | file is currently ASCII-only, suffixed .WXR. Note that under Windows, |
| 10 | the .WXR file does not {\it replace} the native Windows resource file, |
| 11 | it merely supplements it. There is no existing native resource format in X |
| 12 | (except for the defaults file, which has limited expressive power). |
| 13 | |
| 14 | Using wxWindows resources for panels and dialogs has an effect on how |
| 15 | you deal with panel item callbacks: you can't specify a callback function in |
| 16 | a resource file, so how do you achieve the same effect as with programmatic |
| 17 | panel construction? The solution is similar to that adopted by Windows, which |
| 18 | is to use the {\it parent} panel or dialog to intercept user events. |
| 19 | |
| 20 | From 1.61, wxWindows routes panel item events that do not have a callback |
| 21 | to the \helpref{OnCommand}{wxwindowoncommand} member of the panel (or dialog). So, to use |
| 22 | panel or dialog resources, you need to derive a new class and override the |
| 23 | default (empty) OnCommand member. The first argument is a reference |
| 24 | to a wxWindow, and the second is a reference to a wxCommandEvent. Check the |
| 25 | name of the panel item that's generating an event by using the \helpref{wxWindow::GetName}{wxwindowgetname}\rtfsp |
| 26 | function and a string comparison function such as \helpref{wxStringEq}{wxstringeq}. |
| 27 | You may need to cast the reference to an appropriate specific type to perform |
| 28 | some operations. |
| 29 | |
| 30 | To obtain a pointer to a panel item when you only have the name (for example, |
| 31 | when you need to set a value of a text item from outside of the {\bf OnCommand} function), |
| 32 | use the function \helpref{wxFindWindowByName}{wxfindwindowbyname}. |
| 33 | |
| 34 | For details of functions for manipulating resource files and loading |
| 35 | user interface elements, see \helpref{wxWindows resource functions}{resourcefuncs}. |
| 36 | |
| 37 | \subsection{The format of a .WXR file} |
| 38 | |
| 39 | A wxWindows resource file may look a little odd at first. It's C++ |
| 40 | compatible, comprising mostly of static string variable declarations with |
| 41 | PrologIO syntax within the string. |
| 42 | |
| 43 | Here's a sample .WXR file: |
| 44 | |
| 45 | \begin{verbatim} |
| 46 | /* |
| 47 | * wxWindows Resource File |
| 48 | * Written by wxBuilder |
| 49 | * |
| 50 | */ |
| 51 | |
| 52 | #include "noname.ids" |
| 53 | |
| 54 | static char *aiai_resource = "bitmap(name = 'aiai_resource',\ |
| 55 | bitmap = ['aiai', wxBITMAP_TYPE_BMP_RESOURCE, 'WINDOWS'],\ |
| 56 | bitmap = ['aiai.xpm', wxBITMAP_TYPE_XPM, 'X'])."; |
| 57 | |
| 58 | static char *menuBar11 = "menu(name = 'menuBar11',\ |
| 59 | menu = \ |
| 60 | [\ |
| 61 | ['&File', 1, '', \ |
| 62 | ['&Open File', 2, 'Open a file'],\ |
| 63 | ['&Save File', 3, 'Save a file'],\ |
| 64 | [],\ |
| 65 | ['E&xit', 4, 'Exit program']\ |
| 66 | ],\ |
| 67 | ['&Help', 5, '', \ |
| 68 | ['&About', 6, 'About this program']\ |
| 69 | ]\ |
| 70 | ])."; |
| 71 | |
| 72 | static char *project_resource = "icon(name = 'project_resource',\ |
| 73 | icon = ['project', wxBITMAP_TYPE_ICO_RESOURCE, 'WINDOWS'],\ |
| 74 | icon = ['project_data', wxBITMAP_TYPE_XBM, 'X'])."; |
| 75 | |
| 76 | static char *panel3 = "dialog(name = 'panel3',\ |
| 77 | style = '',\ |
| 78 | title = 'untitled',\ |
| 79 | button_font = [14, 'wxSWISS', 'wxNORMAL', 'wxBOLD', 0],\ |
| 80 | label_font = [10, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0],\ |
| 81 | x = 0, y = 37, width = 292, height = 164,\ |
| 82 | control = [wxButton, 'OK', '', 'button5', 23, 34, -1, -1, 'aiai_resource'],\ |
| 83 | control = [wxMessage, 'A Label', '', 'message7', 166, 61, -1, -1, 'aiai_resource'],\ |
| 84 | control = [wxText, 'Text', 'wxVERTICAL_LABEL', 'text8', 24, 110, -1, -1])."; |
| 85 | \end{verbatim} |
| 86 | |
| 87 | As you can see, C++-style comments are allowed, and apparently include files |
| 88 | are supported too: but this is a special case, where the included file |
| 89 | is a file of defines shared by the C++ application code and resource file |
| 90 | to relate identifiers (such as FILE\_OPEN) to integers. |
| 91 | |
| 92 | Each {\it resource object} is of standard PrologIO syntax, that is, |
| 93 | an object name such as {\bf dialog} or {\bf icon}, then an open |
| 94 | parenthesis, a list of comma-delimited attribute/value pairs, a closing |
| 95 | parenthesis, and a full stop. Backslashes are required to escape newlines, |
| 96 | for the benefit of C++ syntax. If double quotation marks are used to |
| 97 | delimit strings, they need to be escaped with backslash within a C++ string |
| 98 | (so it's easier to use single quotation marks instead). |
| 99 | |
| 100 | \normalbox{{\it A note on PrologIO string syntax:} A string that begins with |
| 101 | an alphabetic character, and contains only alphanumeric characters, |
| 102 | hyphens and underscores, need not be quoted at all. Single quotes and double |
| 103 | quotes may be used to delimit more complex strings. In fact, single-quoted |
| 104 | and no-quoted strings are actually called {\it words}, but are treated |
| 105 | as strings for the purpose of the resource system.} |
| 106 | |
| 107 | A resource file like this is typically included in the application main file, |
| 108 | as if it were a normal C++ file. This eliminates the need for a separate |
| 109 | resource file to be distributed alongside the executable. However, the |
| 110 | resource file can be dynamically loaded if desired (for example by a non-C++ |
| 111 | language such as CLIPS, Prolog or Python). |
| 112 | |
| 113 | Once included, the resources need to be `parsed' (interpreted), because |
| 114 | so far the data is just a number of static string variables. The function\rtfsp |
| 115 | {\bf ::wxResourceParseData} is called early on in initialization of the application |
| 116 | (usually in {\bf wxApp::OnInit}) with a variable as argument. This may need to be |
| 117 | called a number of times, one for each variable. However, more than one |
| 118 | resource `object' can be stored in one string variable at a time, so you can |
| 119 | get all your resources into one variable if you want to. |
| 120 | |
| 121 | {\bf ::wxResourceParseData} parses the contents of the resource, ready for use |
| 122 | by functions such as {\bf ::wxResourceCreateBitmap} and {\bf wxPanel::LoadFromResource}. |
| 123 | |
| 124 | If a wxWindows resource object (such as a bitmap resource) refers to a |
| 125 | C++ data structure, such as static XBM or XPM data, a further call ({\bf |
| 126 | ::wxResourceRegisterBitmapData}) needs to be made on initialization to tell |
| 127 | wxWindows about this data. The wxWindows resource object will refer to a |
| 128 | string identifier, such as `project\_data' in the example file above. |
| 129 | This identifier will be looked up in a table to get the C++ static data |
| 130 | to use for the bitmap or icon. |
| 131 | |
| 132 | In the C++ fragment below, the WXR resource file is included, |
| 133 | and appropriate resource initialization is carried out in {\bf OnInit}. |
| 134 | Note that at this stage, no actual wxWindows dialogs, menus, bitmaps or |
| 135 | icons are created; their `templates' are merely being set up for later |
| 136 | use. |
| 137 | |
| 138 | \begin{verbatim} |
| 139 | /* |
| 140 | * File: noname.cc |
| 141 | * Purpose: main application module, generated by wxBuilder. |
| 142 | */ |
| 143 | |
| 144 | #include "wx.h" |
| 145 | #include "wx_help.h" |
| 146 | #include "noname.h" |
| 147 | |
| 148 | // Includes the dialog, menu etc. resources |
| 149 | #include "noname.wxr" |
| 150 | |
| 151 | // Includes XBM data |
| 152 | #include "project.xbm" |
| 153 | |
| 154 | // Declare an instance of the application: allows the program to start |
| 155 | AppClass theApp; |
| 156 | |
| 157 | // Called to initialize the program |
| 158 | wxFrame *AppClass::OnInit(void) |
| 159 | { |
| 160 | #ifdef wx_x |
| 161 | wxResourceRegisterBitmapData("project_data", project_bits, project_width, project_height); |
| 162 | #endif |
| 163 | wxResourceParseData(menuBar11); |
| 164 | wxResourceParseData(aiai_resource); |
| 165 | wxResourceParseData(project_resource); |
| 166 | wxResourceParseData(panel3); |
| 167 | ... |
| 168 | } |
| 169 | \end{verbatim} |
| 170 | |
| 171 | |
| 172 | \subsection{Dialog resource format} |
| 173 | |
| 174 | A dialog resource object may be used for either panels or dialog boxes, and |
| 175 | consists of the following attributes. In the following, a {\it font specification}\rtfsp |
| 176 | is a list consisting of point size, family, style, weight, underlined, optional facename. |
| 177 | |
| 178 | \begin{twocollist}\itemsep=0pt |
| 179 | \twocolitemruled{Attribute}{Value} |
| 180 | \twocolitem{name}{The name of the resource.} |
| 181 | \twocolitem{style}{Optional dialog box or panel window style.} |
| 182 | \twocolitem{title}{The title of the dialog box (unused if a panel).}. |
| 183 | \twocolitem{modal}{Whether modal: 1 if modal, 0 if modeless, absent if a panel resource.} |
| 184 | \twocolitem{button\_font}{The font used for control buttons: a list comprising point size (integer), |
| 185 | family (string), font style (string), font weight (string) and underlining (0 or 1).} |
| 186 | \twocolitem{label\_font}{The font used for control labels: a list comprising point size (integer), |
| 187 | family (string), font style (string), font weight (string) and underlining (0 or 1).} |
| 188 | \twocolitem{x}{The x position of the dialog or panel.} |
| 189 | \twocolitem{y}{The y position of the dialog or panel.} |
| 190 | \twocolitem{width}{The width of the dialog or panel.} |
| 191 | \twocolitem{height}{The height of the dialog or panel.} |
| 192 | \twocolitem{background\_colour}{The background colour of the dialog or panel. Only valid if the style includes wxUSER\_COLOURS.} |
| 193 | \twocolitem{label\_colour}{The default label colour for the children of the dialog or panel. Only valid if the style includes wxUSER\_COLOURS.} |
| 194 | \twocolitem{button\_colour}{The default button text colour for the children of the dialog or panel. Only valid if the style includes wxUSER\_COLOURS.} |
| 195 | \twocolitem{label\_font}{Font spec} |
| 196 | \twocolitem{button\_font}{Font spec} |
| 197 | \end{twocollist} |
| 198 | |
| 199 | Then comes zero or more attributes named `control' for each control |
| 200 | (panel item) on the dialog or panel. The value is a list of further |
| 201 | elements. In the table below, the names in the first column correspond to |
| 202 | the first element of the value list, and the second column details the |
| 203 | remaining elements of the list. |
| 204 | |
| 205 | \begin{twocollist}\itemsep=0pt |
| 206 | \twocolitemruled{Control}{Values} |
| 207 | \twocolitem{wxButton}{title (string), window style (string), name (string), x, y, width, height, button bitmap resource (optional string), button font spec} |
| 208 | \twocolitem{wxCheckBox}{title (string), window style (string), name (string), x, y, width, height, default value (optional integer, 1 or 0), label font spec} |
| 209 | \twocolitem{wxChoice}{title (string), window style (string), name (string), x, y, width, height, values (optional list of strings), label font spec, button font spec} |
| 210 | \twocolitem{wxComboBox}{title (string), window style (string), name (string), x, y, width, height, default text value, values (optional list of strings), label font spec, button font spec} |
| 211 | \twocolitem{wxGauge}{title (string), window style (string), name (string), x, y, width, height, value (optional integer), range (optional integer), label font spec, button font spec} |
| 212 | \twocolitem{wxGroupBox}{title (string), window style (string), name (string), x, y, width, height, label font spec} |
| 213 | \twocolitem{wxListBox}{title (string), window style (string), name (string), x, y, width, height, values (optional list of strings), multiple (optional string, wxSINGLE or wxMULTIPLE), |
| 214 | label font spec, button font spec} |
| 215 | \twocolitem{wxMessage}{title (string), window style (string), name (string), x, y, width, height, message bitmap resource (optional string), label font spec} |
| 216 | \twocolitem{wxMultiText}{title (string), window style (string), name (string), x, y, width, height, default value (optional string), |
| 217 | label font spec, button font spec} |
| 218 | \twocolitem{wxRadioBox}{title (string), window style (string), name (string), x, y, width, height, values (optional list of strings), number of rows or cols, |
| 219 | label font spec, button font spec} |
| 220 | \twocolitem{wxRadioButton}{title (string), window style (string), name (string), x, y, width, height, default value (optional integer, 1 or 0), label font spec} |
| 221 | \twocolitem{wxScrollBar}{title (string), window style (string), name (string), x, y, width, height, value (optional integer), |
| 222 | page length (optional integer), object length (optional integer), view length (optional integer)} |
| 223 | \twocolitem{wxSlider}{title (string), window style (string), name (string), x, y, width, height, value (optional integer), minimum (optional integer), maximum (optional integer), |
| 224 | label font spec, button font spec} |
| 225 | \twocolitem{wxText}{title (string), window style (string), name (string), x, y, width, height, default value (optional string), |
| 226 | label font spec, button font spec} |
| 227 | \end{twocollist} |
| 228 | |
| 229 | \subsection{Menubar resource format} |
| 230 | |
| 231 | A menubar resource object consists of the following attributes. |
| 232 | |
| 233 | \begin{twocollist}\itemsep=0pt |
| 234 | \twocolitemruled{Attribute}{Value} |
| 235 | \twocolitem{name}{The name of the menubar resource.} |
| 236 | \twocolitem{menu}{A list containing all the menus, as detailed below.} |
| 237 | \end{twocollist} |
| 238 | |
| 239 | The value of the {\bf menu} attribute is a list of menu item specifications, where each menu |
| 240 | item specification is itself a list comprising: |
| 241 | |
| 242 | \begin{itemize}\itemsep=0pt |
| 243 | \item title (a string) |
| 244 | \item menu item identifier (a string or non-zero integer, see below) |
| 245 | \item help string (optional) |
| 246 | \item 0 or 1 for the `checkable' parameter (optional) |
| 247 | \item optionally, further menu item specifications if this item is a pulldown menu. |
| 248 | \end{itemize} |
| 249 | |
| 250 | If the menu item specification is the empty list ([]), this is interpreted as a menu separator. |
| 251 | |
| 252 | If further (optional) information is associated with each menu item in a future release of wxWindows, |
| 253 | it will be placed after the help string and before the optional pulldown menu specifications. |
| 254 | |
| 255 | Note that the menu item identifier must be an integer if the resource is being |
| 256 | included as C++ code and then parsed on initialisation. Unfortunately,\rtfsp |
| 257 | \verb$#$define substitution is not performed inside strings, and |
| 258 | therefore the program cannot know the mapping. However, if the .WXR file |
| 259 | is being loaded dynamically, wxWindows will attempt to replace string |
| 260 | identifiers with \verb$#$defined integers, because it is able to parse |
| 261 | the included \verb$#$defines. |
| 262 | |
| 263 | \subsection{Bitmap resource format} |
| 264 | |
| 265 | A bitmap resource object consists of a name attribute, and one or more {\bf bitmap} attributes. |
| 266 | There can be more than one of these to allow specification of bitmaps that are optimum for the |
| 267 | platform and display. |
| 268 | |
| 269 | \begin{itemize}\itemsep=0pt |
| 270 | \item Bitmap name or filename. |
| 271 | \item Type of bitmap; for example, wxBITMAP\_TYPE\_BMP\_RESOURCE. See class reference under {\bf wxBitmap} for |
| 272 | a full list). |
| 273 | \item Platform this bitmap is valid for; one of WINDOWS, X, MAC and ANY. |
| 274 | \item Number of colours (optional). |
| 275 | \item X resolution (optional). |
| 276 | \item Y resolution (optional). |
| 277 | \end{itemize} |
| 278 | |
| 279 | \subsection{Icon resource format} |
| 280 | |
| 281 | An icon resource object consists of a name attribute, and one or more {\bf icon} attributes. |
| 282 | There can be more than one of these to allow specification of icons that are optimum for the |
| 283 | platform and display. |
| 284 | |
| 285 | \begin{itemize}\itemsep=0pt |
| 286 | \item Icon name or filename. |
| 287 | \item Type of icon; for example, wxBITMAP\_TYPE\_ICO\_RESOURCE. See class reference under {\bf wxBitmap} for |
| 288 | a full list). |
| 289 | \item Platform this bitmap is valid for; one of WINDOWS, X, MAC and ANY. |
| 290 | \item Number of colours (optional). |
| 291 | \item X resolution (optional). |
| 292 | \item Y resolution (optional). |
| 293 | \end{itemize} |
| 294 | |
| 295 | |
| 296 | \subsection{Resource format design issues} |
| 297 | |
| 298 | The .WXR file format is a recent addition and subject to change. |
| 299 | The use of an ASCII resource file format may seem rather inefficient, but this |
| 300 | choice has a number of advantages: |
| 301 | |
| 302 | \begin{itemize}\itemsep=0pt |
| 303 | \item Since it is C++ compatible, it can be included into an application's source code, |
| 304 | eliminating the problems associated with distributing a separate resource file |
| 305 | with the executable. However, it can also be loaded dynamically from a file, which will be required |
| 306 | for non-C++ programs that use wxWindows. |
| 307 | \item No extra binary file format and separate converter need be maintained for the wxWindows project |
| 308 | (although others are welcome to add the equivalent of the Windows `rc' resource |
| 309 | parser and a binary format). |
| 310 | \item It would be difficult to append a binary resource component onto an executable |
| 311 | in a portable way. |
| 312 | \item The file format is essentially the PrologIO object format, for which |
| 313 | a parser already exists, so parsing is easy. For those programs that use PrologIO |
| 314 | anyway, the size overhead of the parser is minimal. |
| 315 | \end{itemize} |
| 316 | |
| 317 | The disadvantages of the approach include: |
| 318 | |
| 319 | \begin{itemize}\itemsep=0pt |
| 320 | \item Parsing adds a small execution overhead to program initialization. |
| 321 | \item Under 16-bit Windows especially, global data is at a premium. |
| 322 | Using a .RC resource table for some wxWindows resource data may be a partial solution, |
| 323 | although .RC strings are limited to 255 characters. |
| 324 | \item Without a resource preprocessor, it is not possible to substitute integers |
| 325 | for identifiers (so menu identifiers have to be written as integers in the resource |
| 326 | object, in addition to providing \verb$#$defines for application code convenience). |
| 327 | \end{itemize} |
| 328 | |
| 329 | \subsection{Compiling the resource system} |
| 330 | |
| 331 | To enable the resource system, set {\bf wxUSE\_WX\_RESOURCES} to 1 in setup.h. |
| 332 | If your wxWindows makefile supports it, set the same name in the makefile to 1. |
| 333 | |