I started with the FLTK GUI framework for the little thing I'm
hobby-working on at the moment on. But then I discovered that the main
widget I needed, a tree view, was nowhere to be found in FLTK, although
there had been a version with that widget (which google found
initiallly, which is why I felt confident enough to just start coding
with FLTK).
So I switched to wxWidgets as portable GUI framework, because Qt has
that decidedly uncute preprocessing, a custom language dialect.
I remembered from some 10-15 years ago, whatever, that wxWidgets has a
problem with global variables and the static initialization order
fiasco. That hasn't bitten me yet, but there was a problem with its main
header including `<windows.h>` in Windows. That's a lot of macros! Like
a zillion. Also it did it in a way that produced a compilation error
within some Windows header dragged in by <windows.h>. The solution: to
define `WIN32_LEAN_AND_MEAN`.
Also, I discovered, `_UNICODE` (not just `UNICODE`) needs to be defined
to make the wxWidgets environment detection scheme work.
Oh, and there was an issue with <wx/setup.h>, which is not found via the
ordinary general include path, but requires its own special include
path, down in [wxWidget root]/lib/vc_lib/mswu. Not a bad idea for
configuration. But it wasn't so clearly documented. I think tutorials
should explain things like that. The critical showstopper things.
Even with those fixes the example "Hello, world!" code I found in the
short-short tutorial at <url:
http://docs.wxwidgets.org/stable/overview_helloworld.html> didn't build
as a Windows console program. Uh oh, no `main` function! So what should
go in `main` for a wxWidgets app?
For that i dived into the macros that didn't quite work, and hopefully
reproduced the same code execution via `main`. wxWindows appears to be
built of macros, a very very 1990s approach. It so far appears very
MFC-ish, including "message maps" for mapping events to handlers.
For the release version in Visual Studio I linked with wxbase31ud.lib,
wxmsw31ud_core.lib, wxpng.lib, wxzlib.lib, kernel32.lib, user32.lib,
gdi32.lib, comdlg32.lib, comctl32.lib and rpcrt4.lib, which appears to
be minimal, roughly.
Anyway here's my result code, the tutorial's code fixed so that it
works, and re-styled to more like my code (he he), a working wxWindows
"Hello, world!" for Windows:
-----------------------------------------------------------------------
#include <stdlib/extension/type_builders.hpp> //
https://github.com/alf-p-steinbach/Wrapped-stdlib
using namespace stdlib::ext::type_builders;
// The following two macros defined by <wrapped-windows/windows-h.hpp>:
// WIN32_LEAN_AND_MEAN avoids dragging in buggy part of <windows.h>
// _UNICODE makes wxWidgets macro scheme work.
#include <wrapped-windows/windows-h.hpp> //
#include <wx/wx.h> // Includes <windows.h> :(
struct Cmd_id
{
enum Enum
{
hello = 1
};
};
class Main_window: public wxFrame
{
void on_cmd_hello( wxCommandEvent& )
{
wxLogMessage( "Hello world from wxWidgets!" );
}
void on_cmd_exit( wxCommandEvent& )
{
Close( true );
}
void on_cmd_about( wxCommandEvent& )
{
wxMessageBox( "This is a wxWidgets' Hello world sample",
"About Hello World", wxOK | wxICON_INFORMATION );
}
wxDECLARE_EVENT_TABLE();
public:
Main_window( const wxString& title, const wxPoint& pos, const
wxSize& size ):
wxFrame( nullptr, wxID_ANY, title, pos, size )
{
const ptr_<wxMenu> file_menu = new wxMenu;
file_menu->Append( Cmd_id::hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu
item");
file_menu->AppendSeparator();
file_menu->Append(wxID_EXIT);
const ptr_<wxMenu> help_menu = new wxMenu;
help_menu->Append( wxID_ABOUT );
const ptr_<wxMenuBar> menu_bar = new wxMenuBar;
menu_bar->Append( file_menu, "&File" );
menu_bar->Append( help_menu, "&Help" );
SetMenuBar( menu_bar );
CreateStatusBar();
SetStatusText( "Welcome to wxWidgets!" );
}
};
wxBEGIN_EVENT_TABLE( Main_window, wxFrame )
EVT_MENU( Cmd_id::hello, Main_window::on_cmd_hello )
EVT_MENU( wxID_EXIT, Main_window::on_cmd_exit )
EVT_MENU( wxID_ABOUT, Main_window::on_cmd_about )
wxEND_EVENT_TABLE()
class App: public wxApp
{
public:
auto OnInit()
-> bool override
{
const ptr_<Main_window> window =
new Main_window( "Hello World", wxPoint( 50, 50 ), wxSize(
450, 340 ) );
window->Show();
return true;
}
};
// wxIMPLEMENT_APP(App);
wxIMPLEMENT_WX_THEME_SUPPORT // Does nothing in Windows. :(
auto main()
-> int
{
wxDISABLE_DEBUG_SUPPORT(); // Don't know why, but that's in
wxIMPLEMENT_APP.
wxApp::SetInitializerFunction( []() -> ptr_<wxAppConsole> { return
new App; } );
return wxEntry(); // Undocumented, uses process arguments.
}
-----------------------------------------------------------------------
Cheers!,
- Alf