Đây là một dự án hoàn chỉnh, chỉ tiếp tục chạy một phiên bản của ứng dụng, và điều này sẽ làm cho cửa sổ thể hiện đang chạy đến trước.
Bạn có thể tải về một testing project
hoặc thử mã, mà sau:
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, 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, CurrThreadID, 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.
Tested trên các phiên bản hệ điều hành:
- Windows 8.1 64-bit
- Windows 7 SP1 64-bit Home Premium
- Windows XP SP 3 32-bit Professional
Các vấn đề và giới hạn đã biết:
MainFormOnTaskbar
không được tính đến; nó phải được đặt thành True tại thời điểm này
bạn nên sử dụng 'Mutex' để thực hiện việc kiểm tra và phát thông báo này để thông báo cho trường hợp hiện tại – teran
Vấn đề không phải là làm cách nào để biết chương trình của tôi có đang chạy hay không, mà là cách kích hoạt nó đúng cách từ một phiên bản khác của chương trình đó. – ertx
gửi tin nhắn quảng bá với mã đã biết ('RegisterWindowMessage'), sau đó xử lý thông báo này trong chương trình và để chương trình tự khôi phục. – teran