ProgEx43 : Command Line Compiling With The GNU Compilers

Started by Frederick J. Harris, January 05, 2013, 04:55:40 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris

Below is an example I owe Jose Roca for in terms of its inspiration.  Several years back he posted a PowerBASIC example where he bypassed the Windows Dialog Engine and created the Dialog Box programatically using CreateWindowEx() and a regular WndProc() instead of a Dialog Procedure.  I altered his example considerably, but that is where I obtained the idea I used in this Command Line Compiling example, translated to C++ of course.


  ProgEx43 -- Command Line Compiling With The GNU MinGW Compiler g++.  Also, Creating Menus
              And Dialog Boxes Programatically Without The Windows Dialog Engine and Resource
              Scripts (Interesting Stuff).

  Command line compiling is fun, and a worthwhile skill to learn.  You should be able to use
  this code for any recent GNU Mingw installation on Windows.  I have tested it with the 4.4.1
  Code::Blocks installation that came with Code::Blocks Version 10.05, and the newer 4.7 series
  x86 / x64 compiler which creates 64 bit executables (x86_64-w64-mingw32 - GCC 4.7 Series).
  These directions won't exactly work with Microsoft's compilers (installed with Visual Studio,
  usually), because they take somewhat different command line parameters.  I'll demonstrate
  use of Microsoft's compilers a bit later.

  If you've been learning programming using an IDE (Integrated Development Environment), this
  material will give you an idea how the various IDE menu and toolbar commands work in creating
  your executable binaries.  Taking a very high level view, compilers are nothing more than code
  translators that read in a source file containing programming code, and output a binary file
  containing machine instructions for a specific processor.  As such, they don't themselves have
  any graphical user interface, but rather always work as command line tools where one invokes
  them from a command prompt.  For example, the C++ compiler for the Mingw suite is g++.exe.

  When one installs a compiler (usually packaged with a development environment, such as
  Microsoft's Visual Studio or Code::Blocks), it naturally installs in a directory somewhere,
  and there are usually quite a few subdirectories and files associated with it.  For example,
  when I installed Code::Blocks, I had the installer create a C:\Program Files (x86)\CodeBlocks
  folder.  Under that folder is where the Mingw compiler 'toolchain' was installed by the
  Code::Blocks installation program, so I ended up with this ...

  C:\Program Files (x86)\CodeBlocks\MinGW

  Further, under the \MinGW directory are all the components the compiler needs.  There are
  usually quite a few subdirectories and files.  However, the most important subdirectores
  are usually as follows ...

  \MinGW\bin
  \MinGW\include
  \MinGW\lib

  The actual compiler for C++, that is, g++.exe, can be found in \MinGW\bin.  Also noteworthy
  there are gcc.exe, which is the C compiler, and windres.exe, which is the resource compiler.
  You'll also see ld.exe there, which is the linker, but you usually don't have to use that
  seperately unless you have some specific reason for doing so - and there are various reasons.

  Its also possible to install a compiler by itself, that is, not part of any development
  product such as Code::Blocks or Visual Studio.  For example, on the laptop on which I'm
  writing this tutorial, I have two versions of the MinGW compiler suite installed. In
  addition to the one installed with my Code::Blocks 10.05 installation, I have a more
  current installation of the 4.7 series compiler at ...

  C:\MinGW64

  That version can create both 32 bit and 64 bit binaries.  Actually, in a lot of ways, or
  for me anyway, the hardest part of doing command line compiling is getting my paths right
  so that my computer can find the various necessary support files during the compile.
  Here is what I do.

  First I create a project directory wherever I want for the project.  On all my computers
  I have a C:\Code directory and that's where I put all my source code for all the different
  compilers I have - and I kind of collect them so I have quite a few.  For this CodeBlocks
  developed example I made the following directory...

  C:\Code\CodeBlks\CPrimer\ProgEx43\x64

  Next I make a little batch file and put a shortcut to it on my Desktop.  For this project
  here is the batch file I use for the MinGW-w64 64/32-bit Edition (4.7.1)...

  CD\
  cd C:\Code\CodeBlks\CPrimer\ProgEx43\x64
  C:\Windows\system32\cmd.exe

  If you aren't familiar with batch files paste into Notepad the above three lines or make
  up your own using directory paths you are using, and save the file to your newly made
  project directory as described above with a *.bat extension (Mine would be ProgEx43.bat).

  The 1st line backs us out of whatever directory we are presently in and puts us in C:
  root.  The 'cd' command on line 2 then changes the directory to our project directory where
  we will have our source code files. Finally, I invoke the command processor cmd.exe and
  I'll have a command window to work and compile from.  You may want to use the 'Properties'
  of the Command Prompt Console Window to increase the width a mite, so as to prevent line
  breaks of your command strings - if that bothers you (it does me).

  Now if you are wanting to use the Mingw compiler that Code::Blocks installs you would have
  more luck with the following batch file, as it sets the PATH to the installation of the
  Mingw toolchain if you've used the Code::Blocks default installation directory of
  C:\Program Files or C:\Program Files (x86) for 64 bit Operating System installs ...

  CD\
  cd C:\Code\CodeBlks\CPrimer\ProgEx43
  PATH=C:\Program Files (x86)\CodeBlocks\MinGW\bin;C:\Program Files (x86)\CodeBlocks\MinGW\lib
  C:\Windows\system32\cmd.exe

  The reason they are different involves the concept of PATHs the operating system uses.  When
  I installed one of the later Mingw compilers seperately from any IDE (Integrated Development
  Environment, i.e., Code::Blocks, Dev-C++, etc.) installation, the setup program apparently
  installed the C:\MINGW64\bin; path to my computer's environment.  Therefore, any time I execute
  a file from a command prompt, the operating system will search all the paths set into my PATH
  variable of my computer's environment.  If it hits the path to my newer 64 bit compiler first -
  it will use that compiler.  That's fine if that's the compiler I want to use.  But if it isn't
  and I want my other one, i.e., the Code::Blocks installed one, I'd be out of luck (my Code::Blocks
  installation didn't modify my environment path).  So what I need to do to override the PATH set
  in my environment, is set a temporary PATH in my batch file so the command processor looks there
  first.

  In the batch file above, I'm actually over-riding the PATH Environment variable's path with
  my own temporary PATH, so that the Code::Blocks MinGW's installation is used, rather than the
  newer 4.7 series compiler which modified my PATH Environment variable.  It is somewhat confusing,
  I admit.  If you don't have multiple versions of the same compiler installed in different places
  on your computer, you won't have to deal with this.

  Provided you can get your paths set right, the next step is to compile the code.  Right below
  you'll find Main.cpp and ProgEx43.h.  Put those files in your project directory, and invoke the
  Mingw C++ compiler, which is g++.exe.

  For my seperate stand alone installation of the Series 4.7 x86 / x64 compiler, my command prompt
  window looked like this when I executed my batch file ...

  C:\Code\CodeBlks\CPrimer\ProgEx43\x64>

  I typed my command line to g++ like so ...

  g++ -Wall Main.cpp -oProgEx43_x64.exe -mwindows -Os -s

  or

  g++ -Wall Main.cpp -oProgEx43_x64.exe -mwindows -m64 -Os -s

  However, that all goes after the command prompt, so the finished screen actually showe this ...

  C:\Code\CodeBlks\CPrimer\ProgEx41\x64>g++ -Wall Main.cpp -oProgEx43_x64.exe -mwindows -Os -s

  Then just press the [ENTER] key.  It may take a few seconds to finish, and if you finally see the
  command prompt return, then it succeeded.  Otherwise, you'll be treated to a nasty screen of ugly
  errors and warnings.  Here is what I found on my screen in the command prompt window after the
  successful compilation, and after I executed a dir command at the prompt to reveal the contents
  of my working directory ...


  C:\Code\CodeBlks\CPrimer\ProgEx43\x64>g++ -Wall Main.cpp -oProgEx43_x64.exe -mwindows -Os -s


  C:\Code\CodeBlks\CPrimer\ProgEx43\x64>dir
   Volume in drive C is OSDisk
   Volume Serial Number is 3E79-B713

   Directory of C:\Code\CodeBlks\CPrimer\ProgEx43\x64

  01/02/2013  04:37 PM    <DIR>          .
  01/02/2013  04:37 PM    <DIR>          ..
  01/02/2013  03:23 PM            20,250 ExtraMaterial.txt
  01/02/2013  04:33 PM            51,816 Main.cpp
  01/02/2013  12:18 PM                76 ProgEx41.bat
  01/02/2013  03:31 PM             1,290 ProgEx41.h
  01/02/2013  04:37 PM            41,984 ProgEx43_x64.exe
                 5 File(s)        115,416 bytes
                 2 Dir(s)  134,642,028,544 bytes free


  Note you'll find ProgEx43_x64 in the list above comprising 41,984 bytes.  If I wanted to do a 32 bit
  compile I'd have used this command line ...

  g++ -Wall Main.cpp -oProgEx43_x86.exe -mwindows -m32 -Os -s

  Note that this compiler defaults to a 64 bit compile, so if you don't specify -m32 or -m64 you'll get
  a 64 bit executable, if you've done everything right and your code is without errors.

  For the older MinGW installation associated with the Code::Blocks install, my command line looked like
  so after executing my batch file ...

  C:\Code\CodeBlks\CPrimer\ProgEx43>

  Then I typed the following after that ...

  C:\Code\CodeBlks\CPrimer\ProgEx43>g++ -Wall Main.cpp -oProgEx43.exe -mwindows -s

  Why don't I just copy the relavant output from my command prompt window showing the compiler invocation
  along with output following a dir command which reveals the results of the successful compile?  Here is
  that ...


  C:\Code\CodeBlks\CPrimer\ProgEx43>g++ -Wall Main.cpp -oProgEx43.exe -mwindows -s

  C:\Code\CodeBlks\CPrimer\ProgEx43>dir
   Volume in drive C is OSDisk
   Volume Serial Number is 3E79-B713

   Directory of C:\Code\CodeBlks\CPrimer\ProgEx43

  01/03/2013  11:14 AM    <DIR>          .
  01/03/2013  11:14 AM    <DIR>          ..
  01/02/2013  03:42 PM    <DIR>          .objs
  01/03/2013  11:12 AM            58,074 Main.cpp
  01/02/2013  04:18 PM               166 ProgEx43.bat
  02/01/2010  01:28 AM               914 ProgEx43.cbp
  01/02/2013  03:31 PM             1,290 ProgEx43.h
  01/03/2013  09:45 AM               347 ProgEx43.layout
  01/03/2013  11:14 AM            11,776 ProgEx43.exe
  01/02/2013  04:37 PM    <DIR>          x64
                 6 File(s)         72,567 bytes
                 4 Dir(s)  134,637,318,144 bytes free

  C:\Code\CodeBlks\CPrimer\ProgEx43>


  If you are having problems such as command prompt errors stating that no such file or directory exists,
  or it can't find such and such, then your PATHs aren't right and you are going to have to figure it out
  and fix it.  Your fix can entail either setting the path in your environment, or setting it in a batch
  file.

  In terms of the details of the command line parameters, they are compiler specific, and you'll need to
  obtain the documentation on the compiler to see what you need.  They can become long and complex.  In
  the example above they were pretty simple.  Obviously, Main.cpp is the source code file.  The -o syntax
  specifies the name you desire for the output binary.  -mwindows specifies a Windows executable (g++ can
  create executables for several operating systems).  The -s is an optimization which causes the compiler
  to remove debugging symbols from the executable.  This makes it smaller.  There are many other
  optimizations, and like I said, you need to look them up.

                                -- End Command Line Compiling Information --

  In terms of this program itself, I got the idea for this program from a Dialog Box example written
  in PowerBASIC Jose Roca posted some time ago where he used CreateWindowEx() calls to create a Dialog
  Box completely bypassing the Windows Dialog Engine.  I liked that and thought it was interesting
  because I really dislike the Windows Dialog Engine and use it as little as possible in my work.  Using
  Jose's technique I think its possible to completely eliminate its use if a person would want to do that.

  So anyway, this program contains a bona fide dialog box without any dialog template in an *.rc file.
  Since we've eliminated the dialog box from the rc file, I thought, "Why not eliminate the menu from the
  rc file too?  That way we won't even need any rc file at all!  Cool!"  So what this program does (in
  addition to teaching command line compiling) is present a little white background main window with a
  main menu in the menu bar.  The menu is created programatically in the main window's WM_CREATE handler.
  The menu contains File, Options, and Help submenues.  When you click the 'About' from the Help menu
  the non-resource file Dialog Box is created.  The procedure just below...

  LRESULT CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

  ...is the Window Procedure for the Dialog Box.  It is a normal Window Procedure - not a dialog box
  procedure.  Here's how it all works.  In fnWndProc_OnCreate(), which is the WM_CREATE handler for the
  program's main window, we register a window class named "Dialog", which is a custom window class I
  made up; its not any pre-defined window class of Windows.  There is nothing at all unusual I did in
  setting up the fields of the WNDCLASSEX struct.  I did set the Window Procedure for this class as
  being DlgProc() though.  What makes it a dialog box though is what happens in WndProc_OnAbout(). Here
  is the CreateWindowEx() call.  Note the extended and window styles...


  hDlg=
  CreateWindowEx
  (
   WS_EX_DLGMODALFRAME | WS_EX_CONTROLPARENT,
   "Dialog",
   "Dialog Window",
   WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
   175,
   100,
   400,
   145,
   Wea->hWnd,
   0,
   Wea->hIns,
   NULL
  );


  Then, right after that are various CreateWindow() calls to create the child windows in the "Dialog Box".
  Note that I created a group box, put an 'OK' and 'Cancel' button in the group box, and added the
  WS_TABSTOP style to the buttons to enable standard dialog box tabbing functionality.  If you start the
  program and bring up the 'About' dialog box and hit the TAB key, you'll see it tabs between the 'OK' and
  'Cancel' buttons, and responds to hitting the [ENTER] key just like a dialog box should.  This is made
  possible by the unusual message pump at the bottom of the WndProc_OnAbout() function...


  while(GetMessage(&Msg, NULL, 0, 0))
  {
        if(!IsDialogMessage(hDlg,&Msg))
        {
           TranslateMessage(&Msg);
           DispatchMessage(&Msg);
        }
  }


  In the code above hDlg is the handle of the just created CreateWindowEx() Dialog Box.  The tab order/[ENTER]
  key behavior is made possible through the IsDialogMessage() function which does the necessary keystroke
  translations to make it seem like a Dialog Box.  I might point out that if you didn't need that behavior, and
  just needed to disable the main window while the Dialog Box was active, you could dispense with the message
  loop in fnWndProc_OnAbout(), and just use EnableWindow(hMainWnd,FALSE) to disable the main window.
[/CODE]


//ProgEx43.h
#ifndef Main_h
#define Main_h

#define dim(x) (sizeof(x) / sizeof(x[0]))

#define IDC_STATIC            -1
#define ID_FILE_OPEN          1500
#define ID_FILE_SAVE          1505
#define ID_FILE_EXIT          1510
#define ID_OPTIONS            1600
#define IDD_ABOUT             1700
#define IDD_DIALOGABOUT       1700
#define IDD_GROUP             1705
#define IDD_OK                1710
#define IDD_CANCEL            1715

struct                        WndEventArgs
{
HWND                         hWnd;
WPARAM                       wParam;
LPARAM                       lParam;
HINSTANCE                    hIns;
};

typedef WndEventArgs*         lpWndEventArgs;

long fnWndProc_OnCreate       (lpWndEventArgs Wea);
long fnWndProc_OnCommand      (lpWndEventArgs Wea);
long fnWndProc_OnPaint        (lpWndEventArgs Wea);
long fnWndProc_OnDestroy      (lpWndEventArgs Wea);

struct EVENTHANDLER
{
unsigned int                 iMsg;
long                         (*fnPtr)(lpWndEventArgs);
};

const EVENTHANDLER EventHandler[]=
{
{WM_CREATE,                  fnWndProc_OnCreate},
{WM_COMMAND,                 fnWndProc_OnCommand},
{WM_PAINT,                   fnWndProc_OnPaint},
{WM_DESTROY,                 fnWndProc_OnDestroy}
};
#endif




//Main.cpp
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <tchar.h>
#include <commdlg.h>
#include "ProgEx43.h"


LRESULT CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
    case WM_CREATE:
      EnableWindow(GetParent(hwnd),FALSE);
      return 0;
    case WM_COMMAND:
      switch(LOWORD(wParam))
      {
         case IDD_OK:
           MessageBox(hwnd,_T("You Clicked The OK Button!"),_T("OK Button Click!"),MB_OK);
           SendMessage(hwnd,WM_CLOSE,0,0);
           break;
         case IDD_CANCEL:
           MessageBox(hwnd,_T("You Clicked The Cancel Button!"),_T("Cancel Button Click!"),MB_OK);
           SendMessage(hwnd,WM_CLOSE,0,0);
           break;
      }
      return 0;
    case WM_CLOSE:
      EnableWindow(GetParent(hwnd),TRUE);
      DestroyWindow(hwnd);
      return 0;
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
}

return DefWindowProc(hwnd, msg, wParam, lParam);
}


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
TCHAR szClassName[]=_T("Dialog");
TCHAR* ptrOpenFileName=NULL;
HMENU hMenu, hSubMenu;
WNDCLASSEX wc;

Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_FILE_OPEN,  _T("&Open"));
AppendMenu(hSubMenu,  MF_STRING,            ID_FILE_SAVE,            _T("&Save"));
AppendMenu(hSubMenu,  MF_SEPARATOR,         0,                                 0);
AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_FILE_EXIT,  _T("E&xit"));
AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,      _T("&File"));

hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)ID_OPTIONS,_T("&Explorer"));
AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,   _T("O&ptions"));

hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,  MF_STRING,            (UINT_PTR)IDD_ABOUT,    _T("&About"));
AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu,      _T("&Help"));
SetMenu(Wea->hWnd, hMenu);

//Then Register Window Class For Dialog Box
wc.lpszClassName=szClassName,               wc.lpfnWndProc=DlgProc;
wc.cbSize=sizeof(wc),                       wc.style=CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra=0,                            wc.cbWndExtra=0;
wc.hInstance=Wea->hIns,                     wc.hCursor=LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,   wc.lpszMenuName=NULL;
wc.hIcon=0;                                 wc.hIconSm=0;
RegisterClassEx(&wc);

//And finally Allocate Memory To Store File Name from Open File Dialog for
ptrOpenFileName=(TCHAR*)GlobalAlloc(GPTR,256*sizeof(TCHAR)); //later display in WM_PAINT
if(ptrOpenFileName)                                          //handler on the main window
    SetWindowLongPtr(Wea->hWnd,GWLP_USERDATA,(LONG_PTR)ptrOpenFileName);
else
    return -1;

return 0;
}


long WndProc_OnFileOpen(lpWndEventArgs Wea)
{
static TCHAR szFilter[]=_T("C Files (*.C),CPP Files (*.cpp)\0*.c;*.cpp\0\0");
static TCHAR szTitleName[_MAX_FNAME+_MAX_EXT];
static TCHAR szFileName[_MAX_PATH];
TCHAR* ptrOpenFileName=NULL;
TCHAR lpszBuffer[256];
OPENFILENAME ofn;

GetCurrentDirectory(256*sizeof(TCHAR),lpszBuffer);
memset(&ofn,_T('\0'),sizeof(OPENFILENAME));
ofn.lStructSize=sizeof(OPENFILENAME);
ofn.lpstrFilter = szFilter;
ofn.nMaxFile=_MAX_PATH;
ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
ofn.lpstrInitialDir = lpszBuffer;
ofn.lpstrDefExt = _T("cpp");
ofn.hInstance=GetModuleHandle(_T(""));
ofn.hwndOwner = Wea->hWnd;
ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
ofn.lpstrFile=szFileName;
ofn.lpstrFileTitle=szTitleName;
GetOpenFileName(&ofn);
ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
_tcscpy(ptrOpenFileName,ofn.lpstrFile);
InvalidateRect(Wea->hWnd,NULL,FALSE);

return 0;
}


long WndProc_OnFileSave(lpWndEventArgs Wea)
{
static TCHAR szFilter[]=_T("C Files (*.C),CPP Files (*.cpp)\0*.c;*.cpp\0\0");
static TCHAR szTitleName[_MAX_FNAME+_MAX_EXT];
static TCHAR szFileName[_MAX_PATH];
TCHAR* ptrOpenFileName=NULL;
TCHAR lpszBuffer[256];
OPENFILENAME ofn;

GetCurrentDirectory(256*sizeof(TCHAR),lpszBuffer);
memset(&ofn,_T('\0'),sizeof(OPENFILENAME));
ofn.lStructSize=sizeof(OPENFILENAME);
ofn.lpstrFilter = szFilter;
ofn.nMaxFile=_MAX_PATH;
ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
ofn.lpstrInitialDir = lpszBuffer;
ofn.lpstrDefExt = _T("cpp");
ofn.hInstance=GetModuleHandle(_T(""));
ofn.hwndOwner = Wea->hWnd;
ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
ofn.lpstrFile=szFileName;
ofn.lpstrFileTitle=szTitleName;
GetSaveFileName(&ofn);
ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
_tcscpy(ptrOpenFileName,ofn.lpstrFile);
InvalidateRect(Wea->hWnd,NULL,FALSE);

return 0;
}


long WndProc_OnAbout(lpWndEventArgs Wea)
{
TCHAR szCap2[]=_T("An Example Program Showing How To");
TCHAR szCap1[]=_T("About This Program");
DWORD dwExStyle,dwStyle,dwSty;
HWND hDlg,hGroup;
MSG Msg;

dwExStyle = WS_EX_DLGMODALFRAME | WS_EX_CONTROLPARENT;
dwStyle   = WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE;
dwSty     = WS_CHILD|WS_VISIBLE;
Wea->hIns=GetModuleHandle(_T(""));
hDlg=CreateWindowEx(dwExStyle,_T("Dialog"),_T("Dialog Window"),dwStyle,175,100,400,145,Wea->hWnd,0,Wea->hIns,NULL);
hGroup=CreateWindow(_T("button"),szCap1,BS_GROUPBOX|dwSty,5,5,385,100,hDlg,(HMENU)IDD_GROUP,Wea->hIns,0);
CreateWindow(_T("button"),_T("OK"),WS_TABSTOP|dwSty,295,25,80,25,hDlg,(HMENU)IDD_OK,Wea->hIns,0);
CreateWindow(_T("button"),_T("Cancel"),WS_TABSTOP|dwSty,295,65,80,25,hDlg,(HMENU)IDD_CANCEL,Wea->hIns,0);
CreateWindow(_T("static"),szCap2,dwSty,25,25,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
CreateWindow(_T("static"),_T("              Use Dialog Boxes"),dwSty,25,42,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
CreateWindow(_T("static"),_T("                     By Fred"),dwSty,25,72,275,25,hGroup,(HMENU)-1,Wea->hIns,0);
while(GetMessage(&Msg, NULL, 0, 0))
{
    if(!IsDialogMessage(hDlg,&Msg))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
}

return 0;
}


long WndProc_OnOptions(lpWndEventArgs Wea)
{
system("explorer c:\\");
return 0;
}


long WndProc_OnExit(lpWndEventArgs Wea)
{
SendMessage(Wea->hWnd,WM_CLOSE,0,0);
return 0;
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
switch(LOWORD(Wea->wParam))
{
    case ID_FILE_OPEN:
      return WndProc_OnFileOpen(Wea);
    case ID_FILE_SAVE:
      return WndProc_OnFileSave(Wea);
    case IDD_ABOUT:
      return WndProc_OnAbout(Wea);
    case ID_OPTIONS:
      return WndProc_OnOptions(Wea);
    case ID_FILE_EXIT:
      return WndProc_OnExit(Wea);
}

return 0;
}


long fnWndProc_OnPaint(lpWndEventArgs Wea)
{
TCHAR* ptrOpenFileName=NULL;
PAINTSTRUCT ps;
HDC hDC;

hDC=BeginPaint(Wea->hWnd,&ps);
ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
TextOut(hDC,2,2,ptrOpenFileName,(int)_tcslen(ptrOpenFileName));
EndPaint(Wea->hWnd,&ps);

return 0;
}


long fnWndProc_OnDestroy(lpWndEventArgs Wea)
{
TCHAR* ptrOpenFileName=NULL;

ptrOpenFileName=(TCHAR*)GetWindowLongPtr(Wea->hWnd,GWLP_USERDATA);
GlobalFree(ptrOpenFileName);
PostQuitMessage(0);

return 0;
}


LRESULT CALLBACK WndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
WndEventArgs Wea;

for(unsigned int i=0; i<dim(EventHandler); i++)
{
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
}

return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpCmdLine, int nCmdShow)
{
TCHAR szClass[]=_T("Dialogs");
WNDCLASSEX wc;
HWND hWnd;
MSG Msg;

wc.lpszClassName=szClass,               wc.lpfnWndProc=WndProc;;
wc.cbSize=sizeof(WNDCLASSEX),           wc.style=0;
wc.cbClsExtra=0,                        wc.cbWndExtra=0;
wc.hInstance=hIns,                      wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL,IDC_ARROW),  wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL,                   wc.hIconSm=NULL;
RegisterClassEx(&wc);
hWnd=CreateWindow(szClass,_T("Non-Dialog Engine Dialog Boxes"),WS_OVERLAPPEDWINDOW,350,350,400,200,NULL,NULL,hIns,NULL);
ShowWindow(hWnd,nCmdShow);
while(GetMessage(&Msg, NULL, 0, 0))
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

return (int)Msg.wParam;
}
 

James C. Fuller

Fred,
  Good stuff but a couple of things you might want to add.
Never install any MinGW bundle to a directory tree with spaces. I know it seems to work and it might just be for older tool chains but ....

clarification on -mwindows:
I got this from somewhere on the web.
To build Win32 GUI application, -mwindows switch is used . If -mwindows is not added, -mconsole is automatically added. If -mconsole is added for building GUI application, the window of the command prompt  appears at the same time as GUI application when you invoke the program on Windows.

James

Frederick J. Harris

About the 'Program Files' directory and the spaces, I agree with you there, and I've read that many times too in the GNU documentation.  Years ago when I was a happy Dev-C++ user I always installed that right off of my C: root (as recommended by them), and never had too much trouble with it.  I remember in the Dev-C++ Forum that folks who installed to C:\Program Files led unhappy lives, plagued with blue screens of death, still born children, and general evil. 

I've just taken it for granted though that the team that built Code::Blocks are in lockstep with Microsoft's determination that everything goes in 'Program Files', because that comes up in the defaults when you install Code::Blocks, and I've never changed that default, figuring that's where Code::Blocks wants to put it.  I've never had any problems, and I've installed Code::Blocks dozens of times.  I never asked anybody about it though, so I'm assumming my determination is correct, and I've been wrong before.  Maybe somebody (like me) ought to ask for an 'official' determination on that.  I will say this though.  Code::Blocks doesn't modify the environment PATH when it is installed, so that kind of points to the fact that they've dealt with the whole pathing thing in their code.

Thoughts?

Frederick J. Harris

Quote
To build Win32 GUI application, -mwindows switch is used . If -mwindows is not added, -mconsole is automatically added. If -mconsole is added for building GUI application, the window of the command prompt  appears at the same time as GUI application when you invoke the program on Windows.

Good info.  I didn't know that about the -mconsole.  I suppose anyone using this will read these comments. 

James C. Fuller

Fred,
  I have not used code::blocks much and like you I assume it knows what it's doing.
The problems I ran into was shelling to a batch file from RadAsm3 using bc9. For Projects it was fine as it passed only the file name, but for single files it passed the complete path without quotes. I managed a work around but it's just easier to not use spaces in the file paths.

Your next challenge should you choose to accept it: try msys with MinGW and learn to compile using a unix like shell and install scripts :)

I finally found out how to use different compilers although not using MingTDM64. There is a way but it was just easier installing the 32bit  only version for compiling 32bit libraries.

I even managed to compile the latest  pcre-8.32 and use it with bc9.
Not as successful with the latest wxWidgets though.

James


Frederick J. Harris

Quote
Your next challenge should you choose to accept it: try msys with MinGW and learn to compile using a unix like shell and install scripts

Nah, I think I'll pass on that, although I've thought of it.  I guess I'm just not into it that much.  I used to experiment with Linux a lot, but gave that up because it just doesn't have much applicability to the work I do, which involves Windows essentialy. 

James C. Fuller

Fred,
  Doesn't code::blocks use make for compiling/building ?

There is a supposed easier replacement for make although I haven't tried it yet:
http://forum.pellesc.de/index.php?topic=5101.0

James



Frederick J. Harris

You know, I don't even know James.  I just recently installed their 12.11 version on one of my laptops and did a quick look through to see if it was obvious from anything there, but didn't see anything.  My guess is it doesn't though.  I've always noted in the code output window for a compile it lists fully qualified paths to everything, for example, this ...


mingw32-g++.exe -Wall -fexceptions  -O2     -c C:\Code\CodeBlks\SizeOf\main.cpp -o C:\Code\CodeBlks\SizeOf\.objs\main.o
mingw32-g++.exe  -o SizeOf.exe C:\Code\CodeBlks\SizeOf\.objs\main.o   -s 


I imagine that's because it doesn't install any PATH or LIB or MINGW or whatever entries in the ENVIRONMENT.  At least not that I noticed.

James C. Fuller

Fred,
  Just a FYI:
  This is an excellent package which I just noticed  was updated recently. Give his page a good read.
It is 32bit only but personally  I see very little reason for 64bit ??
I did a bit of boost testing awhile ago. Amazing library.


http://nuwen.net/mingw.html


James

James C. Fuller

Fred,
  Here is another FYI that you may already know that jumped up and bit me this AM.
I was testing MinGW95 and had problems with InitCommonControlsEx. I needed to add -D_WIN32_IE=0x0300 to my compile line.
I must have changed it in my MinGWTDM64 commctrl.h ?

James