Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Screen position of Icon in SysTray

Posted on 2000-04-19
12
Medium Priority
?
382 Views
Last Modified: 2010-04-04
I create a icon in the windows systray. When I right click the icon, it pops up a menu. Now I try to use short cut (like pressing Ctrl + c)to actvate the menu, But Menu's popup method requires the position point(x, y), How can I get the icon position?

Best regards

Peter Shaw
0
Comment
Question by:petershaw9
  • 5
  • 3
  • 2
  • +1
12 Comments
 
LVL 2

Expert Comment

by:PeterLarsen
ID: 2730140
Hi Peter.
I have created a similar program, but i'm not satisfied with the result. My problem is, that the popupmenu only receive keyboard focus if the application have a visible form.
Would it be possible to see how you solved that problem ??

Regarding your question. I don't know how to get the position if a particular trayicon. But i can show you how to get the position of the taskbar :

procedure .....
var
 AP : PAppBarData;
begin
 new(ap);
 ap^.cbSize:=Sizeof(ap^);
 SHAppBarMessage(ABM_GETTASKBARPOS, AP^);
 showmessage(inttostr(ap^.rc.Left)+' - '+inttostr(ap^.rc.Top));
 Dispose(ap);
end;

Please let me know if you find a way to get the position of a trayicon.

Good luck
Peter
0
 
LVL 1

Expert Comment

by:tomer_engel
ID: 2730141
ok,,you don't need the icon's poition,you need the cursor's position

procedure TMyForm.TryIconIconCallback(var Msg:TMessage);
var
  Windows_Cursor_Pos : TPoint;
begin
  case Msg.lParam of
  WM_LBUTTONDOWN :
    begin
     //mouse cur. position
        GetCursorPos(CursorPos);
    //do your stuuf now like popups..
        mypopup.Popup(Windows_Cursor_Pos .X,Windows_Cursor_Pos.Y);
      end;
  end;
end;
0
 

Author Comment

by:petershaw9
ID: 2732611
Hi!
I show my client the program. They said they don't want use the mouse to operate, because keyboard is fast. The getcursor position is the current method that I use, but they don't like it.

PeterLarsen
I set main KeyPreview = true, and on the Keydown event I write the code,
  SysTrayform.PopupMenu1.Popup(p.x,p.y);
The problem is I don't know the icon's p.x, p.y.


Thanks

Peter  
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 4

Expert Comment

by:Radler
ID: 2732763
The complete code my time avoid give you, the hints are:
FindWindow to  'TrayNotifyWnd' to get the handle
ClientToScreen with the tray handle and a tpoint = (0,0) or a calculated value ( using GetViewportExtEx with GetDC( trayhandle ) ).
If used GetDc, call ReleaseDc after,OK ?

T++, Radler.
0
 

Author Comment

by:petershaw9
ID: 2732975
I tried:
var hdl : HWND;
begin
  hdl := FindWindow('TForm2', 'Form2');
  Showmessage(inttostr(hdl));
end;

It will show me a number.

But if I wrote
  P.x := form2.Left;
  P.Top := fvorm2.top;  
  P := hdl.ClienttoScreen(P);
Compiler gives me error on P := hdl.ClienttoScreen(P);

So, for systray icon, what is the icon class -- TIcon?, What is the Icon name, the icon file name? When I created the systray, this is a Icon handle: IconData.hIcon := frmSysTray.Icon.Handle; Can I use frmSysTray.Icon.Handle instead of FindWindow ?

  How to use ClientToScreen with the Icon handle?

Thanks

PeterShaw
0
 
LVL 2

Expert Comment

by:PeterLarsen
ID: 2737546
Radler, i don't get it.
I have tried the following, but i think i'm using the wrong handle because GetViewportExtEx(d, TG) gives the position 1,1 and Windows.ClientToScreen(IconData.Wnd, TPO) gives the position 287, 182 !?!
How do i get the "tray-handle" ??

IconData : TNotifyIconData;
....
procedure TForm1.Button3Click(Sender: TObject);
var
 h : HWND;
 d : HDC;
 TG : tagsize;
 TPO : tagpoint;
begin
 d:=getdc(IconData.Wnd);
 GetViewportExtEx(d, TG);
 ReleaseDC(IconData.Wnd, d);
 showmessage(inttostr(tg.cx)+' - '+inttostr(tg.cy));
 Windows.ClientToScreen(IconData.Wnd, TPO);
 showmessage(inttostr(tpo.x)+' - '+inttostr(tpo.y));
end;

Regards
Peter
0
 
LVL 4

Expert Comment

by:Radler
ID: 2743917
Sorry peter,

I should provide more details really
Well, a better way maybe
procedure TForm1.FormDblClick(Sender: TObject);
var
      Pos : TPoint;
      Rec : TRect;
      Win : THandle;
begin
      Win:=FindWindow('Shell_TrayWnd', nil );
      Win:=FindWindowEx( Win, 0, 'TrayNotifyWnd', nil );
      if IsWindowVisible( Win ) then begin
            Windows.GetClientRect( Win, Rec );
            Pos.x:=Rec.Left + (Rec.Right - Rec.Left) div 2;
            Pos.y:=Rec.Bottom - (Rec.Bottom - Rec.Top) div 2;
            Windows.ClientToScreen( Win, Pos );
            Self.TrayIcon1.PopupMenu.Popup( Pos.x + 2, Pos.y -2 );
            //MessageDlg( IntToStr( Pos.x + 1), mtInformation, [mbOK], 0);
      end else begin
            MessageDlg( IntToStr( Win ), mtInformation, [mbOK], 0);
      end;
end;


NOTE : TrayIcon1 is my component to lead with tray( you have one I imagine ).

Good luck, Radler.
0
 

Author Comment

by:petershaw9
ID: 2749707
Hi, Radler,
Thank you for your help. I tried your code, it works well.
In my application, it generates two tray icons. How can I differentiate these two icons?

best regardds

Peter Shaw
0
 
LVL 1

Expert Comment

by:tomer_engel
ID: 2750624
if you create the icons using the NOTIFYICONDATA structure then there's a field in that stucture that named uID, that holds the icon id-- meaning if you have two icons put the id of the first to 1,and the second to two,, now when you get the callback function,the icon id is in the wParam field of the function ( just make a case statement):

 Procedure  On_MYWM_NOTIFYICON( wParam:WPARAM; lParam:LPARAM )  
 Var
    uID : UINT;  
    uMouseMsg : UINT;
  Begin
       
   
      uID = UINT (wParam);  
      uMouseMsg = UINT (lParam);  
   
      if (uMouseMsg = WM_LBUTTONDOWN) then
      begin
          case (uID)  of
           IDI_MYBATTERYICON:  
   
                  // The user clicked the battery icon. Display the  
                 // battery status.  
                  ShowBatteryStatus();  
           IDI_MYPRINTERICON:  
   
                  // The user clicked the printer icon. Display the  
                  // status of the print job.  
                  ShowJobStatus();  
          end;//the case statment
       end;//the if  uMouseMsg = WM_LBUTTONDOWN
     
   End;//the procedure  
0
 
LVL 4

Accepted Solution

by:
Radler earned 150 total points
ID: 2753364
Hi peter,

More details about this you can take at
http://skyscraper.fortunecity.com/gigo/311/winprog.html
I know this link ( thanks nick ) a long time but being C/C++ I omitted it.

T++, Radler.
0
 

Author Comment

by:petershaw9
ID: 2842995
Comment accepted as answer
0
 

Author Comment

by:petershaw9
ID: 2842996
Comment accepted as answer
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Screencast - Getting to Know the Pipeline
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

971 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