|

Win32/ FPC - Chapter 3 - by Delax
Now we will take a closer look at a typical Windows application. First on the list: Windows Classes.
Every Window, Dialog Box, Message Box or Fullscreen Window has a Windows Class. This class defines the look and the behavior of a window. Of course there are standard classes for nearly every purpose, but in reality you want to use your own Window Class for your application.
I won't cover Window Classes en detail as it would take about 5 chapters and many lists of parameters to cover every aspect. Instead, I will only talk about the basics here and we'll go deeper into this matter as the tutorial is proceeding.
The last time we had a look at a simple "Hello World" application. FPC has it's own "Hello World" application. But the FPC Version is a little more complicated. Let's have a look.
{
$Id: winhello.pp,v 1.4 2002/09/07 15:06:35 peter Exp $
Copyright (c) 1996 by Charlie Calvert
Modifications by Florian Klaempfl
Standard Windows API application written in Object Pascal.
No VCL code included. This is all done on the Windows API
level.
}
{$APPTYPE GUI}
{$MODE DELPHI}
program WinHello;
uses
Strings, Windows;
const
AppName = 'WinHello';
function WindowProc(Window: HWnd; AMessage: UINT; WParam : WPARAM;
LParam: LPARAM): LRESULT; stdcall; export;
var
dc : hdc;
ps : paintstruct;
r : rect;
begin
WindowProc := 0;
case AMessage of
wm_paint:
begin
dc:=BeginPaint(Window,@ps);
GetClientRect(Window,@r);
DrawText(dc,'Hello world by Free Pascal',-1,@r,
DT_SINGLELINE or DT_CENTER or DT_VCENTER);
EndPaint(Window,ps);
Exit;
end;
wm_Destroy:
begin
PostQuitMessage(0);
Exit;
end;
end;
WindowProc := DefWindowProc(Window, AMessage, WParam, LParam);
end;
{ Register the Window Class }
function WinRegister: Boolean;
var
WindowClass: WndClass;
begin
WindowClass.Style := cs_hRedraw or cs_vRedraw;
WindowClass.lpfnWndProc := WndProc(@WindowProc);
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := system.MainInstance;
WindowClass.hIcon := LoadIcon(0, idi_Application);
WindowClass.hCursor := LoadCursor(0, idc_Arrow);
WindowClass.hbrBackground := GetStockObject(WHITE_BRUSH);
WindowClass.lpszMenuName := nil;
WindowClass.lpszClassName := AppName;
Result := RegisterClass(WindowClass) >< 0;
end;
{ Create the Window Class }
function WinCreate: HWnd;
var
hWindow: HWnd;
begin
hWindow := CreateWindow(AppName, 'Hello world program',
ws_OverlappedWindow, cw_UseDefault, cw_UseDefault,
cw_UseDefault, cw_UseDefault, 0, 0, system.MainInstance, nil);
if hWindow >< 0 then begin
ShowWindow(hWindow, CmdShow);
ShowWindow(hWindow, SW_SHOW);
UpdateWindow(hWindow);
end;
Result := hWindow;
end;
var
AMessage: Msg;
hWindow: HWnd;
begin
if not WinRegister then begin
MessageBox(0, 'Register failed', nil, mb_Ok);
Exit;
end;
hWindow := WinCreate;
if longint(hWindow) = 0 then begin
MessageBox(0, 'WinCreate failed', nil, mb_Ok);
Exit;
end;
while GetMessage(@AMessage, 0, 0, 0) do begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
Halt(AMessage.wParam);
end.
{
$Log: winhello.pp,v $
Revision 1.4 2002/09/07 15:06:35 peter
* old logs removed and tabs fixed
Revision 1.3 2002/02/22 13:37:49 pierre
* fix problem if started through cygwin bash
}
Download the Source Code here.
OK. Take a deep breath and don't panic. Right now we are only interested in the part "Register the Windows Class".
{ Register the Window Class }
function WinRegister: Boolean;
var
WindowClass: WndClass;
begin
WindowClass.Style := cs_hRedraw or cs_vRedraw;
WindowClass.lpfnWndProc := WndProc(@WindowProc);
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := system.MainInstance;
WindowClass.hIcon := LoadIcon(0, idi_Application);
WindowClass.hCursor := LoadCursor(0, idc_Arrow);
WindowClass.hbrBackground := GetStockObject(WHITE_BRUSH);
WindowClass.lpszMenuName := nil;
WindowClass.lpszClassName := AppName;
Result := RegisterClass(WindowClass) >< 0;
end;
There you have a typical Windows Class stucture. A Windows Class is much like a structure or a record that has a couple of values that define the class itself. So we just store our values (= how we would like the class to be) in the fields of the structure and that's it! Let's have a look at the fields.
style: This field has a ton of possible parameters. If you want them all take a look at the SDK Reference. Here are the "most usual" ones: CS_REDRAW (redraws a Window if a user moved it); CS_VREDRAW / CS_HREDRAW (redraws a Window if the user changed it's size); CS_OWNDC (important - here we get an independant Device Context for our window. More on that later); CS_NOCLOSE (deactivates the "Close Window" icon); CS_DBLCLKS (sends a message if the user double clicks in our Window).
lpfnWndProc: This is a pointer to our WinProc. What a WinProc is? Remember what I said in chapter 2 about Windows being event driven and that our application would need to process the messages sent by the OS? Well, the WinProc is the part of your application that processes all Windows messages. You need to define the name of your message handling routine, that's all. Again: more on that when we get to Windows messages.
cbClsExtra and cbWndExtra: not important right now. Set to 0.
hInstance: complicated. Let's just say the hInstance is a handle for Windows to identify your application. Remember the things about the Scheduler giving every application a number and putting them into a list? Here you go.
hIcon: Yaaaay! Something familiar :). This is the icon of our application. We'll take the standard icon for now.
hCursor: The mouse cursor used in our Window. We'll take the standard cursor.
hbrBackground: This is the background color of our window. But it would be too easy just to enter some RGB values. The GDI (Graphical Device Interface) is a bit more complicated and so we have to enter a brush defined by the GDI interface. More on the GDI later.
lpszMenuName: This would be the name of the menu of our window - if we had one. We don't, so there is no need for a name.
lpszClassName: Now we need a name for our shiny new Window Class. Anything will do.
And that's it! Look at it again and try to understand it.
WindowClass.Style := cs_hRedraw or cs_vRedraw;
WindowClass.lpfnWndProc := WndProc(@WindowProc);
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := system.MainInstance;
WindowClass.hIcon := LoadIcon(0, idi_Application);
WindowClass.hCursor := LoadCursor(0, idc_Arrow);
WindowClass.hbrBackground := GetStockObject(WHITE_BRUSH);
WindowClass.lpszMenuName := nil;
WindowClass.lpszClassName := AppName;
Yeah, I know this is boring stuff, but it's important. No Windows application without these basics! So get yourself a Coke or whatever and try to understand what is happening here. Next chapter you will learn what you can do with your Window Class.
Delax/ Sundancer Inc.
[delax@sundancerinc.de]
Back to previous page
|