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;
}
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
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?
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.
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
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.
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
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.
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
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