1

I am creating a notifyIcon for my program, in the future it would be os independant but for now i am writing the win-32 part.

When i show a popupmenu after receiving a WM_RBUTTONDOWN message, i show a menu, but this menu is behind the taskbar. how to create a regular menu that would be in front of the taskbar?

The problem lies in the fmx.popupmenu, is it wrong to assume it has the same behaviour as VCL.popupmenu?

Edited code :

{$IFDEF MSWINDOWS}
Tray:=TPWTrayIcon.Create((handle));
{$ENDIF MSWINDOWS}
Tray.popupmenu:=pmTray;

constructor TPWTrayIcon.Create(pHANDLE:TFMXHandle);
Var
  HIco: HICON;
  p:tMenuitem;
begin
{$IFDEF MSWINDOWS}
  FHandle := AllocateHWnd(HandleIconMessage);
  AHandle := FmxHandleToHWND(pHandle);
  try
    Hico:= LoadIcon(MainInstance,'MAINICON');

    tIcon.cbSize := sizeof(tIcon);//TNotifyIconData);
    with tIcon do begin
      Wnd := FHandle;
      uID := 123;
      //guidItem:=123;
      uFlags := NIF_ICON or NIF_MESSAGE or NIF_GUID or NIF_TIP;
      uCallbackMessage := WM_NOTIFYICON;
      hIcon := HIco;
      uVersion:=NOTIFYICON_VERSION_4;
    end;
    Shell_NotifyIcon(NIM_ADD, @tIcon);
    Shell_NotifyIcon(NIM_SETVERSION, @tIcon);
  except

  end;
  {$ENDIF MSWINDOWS}
end;


procedure TPWTrayIcon.HandleIconMessage(var Msg: TMessage);
var
  tmpPoint:TPoint;
begin
  if Msg.Msg = WM_NOTIFYICON then begin
      case LOWORD(Msg.LParam )of
        WM_RBUTTONDOWN:
          if Assigned(PopUp) then begin
            Cardinal(tmpPoint):=(GetMessagePos);  
            {EDIT: the following doesnt work in Firemonkey}
            //SetForegroundWindow(Application.Handle);
            //Application.ProcessMessages;
            if SetForegroundWindow(AHANDLE) then            
              Popup.Popup(tmpPoint.X,tmpPoint.Y);  
          end;       
    end;
  end;

edit: Workaround:

Use VCL.Menu. instead of Firemonkey.menus

r_j
  • 1,348
  • 15
  • 35
  • 1
    Have you tried to do, what `TCustomTrayIcon` does ? It sets the `Application` window to front and processes the messages in the queue. So try to add `SetForegroundWindow(Application.Handle); Application.ProcessMessages;` before you popup the menu. – TLama Mar 05 '13 at 14:20
  • I guess this boils down to how we translate the code in @TLama's comment into FMX. – David Heffernan Mar 05 '13 at 14:54
  • 1
    From my now deleted answer: Don't use `GetCursorPos`, use `GetMessagePos`. Remember that people use the keyboard as well as the mouse. – David Heffernan Mar 05 '13 at 14:54
  • So i need to get the Handle of the Application , not the Mainform, and set it as foregroundwindow. Tobad Fmx doenst had sometinhg like this, may need to use another shellApi for it? – r_j Mar 05 '13 at 15:00
  • There only is one shell API for notification icons. You're using it. I've no idea what the equivalent to Application.Handle is in FMX. The main form handle would have been my guess. – David Heffernan Mar 05 '13 at 15:06
  • 1
    Use `FmxHandleToHWND(Form1.Handle);` in the FMX.Plaform.Win unit to get the handle for the main (or other) form. – Mike Sutton Mar 05 '13 at 20:07
  • thats what i've been doing – r_j Mar 06 '13 at 07:56

1 Answers1

2

I can't comment on why your menu appears behind the taskbar, as I have never seen that happen, but I can comment on something else in your code. Your icon handler needs to use WM_RBUTTONUP or WM_CONTEXTMENU and not WM_RBUTTONDOWN. Also, to combat a well-known OS bug that does not dismiss the popup menu correctly when the mouse is clicked outside of the menu, you need to wrap Popup() with both SetForegroundWindow() and WM_NULL but you are only doing half of that.

procedure TPWTrayIcon.HandleIconMessage(var Msg: TMessage);
var
  tmpPoint: TPoint;
begin
  if Msg.Msg = WM_NOTIFYICON then begin
    case LOWORD(Msg.LParam) of
      WM_RBUTTONUP: // or WM_CONTEXTMENU
        if Assigned(PopUp) then begin
          Cardinal(tmpPoint) := GetMessagePos;
          SetForegroundWindow(AHANDLE);
          Popup.Popup(tmpPoint.X, tmpPoint.Y);
          PostMessage(AHANDLE, WM_NULL, 0, 0);  
        end;       
    end;
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770