This C++ library allows to add simple dialog type graphical user interfaces to Windows console programs. ZWinLib does not try to be a competitor to full-fledged libraries like Microsoft Foundation Classes (MFC) or Trolltech's QT library. Instead of being as powerful as possible and cover any GUI programming problem which one can imagine, ZWinLib provides a thin wrapping layer around part of Windows 32bit application programming interface (WIN32 API), as documented in Microsoft's Windows Platform SDK (software development kit). It tries to keep things simple and handy and has a lot of more or less severe restrictions:
Please also have a look at ZWinLib's close friends ZWinXml for XML document handling, ZWinSql for file based SQL database handling and ZWinCrypt for compression, encryption and hashing files, also available on the same web site.
This library is distributed as a zip file. To install, unzip it into your desired installation directory. You'll get the following directory structure:
To run one of the samples, go to the samples subdirectory and run the respective Sample...exe file. To recompile one of the samples, in a console window change to the the sample's directory and type 'nmake'. This assumes, that Visual C++ compiler, linker, resource editor and (n)make utility are available in the path of your console window.
If you need to recompile the library itself, in a console window change to the src directory and type 'nmake'.
To develop your own ZWinLib applications, create another subdirectory in the samples directory, copy the files from Sample1 into this new subdirectory and start modifying these files.
If you ever want to deinstall ZWinLib again (why should you? :--)) ) simply delete the installation directory and all its subdirectories. ZWinLib does not copy files into any other directory nor does it touch the registry.
The ZWinLib library provides the following user relevant classes:
The first sample Sample1.cpp can be used to demonstrate ZWinLib's basic usage. Sample1 implements a simple text editor. Users can open a text file, edit its contents and save it again.
The user interface is designed using a visual editor like Microsoft's Visual Studio resource editor or Borland's Resource Workshop. In the sample the GUI consists of a dialog box, having a menu, several buttons and an edit field. The design is saved in a so called resource script Sample1.rc. Normally the resource script is automatically generated by the resource editor, but can also be edited manually, if necessary (syntax documented in the Windows Platform SDK).
Programmatically, all user interface items (so called 'Controls') are identified by integer values. When designing the user interface in the resource editor, the user typically assigns a symbolic identifier, typically starting with 'ID_...'. The resource editors then automatically generate an include file Resource.h, which via C #defines assigns integer values to these symbolic identifiers. These integer values should be unique in a certain application. However, if a menu item and a button provide the same functionality, they may share the same identifier and integer value.
#define ID_SAMPLEDIALOG 101 //identifies the dialog box #define ID_SAMPLEMENU 102 //identifies the dialog box's menu #define ID_EDITFIELD 1000 //identifies the edit field #define ID_FILEOPEN 1001 //identifies the file open button and the file open menu item #define ID_FILESAVE 1002 //identifies the file save button and the file save menu item #define ID_EXIT 1003 //identifies the exit button and the exit menu item #define ID_ABOUTSAMPLE1 40001 //identifies the about menu item
The files ZWinLib.h, defining prototypes for the ZWinLib classes and methods, and the file Resource.h must be included in the user's C++ application Sample1.cpp:
#include "ZWinLib.h" #include "Resource.h" using namespace std;
The application defines a WDialog pointer and loads the dialog box:
WDialog *sampleDialog; ... sampleDialog = new WDialog(ID_SAMPLEDIALOG); //instantiate a dialog box class ... //use the dialog box
Depending on the definition in the resource script, the dialog box will be initially visible or hidden. At any time you can show or hide the dialog box by using:
sampleDialog->SetVisible(true); //make the dialog box visible sampleDialog->SetVisible(false); //hide the dialog box
If you are done using the dialog box, you may completely destroy it:
delete sampleDialog;
Programs with graphical user interfaces typically are event driven, i.e. the user clicks on a control (menu item, button, check box, ...) to activate a certain functionality of the program. In a ZWinLib program, such events will be handled by event handler functions. First the event is registered using the WDialog method RegisterEventHandler(), associating the control, identified by its identifier (here ID_EXIT), with an event handling function (here ExitEventHandler()). Once when the user clicks on the control, ZWinLib will call the event handler function, which in this case opens another dialog box, asking the user, if he really wants to exit. This dialog box is one of ZWinLib's predefined standard dialog boxes WMessageBoxQuestion. This dialog box gives the user a YES/NO choice and returns the chosen value (IDYES or IDNO). In the sample application a variable is set, which lets the main program loop quit and terminate the program:
int ExitEventHandler(WEVENT e) //*** Handle the Exit menu and button events ** { if (WStdDialog::WMessageBoxQuestion("Do you really want to exit?")==IDYES) { sampleDialog->dialogActive=false; } return TRUE; } int main(int argc, char *argv[]) //*** Main program **************************** { ... sampleDialog->RegisterEventHandler(ID_EXIT, ExitEventHandler); ... while(sampleDialog->dialogActive) //main program loop { WWait(500); } }
In the above example we can also see the structure of the main() program of ZWinLib
programs:
In the main() function typically the GUI is initialized and event handlers are registered. Then main()
enters an infinite loop, where a flag variable is periodically checked. All other processing is done in the
event handlers. The flag variable is set in the exit event handler, indicating that the main loop shall be
terminated and the program shall exit. For this purpose, all WDialog classes have a variable dialogActive,
which is automatically is set to true, when the dialog box is instantiated and also automatically set to
false, when the user closes the window via the system menu or manually e.g. in an event handler.
For each control users may register a separate event handler or they can register a common event handler
function for several controls. By evaluating the e.id field of the WEVENT e structure or using the
GetEventType() function, a handler can find out, which control and which user action caused the event:
int FileHandler(WEVENT e) //*** Handle the Save and Open menu and button *** { static string fileName="*.*"; fstream fd; string text = ""; switch (e.id) { //*** Save *** case ID_FILEOPEN: fileName=WStdDialog::WFileOpenDialog(".", fileName); . . . sampleDialog->SetText(ID_EDITFIELD, text); break; //*** Open *** case ID_FILESAVE: . . . } return TRUE; } int main(int argc, char *argv[]) //*** Main program **************************** { ... sampleDialog->RegisterEventHandler(ID_FILESAVE, FileHandler); sampleDialog->RegisterEventHandler(ID_FILEOPEN, FileHandler); ... }
In the above example we can also see the structure of using controls in ZWinLib programs:
Besides reacting on events, generated by controls, programs frequently need to modify or query the state of
the controls, e.g. setting the text of buttons or edit text fields, enabling or disabling controls, hiding
or showing controls etc.. To do this, ZWinLib provides a lot of methods in the WDialog class. In contrast
to a dialog box, which has its own object, i.e. an instance of WDialog, a control does not have its own
class instance. The method simply refers to the dialog box, which contains the respective control, and
identifies the control via its ID:
instance_of_dialog_box_containing_the_control -> method(ID_of_the_control, ...)
E.g. to read set the text in the edit field ID_EDITFIELD in the dialog box instance sampleDialog, we use
sampleDialog->SetText(ID_EDITFIELD, text);
To compile the sample's resource script and source code, do run the following commands from a console window (assuming Visual C++ is available via the Windows path in the console window):
rc Sample1.rc cl -MT -GX -W3 -I..\..\inc Sample1.cpp Sample1.res ..\..\lib\ZWinLib.lib user32.lib gdi32.lib comdlg32.lib ws2_32.lib winmm.lib
... or simply type 'nmake', using the makefile provided in the sample's directory.
To get more detailed usage information, have a look at the examples below and look into the detailed functional documentation in file "ZWinLib.chm" (generated by Doxygen from ZWinLib.h, included in ZWinLib's doc subdirectory).
The package comes with some example files:
More samples and additional programming tips may be added in later versions.
ZWinLib was developed and tested with Microsoft Visual C++ 2003 ... 2017 (English version) and tested under Windows XP/7/10. Other versions of Visual C++ and Windows should work, but have not been tested. If you successfully run ZWinLib with other versions, please send the author a short note.
V0.9.1: First public beta release.
V0.9.2: Added more examples. Added WDialog.dialogActive. Added a default event handler for
IDOK, IDCANCEL and WM_DESTROY.
V0.9.3: Allow up to 16 poly lines in a plot.
V0.9.4: Support for tree view controls with the WControls::WTreeView class.
V0.9.5: Autoscrolling in multiline edit controls when setting text.
V0.9.6: Support for resizing of dialog boxes using WDialog::SetResizable().
V0.9.7: Support for tab controls with the WControls::WTab class.
V0.9.8: Implement finite state machines with the WFsm and WFsmState class.
V1.0.0: Fonts of controls can be changed. Considered to be ready for V1.0. Beware!
V1.1.0: Limited support for list view controls (only report style is supported).
V1.2.0: Split panes realized as child dialogs, see Sample8 for details.
V1.3.0: State machines now can handle parallel sub state machines.
V1.4.0: Distribution now includes ZWinCrypt to support hashing, encryption and
compression.
V1.5.0: Added new methods to WSocket.
V1.6.0: WTreeView::GetNodeId substituted by WTreeView::FindNode with wildcard search.
V1.7.0: Several minor modifications, including WTreeView::FindNode.
V1.8.0: Added WSerial and WAudioIn, WAudioOut, WAudioWavFile.
V1.9.0: Added WPort.
V2.0.0: Major change: Event handlers now have return type 'int' instead of
'void' and must return TRUE.
All files are provided in the hope, they might be useful, but without any warranty or support. You may use or modify them on your own risk in non-commercial applications. Even if this software is provided free of charge, it is no freeware. It is copyrighted by Werner Zimmermann.
Windows, Visual C++, Visual Studio, MFC and other product names mentioned here may be trademarks or registered trademarks of their respective owners.
myDialog->RegisterEventHandler(ID_CLOSE, closeEventHandler); //Register an event handler for ID_CLOSE in the myDialog dialog box ... int closeEventHandler(WEVENT e) //Event handler { WDialog pDialogBox = (WDialog*) e.pThis; //Create a pointer to the dialog box ... pDialogBox.setVisible(false); //Manipulate the dialog box ... return TRUE; }Of course, a much simpler method is to make myDialog a global variable, which you can directly access in the event handler. However, global variables are not in the true spirit of object oriented programming.
myDialog->RegisterEventHandler(0, destroyEventHandler, WM_DESTROY); //Register an event handler for exit in the system menu myDialog->RegisterEventHandler(0, destroyEventHandler, WM_SYSCOMMAND); //Register an event handler for minimize/maximize in the system menu
myDialog->SetResizable();Alternatively you can set WS_THICKFRAME for the style of your dialog box in the ressource script. In this case SetResizable() will be called automatically, when the dialog is loaded.