Link to home
Start Free TrialLog in
Avatar of gafoor78
gafoor78Flag for India

asked on

application icon in windows system tray

hi all

thanx in advance

can anyone please help me to put my PB application in the windows system tray...if possible give me the code to do it just like yahoo messenger works in system tray..that is it hav a popup menu while right click, maximize while double click and minimize to system tray while close.

regards

ASKER CERTIFIED SOLUTION
Avatar of SylvainPouliot
SylvainPouliot

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Gafoor,

You can create the Tray Icon using the API functions.
You need couple of User Event which are used to process for the captured user action on the Tray Icon.
Approach :
- Create the Tray Icon while Main window opens.
- Hide the Window. Such that only Icon is visible
- Show hidden window if double clicked on the ICON
- Pop Menu if Right Clicked              

//Local External Functions
FUNCTION integer Shell_NotifyIcon (long dwMessage, REF NOTIFYICONDATA lpData) LIBRARY "shell32.dll" ALIAS FOR "Shell_NotifyIconA"

//Post_open User Event which is posted from Open event of the Window {Eg. Post Event post_open()}

long ll_Icon
ll_Icon = Send(Handle(This),WM_GETICON,1,0)
IconData.cbSize                        = 1000
IconData.hWnd                              = Handle(This)
IconData.uID                              = 1
IconData.uFlags                        = BitOr({NIF_ICON,NIF_MESSAGE,NIF_TIP})
IconData.uCallBackMessage      = WM_COMMAND
IconData.hIcon                              = ll_Icon
IconData.szTip                              = 'TrayIcon -  Loks'
      
If Shell_NotifyIcon(NIM_ADD,IconData) = 0 Then
      MessageBox("System error", "Cannot add to the systray.",StopSign!,Ok!)
END IF
This.Hide()


//Command Event of window
//Capture the Mouse DoubleClick or Right Click of the Tray Icon
Choose Case Message.LongParm
      Case WM_LBUTTONDBLCLK
             This.TriggerEvent("ue_traydoubleclicked")
      Case WM_RBUTTONUP
             This.TriggerEvent("ue_trayrightclicked")
End Choose


//ue_traydoubleclicked Window User Event
//If double Clicked on the Tray ICON then Show the window
SetPointer(HourGlass!)

IF This.Visible = TRUE THEN RETURN
Show(This)
This.WindowState = Maximized!
This.POST SetFocus()


//ue_trayrightClicked window User Event
//If right Clicked on the Icon then Show the Popup Menu
m_systray lm_example
This.SetFocus()
lm_example = CREATE m_systray
lm_example.m_pop.PopMenu(PointerX(),PointerY())
DESTROY lm_example

//Close Event Window Event
IF Shell_NotifyIcon(NIM_DELETE,IconData) = 0 Then
    MessageBox("System error", "Cannot Remove Mysec from the systray!.",StopSign!,Ok!)
END IF

//Resize Window Event
IF sizetype = 1 THEN
     This.Hide()
END IF

//Menu Object has two Menu Items 1. Open & 2. Close
1. Open Menuitem
//Script
ParentWindow.Dynamic Event ue_traydoubleclicked()

2. Close MenuIte,
//Script
Close(ParentWindow)

Loks
Avatar of gafoor78

ASKER

hi

i successfully implemented loading the appl in the system tray and handling mouse events on it, but i hav some problems on it. so pls help me...

1. if i am running the appln, it is comimg in the system tray. if i am again running the appln, then another instance is opening  and another tray icon is coming, but i only need one instance of the application at any time. how can i do it..?.

if another instance is opening, then it shoud only make visible the previously loaded window if it is invisible.

2. i want load the application at bootup time in the tray without adding application in startup folder..like yahoo messenger loads at startup time

if u can give any light on the above pblm more i will be thankful and get u points

i am using  PB 8.0 build 6028

with advance thanx

gafoor
Avatar of SylvainPouliot
SylvainPouliot

Ok for #2, create a key in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

(You will probably see your yahoo messenger over there)


For #1
Use this API
FUNCTION ulong FindWindowA (ulong the_class, string the_name) LIBRARY "user32.dll"

and in the open event of the application:
long val
val = FindWindowA(0, "You application Title")
IF val > 0 THEN
   lb_found= true
   return
end if


You can also put this application executable in startup menu-Programs-Startup of windows.

The application will executed by Windows OS.
If you have hidden the main window in the application code then directly a ICON will be loaded in to the systray.

Regards,
Loks

Regarding loading application once.
Refer to this link where code is available.

http://www.pbdr.com/pbtips/ap/onlyonce.htm
hi


pls read my pblms fully. i think u can understand my pblms. if u can help me on this regards also i can give u more points

i added registry key for startup and restricted to run the application only once..but i hav some more pbls

1.  when the window  is closing then i given a ' return 1 '  in the closequery and only making the window invisible. so that it will remain the system tray.

i can exit the appln by right clicking on the tray icon and selecting the exit from popup menu.

now the problem is   i am unable to shutdown or restart the windows without exiting the application ( bcos i hav given a return 1 in the closequery).. so is there any api or like that to findout that windows is closing the application.. or any other method other than giving return 1 in closequery to stay the application in the system try when the user simply closes the window by the close button.

2. i designed the application such that, when  the application runs, then it will load in the system tray and will be visible. but in the startup time it only needs to load in the sytem try, but not require to visible..but as per the registry entry i made 4 automatic startup, it also loads in the tray and showing the window.. i want to suppress the visiblity only at startup time.

i expect ur earliest reply

regards
1. Use a flag to know if the user has clicked on your popmenu Exit.
Ex:
boolean ib_close
//In your Event for the Exit item
ib_close = true
//then close de window

//In the Closequery event
if ib_close then
else
return 1
end if

2. Why don't you just put
this.visible = false
in your open event...



By the way... you should post multiple questions in different "Question"
Usually, people will skip question that have already been answered.
So if you post new question in the same question, you will not be read by "everyone"...
hi sylvain and lok

thank u 4 ur effort on this.. anyway i am giving the point to sylvain, but the comments u  posted last is not eliminated my pblm. so i will post it as a new question. so u pls read and give me some tips if possible.

SylvainPouliot, do I have to create a new window with the systray icon as the window icon?
Where do all those things go?

Where do these variables get declared?
// Variable for Systray
Constant long NIM_ADD = 0
Constant long NIM_MODIFY = 1
Constant long NIM_DELETE = 2
Constant long NIF_MESSAGEorNIF_ICONorNIF_TIP =7
Constant long WM_MOUSEMOVE = 512
Constant long IMAGE_ICON = 1
Constant long LR_LOADFROMFILE = 16
long hicon
long hicon_working


This function doesn't compile:
public function wstr_notifyicondata wf_setnotifyicondata (long hWnd, long ID, long Flags, long CallBackMessage, long a_icon, string tip);char mytip[64]
    wstr_notifyicondata nidtemp
    nidtemp.cbsize = 88
    nidtemp.hwnd = hwnd
    nidtemp.uid = id
    nidtemp.uflags = flags
    nidtemp.ucallbackmessage = callbackmessage
    nidtemp.hicon = a_icon
    mytip = tip + char(0)
    nidtemp.sztip = mytip
    return nidtemp
end function

It says illegal data type for wstr_notifyicondata.

you have to "import" this function:

$PBExportHeader$wstr_notifyicondata.srs
global type wstr_notifyicondata from structure
      long            cbsize
      long            hWnd
      long            uID
      long            uFlags
      long            uCallBackMessage
      long            hIcon
      character            szTip[64]
end type


Tell me if you have other problem using it..
How do u do that? as in 'import' it.
save this in a text file:

$PBExportHeader$wstr_notifyicondata.srs
global type wstr_notifyicondata from structure
    long          cbsize
    long          hWnd
    long          uID
    long          uFlags
    long          uCallBackMessage
    long          hIcon
    character          szTip[64]
end type


then go in your "library" painter, click on the Import Icon and select your text file.
or simpler, just create a structure called  wstr_notifyicondata with the information you see above.
Oh crap. Nevermind. I got what you were saying. I didn't it carefully.
I have the icon showing in the tray but I have a couple of questions

Couple of questions

In the open event I have the window made to Hide

When the window is hidden, my rightclickmenu from the systray icon shows up correctly.

However when I double click the icon to show the window and then minimize it, the rightclickmenu from the systray doesn't show at all. The popmenu command is fired as the rightclick is recorded but I don't see the menu.

This happens
- when the window is minimized and visible, and
- when the window is minimized and hidden
can you post the code you use to display the popmenu
EVENT SYSTRAY of w_main.
-------------------------------

Case WM_RBUTTONDOWN
            
m_popmenu lm_popmenu
            
This.SetFocus()
            
lm_popmenu = CREATE m_popmenu
            
lm_popmenu.PopMenu(PointerX(), PointerY())
            
DESTROY lm_popmenu
when it doesn't show:
what does lm_popmenu.PopMenu(PointerX(), PointerY()) returns?
and Pointerx(), pointery()?
hi

hi use the following code instead of            lm_popmenu.PopMenu(PointerX(), PointerY())  

for working when it is minimized

 lm_popmenu.m_menu.PopMenu(PointerX(),PointerY())

where ' m_menu '  is the main menu item name of ur popup menu......

regards
gafoor
                  
SylvainPouliot,

PointerX() = -700
PointerY() = 19515
lm_popmenu.PopMenu(PointerX(), PointerY()) = 0

And as soon as it reads the last one, which is this lm_popmenu.PopMenu(PointerX(), PointerY()), the cursor jumps to the Choose Case Message.LongParm statement.  It doesn't even read the Destroy lm_menu

??
Sorry:

PointerX() = 19442

PointerY() = -68
Popmenu function should not return 0....
you should get 1 if it works...

Can you try this line instead:

m_popmenu.PopMenu(500,500)

and tell me if you get better result...
OK, will try it and let you know.

Thx.
No, that doesn't work.

I'm not sure what I'm doing wrong.