{  Example of program using the units
   wApplication0.pp  and  wWindow0.pp
   wRichText0.pp
   This example is very similar to the (tEx008.pp)

   It is mostly the wRichText0.pp unit which has been modified, to
   have more capabilities.

   It uses the  Riched32.dll  file, which should be in your
   windows\system directory.
   This example show how to create a basic text editor
   using the richedit control
  ----------------------------------------------------------------}
program tEx011;

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

type
  PMyWindow = ^TMyWindow;
  TMyWindow = object(TWindow)
  //"""""""""""""""""""""""""
  // Usually it is better to have a pointer on objects than objects,
  // since pointer can also designate descendent of the objects.
  // More, pointer can be nil, indicating that is has not been initialised.
  oRichEdit   : TRichText;   // RichEdit control contained in the window
  oStatusL    : TStatusLine; // Status line of the main window

  // Can we write text, or only read it ?
  fReadOnly : boolean;

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

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

  // Set  strWinClass=''  to use the class defined in the application object
  procedure WinCreate(strWinClass:ShortString); virtual;

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

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

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

// Initialise the object oStatusL and oEditB
oStatusL.Init(@Self);
oRichEdit.Init(@Self);

// Can we write text, or only read it ?  We can wirte by default.
fReadOnly :=FALSE;
end;  // TMyWindow.Init

destructor TMyWindow.Done;
//========================
begin
oStatusL.Done;
oRichEdit.Done;

inherited Done;
end;  // TMyWindow.Init

procedure TMyWindow.MenuCreate;
//=============================
var
  hSubMenu    : HMenu;

begin
hMenuWin := CreateMenu;
hSubMenu := CreateMenu;
AppendMenu(hSubmenu,MF_STRING,101,'&New...');
AppendMenu(hSubmenu,MF_STRING,102,'&Open...');
AppendMenu(hSubmenu,MF_STRING,103,'&Save');
AppendMenu(hSubmenu,MF_STRING,104,'Save &as...');
AppendMenu(hSubmenu,MF_SEPARATOR,0,Nil);
AppendMenu(hSubMenu,MF_String,198,'Open &Debug window');
AppendMenu(hSubmenu,MF_SEPARATOR,0,Nil);
AppendMenu(hSubMenu,MF_String,199,'E&xit');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&File');

hSubMenu := CreateMenu;
// The shortcuts are defined in the system, nothing has to be done.
AppendMenu(hSubMenu,MF_String,201,'&Undo'#8'Ctrl+Z');
AppendMenu(hSubmenu,MF_SEPARATOR,0,Nil);
AppendMenu(hSubMenu,MF_String,202,'&Cut'#8'Ctrl+X');
AppendMenu(hSubMenu,MF_String,203,'&Copy'#8'Ctrl+C');
AppendMenu(hSubMenu,MF_STRING,204,'&Paste'#8'Ctrl+V');
AppendMenu(hSubmenu,MF_SEPARATOR,0,Nil);
AppendMenu(hSubMenu,MF_STRING,205,'Select &All'#8'Ctrl+A');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Edit');

hSubMenu := CreateMenu;
AppendMenu(hSubMenu,MF_String,301,'&Font...');
AppendMenu(hSubMenu,MF_String,302,'Toggle &Read Only');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Options');

hSubMenu := CreateMenu;
AppendMenu(hSubMenu,MF_String,30000,'&30000 = Menu Nr');
AppendMenu(hSubMenu,MF_String,40000,'&40000 = Menu Nr');
AppendMenu(hSubMenu,MF_String,50000,'&50000 = Menu Nr');
AppendMenu(hSubMenu,MF_String,60000,'&60000 = Menu Nr');
AppendMenu(hSubMenu,MF_String,65000,'&65000 = Menu Nr');
AppendMenu(hSubMenu,MF_String,401,'&Info...');
AppendMenu(hMenuWin, MF_POPUP, hSubMenu, '&Help');

end;  // TMyWindow.MenuCreate

procedure TMyWindow.WinCreate(strWinClass:ShortString);
//=====================================================
// Create the window, and insert an edit box and a status line in it.
begin
// here strWinClass=''.
inherited WinCreate(strWinClass);

// Add a status line at the bottom
oStatusL.StatusCreate;
oRichEdit.poStatusLine:=@oStatusL;

// Size = the whole client areat
oRichEdit.vXSizeRel:=1;  // if you don't specify, it is set automatically
oRichEdit.vYSizeRel:=1;  // but for clarity, it is better to specify.
oRichEdit.CtrlCreate;

SetFocus(oRichEdit.hWin);
end;  // TMyWindow.WinCreate

function TMyWindow.WMCommand(wPar:WPARAM; lPar:LPARAM):LRESULT;
//=============================================================
// Handles the menu messages
Var
  wNrMenu,    // selected menu item
  wCheck      // to set a check mark in a menu.
              : word;
begin
WMCommand := 0; // Default return value when processing a message

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

// for the menu, lPar = 0
wNrMenu   := LoWord(wPar);
case wNrMenu of
   101 : oRichEdit.NewText;
   102 : oRichEdit.LoadRICH;
   103 : oRichEdit.SaveRICH;
   104 : oRichEdit.SaveRICHas;
   198 : DBW0(0, ''); // opens the debugging window.
   199 : PostMessage(hWin, WM_Close,0,0);

   // this treatment will become standard in the library in a next version.
   // menu number over 30000 are reserved for the library.
   201 : oRichEdit.UndoText;
   202 : oRichEdit.CutText;
   203 : oRichEdit.CopyText;
   204 : oRichEdit.PasteText;
   205 : oRichEdit.SelectAllText;
   301 : oRichEdit.SelectFont;

   302 : begin // toggle the read only flag.
      fReadOnly:=not fReadOnly;

      // tell the control to set or reset its readonly mode.
      SendMessage(oRichEdit.hWin, EM_SETREADONLY, WPARAM(fReadOnly), 0);

      // Get the handle on the menu
//      hMenuWin:=GetMenu(hWindow);  already done

      // change the menu check mark
      if fReadOnly then wCheck:=MF_CHECKED
      else              wCheck:=MF_UNCHECKED;
      CheckMenuItem(hMenuWin, wNrMenu, MF_BYCOMMAND or wCheck);
      end;

   401 : MessageBox( hWin, 'Test menu Nr. reserved for the library. Above 30000.',
                    'Menu Nr. above 30000 are reserved for the library.',
                     MB_OK Or MB_IconInformation);
   30000..65000 : DBW0(262144, 'Menu Nr=' + ITS(wNrMenu));
   else WMCommand:=inherited WMCommand(wPar, lPar);
   end;  // case
end;  // TMyWindow.WMCommand

function TMyWindow.WindowProc(hWindow:HWND; wMsg:UINT; wPar:WPARAM; lPar:LPARAM):LRESULT;
//====================================================================================
// All window messages are send here.
Var
  rRec        : rect;
  wStatH      : Word;
  alEdges     : array[1..2] of LongInt;

Begin
WindowProc := 0; // Default return value when processing a message

Case wMsg Of
   WM_Close : begin
      oRichEdit.AskSave;
      WindowProc:=inherited WindowProc(hWindow, wMsg, wPar, lPar);
      end;
//   WM_Destroy : PostQuitMessage (0); // This is the default behaviour.
//              This should not be treated here, or at least the
//              inherited WindowProc should be called.
//              This allows to save the window position and size in a file
   WM_SetFocus : SetFocus(oRichEdit.hWin);
   WM_EraseBkgnd : Exit;
   WM_Size : begin
      GetClientRect(oStatusL.hWin, @rRec);
      wStatH := word(rRec.Bottom - rRec.Top);
      GetClientRect(hWindow, @rRec);
      MoveWindow (oRichEdit.hWin,0,0, rRec.Right, rRec.Bottom - wStatH, False);
      MoveWindow (oStatusL.hWin,0, rRec.Bottom - wStatH, rRec.Right, rRec.Bottom, False);

      // Define the position of the separation in the Status line
      alEdges[1] := rRec.Right  - rRec.Left - 80;
      alEdges[2] := rRec.Right  - rRec.Left;
      SendMessage(oStatusL.hWin, SB_SETPARTS, 2, LongInt(@alEdges));
      end; // WM_Size
   WM_Command : WindowProc:=WMCommand(wPar, lPar);
//   WM_Notify :  WindowProc:=WMNotify(wPar, lPar);
     // if you treat the notifications messages, you must call the parent
     // WindowProc:=WMNotify(wPar, lPar);  method to handle them correctly.
   WM_CtlColorEdit : begin
      SetTextColor(wPar, oRichEdit.TheColor);
      Exit(GetSysColorBrush(COLOR_WINDOW));
      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        : TApplication;
  poMyMainWin : PMyWindow;

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

// Creation of the main window
new(poMyMainWin, Init('Title of the Example011 (Ex011.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. // program tEx011;

