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 Programmierung mit FPC - Teil 4 - by Delax

Hallo mal wieder! Ich hoffe ihr seid im letzten Teil nicht zu sehr entmutigt worden. Diese Art von Strukturen gehören eben zu Windows dazu. um ehrlich zu sein besteht fast jede Art von Information aus einer Art Struktur. Man muß sie dann nur noch anwenden.

Wir hatten uns das letzte Mal die Definition einer Fensterklasse angesehen. Gut und schön, aber wir müssen Windows auch mitteilen das wir diese unsere Fensterklasse auch wirklich nutzen wollen. Also müssen wir die Klasse registrieren, damit Windows überhaupt etwas damit anfangen kann. Das ist einfacher, als es sich anhört und ist mit einer Zeile schon getan:

  Result := RegisterClass(WindowClass) <> 0;

Das RegisterClass(WindowClass) macht die Hauptarbeit und registriert unsere Fensterklasse. Wir prüfen aber in Result, ob auch wirklich alles glatt gegangen ist. Falls die Klasse nicht registriert werden konnte, wissen wir das ein Fehler aufgetreten ist und können das Programm anhalten.

Nun gut, jetzt haben wir eine registrierte Klasse. Die ist aber nichts wert ohne ein Fenster, welches mit dieser Klasse geöffnet wird. Schauen wir uns noch einmal das "Hello World" an.

{
  $Id: winhello.pp,v 1.1 1998/12/20 22:23:54 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, WParam,
                    LParam: Longint): Longint; 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);
    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.1  1998/12/20 22:23:54  peter
    * new name

}

Hier als Datei zum download

Wieder ist nur ein bestimmter Teil interessant - jener mit der Überschrift "Create the Window Class". Das ist der Standard um ein Fenster (oder fensterähnliche Objekte) zu öffnen. Gehen wir wieder Schritt für Schritt vor. Als erstes jedoch mal ein Muster einer CreateWindow Funktion.

CreateWindow(
	LPCTSTR		lpClassName,
	LPCTSTR		lpWindowName,
	DWORD		dwStyle,
	int		x,
	int		y,
	int		nWidth,
	int		nHeight,
	HWND		hWndParent,
	HMENU		hMenu,
	HINSTANCE		hInstance,
	LPVOID		lpParam);

Ich bin nicht so ganz sicher, ob das so 100% stimmt, aber es stimmt genug, um nicht ganz falsch zu liegen. Zur Not wie immer der Verweis auf die Win32 API Hilfe.

lpClassName: Das ist der Name eurer Fensterklasse. Wenn ihr euch erinnert haben wir deren Name mit der Konstanten "AppName" angegeben.

lpWindowName: Hier kommt der Titel eures Fensters hinein. Also "Mein erstes Windows Fenster" oder so.

dwStyle: Wichtig. Dies beschreibt wie sich das Fenster verhält. Ihr könnt unheimlich viele Einstellungen vornehmen wie "Fenster zu Anfang geschlossen", "Fenster als Pop Up", "Fenster mit Scrollbalken" und so weiter. Hier kommt wieder die Win32 API Hilfe ins Spiel. Ich werde aber in späteren Kursen immer mal wieder unterschiedliche Werte hier nutzen.

x/ y: Die beiden Werte sind einfach nur die X und Y Position eures Fensters ausgehend von der linken oberen Ecke des Desktops. Wenn es euch egal ist nutzt CW_USEDEFAULT und Windows wird eurem Fenster einen Platz zuweisen.

nWidth/ nHeight: Das ist die Höhe und Breite eures Fensters in Pixeln. CW_USEDEFAULT ist wieder die Alternative. Wichtig: Die Höhe und Breite eures Fensters ist inklusive der Rahmen-, Menu- und Titelleisten. Das bedeutet das ein 640x480 Fenster mit Titelleiste kein 640x480 großen Fensterinhalt hat!

hWndParent: Das ist ein Handle zu einem übergeordneten Fenster (falls es denn eines gibt). Die meißten Programme haben den Desktop als übergeordnetes Fenster, aber wenn ihr innerhalb eurer Applikation noch Fenster öffnen wollt ist eure Applikation das übergeordnete Fenster. Unnötig zu sagen, das wenn das Parent Fenster geschlossen wird auch alle Childs mitgeschlossen werden.

hMenu: Hier könnt ihr eine Menüleiste zu eurem Fenster hinzufügen. Im Grunde hat jede Applikation irgendeine Form von Menu. Bis wir dahin kommen belassen wir es fürs erste bei NULL.

hInstance: Wichtig. Dies ist das Handle zu unserem Programm. Erinnert ihr euch noch an den ersten Teil und wie Windows arbeitet? Dies ist das Handle eures Programmes, welches ihr in der WinMain definiert. Dieses Handle identifiziert eure Applikation für Windows.

lpParam: Im Moment nicht wichtig. NULL

So. Wenn das Fenster nicht erstellt werden konnte nach diesem Versuch wird Windows NULL zurückliefern. Somit können wir die ganze Sache in eine IF-Prüfung packen und gleich Alarm geben wenn etwas schief gegangen ist. Im ganzen wird dann folgendes daraus:

  if longint(hWindow) = 0 then begin
    MessageBox(0, 'WinCreate failed', nil, mb_Ok);
    Exit;
  end;

Ihr könnt wieder aufatmen. Ihr wisst jetzt wie man Fenster initialisiert. Zumindest theoretisch. Praktisch fehlt noch ein bischen um das ganze zu einem fertigen Programm zusammen zu fügen. Aber das kommt das nächste Mal. Freut euch schon jetzt auf Event Handling - der wahre Genuß!

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

Back to previous page

Useful Links









Link to us