Here is what I consider to be the simplest possible Windows GUI program written against the Windows Api, i.e., no class frameworks, that nonetheless uses RegisterClassEx() to register a Window Class, and CreateWindowEx() to create a window...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
// cl Main.cpp /O1 /Os /MT user32.lib
#include <windows.h>
LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
if(msg==WM_DESTROY)
{
PostQuitMessage(0);
return(0);
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
char szClassName[]="Form1";
WNDCLASSEX wc;
MSG messages;
HWND hWnd;
memset(&wc,0,sizeof(wc));
wc.lpszClassName=szClassName; wc.lpfnWndProc=fnWndProc;
wc.cbSize=sizeof (WNDCLASSEX); wc.hInstance=hIns;
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;
RegisterClassEx(&wc);
hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
|
I used command line compilation with Visual Studio 2008 (that's an old version) and built as 32 bit. My command line compilation string is at top. I'm seeing 37,376 bytes for the stand alone executable built /MT linkage, i.e., no dependencies except a valid Windows installation. Now, that same program built with the newer Visual Studio build chains is 80 to 100k.
Now, here is what that exact program looks like in PowerBASIC...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
#Compile Exe "Form1.exe"
#Dim All
#Include Once "Windows.inc"
Function fnWndProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If wMsg=%WM_DESTROY Then
PostQuitMessage(0)
Exit Function
End If
fnWndProc=DefWindowProc(hWnd, wMsg, wParam, lParam)
End Function
Function WinMain(ByVal hInstance As Long, ByVal hPrevIns As Long, ByVal lpCmdLn As Asciiz Ptr, ByVal iShowWnd As Long) As Long
Local szAppName As Asciiz*16
Local wc As WNDCLASSEX
Local hWnd As Dword
Local Msg As tagMsg
szAppName="Form1"
wc.lpszClassName=VarPtr(szAppName) : wc.lpfnWndProc=CodePtr(fnWndProc)
wc.hInstance=hInstance : wc.hbrBackground=%COLOR_BTNFACE+1
wc.cbSize=SizeOf(wc)
RegisterClassEx(wc)
hWnd=CreateWindowEx(0,szAppName,"Form1",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hInstance,ByVal 0)
Call ShowWindow(hWnd,iShowWnd)
While GetMessage(Msg,%NULL,0,0)
TranslateMessage Msg
DispatchMessage Msg
Wend
Function=msg.wParam
End Function
|
Here is the compiler output for the above...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
PowerBASIC 10 for Windows
Copyright (c) 1996-2011 PowerBasic Inc.
Englewood, Florida USA
All Rights Reserved
Primary source: C:\Code\PwrBasic\PBWin10\Forms\Form1\Form1A.bas {191328 total lines}
Target compilation: Form1.exe
Compile time: 0.9 seconds, at 12755200 lines/minute
960 bytes compiled code, 3276 bytes RTLibrary,
12 bytes string literals, and 2692 bytes dgroup.
Executable stack size: 1048576 bytes.
Disk image: 7680 bytes Memory image: 5980 bytes.
|
So PowerBASIC's code generation is so tight that its creating the exact same program in 5980 bytes, which is a very, very small fraction of what Microsoft's compilers can do, seemingly.
Also, note the compilation speed. Much, much faster than any C++ compiler out there. PowerBASIC is written in pure handcrafted assembler.
There's a whole lot can be said about the above, but unfortunately, my time is limited right now. I'll have more time in 10 days or so.
But I'll say this. The above C++ code can be built by the older Mingw build chain to 7168 bytes, which is close to the PowerBASIC build size. Whole lot going on there too. Mingw uses msvcrt.dll for its C Runtime which Microsoft is furious about. But its a key to what's going on.
On the variable types. PowerBASIC variable types are exactly like MASM. A 32 bit unsigned variable is a Dword. This simplifies all the ridiculous Windows C/C++ data types which are HANDLEs - which are all 32 bit unsigned numbers in x86 builds, and 64 bit unsigned integers in 64 bit builds. In C parlance you have a ridiculous assembladge of things like...
HWND - Handle to Window
HDC - Handle to Device Context
HBRUSH - Handle to Brush
...etc, ad infinitum. In PowerBASIC, they are all Dwords. You'll see in my PowerBASIC WinMain....
1 2 3 4 5 6 7
|
Local hWnd As Dword
[//CODE]
If I needed an HDC for a Handle to a Device Context, it would be not this (in C parlance...
[CODE]
HDC hDC
|
but this...
They are all 32 bit unsigned integers. So PowerBASIC is a 'weakly typed' programming language. That's actually my personal preference. I'm 64 years old, and have been writting code since Fortran days on main frames in the 1970, and in my entire programming career I have never encountered a bug in my code that could have been prevented by a strongly typed programming language like C++. All this nonsense in C++ about type safty and all these bizarre syntactically ugly casts is in my opinion nothing but vanity and vexation of the spirit.
To facilitate interaction with the Windows Api and C/C++ code, PowerBASIC includes a full set of fixed length string variable types that somewhat mimic...
or...
In PowerBASIC that would be...
|
Local szBuffer As Asciiz*128
|
or...
|
Local szBuffer As WStringZ*128
|
The later would be 'Wide Character Z String or zero terminated string. The PowerBASIC language automatically null terminates Z Strings. In my PowerBASIC code above I used a szClassName Asciiz*16 to contain the name of the class. Note it can be assigned through direct assignment with the '=' sign as opposed to in C/C++ one would need strcpy/wcscpy to copy characters to it.
The WPARAM and LPARAM parameters to a Window Procedure are just Longs or Dwords in PowerBASIC. They are not typed as anything special like in C/C++. Basically, in 32 bit builds integers are either signed or unsigned. There aren't any other alternatives. C makes a mess out of it with all these platform specific data types, i.e., LPARAM, WPARAM, HINSTANCE, HWND, HBRUSH, HDC, HANDLE, etc., ad infinitum. Can't continue any more now.