Solved

2 instances of program running, but only want one image in the system tray???

Posted on 2001-07-06
16
139 Views
Last Modified: 2010-04-06
My users may run 3 instances of my program at once.  I have a timer that based on a certain condition places an image down in the system tray.  My problem is that I don't want 3 images down in the system tray, just one.  How do I check the system tray's icons for the matching icon???
0
Comment
Question by:rwhitaker
16 Comments
 
LVL 22

Expert Comment

by:mnasman
ID: 6260157
Hello

  I don't know if i understood you well, but if you want only one image in system tray, when u run ur program check it there are any instance, if it's the first instanece place an image in the system tray, if there are any instance, that's mean there's one already and u don't want to add another one

Mohammed
0
 

Author Comment

by:rwhitaker
ID: 6260186
But there may be 3 instances without any icons in the system tray.  The only time I put an image in the system tray is if certain things happen.  What I want to avoid is all 3 instances putting 3 images in the system tray.

How do I look in the system tray for a certain image and tie that back to a certain program?
0
 

Author Comment

by:rwhitaker
ID: 6260218
But there may be 3 instances without any icons in the system tray.  The only time I put an image in the system tray is if certain things happen.  What I want to avoid is all 3 instances putting 3 images in the system tray.

How do I look in the system tray for a certain image and tie that back to a certain program?
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 6260253
The instances have to communicate. I think JclAppInst from the Jedi Code Library (http://delphi-jedi.org pare 'Code Library') could help.
One instance (the first one would be a logical choice) shows the tray icon, the others stay hidden and signal the master instance to show the icon if needed.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6260264
Use CreateMutex to check if another instance already put an icon in the tray:

var mutex: Cardinal;


  mutex := CreateMutex(nil, true, 'icon_in_tray');
  if mutex <> 0 then
    // put the icon in tray


When you remove the icon from the tray, close the mutex handle to allow anther instance to put an icon in the tray:

  CloseHandle(mutex);
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6260327
Little mistake

mutex := CreateMutex(nil, true, 'icon_in_tray');
 if mutex <> 0 then
   if GetLastError <> ERROR_ALREADY_EXISTS then
     // put the icon in tray
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6260347
Here's a full examle:


unit unit1;

interface

uses Windows, Classes, Forms, Messages, Controls, ShellAPI, Menus, SysUtils,
     StdCtrls;

type
  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    ShowForm1: TMenuItem;
    Exit1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure WndProc(var Message: TMessage); override;
    procedure Showform1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
  private
    { Private declarations }
    mutex: Cardinal;
  public
    { Public declarations }
    IconNotifyData : TNotifyIconData;
  end;

  TFunc = function(dwProcessID, dwType: DWORD): DWORD; stdcall;

var
  Form1: TForm1;

implementation

{$R *.DFM}

// Catch the Minimize event before the application
procedure TForm1.WndProc(var Message: TMessage);
var
  p : TPoint;
begin
  case Message.Msg of
    WM_SYSCOMMAND:
      case Message.WParam and $FFF0 of
        SC_MINIMIZE: begin
          // Hide the Mainform
          Hide;
          // Bail out here, so the Application dont starts to show the form
          exit;
        end;
        SC_RESTORE: ;
      end;
    WM_USER + 1:
      case Message.lParam of
        WM_RBUTTONDOWN: begin
          GetCursorPos(p);
          PopupMenu1.Popup(p.x, p.y);
        end;
        WM_LBUTTONDOWN: begin
          Show;
        end;
      end;
  end;
  inherited ;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  mutex := CreateMutex(nil, true, 'icon_in_tray');
  if mutex <> 0 then
    if (GetLastError <> ERROR_ALREADY_EXISTS) then
    begin
      //Now set up the IconNotifyData structure so that it receives
      //the window messages sent to the application and displays
      //the application's tips
      with IconNotifyData do begin
        hIcon := Application.Icon.Handle;
        uCallbackMessage := WM_USER + 1;
        cbSize := sizeof(IconNotifyData);
        Wnd := Handle;
        uID := 100;
        uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
      end;

      //Copy the Application's Title into the tip for the icon
      StrPCopy(IconNotifyData.szTip, Application.Title);

      //Add the Icon to the system tray and use the
      //the structure and its values
      Shell_NotifyIcon(NIM_ADD, @IconNotifyData);
    end
    else
      CloseHandle(mutex);
end;


// Shows the form when user click on TrayIcon
procedure TForm1.Showform1Click(Sender: TObject);
begin
  // Show the Mainform.
  Show;
  // Put the form in top of all others.
  SetForegroundWindow(Self.handle);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if mutex <> 0 then
  begin
    Shell_NotifyIcon(NIM_DELETE, @IconNotifyData);
    CloseHandle(mutex);
  end;
end;

procedure TForm1.Exit1Click(Sender: TObject);
begin
  Close;
end;

end.
0
 

Author Comment

by:rwhitaker
ID: 6260399
Thanks Epsylon,

But how do I pass the icon in the tray as a PChar.  I have tried PChar(strayReadyToPrint.Icon.GetNamePath) without success.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 13

Expert Comment

by:Epsylon
ID: 6260424
Pass the icon in the tray as a PChar?????
0
 

Author Comment

by:rwhitaker
ID: 6260475
yep that is what CreateMutex is looking for.  Anyways, I figured it out, but now I get an external exception when I try to call CloseHandle....
0
 
LVL 13

Accepted Solution

by:
Epsylon earned 200 total points
ID: 6260527
I think you didn't understand it fully. The string 'icon_in_tray' is just for identification. It can be anything you want:

  mutex := CreateMutex(nil, true, 'Hello world');
  if mutex <> 0 then
    if GetLastError <> ERROR_ALREADY_EXISTS then
      // put the icon in tray
    else
      CloseHandle;


When you want to remove the icon use this:

  if mutex <> 0 then
  begin
    // remove icon from tray
    CloseHandle(mutex);
  end;
0
 

Author Comment

by:rwhitaker
ID: 6269868
ok, i am with you now.  but I still have a problem with it;  mutex never gets set back to 0, do I need to set this to 0 when removing the icon?  I currently get an exception in the main else when closing the handle.  Here is sample code.  
  if (condition is met to put add icon to tray) then
  begin
    mutex := CreateMutex(nil, true, 'READY TO PRINT ICON');
    if mutex <> 0 then
      if GetLastError <> ERROR_ALREADY_EXISTS then
        strayReadyToPrint.Active := True  //adds icon
      else
        CloseHandle (mutex);  //remove handle
  end
  else
  begin
    strayReadyToPrint.Active := False;  //removes icon
    if mutex <> 0 then
      CloseHandle(mutex);
  end;
0
 

Author Comment

by:rwhitaker
ID: 6270487
Epsylon,

ok, i figured it out.  Because I have the above function tied to a timer event, I need to do it a little differently.  But I am still using CreateMutex.

Thanks for the help Epsylon.  It works awesome.  Post an answer and I will accept with high grade.

Thanks again.......

Rick
0
 

Author Comment

by:rwhitaker
ID: 6270493
Thanks Epsylon
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6270542
Oh well, I was about to look at your code  :o)

Thank you too.


Btw, setting mutex:=0 after CloseHandle is a wise idea if you re-use the mutex handle.
0
 

Author Comment

by:rwhitaker
ID: 6270994
yep, that is exactly what I did, plus a few other minor changes to take in account the timer.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Filemaker 14 vs Delphi Embarcadero 7 160
Splash screen too shortlived 11 113
delphi prevent click fast 2 166
Base1 Encode/Decode 3 31
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now