Recent

Author Topic: How to trace and log user's actions on a form ?  (Read 739 times)

mirce.vladimirov

  • Sr. Member
  • ****
  • Posts: 259
How to trace and log user's actions on a form ?
« on: May 11, 2023, 11:45:26 am »
How can i trace user actions on a Lazarus form, to write a line that contains control's name and user's action, may looks like :
Code: Pascal  [Select][+][-]
  1. combobox_select_user_action;selected text="the text that was selected in this combobox";
  2. edit_phonenumber;got focus;
  3. edit_phonenumber;changed from "previous text" to "the newly typed text";
  4. button_write;got focus;
  5. button_write;clicked;

Is there a way to create one single procedure or function that would be invoked always, no matter which control the user is performing action ?

I need to trace how and what exactly users are doing,  but no need to catch all actions, eg. no need to trace mouse-over, mouse-enter, mouse-leave...
« Last Edit: May 11, 2023, 12:18:25 pm by mirce.vladimirov »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: How to trace and log user's actions on a form ?
« Reply #1 on: May 11, 2023, 05:42:24 pm »
Have you tried using Application.OnUserInput with a filter to ignore mouse events?

mirce.vladimirov

  • Sr. Member
  • ****
  • Posts: 259
Re: How to trace and log user's actions on a form ?
« Reply #2 on: May 11, 2023, 07:58:16 pm »
Have you tried using Application.OnUserInput with a filter to ignore mouse events?

No, I don't even know a thing about that, where can I read about it, or see some examples ?

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: How to trace and log user's actions on a form ?
« Reply #3 on: May 11, 2023, 09:57:39 pm »
No, I don't even know a thing about that, where can I read about it, or see some examples ?
Application properties. In particular event OnUserInput.

Create a new form, from the additional tab add the non visual component TPapplicationproperties to the Form. Add a memo to the form (Memo1) and other components that you wish to test with.

On the object inspector select the application properties component, switch to the tab events and add the event OnUserInput.

Now you have everything in place to add some code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ApplicationProperties1UserInput(Sender: TObject; Msg: Cardinal);
  2. var
  3.   Info: string = 'unknown';
  4. begin
  5.   case msg of
  6.     //
  7.     LM_NULL              : Info := 'LM_NULL';
  8.     LM_CREATE            : Info := 'LM_CREATE';
  9.     LM_DESTROY           : Info := 'LM_DESTROY';
  10.     LM_MOVE              : Info := 'LM_MOVE';
  11.  
  12.     // keys
  13.     LM_KEYDOWN           : Info := 'LM_KEYDOWN';
  14.     LM_KEYUP             : Info := 'LM_KEYUP';
  15.     LM_CHAR              : Info := 'LM_CHAR';
  16.  
  17.     LM_SYSKEYDOWN        : Info := 'LM_SYSKEYDOWN';
  18.     LM_SYSKEYUP          : Info := 'LM_SYSKEYUP';
  19.     LM_SYSCHAR           : Info := 'LM_SYSCHAR';
  20.  
  21.     //
  22.     LM_COMMAND           : Info := 'LM_COMMAND';
  23.     LM_SYSCOMMAND        : Info := 'LM_SYSCOMMAND';
  24.     LM_TIMER             : Info := 'LM_TIMER';
  25.     LM_HSCROLL           : Info := 'LM_HSCROLL';
  26.     LM_VSCROLL           : Info := 'LM_VSCROLL';
  27.     LM_CTLCOLORMSGBOX    : Info := 'LM_CTLCOLORMSGBOX';
  28.     LM_CTLCOLOREDIT      : Info := 'LM_CTLCOLOREDIT';
  29.     LM_CTLCOLORLISTBOX   : Info := 'LM_CTLCOLORLISTBOX';
  30.     LM_CTLCOLORBTN       : Info := 'LM_CTLCOLORBTN';
  31.     LM_CTLCOLORDLG       : Info := 'LM_CTLCOLORDLG';
  32.     LM_CTLCOLORSCROLLBAR : Info := 'LM_CTLCOLORSCROLLBAR';
  33.     LM_CTLCOLORSTATIC    : Info := 'LM_CTLCOLORSTATIC';
  34.  
  35.     // mouse
  36.     LM_MOUSEMOVE         : Info := 'LM_MOUSEMOVE';
  37.     LM_LBUTTONDOWN       : Info := 'LM_LBUTTONDOWN';
  38.     LM_LBUTTONUP         : Info := 'LM_LBUTTONUP';
  39.     LM_LBUTTONDBLCLK     : Info := 'LM_LBUTTONDBLCLK';
  40.     LM_RBUTTONDOWN       : Info := 'LM_RBUTTONDOWN';
  41.     LM_RBUTTONUP         : Info := 'LM_RBUTTONUP';
  42.     LM_RBUTTONDBLCLK     : Info := 'LM_RBUTTONDBLCLK';
  43.     LM_MBUTTONDOWN       : Info := 'LM_MBUTTONDOWN';
  44.     LM_MBUTTONUP         : Info := 'LM_MBUTTONUP';
  45.     LM_MBUTTONDBLCLK     : Info := 'LM_MBUTTONDBLCLK';
  46.     LM_MOUSEWHEEL        : Info := 'LM_MOUSEWHEEL';
  47.     LM_XBUTTONDOWN       : Info := 'LM_XBUTTONDOWN';
  48.     LM_XBUTTONUP         : Info := 'LM_XBUTTONUP';
  49.     LM_XBUTTONDBLCLK     : Info := 'LM_XBUTTONDBLCLK';
  50.     LM_MOUSEHWHEEL       : Info := 'LM_MOUSEHWHEEL';
  51.  
  52.     LM_PARENTNOTIFY      : Info := 'LM_PARENTNOTIFY';
  53.     LM_CAPTURECHANGED    : Info := 'LM_CAPTURECHANGED';
  54.     LM_DROPFILES         : Info := 'LM_DROPFILES';
  55.  
  56.     LM_SELCHANGE         : Info := 'LM_SELCHANGE';
  57.     LM_DPICHANGED        : Info := 'LM_DPICHANGED';
  58.     LM_CUT               : Info := 'LM_CUT';
  59.     LM_COPY              : Info := 'LM_COPY';
  60.     LM_PASTE             : Info := 'LM_PASTE';
  61.     LM_CLEAR             : Info := 'LM_CLEAR';
  62.  
  63.     // control notifications
  64.     CN_KEYDOWN          : Info := 'CN_KEYDOWN';
  65.     CN_KEYUP            : Info := 'CN_KEYUP';
  66.     CN_CHAR             : Info := 'CN_CHAR';
  67.     CN_SYSKEYUP         : Info := 'CN_SYSKEYUP';
  68.     CN_SYSKEYDOWN       : Info := 'CN_SYSKEYDOWN';
  69.     CN_SYSCHAR          : Info := 'CN_SYSCHAR';
  70.     CN_NOTIFY           : Info := 'CN_NOTIFY';
  71.   end;
  72.  
  73.   if msg <> LM_MOUSEMOVE then
  74.   begin
  75.     Memo1.Append(Format('Control = %s, message = %s (%d) ', [Sender.ClassName, info, msg]));
  76.     {$ifdef LCLGTK2}
  77.     Memo1.SelStart:=Length(Memo1.Lines.Text)-1;
  78.     Memo1.SelLength:=0;
  79.     {$endif}
  80.   end;
  81. end;
  82.  
Build the application, run it and do some stuff to your form's components to see what is happening.

As you can see, it is very rudimentary messaging that you receive. You would need to add specific handling for each of your used components. You have access to the component and you know which action was taken. For example in an edit box the mousebutton is pressed (button down) to select some text (no event) and it was released (buttonup). Now you can check in your edit box's properties if the selection was changed. Same goes for all other things that you would like to check: which means a lot of work if you want something like you asked for.

I wonder if it would not be easier to add the events to the components themselves and act on it, e.g. I do not know if some things could be implemented in a generic manner for example for all the edit boxes, or buttons etc.

edit: I forgot to mention that in order to be able to make use of the constants you need to add the unit lmessages to your use clause.
« Last Edit: May 11, 2023, 10:08:38 pm by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

 

TinyPortal © 2005-2018