170 lines
4.4 KiB
ObjectPascal
170 lines
4.4 KiB
ObjectPascal
unit AppInstDemoMain;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
JclAppInst, ComCtrls, StdCtrls;
|
|
|
|
type
|
|
TForm1 = class(TForm)
|
|
InstancesListView: TListView;
|
|
Label1: TLabel;
|
|
SwitchBtn: TButton;
|
|
MsgBtn: TButton;
|
|
ColorDialog1: TColorDialog;
|
|
Memo1: TMemo;
|
|
SendBtn: TButton;
|
|
AutoUpdateCheckBox: TCheckBox;
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure SwitchBtnClick(Sender: TObject);
|
|
procedure MsgBtnClick(Sender: TObject);
|
|
procedure SendBtnClick(Sender: TObject);
|
|
procedure Memo1Change(Sender: TObject);
|
|
private
|
|
procedure BuildInstancesList;
|
|
procedure ApplicationEvents1Message(var Msg: TMsg; var Handled: Boolean);
|
|
public
|
|
procedure WndProc(var Message: TMessage); override;
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
{$R *.DFM}
|
|
|
|
const
|
|
MaxAllowedInstances = 3;
|
|
|
|
MyDataKind = 1;
|
|
|
|
{ TForm1 }
|
|
|
|
procedure TForm1.BuildInstancesList;
|
|
var
|
|
I, CurrIndex: Integer;
|
|
begin
|
|
with InstancesListView, JclAppInstances do
|
|
begin
|
|
Items.BeginUpdate;
|
|
Items.Clear;
|
|
for I := 0 to InstanceCount -1 do
|
|
with Items.Add do
|
|
begin
|
|
Caption := IntToStr(I + 1);
|
|
SubItems.Add(Format('%.8x', [ProcessIDs[I]]));
|
|
SubItems.Add(Format('%.8x', [AppWnds[I]]));
|
|
end;
|
|
CurrIndex := InstanceIndex[GetCurrentProcessId];
|
|
Selected := Items[CurrIndex];
|
|
Items.EndUpdate;
|
|
end;
|
|
Label1.Caption := IntToStr(CurrIndex + 1);
|
|
end;
|
|
|
|
procedure TForm1.FormCreate(Sender: TObject);
|
|
begin
|
|
Application.OnMessage := ApplicationEvents1Message;
|
|
BuildInstancesList;
|
|
end;
|
|
|
|
procedure TForm1.ApplicationEvents1Message(var Msg: TMsg; var Handled: Boolean);
|
|
begin
|
|
// AI_* messages handler. These messages are automatically send to all instances
|
|
// of the application.
|
|
with Msg do
|
|
if (hwnd = 0) and (message = JclAppInstances.MessageID) then
|
|
begin
|
|
case wParam of
|
|
AI_INSTANCECREATED, AI_INSTANCEDESTROYED:
|
|
BuildInstancesList;
|
|
AI_USERMSG:
|
|
Label1.Font.Color := TColor(lParam);
|
|
end;
|
|
Handled := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.SwitchBtnClick(Sender: TObject);
|
|
begin
|
|
JclAppInstances.SwitchTo(InstancesListView.Selected.Index);
|
|
end;
|
|
|
|
procedure TForm1.MsgBtnClick(Sender: TObject);
|
|
begin
|
|
with ColorDialog1 do
|
|
begin
|
|
Color := Label1.Font.Color;
|
|
if Execute then
|
|
JclAppInstances.UserNotify(Color);
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.SendBtnClick(Sender: TObject);
|
|
begin
|
|
// TForm.ClassName matches window class name. It sends the data to all windows
|
|
// belonging instances of this application. The last parameter identifies the
|
|
// 'TForm1' (ClassName) window of this instance.
|
|
JclAppInstances.SendStrings(ClassName, MyDataKind, Memo1.Lines, Handle);
|
|
end;
|
|
|
|
var
|
|
MemoChanging: Boolean;
|
|
|
|
procedure TForm1.WndProc(var Message: TMessage);
|
|
begin
|
|
// Interprocess communication handler.
|
|
|
|
// First check whether we can safely read TForm.Handle property ...
|
|
if HandleAllocated and not (csDestroying in ComponentState) then
|
|
begin
|
|
// ... then whether it is our message. The last paramter tells to ignore the
|
|
// message sent from window of this instance
|
|
case ReadMessageCheck(Message, Handle) of
|
|
MyDataKind: // It is our data
|
|
begin
|
|
MemoChanging := True; // prevent deadlock, TMemo.OnChange is also fired now
|
|
Memo1.Lines.BeginUpdate;
|
|
try
|
|
// Read TStrings from the message
|
|
ReadMessageStrings(Message, Memo1.Lines)
|
|
finally
|
|
Memo1.Lines.EndUpdate;
|
|
MemoChanging := False;
|
|
end;
|
|
end;
|
|
else
|
|
inherited;
|
|
end;
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
|
|
procedure TForm1.Memo1Change(Sender: TObject);
|
|
begin
|
|
if not MemoChanging and AutoUpdateCheckBox.Checked then
|
|
SendBtnClick(nil);
|
|
end;
|
|
|
|
initialization
|
|
|
|
with JclAppInstances do
|
|
// CheckInstance returns False if current instance number is greater than
|
|
// MaxAllowedInstances constant
|
|
if not CheckInstance(MaxAllowedInstances) then
|
|
begin
|
|
// Switch to the first instance of the application
|
|
SwitchTo(0);
|
|
// Close this instance
|
|
KillInstance;
|
|
end;
|
|
|
|
// Note: For preventing more than one instance of the application you can put
|
|
// simple JclAppInstances.CheckSingleInstance line to initialization section
|
|
// instead of code above
|
|
|
|
end.
|