Welcome to the new Friends-of-FPC!

Here you can find all kinds of information about the FreePascal Compiler. We have many tutorials and howtos as well as a selection of tools to help you with your programming. We also have some example codes for you. And if you want to contribute some information/ sources/ tools yourself you can do so.
Also we have finally relaunched the FoFPC forum. It's your chance for some Q&A about everything FreePascal.

Friends-of-FPC

Tutorials: Learn how to code with FreePascal.

Source Codes: A collection of examples, miscellaneous source codes and open source stuff.

Tools and Help Files: Intro- duction of some tools that might help you with FPC.

Community

Forum: Ask or answer questions about the FreePascal Compiler, programming or just babble about coding.

Contribute! Contribute your own Tutorial, Source Codes or Tools and send them to us!

Website

About: Information about Friends-of-FPC.org.

Win32/ FPC - Chapter 6 - by Delax

Now we will have some fun! We put all the basics together and create a working Windows application. All the different parts will be put in seperate procedures to avoid confusion and we'll add some error handling to track bugs.

Let's take a look at the variable section.

{$APPTYPE GUI}
{$MODE DELPHI}

program Win32_Source03;

uses  windows;

const
  AppName = 'Win32/ FPC - Source 03';

VAR

  active : BOOLEAN;
  msg : MSG;
  hWindow : hwnd;

The unit Windows should be self explaining. active is a simple variable to check if the user has terminated our application. msg is a variable where the Windows messages will be stored in. hWindow will be the handle of our window.

The program starts with a little procedure to handle errors that might occur in our program. Whenever an error occurs, we call this procedure that puts out an error message and terminates the application.

// Try, Throw, Catch mechanism. Simple proc to display given errors. //
procedure ThrowError(pcErrorMessage : pChar);
begin
  MessageBox(0, pcErrorMessage, 'Error', MB_OK);
  Halt(0);
end;

Now for the function to handle Windows messages - the WinProc. In C/ Cpp the WinProc has to be the first procedure (but has to be below the WinMain, but that's a C/ Cpp problem ;).

// WinProc to handle Windows messages. //
function WindowProc(hEventWindow : hwnd; msg : DWORD; wParam : WPARAM;
		    lParam : LPARAM) : LRESULT; export;
begin
  case (msg) of

   WM_ACTIVATE : begin
		  active := true;
		end;

   WM_DESTROY : begin
		  active := false;
		  PostQuitMessage(0);
		  Exit;
		end;

   WM_KEYDOWN : begin
		  active := false;
		end;

  else
    WindowProc := DefWindowProc(hEventWindow, msg, wParam, lParam);
  end;
end;

All right. We are checking for 3 events: WM_ACTIVATE, WM_DESTROY and WM_KEYDOWN. WM_ACTIVATE is sent if our window is opened. In this case we set the active variable to true. If WM_DESTROY is sent, we'll terminate the program. The same happens if the user presses a key.

Next, we need a Windows Class.

// Register the Window Class //
procedure RegisterWindow();
var
  WinClass: WndClassEx;

begin
  WinClass.cbSize		:= Sizeof(WndClassEx);
  WinClass.Style		:= cs_hRedraw OR cs_vRedraw;
  WinClass.lpfnWndProc		:= WndProc(@WindowProc);
  WinClass.cbClsExtra		:= 0;
  WinClass.cbWndExtra		:= 0;
  WinClass.hInstance		:= system.MainInstance;
  WinClass.hIcon		:= LoadIcon(0, idi_Application);
  WinClass.hCursor		:= LoadCursor(0, idc_Arrow);
  WinClass.hbrBackground	:= GetStockObject(LTGRAY_BRUSH);
  WinClass.lpszMenuName		:= nil;
  WinClass.lpszClassName	:= 'WindowClass';
  WinClass.hIconSm		:= LoadIcon(0, IDI_APPLICATION);

  if RegisterClassEx(WinClass) = 0 then ThrowError('Registering the Windows Class failed!');
end;

Note that we don't use WndClass, but WndClassEx. The "Ex" is for extended and was introduced with Windows 98. Windows 95 and NT4 do not know the Ex structure, but on the other hand: it does not hurt either as older versions of Windows just use the normal Window Class structure instead. And it's the modern version, so we'll use it from now on.

Note that we are checking if the Window Class has been correctly registered. If not we throw an error.

Now we'll create the Window.

// Create the window. Throw error if this fails. //
procedure CreateWindow();
begin

 hWindow := CreateWindowEx(
               WS_EX_TOPMOST, 
	       'WindowClass', 
	       AppName, 
	       WS_CAPTION OR WS_POPUPWINDOW OR WS_VISIBLE,
	       0, 0, 
	       640, 480, 
	       0, 0,
               system.MainInstance, 
	       NIL);

  if hWindow <> 0 then begin
    ShowWindow(hWindow, CmdShow);
    ShowWindow(hWindow, SW_SHOW);
    UpdateWindow(hWindow);
  end else ThrowError('Window could not be created');
end;

We'll use CreateWindowEx because we also used the extended Window Class. We also check if our window has been created properly. If the Window could not be created we'll throw an error message.

// Destroy the window. //
procedure KillWindow();
begin
    DestroyWindow(hWindow);
end;

Here the window is killed and the window handle is freed again. This should be done for a really clean escape. Now for the main loop.

// Main. //
begin

active := false;

 RegisterWindow();
 CreateWindow();

// Main loop. //
repeat

if PeekMessage(@msg,0,0,0,0) = TRUE then begin // if message waiting then get it
  GetMessage(@msg,0,0,0);
  TranslateMessage(msg);
  DispatchMessage(msg);
end;

// -------- enter main loop code here -------- //

until active = false;

 KillWindow();

end.

First, we set active to false. Why? Because if the window is created properly, active will become true anyway. If it is not created, the program will terminate itself automatically.

Now we call our procedures to create the Window Class and the window. Then we start the actual main loop. In this case it is a Repeat/ Until loop.

As of right now we only to the message handling here, but in a real application we would do all our main loop work here. As we will see most of the code is done in the WinProc actually, depending on the type of application. In our little program we only wait if there is a quit or keypressed message so we can leave the Repeat/ Until loop and therefore terminate our program.

Yaaaaay! We did it! We opened a Window! You can get the Source Code here. Download it, play around and then let's start off with the real coding ;)

Delax/ Sundancer Inc.
[delax@sundancerinc.de]

Back to previous page

Useful Links









Link to us