Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Eigenes Handle finden (https://www.delphipraxis.net/141221-eigenes-handle-finden.html)

Schwedenbitter 5. Okt 2009 16:13

Re: Eigenes Handle finden
 
Zitat:

Zitat von Sherlock
Wenn Du kein Handle hast, dann kannst Du auch keines übergeben, versuchs an der Stelle mal mit nil oder so.

nil kann nicht gehen (Siehe oben). Und 0 bringt auch kein Ergebnis. Das hatte ich noch vor dem Erstellen des Thread selbst probiert.

Ich habe aber hier zufällig eine Lösung gefunden. Es wird - wenn auch in anderer Sache - einfach mit FindWindow ein temporäres Handle abgefragt und dann mit diesem die Function aufgerufen. Bis jetzt klappt das so. Wenn ich ein paar mehr Tests damit erfolgreich gemacht habe, dann wird der Thread als gelöst markiert!

@Luckie
Mit EnumWindows muss ich mich noch belesen. Die Frage war im Grunde nur am Rande und wird später noch gebraucht werden. Danke für den Tip.

Gruß, Alex

[EDIT]Also die Tests laufen Prima. :cheers: Mein Problem ist damit gelöst - die Ausgangsfrage von mir aber nicht: Denn ich kann jetzt zwar die Funktion erfolgreich aufrufen. Das Handle meiner nonVCL-Anwendung kenne ich aber immer noch nicht.[/EDIT]

turboPASCAL 5. Okt 2009 18:13

Re: Eigenes Handle finden
 
Wie ist denn deine App nun aufgebaut ?

Ein Handle bekommt diese erst wenn sie auf irgrnd eine Weise ein Fenster erstellt.


Delphi-Quellcode:
programm Noppe;

uses
  Windows;

begin
  while True do
  begin
    Time = GetTickCount;
  end;
end.
Hat zB. kein Handle, sondern nur eine Process ID.

Schwedenbitter 5. Okt 2009 20:15

Re: Eigenes Handle finden
 
Zitat:

Zitat von turboPASCAL
Wie ist denn deine App nun aufgebaut ?
Ein Handle bekommt diese erst wenn sie auf irgrnd eine Weise ein Fenster erstellt.

Dann habe ich maximal eine ProcessID. Es ist ein Programm wie zu Zeiten von TurboPascal 5 (= war das erste, mit dem ich Kontakt hatte). Ein Fenster kommt nur, wenn es einen Fehler gibt zur Information des Benutzer ohne jede Interaktion. Ohne Fehler, gibts auch kein Fenster.
Zum Ablauf: Wenn der Benutzer eine Datei bearbeiten möchte, wird diese auf seinen Rechner in ein Temp-Verzeichnis kopiert. Dort mit dem in Win verknüpften Programm geöffnet. Das Programm wird überwacht (Fenstername und Lock-Datei). Für ersteres brauchte ich ein Handle. Wenn die Datei geschlossen wird, wird geprüft, ob es Änderungen gibt und die Datei dann zurückkopiert oder verworfen. Der Sinn ist es einem lahmen VPN auf die Sprünge zu helfen, kurzfristige Netzausfälle abzupuffern und die Anzahl der über das VPN offen gehaltenen Dateien möglichst auf Null zu reduzieren.

Also müsste der Titel vom Thread wohl eher lauten: Eigenes Handle von fensterlosem Programm finden. Soll ich das - soweit noch möglich - ändern?

Gruß, Alex

Fridolin Walther 5. Okt 2009 20:34

Re: Eigenes Handle finden
 
Ohje, da läuft ja einiges an einander vorbei ...

Zuerst einmal Schwedenbitter ist es so, daß nonVCL von den meisten so aufgefasst wird, daß Du eine Anwendung mit Fenstern hast, bei der Du aber keine VCL Komponenten verwendest sondern direkt auf die Windows Fenster API zugreifst. Daher hat Dich auch jeder gefragt, wieso Du das Handle zu Deinem Fenster nicht hast, wenn Du es denn schon manuell erstellt hast. Da Du aber offensichtlich eine Anwendung hast, die keine Fenster anzeigt oder besitzt, ist die Frage recht simpel:

Wenn Du kein Fenster erstellst, hast Du auch kein Fenster Handle. Willst Du ein eigenes Fenster Handle haben, musst Du eines erstellen.

Ansonsten scheinst Du ja mit Hilfe des Fenster Handle überprüfen zu wollen, ob eine bestimmte Anwendung noch aktiv ist. Das ist um ehrlich zu sein weder sonderlich effektiv noch sicher. Aber wenn Du genau schilderst (am Besten mit exakten Anwendungsnamen) was Du möchtest, wird man Dir sicher nähere Informationen geben können.

Schwedenbitter 5. Okt 2009 23:50

Re: Eigenes Handle finden
 
Zitat:

Zitat von Fridolin Walther
Ansonsten scheinst Du ja mit Hilfe des Fenster Handle überprüfen zu wollen, ob eine bestimmte Anwendung noch aktiv ist.

Genau das ist/war mein Ziel. :lol:

Zitat:

Zitat von Fridolin Walther
Das ist um ehrlich zu sein weder sonderlich effektiv noch sicher.

Was ist effektiver und sicherer? Ich frage gerade deshalb und lerne gern dazu. Diese Behauptung aufzustellen ist leicht. Eine funktionierende Alternative anzubieten aber offenbar schwer.

Zitat:

Zitat von Fridolin Walther
Aber wenn Du genau schilderst (am Besten mit exakten Anwendungsnamen) was Du möchtest, wird man Dir sicher nähere Informationen geben können.

Das habe ich schon und niemand hatte bislang eine bessere Idee! Ich gehe jetzt schlafen. Vielleicht hat sich ja bis morgen mein Problem gelöst und jemand eine bessere Idee gepostet.

Das Problem mit dem Handle hat sich sowieso relativiert: Ich habe jetzt ein paar Fehler provoziert und festgestellt, dass meine Fehlermeldungen nicht in den Vordergrund kommen / von anderen geöffneten Fenstern verdeckt sind. Das ist schlecht, weil sie so niemand sieht und ich musste nachhelfen. Hierzu brauchte ich wiederum das vor Erstellung meines ersten Fensters nicht existente Handle meines Programms. Also habe ich mir ein Message-Only-Window erstellt und kann so dessen Handle gleich verwenden.

Wie gesagt: Ich bin für Tipps immer offen. 8)

Gruß, Alex

Fridolin Walther 6. Okt 2009 10:19

Re: Eigenes Handle finden
 
Zitat:

Zitat von Schwedenbitter
Zitat:

Zitat von Fridolin Walther
Aber wenn Du genau schilderst (am Besten mit exakten Anwendungsnamen) was Du möchtest, wird man Dir sicher nähere Informationen geben können.

Das habe ich schon und niemand hatte bislang eine bessere Idee! Ich gehe jetzt schlafen. Vielleicht hat sich ja bis morgen mein Problem gelöst und jemand eine bessere Idee gepostet.

Wenn Du nicht darauf warten möchtest, das OpenOffice sich beendet, weil Du befürchtest die Synchronisation würde darunter leiden, wäre es evtl. sinnvoll 2 Methoden zu kombinieren:

Mit MSDN-Library durchsuchenFindFirstChangeNotification warten bis sich die Datei ändert und gegebenenfalls synchronisieren und das ganze so lange fortführen bis die Anwendung geschlossen wurde.

Zitat:

Wie gesagt: Ich bin für Tipps immer offen. 8)
Wenn Du von Deiner Fensterlösung nicht weg willst, wäre es eindeutig sinnvoller sich mit EnumDesktopWindows alle Fenster des Desktops zu holen und über die Fenster Klasse die für Dich relevanten Fenster zu identifizieren:
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE}

uses
  Windows;

type
  TOpenOfficeWindow = record
    WindowHandle: THandle;
    WindowTitle: string;
  end;

  TOpenOfficeWindowArray = array of TOpenOfficeWindow;
  POpenOfficeWindowArray = ^TOpenOfficeWindowArray;

function EnumWindowsCallback(hwnd: THandle; WindowArray: POpenOfficeWindowArray)
  : LongBool; stdcall;
const
  WINDOW_TITLE_BUFFER_SIZE = 65 * 1024;
  OPENOFFICE_WINDOW_CLASSNAME = 'SALFRAME';
var
  WindowTitle: array [0 .. WINDOW_TITLE_BUFFER_SIZE] of WideChar;
  WindowClassName: array [0 .. WINDOW_TITLE_BUFFER_SIZE] of WideChar;
begin
  Result := true;
  // Uns interessieren nur sichtbare Fenster
  if IsWindowVisible(hwnd) then
    begin
      // Wir holen uns den ClassName des Fensters
      FillChar(WindowClassName, SizeOf(WindowClassName), 0);
      if (GetClassName(hwnd, @WindowClassName, WINDOW_TITLE_BUFFER_SIZE) > 0)
        and (WindowClassName = OPENOFFICE_WINDOW_CLASSNAME) then
        begin
          // Wir ermitteln den Fenster Titel
          FillChar(WindowTitle, SizeOf(WindowTitle), 0);
          GetWindowText(hwnd, @WindowTitle, WINDOW_TITLE_BUFFER_SIZE);

          // Wir erweitern das übergebene WindowArray um 1 und füllen es mit den ermittelten Informationen
          SetLength(WindowArray^, Length(WindowArray^) + 1);
          WindowArray^[ High(WindowArray^)].WindowHandle := hwnd;
          WindowArray^[ High(WindowArray^)].WindowTitle := WindowTitle;
        end;
    end;
end;

function EraseAndFillWindowArray(var WindowArray: TOpenOfficeWindowArray)
  : Boolean;
begin
  // Array löschen
  SetLength(WindowArray, 0);
  // Wir lassen uns alle Fenster zurückgeben die auf dem Desktop angezeigt werden
  EnumDesktopWindows(0, @EnumWindowsCallback, Cardinal(@WindowArray));
  // Falls Einträge im WindowArray vorhanden sind, geben wir true, ansonsten false zurück
  Result := Length(WindowArray) <> 0;
end;

var
  WindowArray: TOpenOfficeWindowArray;
  i : Integer;

begin
  writeln(EraseAndFillWindowArray(WindowArray));
  writeln;
  for i := 0 to Length(WindowArray) - 1 do
    begin
      writeln('Fenster Handle: ', WindowArray[i].WindowHandle);
      writeln('Fenster Titel: ', WindowArray[i].WindowTitle);
      writeln;
    end;
  readln;
end.
Bei mir ergibt das folgenden Output:
Code:
TRUE

Fenster Handle: 196900
Fenster Titel: On-Access scanner design.docx - OpenOffice.org Writer

Fenster Handle: 527992
Fenster Titel: onaccessscannerdesign.docx - OpenOffice.org Writer
Jetzt könntest Du Dir noch aus dem Fenstertitel den Dateinamen herauspopeln und wüsstest damit sogar welches Fenster zu welcher Datei gehört (vorrausgesetzt die Dateinamen sind unterschiedlich).


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:26 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz