Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Track all menu uses with AppAnalytics?


This question is answered.


Permlink Replies: 5 - Last Post: Jul 10, 2015 10:03 AM Last Post By: Lajos Juhasz
Kevin Killion

Posts: 19
Registered: 2/3/03
Track all menu uses with AppAnalytics?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 8, 2015 3:19 PM
I'd like to use an AppAnalytics custom TrackEvent to track uses of all menu items. This would help us learn which menu items users actually use.

But how can I intercept all menu requests in order to do this? There must be a better way other than adding a line to each and every onClick handler for every menu item. I just need to know which menuItem was affected (in order to pick up its name).

-- Kevin
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: Track all menu uses with AppAnalytics?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 9, 2015 10:26 AM   in response to: Kevin Killion in response to: Kevin Killion
Kevin Killion wrote:

I'd like to use an AppAnalytics custom TrackEvent to track uses of
all menu items. This would help us learn which menu items users
actually use.

But how can I intercept all menu requests in order to do this? There
must be a better way other than adding a line to each and every
onClick handler for every menu item. I just need to know which
menuItem was affected (in order to pick up its name).

Place this above the form declaration:

TMenuItem = class(Vcl.Menus.TMenuitem)
public
procedure Click; override;
end;

Implement the method as

procedure TMenuItem.Click;
begin
inherited;
... log Name property and perhaps Owner.Name to catch the form name
here
end;

If you want to reuse this interposer class for different forms, create
a new unit, add Vcl.Menus to the interface Uses clause, the class
declaration to the interface of the unit and the implementation as
usual to the Implementation section. If you now add this unit to the
Interface uses clause of a form unit, after Vcl.Menus, the form will
use your replacement menu item class. This also affects popup menus, by
the way.

Tested very briefly with XE7.

--
Peter Below (TeamB)
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: Track all menu uses with AppAnalytics?
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 9, 2015 10:32 AM   in response to: Kevin Killion in response to: Kevin Killion
Kevin Killion wrote:

I'd like to use an AppAnalytics custom TrackEvent to track uses of
all menu items. This would help us learn which menu items users
actually use.

But how can I intercept all menu requests in order to do this? There
must be a better way other than adding a line to each and every
onClick handler for every menu item. I just need to know which
menuItem was affected (in order to pick up its name).

Place this above the form declaration:

TMenuItem = class(Vcl.Menus.TMenuitem)
public
procedure Click; override;
end;

Implement the method as

procedure TMenuItem.Click;
begin
inherited;
... log Name property and perhaps Owner.Name to catch the form name
here
end;

If you want to reuse this interposer class for different forms, create
a new unit, add Vcl.Menus to the interface Uses clause, the class
declaration to the interface of the unit and the implementation as
usual to the Implementation section. If you now add this unit to the
Interface uses clause of a form unit, after Vcl.Menus, the form will
use your replacement menu item class. This also affects popup menus, by
the way.

Tested very briefly with XE7.

--
Peter Below (TeamB)
Kevin Killion

Posts: 19
Registered: 2/3/03
Re: Track all menu uses with AppAnalytics?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 9, 2015 1:28 PM   in response to: Peter Below in response to: Peter Below
Peter, your solution is clean and elegant, simple as can be, and works beautifully! THANK YOU!

... except for one thing. I used a little loop to walk from a menu item up through its parent, and parent's parent, etc.:

{in the interposer unit}
procedure TMenuItem.Click;
var
  m: TMenuItem;
  s: string;
begin
  inherited;
  ...
  ...
      m := SELF;
      s := m.Caption;
 
      while m.Parent <> NIL do
          begin
            s := m.Parent.Caption + '>' + s;
            m := m.Parent;  { <--- COMPILE ERROR HERE}
          end;


At the line shown, I get this error from the compiler:
[dcc32 Error] MenuInterposer.pas(51): E2010 Incompatible types: 'MenuInterposer.TMenuItem' and 'Vcl.Menus.TMenuItem'

I've tried different things, but haven't figured out what the magic is to make this work.

The full code of the unit is below.

AGAIN, MANY THANKS!!!

Kevin


unit MenuInterposer;
 
interface
 
uses
  Vcl.Menus,
  StdCtrls; {for memo}
 
type
  TMenuItem = class(Vcl.Menus.TMenuitem)
  public
    procedure Click; override;
  end;
 
procedure InterposerInit(log: TMemo);  {testing by writing results to a Memo for now}
 
implementation
 
uses
  SysUtils,
  Dialogs; {for ShowMessage}
 
var
  miLog: TMemo;
 
procedure InterposerInit(log: TMemo);
begin
  miLog := log;
end;
 
 
procedure TMenuItem.Click;
const
  showMenuTrail = TRUE;  {do we want to record the whole chain of menus and submenus?}
var
  hasSubMenu: Boolean;
  m: TMenuItem;
  s: string;
begin
  inherited;
  hasSubMenu := (SELF.Count > 0);
  if NOT hasSubMenu then {only log menu items, not menu parents}
    begin
      m := SELF;
      s := m.Caption;
 
      {walk thru menus and their parents to show whole chain}
      if showMenuTrail then
        while m.Parent <> NIL do
          begin
            s := m.Parent.Caption + '>' + s;
            m := m.Parent;
          end;
 
      miLog.Lines.Append('LOG:  ' + s);
    end;
end;
 
 
end.
Lajos Juhasz

Posts: 801
Registered: 3/14/14
Re: Track all menu uses with AppAnalytics?
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 9, 2015 11:04 PM   in response to: Kevin Killion in response to: Kevin Killion
Kevin Killion wrote:

m := m.Parent; { <--- COMPILE ERROR HERE}
end;
 
At the line shown, I get this error from the compiler:
[dcc32 Error] MenuInterposer.pas(51): E2010 Incompatible types:
'MenuInterposer.TMenuItem' and 'Vcl.Menus.TMenuItem'</div>
 
This one is easy, define m as Vcl.Menus.TMenuItem:
 

var m: Vcl.Menus.TMenuItem
{code}
Lajos Juhasz

Posts: 801
Registered: 3/14/14
Re: Track all menu uses with AppAnalytics?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 10, 2015 10:03 AM   in response to: Kevin Killion in response to: Kevin Killion
Kevin Killion wrote:

m := m.Parent; { <--- COMPILE ERROR HERE}
end;
 
At the line shown, I get this error from the compiler:
[dcc32 Error] MenuInterposer.pas(51): E2010 Incompatible types:
'MenuInterposer.TMenuItem' and 'Vcl.Menus.TMenuItem'</div>
 
This one is easy, define m as Vcl.Menus.TMenuItem:
 

var m: Vcl.Menus.TMenuItem
{code}
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02