{ Example of creating dialog boxes.
  This example show how to create dialog boxes, using resources.
  Resources are "compiled" from a text resource descriptor file.
  The resources text file is  tEx022.rc
  The "compiled" resources file is  tEx022.res
  It was "compiled" with the  rc.exe  resource compiler from Microsoft.

  It shows the use of a modal dialog box, i.e. the program doesn't accept
  input while the dialog box is opened, but still can receive messages

  It shows the use of a modeless dialog box, i.e. the program continues
  normaly while the dialog box is opened.

  I find it quite complicate, and will simplify it in the library.

  In the next example, tEx023.pp, we will see how to create dialog boxes
  without resources.
  Later I will use this method to create dynamicaly a dialog box from
  a simple text file descriptor. I hope to have a first version of it
  at the beginning of february 2002.

  --------------------------------------------}
program tEx022;

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

{$R tEx022.res}

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

  constructor Init(strWinTitlePrm:ShortString);

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

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

  procedure WMCreateDlgModal; virtual;
  // Creates a Modal dialog box.
  // Modal means that the rest of the application will not be accessible
  // while the dialog box is opened.

  procedure WMCreateDlgModeless; virtual;
  // Creates a Modeless dialog box.
  // Modeless means that the rest of the application will be accessible
  // while the dialog box is opened.

  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
  glhModelessDlg : HWND;
  // handle on the modeless dialog box.
  // It is 0 if closed, <> 0 if open.

// 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

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 dialog box...');
AppendMenu(hSubmenu,MF_STRING,102,'&2nd dialog box...');
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...');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Help');
end;  // TMyWindow.MenuCreate

function DialogProc(hWindow:HWND; wMsg:UINT; wPar:WPARAM; lPar:LPARAM):BOOL;  stdcall; export;
//============================================================================================
// This is the function which receives all messages from window.
// some standard button :
// IDOK=1, IDCANCEL=2, IDABORT=3, IDRETRY=4, IDIGNORE=5, IDYES=6, IDNO=7,
var
  wNotiCode   : Word;
  hEdit1      : HWND; // handle of the first edit box control.
  hEdit2      : HWND; // handle of the second edit box control.
  hPar        : HWND; // handle of the parent
  strS        : string[12]; // set a low limit, to see that only 10 char are accepted

begin
hWindow:=hWindow; wPar:=wPar; lPar:=lPar;  // to remove Hints.

DialogProc:=True; // default return value

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

{if (wMsg = WM_COMMAND) then begin
   wNotiCode := HiWord(wPar);
   DBW0(64, DBNotifToStr(wNotiCode) + ITS(LoWord(wPar)));
   end;  }
wNotiCode:=wNotiCode;

case wMsg of
   WM_InitDialog : begin
      // Gets the handle on the first edit box control
      // 101 = the ID given to it in tEx022.rc (=> in tEx022.res)
      hEdit1:=GetDlgItem(hWindow, 101);

      // gives the focus to the first edit box, at the entrance of the dialog
      SetFocus(hEdit1);

      // must return false in this case.
      // In other cases, return True when the message was treated.
      DialogProc:=False;
      exit;
      end;

   WM_Close : begin
      // the dialog box has been closed, it has the same effect as a cancel
      // It tells to end the dialog Box
      // return  IDCANCEL (=2)  to tell that the CANCEL button
      // has been pressed or that the dialog has been closed.

      if (hWindow = glhModelessDlg) then DestroyWindow(hWindow)
      else                               EndDialog(hWindow, IDCANCEL);
      Exit;
      end; // WM_Close : begin

   WM_Command : begin
      if (wPar = 11) then begin
         // In the modal dialog box, send a message to its parent window
         hPar:=GetParent(hWindow);

         // sends a message to the parent window, with a pointer
         // to the content of the first edit box.
         hEdit1:=GetDlgItem(hWindow, 101);
         GetWindowText(hEdit1, @strS[1], SizeOf(strS)-2);
         strS[0]:=char(StrLen(@strS[1]));
         SendMessage(hPar, WM_User + 1000, 0, LPARAM(@strS));
         end;

      if (wPar = IDOK) or (wPar = 10) then begin
         // IDOK = 1 is the standard value for the ok button.
         // but this ID must have been given to the OK button
         // in the dialog box description defined in tEx022.rc
         // 10 is the "Validate" button ID of the modeless dialog box.

         // Gets the text of the edit box control.
         hEdit1:=GetDlgItem(hWindow, 101);
         GetWindowText(hEdit1, @strS[1], SizeOf(strS)-2);
         strS[0]:=char(StrLen(@strS[1]));
         DBW0(1024, 'Edit1 = ' + strS);

         // 102 = ID of secong edit box, defined in tEx022.rc (=> in tEx022.res)
         hEdit2:=GetDlgItem(hWindow, 102);
         GetWindowText(hEdit2, @strS[1], SizeOf(strS)-2);
         strS[0]:=char(StrLen(@strS[1]));
         DBW0(1024, 'Edit2 = ' + strS);

         // It tells to end the dialog Box
         // return  1  to tell that the OK button has been pressed.
         if (hWindow <> glhModelessDlg) then EndDialog(hWindow, IDOK);
         Exit;
         end;

      if (wPar = IDCANCEL) then begin
         // IDCANCEL = 2 is the standard value for the ok button.
         // but this ID must have been given to the CANCEL button
         // in the dialog box description defined in tEx022.rc

         // It tells to end the dialog Box
         // return  0  to tell that the CANCEL button has been pressed.
         if (hWindow = glhModelessDlg) then DestroyWindow(hWindow)
         else                               EndDialog(hWindow, IDCANCEL);
         Exit;
         end;
      end; // WM_Command : begin

   WM_Destroy : begin
          if (hWindow = glhModelessDlg) then begin
             glhModelessDlg:=0; // the dialog is closed.

             // Must be set to 0 because no more Modeless dialogs
             // are opened.
             // glhModelessDlg is defined in wApplication0.pp
             gglhDialogWin:=0;
             end;
          end;

   else DialogProc:=False;
   end; // case wMsg of

end;  // DialogProc

procedure TMyWindow.WinCreate(strWinClass:ShortString);
//=====================================================
// Creates a new window.
Begin
inherited WinCreate(strWinClass);
End;  // TMyWindow.WinCreate

procedure TMyWindow.WMCreateDlgModal;
//===================================
// Creates a Modal dialog box.
var
  nRet : integer;
begin
// 'Dialog_1' is the name given to the dialog box in the
// tEx022.rc  resources description file.
nRet:= DialogBox( System.MainInstance, 'Dialog_1', hWin,
                  DLGPROC(@DialogProc));

DBW0(1, 'Return value from Dialog =' + ITS(nRet));
end;  // TMyWindow.WMCreateDlgModal

procedure TMyWindow.WMCreateDlgModeless;
//======================================
// Creates a Modeless dialog box.
begin
if (glhModelessDlg <> 0) then begin
   MessageBeep(0);
   exit; // don't want to open it twice
   end;

// 'Dialog_' is the name given to the dialog box in the
// tEx022.rc  resources description file.
glhModelessDlg:=CreateDialog( System.MainInstance, 'Dialog_2', hWin,
                              DLGPROC(@DialogProc));

// To treat the keys input correctly of the modeless dialog box.
// The Tabs will work correctly.
// glhModelessDlg is defined in wApplication0.pp
gglhDialogWin:=glhModelessDlg;

// Show the window dialog box
ShowWindow(glhModelessDlg, SW_SHOWNORMAL);
end;  // TMyWindow.WMCreateDlgModeless

function TMyWindow.WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT;
//=============================================================
// Handles the menu messages
Var  wNrMenu     : word;
begin
WMCommand:=0;  // default return value

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

// for the menus,  lPar = 0
//=========================
wNrMenu   := LoWord(wPar);
Case wNrMenu Of
   100 : DBW0(0, '');  // just open the debugging window
   101 : WMCreateDlgModal;
   102 : WMCreateDlgModeless;

   200 : PostMessage( hWin,WM_Close,0,0);
   401 : MessageBox( hWin,'No Help, try simply the dialog boxes.',
                          'No Help',
                     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.
Type PShortString = ^ShortString;
var
  pstrS : PShortString;

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_User + 1000: begin
      // message from the modale dialog box
      pstrS:=PShortString(lPar);
      DBW0(64, 'from Dlg = ' + pstrS^);
      end;

   WM_Command     : WindowProc:=WMCommand(wPar, lPar);

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

// the dialog box is not open.
glhModelessDlg:=0;

// 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('tEx022. Creating dialog boxes using external ''.res'' resources.'));

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

