Einzelnen Beitrag anzeigen

RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#18

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 6. Mär 2013, 15:11
Letzter Stand (2. Instanz bringt die erste nach vorn):
Delphi-Quellcode:
const
  ProgUID = 'geheim :-p';
  WM_AnswerToSecondInstance = WM_USER + 1;

var
  HMutex: THandle = 0;
  PBroadcastRecipients: PDWORD;
  WM_CCCSingleInstanceBroadcast: UINT = 0;

function TIrgendeineKlasse.SingleInstanceBroadcastReceiver(var m: TMessage): Boolean; // muss zwecks Akzeptanz durch Application.HookMainWindow als Methode einer Klasse implementiert sein
var
  LHandle: HWnd;
  TopWindow: HWnd;
begin
  Result := False;
  if m.Msg = WM_CCCSingleInstanceBroadcast then
  begin
    // Logic copied from Application.BringToFront
    if Application.MainFormOnTaskBar and (Application.MainForm <> nil) then
      LHandle := Application.MainForm.Handle
    else
      LHandle := Application.Handle;
    if LHandle <> 0 then
    begin
      TopWindow := GetLastActivePopup(LHandle);
      if (TopWindow <> 0) and (TopWindow <> Application.Handle) and
        IsWindowVisible(TopWindow) and IsWindowEnabled(TopWindow) then
        PostMessage(m.WParam, m.LParam, TopWindow, 0);
    end;
  end;
end;

function TIrgendeineKlasse.SecondInstanceReceiver(var m: TMessage): Boolean; // muss zwecks Akzeptanz durch Application.HookMainWindow als Methode einer Klasse implementiert sein
begin
  Result := False;
  case m.Msg of
    WM_AnswerToSecondInstance:
      SetForegroundWindow(m.WParam);
  end;
end;

initialization

  WM_CCCSingleInstanceBroadcast := RegisterWindowMessage(ProgUID); // eindeutige Message-ID holen
  HMutex := CreateMutex(nil, True, ProgUID);
  if (HMutex = 0) or (GetLastError = ERROR_ALREADY_EXISTS) or
     (GetLastError = ERROR_ACCESS_DENIED) then
  begin
    // dieser Code läuft nur in der 2. Instanz des Programms
    Application.HookMainWindow(TIrgendeineKlasse.SecondInstanceReceiver); // Klassenmethode sollte gehen - dieser Teil ist bei mir ganz anders umgesetzt
    New(PBroadcastRecipients);
    try
      PBroadcastRecipients^ := BSM_APPLICATIONS;
      BroadcastSystemMessage(BSF_IGNORECURRENTTASK, PBroadcastRecipients,
        WM_CCCSingleInstanceBroadcast, MessageDistributor.Handle,
        WM_AnswerToSecondInstance); // an alle: hier ist noch einer
    finally
      Dispose(PBroadcastRecipients);
    end;
    SwitchToThread; // Rest der Zeitscheibe verwerfen, damit die 1. Instanz antworten kann (falls das durch Race-Condition nicht klappt: Pech gehabt)
    Application.ProcessMessages; // Antwort verarbeiten
    MessageBox(0, 'Das Programm läuft bereits', '',
      MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST); // über die erste Instanz legen
    Halt;
  end;
  Application.HookMainWindow(TIrgendeineKlasse.SingleInstanceBroadcastReceiver); // Klassenmethode sollte gehen - dieser Teil ist bei mir ganz anders umgesetzt

finalization

  if HMutex > 0 then
    CloseHandle(HMutex);

end.
Mann, ist das viel Code geworden, aber letztlich steckt ja gar nicht so viel dahinter...
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat