Watch, Follow, &
Connect with Us

Please visit our new home
community.embarcadero.com.


Welcome, Guest
Guest Settings
Help

Thread: Developing OSX Menu-lets using Delphi XE7?


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 7 - Last Post: Dec 31, 2017 12:06 PM Last Post By: Chris Pimlott Threads: [ Previous | Next ]
Charles Stack

Posts: 3
Registered: 10/23/99
Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 19, 2014 12:07 PM
I was wondering if anyone has figured out how to develop "menu-let" applications using Delphi XE6 or XE7?

By "Menu-let" I am referring to the apps that appear in the system menu bar on the right (i.e Dropbox, WiFi, Date/Time, etc) reside. Clicking on them brings up a context menu or opens a windowed app.

I am writing a cross platform app that needs to appear as a "Menulet" on OSX and as a TrayIcon app on Windows 32/64.

Any help is appreciated.

Thanks!
Ronald Klitsche

Posts: 326
Registered: 8/26/01
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 22, 2014 1:22 AM   in response to: Charles Stack in response to: Charles Stack
I was wondering if anyone has figured out how to develop "menu-let"
applications using Delphi XE6 or XE7?

By "Menu-let" I am referring to the apps that appear in the system menu bar
on the right
(i.e Dropbox, WiFi, Date/Time, etc) reside. Clicking on them brings up a
context menu or opens a windowed app.

I am writing a cross platform app that needs to appear as a "Menulet" on
OSX and as a TrayIcon app on Windows 32/64.

Using the TNSStatusBar class in Macapi.AppKit unit.
The following code is quick copy/paste:

TFMXTrayItem = class(TOCLocal)
private
NSStatItem : NSStatusItem;
public
constructor Create;
destructor Destroy; override;
function GetObjectiveCClass: PTypeInfo; override;
procedure call_mymethod; cdecl;
end;

constructor TFMXTrayItem.Create;
var
NSContMenu : NSMenu;
NSContItem : NSMenuItem;
NSStatBar : NSStatusBar;
NSImg : NSImage;
AppBundle : NSBundle;
NSpImg: Pointer;
Path: String;
begin
inherited Create;

NSStatBar := TNSStatusBar.Create;
NSStatBar := TNSStatusBar.Wrap(TNSStatusBar.OCClass.systemStatusBar);
NSStatItem:= NSStatBar.statusItemWithLength(NSVariableStatusItemLength);
NSStatItem.setTarget(GetObjectID);

// Create context menu
NSContMenu := TNSMenu.Create;
NSContMenu := TNSMenu.Wrap(NSContMenu.initWithTitle(StrToNSStr('The
caption')));

NSContItem:=TNSMenuItem.Create;
NSContItem:=TNSMenuItem.Wrap(NSContItem.initWithTitle(StrToNSStr('1. menu
item'),sel_getUid(PAnsiChar('call_mymethod')),StrToNSStr('')));
NSContItem.setTarget(GetObjectID);
NSContMenu.addItem(NSContItem);
NSContItem.release;

// Add menu
NSStatItem.retain;
NSStatItem.setHighlightMode(true);
NSStatItem.setMenu(NSContMenu);
NSContMenu.release;

// Get path to dir
AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
Path:=AppBundle.bundlePath.UTF8String+'/Contents/yourimage16x16.png';
NSpImg := TNSImage.Alloc.initWithContentsOfFile(StrToNSStr(Path));
// Create Icon
NSImg := TNSImage.Create;
NSImg := TNSImage.Wrap(NSpImg);
NSStatItem.setImage(NSImg);
NSImg.release;
end;

destructor TFMXTrayItem.Destroy;
begin
NSStatItem.release;
inherited;
end;

function TFMXTrayItem.GetObjectiveCClass: PTypeInfo;
begin
Result :=TypeInfo(IFMXTrayItem);
end;

procedure TFMXTrayItem.call_properties;
begin
// your event code of the menu item
end;

Ronald

Jamie Foster

Posts: 3
Registered: 5/1/14
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2015 5:26 AM   in response to: Ronald Klitsche in response to: Ronald Klitsche
Hi Ronald,

Thanks for the sample code.

How do you define the IFMXTrayIcon interface? Couldn't find that one.

Thanks,
Jamie
Jamie Foster

Posts: 3
Registered: 5/1/14
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2015 5:38 AM   in response to: Ronald Klitsche in response to: Ronald Klitsche
Hi Ronald,

How do you define the IFMXTrayIcon interface?

Thanks,
Jamie
Ronald Klitsche

Posts: 326
Registered: 8/26/01
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2015 6:19 AM   in response to: Jamie Foster in response to: Jamie Foster
Hi Jamie,

How do you define the IFMXTrayIcon interface?

in this way:

IFMXTrayItem = interface(NSObject)
['{7756ABE3-2BE7-4CBA-BF78-731F96B1B378}']
procedure call_mymethod; cdecl;
end;

The code will be executed in the TFMXTrayItem class and assigned by name:

...
NSContItem:=TNSMenuItem.Create;
NSContItem:=TNSMenuItem.Wrap(NSContItem.initWithTitle(StrToNSStr('1.
menuitem'),sel_getUid(PAnsiChar('call_mymethod')),StrToNSStr('')));
...

Ronald
Jamie Foster

Posts: 3
Registered: 5/1/14
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2015 9:04 AM   in response to: Ronald Klitsche in response to: Ronald Klitsche
Thank you, Ronald.

I got it working just before reading your answer, and I wrote it like this:

IFMXTrayItem = interface(NSObject)
procedure call_mymethod; cdecl;
end;

So my question is: do I need to set a GUID for the interface? I assume that in your example :

{7756ABE3-2BE7-4CBA-BF78-731F96B1B378}

is a newly generated GUID, right?

Thanks once again!

Ronald Klitsche wrote:
Hi Jamie,

How do you define the IFMXTrayIcon interface?

in this way:

IFMXTrayItem = interface(NSObject)
['{7756ABE3-2BE7-4CBA-BF78-731F96B1B378}']
procedure call_mymethod; cdecl;
end;
Ronald Klitsche

Posts: 326
Registered: 8/26/01
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 9, 2015 5:02 AM   in response to: Jamie Foster in response to: Jamie Foster
So my question is: do I need to set a GUID for the interface? I assume that
in your example :
{7756ABE3-2BE7-4CBA-BF78-731F96B1B378}

I assume: you dont need a GUID.

Ronald
Chris Pimlott

Posts: 4
Registered: 1/14/15
Re: Developing OSX Menu-lets using Delphi XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 31, 2017 12:06 PM   in response to: Ronald Klitsche in response to: Ronald Klitsche
Fantastic article, it works like a treat!

I'm trying to adapt it so that rather than presenting a menu, it can show a custom form when you click on the status item icon.

According to the official documentation, it seems that all I should need to do is call:

NSStatusItem.setAction(sel_getUid(PAnsiChar('call_mymethod')));

And don't create or assign the menu to NSStatusItem. I've done this and changed my selector signature for call_mymethod to:

procedure call_mymethod(sender: Pointer);

(I've also done this in the IFMXTrayItem interface).

But it doesn't work. When I click on the icon, it highlights but the method isn't called. No errors are raised either, so not sure where I might be going wrong.
Does anyone have any ideas?

Thanks

Ronald Klitsche wrote:
I was wondering if anyone has figured out how to develop "menu-let"
applications using Delphi XE6 or XE7?

By "Menu-let" I am referring to the apps that appear in the system menu bar
on the right
(i.e Dropbox, WiFi, Date/Time, etc) reside. Clicking on them brings up a
context menu or opens a windowed app.

I am writing a cross platform app that needs to appear as a "Menulet" on
OSX and as a TrayIcon app on Windows 32/64.

Using the TNSStatusBar class in Macapi.AppKit unit.
The following code is quick copy/paste:

TFMXTrayItem = class(TOCLocal)
private
NSStatItem : NSStatusItem;
public
constructor Create;
destructor Destroy; override;
function GetObjectiveCClass: PTypeInfo; override;
procedure call_mymethod; cdecl;
end;

constructor TFMXTrayItem.Create;
var
NSContMenu : NSMenu;
NSContItem : NSMenuItem;
NSStatBar : NSStatusBar;
NSImg : NSImage;
AppBundle : NSBundle;
NSpImg: Pointer;
Path: String;
begin
inherited Create;

NSStatBar := TNSStatusBar.Create;
NSStatBar := TNSStatusBar.Wrap(TNSStatusBar.OCClass.systemStatusBar);
NSStatItem:= NSStatBar.statusItemWithLength(NSVariableStatusItemLength);
NSStatItem.setTarget(GetObjectID);

// Create context menu
NSContMenu := TNSMenu.Create;
NSContMenu := TNSMenu.Wrap(NSContMenu.initWithTitle(StrToNSStr('The
caption')));

NSContItem:=TNSMenuItem.Create;
NSContItem:=TNSMenuItem.Wrap(NSContItem.initWithTitle(StrToNSStr('1. menu
item'),sel_getUid(PAnsiChar('call_mymethod')),StrToNSStr('')));
NSContItem.setTarget(GetObjectID);
NSContMenu.addItem(NSContItem);
NSContItem.release;

// Add menu
NSStatItem.retain;
NSStatItem.setHighlightMode(true);
NSStatItem.setMenu(NSContMenu);
NSContMenu.release;

// Get path to dir
AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
Path:=AppBundle.bundlePath.UTF8String+'/Contents/yourimage16x16.png';
NSpImg := TNSImage.Alloc.initWithContentsOfFile(StrToNSStr(Path));
// Create Icon
NSImg := TNSImage.Create;
NSImg := TNSImage.Wrap(NSpImg);
NSStatItem.setImage(NSImg);
NSImg.release;
end;

destructor TFMXTrayItem.Destroy;
begin
NSStatItem.release;
inherited;
end;

function TFMXTrayItem.GetObjectiveCClass: PTypeInfo;
begin
Result :=TypeInfo(IFMXTrayItem);
end;

procedure TFMXTrayItem.call_properties;
begin
// your event code of the menu item
end;

Ronald

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02