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

  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 you will see :
  - Push buttons
  - Radio buttons
  - Check boxes
  - Static text
  - Edit text
  - Combo bosex

  See  "CreateWindow"  in Win32.hlp sdk help for many options
  which could change the style of control.
  oButton1.
  dwStyle := dwStyle or ... can add properties of the style
  dwExStyle cans be changed also, see  "CreateWindowEx"  of Win32.hlp

  We see also some other effects, like changing the background color,
  having hints.
  Hints colors and timing can be changed using the variable
  gglpoPrm defined in wParamApplic2.pp
  gglpoPrm^.nHintStart = starting time in 1/10 sec of displaying the hint
  gglpoPrm^.nHintStop = stopping time in 1/10 sec of displaying the hint
  gglpoPrm^.colHintText  =RGB(0,0,0);
  gglpoPrm^.colHintBack  =RGB(255,255,196);
  gglpoPrm^.nHintDXPos   = 2;  little positionning
  gglpoPrm^.nHintDYPos   =20;
  gglpoPrm^.nHintDWidth  = 6;
  gglpoPrm^.nHintDHeight = 4;
  gglpoPrm^.fHintDraw    = TRUE; // want to see the hints ?

  Later we will show the use of Dialog Boxes.

  Later we will see how to make it all very simple. Here there is still
  quite a lot of work to handle controls.

  Many procedures ( or methodes) are quit long. But they are linear,
  no loops, thus it is not difficult to read and understand them. (I think)
  --------------------------------------------}
program tEx017;

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

Uses
  wApplication0
 ,wWindow0
 ,wButtonPush0
 ,wButtonRadio0
 ,wButtonCheck0
 ,wStatic0
 ,wEditBox0
 ,wComboBox0
 ,wWindowBase0
 ,wErrors0
 ,wDebug0
 ,wGlobals2
 ,Windows;

const
  SEVEN = 7;
  THREE = 3;

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

  oButton1 : TButtonPush;
  // A push button

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

  oStatic1 : TStatic;
  // A static text

  aoRadioB : array[1..SEVEN] of TButtonRadio;
  // SEVEN radio buttons

  aoCheckB : array[1..THREE] of TButtonCheck;
  // THREE check boxes

  oEditBox1 : TEditBox;
  // to insert an edit box.
  // Here it will be a simple monoline edit box.

  oComboBox1 : TComboBox;
  // to insert a Drop Down combo box.

  oComboBox2 : TComboBox;
  // to insert a Drop Down List combo box.
  // The difference with the previous one, is that you cannot edit text.
  // You have a limited choice.

  poANewWindow : PMyWindow;
  // To create other windows.

   colBack : integer;
   // color of the background of the window.
   // just as a demo for this example.

  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);
//=====================================================
var nn : integer;
begin
inherited Init(strWinTitlePrm);

oButton1.Init(@Self);
oButtonQuit.Init(@Self);
oStatic1.Init(@Self);

for nn:=1 to SEVEN do aoRadioB[nn].Init(@Self);
for nn:=1 to THREE do aoCheckB[nn].Init(@Self);

poANewWindow :=NIL;

// color of the background of the window.
colBack :=-2;  // default (set in this program) = desktop color,

oEditBox1.Init(@Self);
oComboBox1.Init(@Self);
oComboBox2.Init(@Self);
end;  // TMyWindow.Init

destructor TMyWindow.Done;
//========================
begin
{ you don't need to dispose the children, it's done by their parent.
oComboBox2.Done;
oComboBox1.Done;
oEditBox1.Done;

if (poANewWindow <> NIL) then dispose(poANewWindow, Done);

// This will not be necessary in the next version of the library
for nn:=1 to THREE do aoCheckB[nn].Done;
for nn:=1 to SEVEN do aoRadioB[nn].Done;
oStatic1.Done;
oButtonQuit.Done;
oButton1.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,'&New 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(hSubmenu,MF_STRING, 402, 'Info &2...');
AppendMenu(hSubmenu,MF_STRING, 403, 'About the &Trans rado button...');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Help');
end;  // TMyWindow.MenuCreate

procedure TMyWindow.WinCreate(strWinClass:ShortString);
//=====================================================
// Creates a new window.
// with controls in it.
// All this will become simpler with dialog boxes and
// facilities to come.
var
  nn          : integer;

  poBtnPopup  : PButtonPush;
  // Here it must be a pointer, not an object directly.
  // I put it here only as an example, it could be defined at the same
  // place as the other controls.
  // Defining it here has the disadvantage that you have less easyer
  // control over it, since you must get the pointer on it from its
  // handle before you can use it.
  // If you don't have the handle, you can have it from the ID with
  // the Windows function : GetDlgItem(hWin, wID); --> handle of the control.

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

   // It is a good idea to give the sizes in char "Ch" units.
   // Sizes are usually given only in "Ch" (=characters) units.
   // vXSizeCh  = 15 means about 15 character long.
   // vYSizeCh =  2 means the height of two characters.
   // If you don't specify sizes, automatic choices will be made.
   // But if they are used bellow, wrong positionning can occur.
   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   :='This is 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

// Playing with this button.
// It will change the state of the first button : "oButton1"
new(poBtnPopup, Init(@Self));
with poBtnPopup^ do begin
   // the default values are not shown again here.
   vXSizeCh   :=  10;  // 10 characters width
   vYSizeCh   :=   2; //   2 characters height, normal for buttons

   vXPosCh    :=  oButton1.vXSizeCh;  // right from the first button
   vXPosMM    :=  oButton1.vXPosMM + 2;
   vYPosMM    :=  oButton1.vYPosMM;

   strCtrlLabel  :='Popup'; // Text on the button
   strCtrlHint   :='Change the "My Button" into a POPUP button';
   wCtrlID:=1141; // identifier of the control,
                  // it will be used in the WMCommand.

   // Creates the button in the window
   CtrlCreate;
   end; // with poBtnPopup do begin

// defines position, size, label, ID of the button
with oButtonQuit do begin
   // the default values are not shown again here.
   // If you don't specify sizes, automatic choices will be made.
   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   :='This is the ''quit'' button'; // 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 static text control.
with oStatic1 do begin
   // the default values are not shown again here.
   // If you don't specify sizes, automatic choices will be made.
   // But if they are used bellow, wrong positionning can occur.
   vXSizeCh   :=  15; // 15 characters width
   vYSizeCh   := 1.5; // 1.5 characters height

   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 :=0; // Position relative to the Top 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 :=0; // Position relative to the Top of the parent window. 0=default

   strCtrlLabel  :='Static text'; // Text on the button
   strCtrlHint   :='A simple text'; // default value = no hints by default.
   wCtrlID:=1201; // 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 :='First stattic control';

   // Center the text in the place reserved for it
   // See CreateWindow in Win32.hlp sdk help for mor options
//   dwStyle:=dwStyle or SS_SS_RIGHT;  // would place it to the right
   dwStyle:=dwStyle or SS_CENTER;

//   fUseDefaultWMPaint :=FALSE; default, to use the next properties.
   colTextFont        :=RGB(255,0,0);       // default = RGB(  0,  0,  0);
//   colTextBack        :=RGB(255,255,255); // default = RGB(255,255,255);
//   colTextTransp      :=TRANSPARENT;      // default = TRANSPARENT, other = OPAQUE;

   colWindowBack :=Cardinal(-1); // default value, which is invisible.
  // This is the background color of the window, which can be
  // larger than the text background.

   // creates the static text
   CtrlCreate;
   end; // with oStatic1 do begin

for nn:=1 to SEVEN do with aoRadioB[nn] do begin
   // the default values are not shown again here.
   // sizes are usually given only in "Ch" (=characters) units.
   vXSizeCh   :=  8; // = number of character  width
   vYSizeCh   :=  1; // = number of character height

   // Position relative to the button1
   vXPosMM    := oButton1.vXPosMM;
   vXPosCh    := (vXSizeCh + 1) * (nn-1); // + oButton1.vXPosCh;  useless since = 0
   vYPosMM    := oButton1.vYPosMM + 3;
   vYPosCh    := oButton1.vYSizeCh; // + oButton1.vYPosCh;  useless since = 0

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

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

//   strCtrlLabel  :='radio'; // Text on the button
   strCtrlHint   :='A radio button'; // default value = no hints by default.
   wCtrlID:=1300 + nn; // identifier of the control, any number
                       // Will be used in the WM_COMMAND

   // we want to change the default colors of the radio buttons.
   fUseDefaultColors :=FALSE;
   colTextFont:=RGB(  0,  0,  0);  // will be changed for the two first.
   colTextTransp :=OPAQUE;

   // this define the color of the control's background.
   // word32(-1) set it transparent.
   colWindowBack :=word32(-1);

   case nn of
      1 : begin
          strCtrlLabel:='black';
          colTextFont:=RGB(255,255,255);
          colTextBack:=RGB(  0,  0,  0);
          end;
      2 : begin
          strCtrlLabel:='Dgray';
          colTextFont:=RGB(255,255,255);
          colTextBack:=RGB( 64, 64, 64);
          end;
      3 : begin
          strCtrlLabel:='gray';
          colTextBack:=RGB(128,128,128);
          end;
      4 : begin
          strCtrlLabel:='Lgray';
          colTextBack:=RGB(192,192,192);
          end;
      5 : begin
          strCtrlLabel:='white';
          colTextBack:=RGB(255,255,255);
          end;
      6 : begin
          strCtrlLabel:='desk';
          colTextBack:=RGB(  0,128, 64);
          end;
      7 : begin
          strCtrlLabel:='trans';
          colTextBack:=RGB(  0,  0,  0);
          colTextTransp :=TRANSPARENT;
          end;
      end;

   // create the radio buttons
   CtrlCreate;
   end;  // for nn:=1 to SEVEN do with aoRadioB[nn] do begin

// To set the pressed rado button. Not very important.
SendMessage(aoRadioB[6].hWin, BM_SetCheck, 1, 0);

for nn:=1 to THREE do with aoCheckB[nn] do begin
   // the default values are not shown again here.
   // sizes are usually given only in "Ch" (=characters) units.
   vXSizeCh   :=  8;
   vYSizeCh   :=  1;

   // Position relative to the static text.
   vXPosMM    :=-3 -oStatic1.vXPosMM; //  -oStatic1.vXSizeMM; useless since = 0
   vXPosCh    :=-oStatic1.vXSizeCh  - (vXSizeCh+1) * (3 - nn);
   vYPosMM    := oStatic1.vYPosMM;
//   vYPosCh    := oStatic1.vYPosCh;  useless since = 0;

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

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

//   strCtrlLabel  :='check box'; // Text on the button
   strCtrlHint   :='a check box'; // default value = no hints by default.
   wCtrlID:=1400 + nn; // identifier of the control, any number
                       // Will be used in the WM_COMMAND

   // we want to change the default colors of the check boxes
   fUseDefaultColors :=FALSE;
   colTextFont:=RGB(  0,  0,  0);
   colTextTransp :=OPAQUE;

   // this define the color of the control's background.
   // word32(-1) set it transparent.
   // colWindowBack :=word32(-1); default value. Change 20 lines further.

   case nn of
      1 : begin
          strCtrlLabel:='red';
          colTextBack:=RGB(255,  0,  0);
          end;
      2 : begin
          strCtrlLabel:='green';
          colTextBack:=RGB(0,255,  0);
          end;
      3 : begin
          strCtrlLabel:='blue';
          colTextBack:=RGB(  0,  0,255);
          colTextFont:=RGB(255,255,255);
          end;
      end;

    // we want to complete control wo have the same color
    colWindowBack:=colTextBack;

   // create the check boxes
   CtrlCreate;
   end; // for nn:=1 to THREE do with aoCheckB[nn] do begin

// defines position, size, label, ID of the edit box
with oEditBox1 do begin
   // the default values are not shown again here.
   // sizes are usually given only in "Ch" (=characters) units.
   vXSizeCh   := 15;
   vYSizeCh   :=  1.5;

   vXPosMM    := oButton1.vXPosMM;
   vYPosMM    :=  20; // Y position in milimeters in the parent window

   vXPosCtrlRef :=0; // top
   vYPosCtrlRef :=0; // left

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=0; // top
   vYPosParentRef :=0; // left

   strCtrlLabel  :='Edit me'; // Text on the button
   strCtrlHint   :='To be edited'; // default value = no hints by default.
   wCtrlID:=1135; // identifier of the control, any number
                 // Could be used in the WM_COMMAND

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

   // creates the edit box
   CtrlCreate;
   end; // with oEditBox1 do begin

// defines position, size, label, ID of the combo Box
with oComboBox1 do begin
   // the default values are not shown again here.
   // sizes are usually given only in "Ch" (=characters) units.
   vXSizeCh   := 15;
   vYSizeCh   :=  8;  // can view  vYSizeCh - 2  lines

   vXPosMM    := oEditBox1.vXPosMM;
   vYPosMM    := oEditBox1.vYPosMM + 3;
   vYPosCh    := oEditBox1.vYPosCh + oEditBox1.vYSizeCh; // to be bellow the edit box

   vXPosCtrlRef :=0; // top
   vYPosCtrlRef :=0; // left

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=0; // top
   vYPosParentRef :=0; // left

   strCtrlLabel  :='to edit too'; // useless to define here
   strCtrlHint   :='Can be edited too'; // default value = no hints by default.
   wCtrlID:=1136; // identifier of the control, any number
                 // Could be used in the WM_COMMAND

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

   // creates the combo box
   CtrlCreate;

   // You cannot add a string before the combo box has been created.
   AddString('first line');
   AddString('second line');
   AddString('third line');
   AddString('fourth line');

   // which line should be shown first.
//   SetCurrentSelection(0); // if not, the  strCtrlLabel  appear.
   end; // with oComboBox1 do begin

// defines position, size, label, ID of the combo Box
with oComboBox2 do begin
   // the default values are not shown again here.
   // sizes are usually given only in "Ch" (=characters) units.
   vXSizeCh   := 15;
   vYSizeCh   :=  7;  // can view  vYSizeCh - 2  lines

   vXPosMM    := oComboBox1.vXPosMM;
   vYPosMM    := oComboBox1.vYPosMM + 3;
   vYPosCh    := oComboBox1.vYPosCh + 1.5; // to be bellow the combo box 1

   vXPosCtrlRef :=0; // top
   vYPosCtrlRef :=0; // left

   // Defines which point of the parent window is take as the origine
   vXPosParentRef :=0; // top
   vYPosParentRef :=0; // left

   strCtrlLabel  :='no meaning'; // useless to define here
   strCtrlHint   :='Cannot be edited'; // default value = no hints by default.
   wCtrlID:=1136; // identifier of the control, any number
                 // Could be used in the WM_COMMAND

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

   // Change the style to be a Drop Down List
   dwStyle   :=dwStyle or CBS_DROPDOWNLIST;

   // creates the combo box
   CtrlCreate;

   // You cannot add a string before the combo box has been created.
   AddString('Line 1');
   AddString('Line 2');
   AddString('Line 3');
   AddString('Line 4');
   AddString('Line 5');
   AddString('Line 6');
   AddString('Line 7');
   AddString('Line 8');
   AddString('Line 9');

   // which line should be shown first.
   SetCurrentSelection(0);  // if not done, no text appear in the combo
   end; // with oComboBox2 do begin

// If you want the tabs to work as expected between the controls.
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
  rRec        : RECT;
  strS        : ShortString;

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

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

// if message from the menu then lPar = 0.
if (lPar > 0) and (wNotiCode = BN_CLICKED) then begin
   // Be carrefull,  BN_CLICKED = 0 = the value of wNotiCode for menus

   // Get a pointer on the control who sended the notification.
   gglGetPointerObjectWinCtrl(lPar, wType, poBtn);
   if (poBtn = NIL) then ErrorComment(0, 'Error in WMCommand, poBtn = NIL !?!');
      // This error should never happend.

   if (lPar = oButtonQuit.hWin) then begin
      PostQuitMessage (0); // Tells the application to quit.
      end;

   if (lPar = oButton1.hWin) 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);

      // Changes the color of the text in some cases.
      if      (oStatic1.colTextFont = RGB(255,  0,  0)) then
               oStatic1.colTextFont:= RGB(  0,255,  0)
      else if (oStatic1.colTextFont = RGB(  0,255,  0)) then
               oStatic1.colTextFont:= RGB(  0,  0,255)
      else if (oStatic1.colTextFont = RGB(  0,  0,255)) then
               oStatic1.colTextFont:= RGB(255,  0,  0);

      // the simple way to redraw the control.
      oStatic1.Redraw;

     // the complicate way to redraw the control
//      GetClientRect(oStatic1.hWin, @rRec);
//      InvalidateRect(oStatic1.hWin, rRec, TRUE);
     end;

   if (wID = 1141) then begin
      // changes the state of the oButton1.
      if (poBtn^.strCtrlLabel = 'Popup') then begin
         // must destroy the associated window, before creating a new button window
         oButton1.WindowDestroy;
         oButton1.poParent:=NIL; // no parent => popup window
         oButton1.CtrlCreate;
         // Creates the button
         // It has no parents, thus its position is independent of any window
         // and is positionned on a fix palce on the screen.
         // Since it is a popup window button, it will not notify any parents
         // when you click on it.
         // If you want to treat the messages corresponding to this button,
         // you have to define a descendent of the TButtonPush class, and
         // use the  CtrlWindowProc  method to receive the messages.
         // It is seldom used, but for Hint texts, it is usefull.
         // And Hint texts don't want to treat any messages.
         // Just for hints, you need also to use a timer. As will be
         // demonstrated in example tEx018.pp

         // changes the label of the button
         poBtn^.strCtrlLabel  :='Child'; // Text on the button
         poBtn^.strCtrlHint   :='Change the "My Button" into a CHILD button';
         poBtn^.NotifyChanges; // to change the caption
         end
      else begin
         // must destroy the associated window, before creating a new button window
         oButton1.WindowDestroy;
         oButton1.poParent:=@Self;
         oButton1.CtrlCreate;
         // Creates the button, it is again a normal child button
         // since it has a parent.

         // changes the label of the button
         poBtn^.strCtrlLabel  :='Popup'; // Text on the button
         poBtn^.strCtrlHint   :='Change the "My Button" into a POPUP button';
         poBtn^.NotifyChanges; // to change the caption
         end;
      end;

   if (wID >= 1301) and (wID <= 1301 + SEVEN) then begin
      // A radio button has been pressed.
      // Changes the background color
      case wID of
         1301 : colBack:=BLACK_BRUSH;
         1302 : colBack:=DKGRAY_BRUSH;
         1303 : colBack:=GRAY_BRUSH;
         1304 : colBack:=LTGRAY_BRUSH;
         1305 : colBack:=WHITE_BRUSH;
         1306 : colBack:=-2; // default.
         1307 : colBack:=-1; // transparent.
         end; // case

      // ask to redraw the background.
      GetClientRect(hWin, @rRec);
      invalidateRect(hWin, rRec, TRUE);
      end;

   if (wID >= 1401) and (wID <= 1401 + THREE) then begin
      // change the color of the text

      oStatic1.colTextFont:=RGB(  0,  0,  0); // default = Black

      if (aoCheckB[1].GetCheckState = 1) then
         oStatic1.colTextFont:=oStatic1.colTextFont or RGB(255,  0,  0);
      if (aoCheckB[2].GetCheckState = 1) then
         oStatic1.colTextFont:=oStatic1.colTextFont or RGB(  0,255,  0);
      if (aoCheckB[3].GetCheckState = 1) then
         oStatic1.colTextFont:=oStatic1.colTextFont or RGB(  0,  0,255);

      oStatic1.Redraw;
      end;

   // call the parent WMCommand method, does nothing... maybe later.
   WMCommand:=inherited WMCommand(wPar, lPar);

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

if (lPar > 0) and (wNotiCode = CBN_CLOSEUP) then begin
    // If a text has been selected in a combo box, get it.
    strS:='Not from a combo'; // this should be replaced bellow.
    if (lPar = oComboBox1.hWin) then strS:=oComboBox1.GetCurrentText;
    if (lPar = oComboBox2.hWin) then strS:=oComboBox2.GetCurrentText;
    DBW0(1, 'combo = ' + strS);
    end;

if (lPar <> 0) then begin
   // call the parent WMCommand method, does nothing... maybe later.
   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
   101 : begin
         // Creates a new window.
         new(poANewWindow, Init('A new window'));
         poANewWindow^.WinCreate('');

         // move it
         MoveWindow( poANewWindow^.hWin,
                     nLeft + 50,
                     nTop  + 50,
                     nWidth, nHeight, TRUE);
         end;

   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 text color changes when you press the button 1.',
       'Color of the text',
                     MB_OK Or MB_IconInformation);
   403 : MessageBox( hWin,
       'When you click the ''Transp'' radio button, the background is not repainted, and the Hints stay visible. It''s NORMAL !',
//       'It seems that nothing chages when you click on the ''Transp'' radio button. But resize the window, you will see.',
       'Radio button ''Transp'' signification',
                     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;
  hDevC       : HDC;
  hBr         : HBRUSH;  // needed to paint

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_ERASEBKGND : begin
      if (colBack = -2) then begin
         WindowProc:=inherited WindowProc(hWindow, wMsg, wPar, lPar);
         exit;
         end;

      if (colBack = -1) then begin
         // If you do not call the inherited proc. then the color will be transparent.
//         WindowProc:=inherited WindowProc(hWindow, wMsg, wPar, lPar);
         exit;
         end;

      // change the color of the window background
      // It is quite complicate for a simple task !
      hDevC:=HDC(wPar);  // the handle on the device context is given.
      GetClientRect(hWindow, @rRec);

      // you must get a brush to paint.
      // you could also create a brush with CreateSolidBrush
      hBr:=GetStockObject(colBack);

      FillRect(hDevC, rRec, hBr);

      WindowProc:=1; // <> 0 should be returned if backgroud erased.
      end; // WM_ERASEBKGND
   WM_Command     : WindowProc:=WMCommand(wPar, lPar);
//   WM_Size : Automatic notifications to their childrens

   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('Example017');

// 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 Example017 (Ex017.pp) Window'));

// to avoid the note 'poMyMainWin not used', It doesn't change the final code
// poMyMainWin:=poMyMainWin;

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

