【问题标题】:How to minimize to the tray on FMX如何在 FMX 上最小化到托盘
【发布时间】:2020-01-02 21:59:40
【问题描述】:

我正在为我的工作应用程序创建一个启动器。我希望当我最小化应用程序时,他会去托盘。我设法用按钮创建图标(单击调用 proc),但我不知道我需要调用 proc 什么事件,没有像 Onminized 这样的事件并且事件 OnHide 不影响。我看到一些关于使用 Hook 的帖子(我不太确定是什么),我尝试了一下,但出现错误: [dcc32 错误] UMain.pas(129): E2036 需要变量。

这点在这里:

 procedure TfrmMain.FormCreate(Sender: TObject);
            begin
                SetWindowsHookEx(WH_CALLWNDPROC, @WndProc, 0, GetCurrentThreadId);               
             end;

更具体到 @wndProc,我尝试删除 @ 并得到 [dcc32 Error] UMain.pas(129): E2009 Incompatible types: 'regular procedure and method pointer'

   Type...

       function WndProc(Code: integer; WParam, LParam: LongInt): LRESULT; stdcall;
    var
            WndProcHook: THandle;
    const 
            WM_TRAYICON =WM_USER+1;

------------------------------------------------------

    procedure TfrmMain.FormCreate(Sender: TObject);

                begin
                SetWindowsHookEx(WH_CALLWNDPROC, @WndProc, 0, GetCurrentThreadId);
                .... 
                end; 
        function TfrmMain.WndProc(Code: integer; WParam, LParam: LongInt): LRESULT;    stdcall;
        var
          msg: TCWPRetStruct;
        begin;


          if (Code >= HC_ACTION) and (LParam > 0) then begin
            msg := PCWPRetStruct(LParam)^;
            if (msg.Message = WM_SIZE) and (msg.WParam = SIZE_MINIMIZED) then begin
              criaIcone;


            end;
          end;
          result := CallNextHookEx(WndProcHook, Code, WParam, LParam)
        end;
//
procedure TfrmMain.CriaIcone;
var
   NotifyIconData: TNotifyIconData;
begin
   with NotifyIconData do
   begin
    cbSize          := SizeOf;
      Wnd             := AllocateHWnd(WMTrayIcon);
      uID             := 0;
      uCallbackMessage:= WM_TRAYICON;
      uFlags          := NIF_ICON or NIF_TIP or NIF_MESSAGE;
      hIcon           := GetClassLong(FmxHandleToHWND(self.Handle),GCL_HICONSM);
      szTip           := 'Teste TrayIcon';
   end;
   Shell_NotifyIcon(NIM_ADD, @NotifyIconData);
end;

【问题讨论】:

  • 您不能对SetWindowsHookEx() 回调使用非静态类方法。所以你的TfrmMain.WndProc() 不会为此工作。您需要改为使用独立函数或类静态方法。话虽如此,我根本不建议使用SetWindowsHookEx() 来完成这项任务。使用SetWindowsLongPtr(GWL_WNDPROC) 或更好的SetWindowSubclass() 直接挂钩表单的FMX 创建的HWND。见FMX - Trayicon message handling
  • 请注意,任务栏右侧时钟旁边区域的正式名称是notification area
  • @RemyLebeau 感谢您的 cmets。我试图理解,但没有走得太远。我复制了你的样本并放了一条节目信息和一个frmMain.WindowState := TWindowState.wsMaximized;。但是当我将鼠标放在图标托盘上并且应用程序未最小化时,它们只会触发。因此,我尝试将我的 proc(WndProc 提早提到)并且无法做到这一点,我知道 CODE 是什么,所以我将WM_ICONTRAY 更改为WM_SIZE。什么也没发生,有什么想法吗?
  • 是的,我是白痴,对不起。我刚刚滚动了一点你链接的帖子并得到了我需要的东西(点击后响应)。现在的问题是,我不知道如何使我的表单处于活动状态或恢复正常。我尝试在 proc 中使用命令 wsMaximazied 并且没有任何操作,(他被最大化,但他没有走到前面。我需要单击任务栏)。但我认为这不是一个大问题,也许是另一篇文章。 ai是怎么发完帖子的? (只需编辑即可解决?)

标签: delphi hook firemonkey


【解决方案1】:

问题就像@RemyLebeau 所说的那样。我对 Delphi 很陌生(3 个月)
这是代码,我用了很多这篇帖子的代码:FMX - Trayicon message handling

有效的代码:

type
....
      procedure FormCreate(Sender: TObject);
      procedure DestroyIcone;



  const
      WM_ICONTRAY = WM_USER + 1;

    private
        { Private declarations }
        create : integer;

        TrayWnd: HWND;
        TrayIconData: TNotifyIconData;
        TrayIconAdded: Boolean;
        procedure TrayWndProc(var Message: TMessage);
   implementation

procedure TfrmMain.FormCreate(Sender: TObject);  
    begin
        TrayWnd := AllocateHWnd(TRayWndProc); // Alocate the wndProc
      with TrayIconData do
      begin                // Instaciate
        cbSize := SizeOf;
        Wnd := TrayWnd;
          uID := 1;
        uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
        uCallbackMessage := WM_ICONTRAY;
        hIcon := GetClassLong(FmxHandleToHWND(self.Handle), GCL_HICONSM);
        StrPCopy(szTip, 'testapp');
      end;
    //creating the icon 
     if not  TrayIconAdded then
      TrayIconAdded := Shell_NotifyIcon(NIM_ADD, @TrayIconData) ;

procedure TfrmMain.TrayWndProc(var Message: TMessage);

begin
 if Message.MSG = WM_ICONTRAY then
  begin
      case Message.LParam of
     WM_LBUTTONDOWN:
                     begin
                      frmMain.Show;//If u use some frmMain.hide 
                      SetForegroundWindow(FmxHandleToHWND(frmMAin.Handle));
                      if TrayIconAdded then
                      begin
                      //Shell_NotifyIcon(NIM_DELETE, @TrayIconData);
                      TrayIconAdded := false;
                      ShowAppOnTaskbar(frmMain);
                      end;

                      end;

       WM_RBUTTONDOWN: ShowMessage('RolePlay , but can be a PopUpMenu');

      end;
     end
  else
    Message.Result := DefWindowProc(TrayWnd, Message.Msg, Message.WParam, Message.LParam);
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    相关资源
    最近更新 更多