加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi:如何在外部应用程序上正确使用ShowWindow

发布时间:2020-12-15 10:11:30 所属栏目:大数据 来源:网络整理
导读:参见英文答案 How can I make the second instance of my program pass control back to the first instance?1个 See also: 07001 我在启动应用程序之前使用以下代码,以检查是否有另一个实例 它已经开始了: var _PreviousHandle : THandle;begin _PreviousH
参见英文答案 > How can I make the second instance of my program pass control back to the first instance?1个

See also:
07001

我在启动应用程序之前使用以下代码,以检查是否有另一个实例
它已经开始了:

var _PreviousHandle : THandle;
begin
  _PreviousHandle := FindWindow('TfrmMainForm',nil);
  if _PreviousHandle <> 0 then
  begin
    ShowMessage('Application "" is already running!');
    SetForegroundWindow(_PreviousHandle);
    ShowWindow(_PreviousHandle,SW_SHOW);
    Application.Terminate;
    Exit;
  end;
...

但是,如果它已经启动,我需要显示该应用程序.问题是以这种方式显示最小化按钮不再起作用,当我单击任务栏中的图标时,它“取消最小化”,并且显示的动画就像它被最小化一样.我错过了什么吗?是否有一种适当的方式来激活和显示外部应用程序,同时它被最小化?

解决方法

这是一个完整的项目,它只运行一个应用程序实例,并且应该将已运行的实例窗口带到前面.

您可以下载testing project或尝试以下代码:

Project1.dpr

program Project1;

uses
  Forms,Windows,Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
  Mutex: THandle;
const
  AppID = '{0AEEDBAF-2643-4576-83B1-8C9422726E98}';
begin
  MessageID := RegisterWindowMessage(AppID);

  Mutex := CreateMutex(nil,False,AppID);
  if (Mutex <> 0) and (GetLastError = ERROR_ALREADY_EXISTS) then
  begin
    PostMessage(HWND_BROADCAST,MessageID,0);
    Exit;
  end;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1,Form1);
  Application.Run;
end.

Unit1.pas

unit Unit1;

interface

uses
  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StrUtils,StdCtrls;

type
  TForm1 = class(TForm)
  private
    function ForceForegroundWindow(WndHandle: HWND): Boolean;
    function ForceRestoreWindow(WndHandle: HWND; Immediate: Boolean): Boolean;
  protected
    procedure WndProc(var AMessage: TMessage); override;
  end;

var
  Form1: TForm1;
  MessageID: UINT;

implementation

{$R *.dfm}

{ TForm1 }

function TForm1.ForceForegroundWindow(WndHandle: HWND): Boolean;
var
  CurrThreadID: DWORD;
  ForeThreadID: DWORD;
begin
  Result := True;
  if (GetForegroundWindow <> WndHandle) then
  begin
    CurrThreadID := GetWindowThreadProcessId(WndHandle,nil);
    ForeThreadID := GetWindowThreadProcessId(GetForegroundWindow,nil);
    if (ForeThreadID <> CurrThreadID) then
    begin
      AttachThreadInput(ForeThreadID,CurrThreadID,True);
      Result := SetForegroundWindow(WndHandle);
      AttachThreadInput(ForeThreadID,False);
      if Result then
        Result := SetForegroundWindow(WndHandle);
    end
    else
      Result := SetForegroundWindow(WndHandle);
  end;
end;

function TForm1.ForceRestoreWindow(WndHandle: HWND;
  Immediate: Boolean): Boolean;
var
  WindowPlacement: TWindowPlacement;
begin
  Result := False;
  if Immediate then
  begin
    WindowPlacement.length := SizeOf(WindowPlacement);
    if GetWindowPlacement(WndHandle,@WindowPlacement) then
    begin
      if (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED) <> 0 then
        WindowPlacement.showCmd := SW_MAXIMIZE
      else
        WindowPlacement.showCmd := SW_RESTORE;
      Result := SetWindowPlacement(WndHandle,@WindowPlacement);
    end;
  end
  else
    Result := SendMessage(WndHandle,WM_SYSCOMMAND,SC_RESTORE,0) = 0;
end;

procedure TForm1.WndProc(var AMessage: TMessage);
begin
  inherited;
  if AMessage.Msg = MessageID then
  begin
    if IsIconic(Handle) then
      ForceRestoreWindow(Handle,True);
    ForceForegroundWindow(Application.Handle);
  end;
end;

end.

在OS版本上测试:

> Windows 8.1 64位
> Windows 7 SP1 64位家庭高级版
> Windows XP SP 3 32位专业版

已知问题和限制:

>根本没有考虑MainFormOnTaskbar;此时必须设置为True

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读