{ Example of program using the units
  wApplication0.pp  and  wWindow0.pp
  This example show how to create control window, like
  edit boxes, buttons, scroller, combo boxes, list boxes

  Normally they are used in a Dialog Box, but they can also be put
  in any normal window.

  Uses the object library to simplify using these controls.

  Here, only push buttons are presented.
  Their localisation in the main window is the same for all controls.

  Later we will show the use of Dialog Boxes.
  --------------------------------------------}
program tEx016;

// 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
 ,wApplication0
 ,wWindowBase0
 ,wWindow0
 ,wButtonPush0
 ,wDebug0;

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

  oButton1 : TButtonPush;
  // handle on a push button

  oButtonQuit : TButtonPush;
  // handle on a push button, will be used to quit the application.

  oButtonSize : TButtonPush;
  // handle on a push button, with a variable size.

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

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

  procedure WinCreate(strWinClass:ShortString); virtual;
  // When creating the window, controls will be added.

  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);

oButton1.Init(@Self);
oButtonQuit.Init(@Self);
oButtonSize.Init(@Self);
end;  // TMyWindow.Init

destructor TMyWindow.Done;
//========================
begin
{ Not necessary, done by the parent.
oButtonQuit.Done;
oButton1.Done;
oButtonSize.Done;
}
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_STRING,101,'&1 A debug msg');
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(hSubmenu,MF_STRING, 402, 'Info &2...');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Help');
end;  // TMyWindow.MenuCreate

procedure TMyWindow.WinCreate(strWinClass:ShortString);
//=====================================================
// Creates a new window.
// with controls in it.

Begin
inherited WinCreate(strWinClass);

// defines position, size, label, ID of the button
with oButton1 do begin
   // the default values could be left unchanged.
   vXPosRel   :=   0; // default value
   vYPosRel   :=   0; // default value
   vXPosMM    :=   3; // X position in milimeters in the parent window
   vYPosMM    :=   2; // Y position in milimeters in the parent window
   nXPosPix   :=   0; // default value
   nYPosPix   :=   0; // default value
   vXPosCh    :=   0; // default value, in character width units
   vYPosCh    :=   0; // default value, in character height units

   vXSizeRel  :=  0; // default value
   vYSizeRel  :=  0; // default value
   vXSizeMM   :=  0; // default value
   vYSizeMM   :=  0; // default value
   nXSizePix  :=  0; // default value
   nYSizePix  :=  0; // default value
   vXSizeCh   := 15; // in character width units
   vYSizeCh   :=  2; // in character height units

   // Minimum control sizes in pixels
   nXSizeMinPix := 5; // default value
   nYSizeMinPix := 5; // default value

   vXPosCtrlRef :=0; // Position relative to the Right  of the control. = default
   vYPosCtrlRef :=0; // Position relative to the Bottom of the control. = default

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=0; // Position relative to the Right  of the parent window. = default
   vYPosParentRef :=0; // Position relative to the Bottom of the parent window. = default

   strCtrlLabel  :='My &Button'; // Text on the button
   strCtrlHint   :='A first button'; // default value = no hints by default.
   wCtrlID:=111; // identifier of the control

   // defined in wWindowBase0.pp
   // Every window can have a name, not usefull for controls, thus
   // the next line is useless.
   strWindowName :='My first buttton0';

   // creates the button
   CtrlCreate;
   end; // with oButton1 do begin

// defines position, size, label, ID of the button
with oButtonQuit do begin
   // the default values are not shown again here.
   vXSizeCh   :=  10;  // 10 characters width
   vYSizeCh   :=   2; //   2 characters height, normal for buttons

   vXPosMM    :=  -2; // X position in milimeters in the parent window
   vYPosMM    :=  -2; // Y position in milimeters in the parent window

   vXPosCtrlRef :=1; // Position relative to the Right  of the control. 0=default
   vYPosCtrlRef :=1; // Position relative to the Bottom of the control. 0=default

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=1; // Position relative to the Right  of the parent window. 0=default
   vYPosParentRef :=1; // Position relative to the Bottom of the parent window. 0=default

   strCtrlLabel  :='Quit'; // Text on the button
   strCtrlHint   :='The button to quit'; // default value = no hints by default.
   wCtrlID:=1134; // identifier of the control, any number

   // defined in wWindowBase0.pp
   // Every window can have a name, not usefull for controls, thus
   // the next line is useless.
   strWindowName :='The Quit button';

   // creates the button
   CtrlCreate;
   end; // with oButtonQuit do begin

// defines position, size, label, ID of the button
with oButtonSize do begin
   // the default values are not shown again here.
   vXPosRel   := oButton1.vXPosRel;
   nXPosPix   := oButton1.nXPosPix;
   vXPosMM    := oButton1.vXPosMM;

   vYPosRel   := oButtonQuit.vYPosRel;
   nYPosPix   := oButtonQuit.nYPosPix;
   vYPosMM    := oButtonQuit.vYPosMM;

   vXSizeRel  := 1.0; // = X size of parent window
   vXSizeMM   :=-vXPosMM  + oButtonQuit.vXPosMM -1;
   vXSizeCh   := - oButtonQuit.vXSizeCh;

   vYSizeRel  := 1.0; // = Y size of parent window
   vYSizeMM   := vYPosMM  - oButton1.vYPosMM -1;
   vYSizeCh   := -oButton1.vYSizeCh;

   vXPosCtrlRef :=0.0; // Position relative to the Left  of the control. 0=default
   vYPosCtrlRef :=1.0; // Position relative to the Bottom of the control. 0=default

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=0.0; // Position relative to the Left  of the parent window. 0=default
   vYPosParentRef :=1.0; // Position relative to the Bottom of the parent window. 0=default

   strCtrlLabel  :='&Size'; // Text on the button
   strCtrlHint   :='A changing size button'; // default value = no hints by default.
   wCtrlID:=1135; // identifier of the control, any number

   // defined in wWindowBase0.pp
   // Every window can have a name, not usefull for controls, thus
   // the next line is useless.
   strWindowName :='The Size button';

   // creates the button
   CtrlCreate;
   end; // with oButtonSize do begin

// do this if you want the  TAB  to jump to the next child.
gglhDialogWin:=hWin;
End;  // TMyWindow.WinCreate

function TMyWindow.WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT;
//=============================================================
// Handles the menu messages
Var
  wNoticode,  // notification code, from a child window.
  wID,        // identification of the button
  wNrMenu     : word;
  wType       : word; // not used, type of the button, as defined in the library
  poBtn       : PButtonPush; // the push button pressed, if any

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

// Be carrefull !  BN_CLICKED = 0 !!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Thus there is no distinction between a button click and a menu selection !
if (wNotiCode = BN_CLICKED) then begin
   // For each menu selection, we enter here !!!!

   gglGetPointerObjectWinCtrl(lPar, wType, poBtn);
   // if we didn't click a button, poBtn = NIL
//   DBW0(128, 'poBtn=' + PTS(poBtn));

   if (wID = oButton1.wCtrlID) or (wID = oButtonQuit.wCtrlID) or
      (wID = oButtonSize.wCtrlID)then begin
      // a button has been clicked.
      DBW0(2, 'Button handle   = ' + ITS(lPar) + ' = ' + ITS(poBtn^.hWin));
      DBW0(2, 'Button ID       = ' + ITS(poBtn^.wCtrlID) + ' = ' + ITS(wID));
      DBW0(2, 'Button class    = ' + poBtn^.strClassName);
      DBW0(2, 'Button Win name = ' + poBtn^.strWindowName);
      DBW0(2, 'Button label    = ' + poBtn^.strCtrlLabel);
      DBW0(2, 'Button hint     = ' + poBtn^.strCtrlHint);

      if (poBtn^.hWin = oButtonQuit.hWin) then begin
         DBWaitSec(1); // wait one second, before quitting
         PostQuitMessage (0); // Tells the application to quit.
         end;

      exit; // a button has been pressed
      end;
   end; // if (wNotiCode = BN_CLICKED) then begin

if (lPar <> 0) then begin
   WMCommand:=inherited WMCommand(wPar, lPar);
   exit;
   end;

// for the menu, 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
   101 : DBW0(   1,'1 -> a debugging message');

   200 : PostMessage( hWin,WM_Close,0,0);
   401 : MessageBox( hWin,
       'See the movement of the ''Quit'' button while resizing the main window',
       'Resize the window',
                     MB_OK Or MB_IconInformation);
   402 : MessageBox( hWin,
       'See the size of the ''Size'' button while resizing the main window',
       'Resize the window',
                     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.
// var  rRec        : RECT;

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_Command     : WindowProc:=WMCommand(wPar, lPar);
//   WM_Size : not necessary, done automatically
   WM_MENUCHAR : begin // should be simplified in a futur library version.
      // alt a letter has been pressed, and this doesn't correspond to a menu
      if (char(LoWord(wPar)) = 'b') or (char(LoWord(wPar)) = 'B') then begin
         // as if the Button 1 has been clicked
         WMCommand(MakeLong( oButton1.wCtrlID, BN_CLICKED),
                             oButton1.hWin);
         end;
      if (char(LoWord(wPar)) = 's') or (char(LoWord(wPar)) = 'S') then begin
         // as if the Size button has been clicked
         WMCommand(MakeLong( oButtonSize.wCtrlID, BN_CLICKED),
                             oButtonSize.hWin);
         end;
      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('Example016');

// 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 Example016 (Ex016.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.

