{ Example of program using the GAP library.
  This example shows how to draw text and pictures.
  Windows, as nearly any other Graphical User Interface, do not
  "remember" what was drawn or painted. Each time a window
  was hidden by another one, and comes in from again, the whole
  window must be repaint.

  What is called the Non Client area, i.e. the title on the top, the
  maximize, close etc. buttons, the frame around the window, the background
  of the window (white in general) are painted by windw.
  But the content of what is called the client area, typically where you
  enter a text, or do some drawings, is over your responsibility, or the
  responsibility of Controls.

  Text is never "written" but always "painted" (or "drawn", equivalent.)
  Thus when I say "paint", it includes text.

  If you want to paint directly on the client part of the window,
  there are two moment when it is done.
  First, if you draw directly something, you must draw it without delay.
  For this, you need to get a Device Context, usually with GetDC(hWin),
  then choose among :
  OBJ_BRUSH        Brush
  OBJ_PEN          Pen
  OBJ_FONT         Font
  OBJ_BITMAP       Bitmap
  OBJ_REGION       Region
  OBJ_EXTPEN       Extended pen
  OBJ_PAL          Palette
  and maybe other things like Metafiles.
  Then you can draw, then you have to close your device context.

  Secondly, if another window came over yours, and goes away,
  the system will send a WM_PAINT message wich tells your program it
  should paint again all your drawings.

  This means that the program must "remember" what has been painted directly
  in the client area, to be able to repaint it when receiving the
  WM_Paint message.
  It the program fails to "remember", the drawing will not reapear
  after another window went over the program's window.

  We will see the four things.
  1) Painting always a same text in the client window.
     (When receiving the WM_Paint message)
  2) Painting some figures done by a user and remembered.
     (When receiving the WM_Paint message)
  3) Drawing some figures, which will be memorised.
  4) Drawing free curves, which will not be memorised, and
     not redrawn when the WM_Paint message arrives.

  To see the evolution, various files will be written
  This one is the  tEx019_a.pp  example file.

  Let's begin ...
  --------------------------------------------}
program tEx019_a;

// To tell FreePascal that the application is a Graphical User Interface
// i.e. is running in windows, not in text mode.
{$APPTYPE GUI}

Uses
  Windows
// ,wGlobals2
 ,wApplication0
// ,wWindowBase0
 ,wWindow0
 ,wErrors0
 ,wDebug0;

type
  PMyWindow = ^TMyWindow;
  TMyWindow = object(TWindow0)
  //""""""""""""""""""""""""""

  constructor Init(strWinTitlePrm:ShortString);
  destructor Done; virtual;

  procedure MenuCreate; virtual;
  // Add a menu to the window

  procedure WMPaint; virtual;
  // the system want the program to repaint the client area.

  function WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT; virtual;
  // Handles the menu messages

  function WindowProc(hWindow:HWND; wMsg:UINT; wPar:WPARAM; lPar:LPARAM):LRESULT; virtual;
  end; // TMyWindow = object(TWindow)

// var nNotUsed : integer; // only to avoid an error message while compliling in DevPascal 1.9

constructor TMyWindow.Init(strWinTitlePrm:ShortString);
//=====================================================
begin
inherited Init(strWinTitlePrm);

end;  // TMyWindow.Init

destructor TMyWindow.Done;
//========================
begin
inherited Done;
end;  // TMyWindow.Done

procedure TMyWindow.MenuCreate;
//=============================
var
  hSubMenu    : HMENU;
begin
hMenuWin := CreateMenu;

hSubMenu := CreateMenu;
AppendMenu(hSubmenu,MF_STRING,100,'&Open debug window');
AppendMenu(hSubmenu,MF_SEPARATOR,0,Nil);
AppendMenu(hSubMenu,MF_String, 200, 'E&xit');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&File');

hSubMenu := CreateMenu;
AppendMenu(hSubmenu,MF_STRING, 401, 'Info &1...');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Help');
end;  // TMyWindow.MenuCreate

procedure TMyWindow.WMPaint;
//==========================
Var
  rRec        : rect;
  hDcPaint    : hdc;
  rPS         : paintstruct;
  strS        : string[100]; // to store the text to be drawn.
  nXPosPix,    // where should the text appear. in pixels
  nYPosPix
              : integer;
begin
// Get a device context.
// Here we have a facility, during the WMPaint, we must always
// begin with  "BeginPaint", which gives a Device Context to paint, and
// end with "EndPaint", to tell that the painting is done.
hDcPaint:=BeginPaint(hWin, @rPS);

// what is the size in pixels of the client area ?
// rRec.Left and rRec.Top will alway be zero with the GetClientRect function
GetClientRect(hWin, @rRec);

// Why not drawing the dimentions of the client rect.
// rRec.Left = rRec.Top = 0 always here.
strS:='The client dimensions are :  Width =' + IntToStr(rRec.Right,4) +
      '   Height =' + IntToStr(rRec.Bottom,4);

// For windows, must convert the pascal type string into a zero terminated string
strS[length(strS)+1]:=#0;

// 20 pixels from the left border. This will not be taken into account,
// since we ask the text to be centered. (With DT_CENTER)
nXPosPix:=10; // pixels from the left border.
nYPosPix:=10; // pixels from the upper border

// If we draw the text now, it would work, but not look very nice.
// We don't want to have a background color of the text.
SetTextColor(hDcPaint, RGB(  0,  0,  0)); // Black is the text color.
SetBkColor(hDcPaint, RGB(255,255,192)); // Yellow is the back color, if OPAQUE
SetBkMode(hDcPaint, TRANSPARENT); // OPAQUE would be the alternative.

// Now we paint the text.
TextOut(hDcPaint, nXPosPix, nYPosPix, @strS[1], length(strS));

// Another way to paint text is the following one :
// It draws (=paints) text, formated in the rectangle described by rRec.
// DrawText( hDcPaint, @strS[1],-1,@rRec, DT_SINGLELINE or DT_CENTER or DT_VCENTER);


EndPaint(hWin, rPS);
end;  // TMyWindow.WMPaint

function TMyWindow.WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT;
//=============================================================
// Handles the menu messages
Var
//  wNoticode,  // notification code, from a child window.
  wNrMenu     : word;

begin
WMCommand:=0; // default return value
// wNotiCode := HiWord(wPar);

{DBW0(64, DBNotifToStr(wNotiCode) + ITS(LoWord(wPar))); }

if (lPar <> 0) then begin
   // call the parent WMCommand method.
   WMCommand:=inherited WMCommand(wPar, lPar);
   exit;
   end;

// for the menus,  lPar = 0
//=========================
wNrMenu   := LoWord(wPar);
Case wNrMenu Of
   // these calls to DBW0 can be done from anywhere
   100 : DBW0(0, '');  // just open the debugging window

   200 : PostMessage( hWin,WM_Close,0,0);
   401 : MessageBox( hWin,
       'Nothing to say yet.',
       'No help for the moment',
                     MB_OK Or MB_IconInformation);
   else WMCommand:=inherited WMCommand(wPar, lPar);
   end;  // Case NrMenu Of
end;  // TMyWindow.WMCommand

function TMyWindow.WindowProc(hWindow:HWND; wMsg:UINT; wPar:WPARAM; lPar:LPARAM):LRESULT;
//=======================================================================================
// All window messages are send here.
Begin
WindowProc := 0; // Default return value when processing a message

{ if (wMsg <> WM_MouseMove)   and (wMsg <> WM_NCMouseMove) and
   (wMsg <> WM_MENUSELECT )   and (wMsg <> WM_ENTERIDLE ) and
   (wMsg <> WM_SetCursor)   and (wMsg <> WM_NCHittest) and
   (wMsg <> WM_SetFocus) and (wMsg <> WM_KillFocus) and
   (wMsg <> WM_KEYDOWN) and (wMsg <> WM_KEYUP) and
   (wMsg <> WM_Move)        and (wMsg <> WM_NCActivate) then
   DBW0(32, DBMsgToStr(wMsg) + ITS(wPar) + ITS(lPar)); }

Case wMsg Of
   WM_Paint   : WMPaint; // must redraw the client area part.
   WM_Command : WindowProc:=WMCommand(wPar, lPar);
//   WM_Size : begin      end;
   else begin // Case wMsg Of
      // Default processing of the messages.
      WindowProc:=inherited WindowProc(hWindow, wMsg, wPar, lPar);
      end; // Case wMsg Of
   End; // Case wMsg Of

End;  // TMyWindow.WindowProc

var
  oApp        : TApplication0;
  poMyMainWin : PMyWindow;

Begin // MAIN ******
// Name under which the main window is registered. Spaces are not allowed
oApp.Init('Example019_a');

// Change the color of the background of the main window.
// to have the desktop color
// oApp.WindowClass.hbrBackground :=COLOR_BACKGROUND+1;

// Creation of the main window
new(poMyMainWin, Init('Title of the Example019 A (Ex019_a.pp) Window'));

// The App.WindowClass can be modified here, if wanted. (Not usual)
oApp.Run;
oApp.Done;  // The main window object is disposed here.
End.

