Entwickler-Ecke
Windows API - API: EnumMonitors benutzen
NeoInDerMATRIX - Do 20.01.05 03:47
Titel: API: EnumMonitors benutzen
Hi,
ich habe ein kleines Problem. Ich benötige die Function "EnumMonitorsA" aus "WinSpool.drv". Soweit so gut. Allerdings habe ich jetzt das problem das ich es nicht hin bekomme die Function koreckt aufzurufen. Ich bekomme per OSError abfrage immer mitgeteilt das ich die Parameter falsch übergebe. Das WinSDK ist leider auch nicht wirklich hilfreich.
Delphi-Quelltext
1:
| Function EnumMonitors(AServerName: pChar; ALevel: DWord; ABuffer: Pointer; ABufferSize: DWord; ABufferNeed: Pointer; ABufferReturned: Pointer): Boolean; StdCall; External 'WinSpool.drv' Name 'EnumMonitorsA'; |
Ich denke ich sehe den Wald for lauter Bäumen nicht.
Also so weit ich das jetzt weis, muss ich die Function einmal mit ABufferSize:=0 aufrufen um die Benötigte Puffer größe zu bekommen. Allerdings bekomme ich dabei bereits einen Fehler. Ich denke ich habe das ganze falsch nach Delphi übersetzt. Deshalb hier die definition aus dem SDK:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| BOOL EnumMonitors( LPTSTR pName, // server name DWORD Level, // information level LPBYTE pMonitors, // monitor information buffer DWORD cbBuf, // size of monitor information buffer LPDWORD pcbNeeded, // bytes received or required LPDWORD pcReturned // number of monitors received ); |
Ich hoffe das mir einer von euch helfen kann.
Thx & Cu
Neo
Delete - Do 20.01.05 03:49
Deklarier die letzten beiden Parameter mal als var Parameter, du willst ja was zurück bekommen. Sorry, da stimmt noch mehr nicht.
NeoInDerMATRIX - Do 20.01.05 04:01
Hi,
@Luckie: Ja das habe ich bereits probiert. Allerdings macht das bei dem letztem Parameter nicht wirklich sin, wenn ich das aus dem SDK richtig verstanden habe!
Aber auch als Var bekomme ich eine Fehler.
Aber trotzdem danke.
Cu
Neo
Delete - Do 20.01.05 04:27
Was willst du eigentlich damit in Erfahrung birngen? Die Anzahl der Monitore? dann wäre wohl
ENUMDISPLAYDEVICES oder
ENUMDISPLAYMONITORS die richtige Wahl. Ich weiß nämlich gar nicht, ob man diese Funktion so aus der drv Datei aufrufen kann. Denn theoretisch sollte es so gehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| type TMONITOR_INFO_1 = record Name: PChar; end; PMONITOR_INFO_1 = ^TMONITOR_INFO_1;
function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer; cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean; stdcall; external 'WinSpool.drv' Name 'EnumMonitorsA';
procedure TForm1.Button1Click(Sender: TObject); var Needed : DWORD; Returned : DWORD; Monitors : Pointer; pWork : Pointer; i : Integer; begin Monitors := nil;
if (not EnumMonitors(nil, 1, Monitors, 0, Needed, Returned) and (GetLastError = ERROR_INSUFFICIENT_BUFFER)) then begin EnumMonitors(nil, 1, Monitors, Needed, Needed, Returned); pWork := Monitors; for i := 0 to Returned - 1 do begin ShowMessage(PMONITOR_INFO_1(pWork)^.Name); Inc(Integer(pWork), sizeof(TMONITOR_INFO_1)); end; end; end; |
Aber beim zweiten Aufruf bekomme ich eine AccessViolation.
NeoInDerMATRIX - Do 20.01.05 22:21
Hi Luckie,
also die anzahl der Monitore habe ich schon. Ich benötige noch den Treiber für den Monitor und den rest der Strings aus der Monitor_Info_2 strucktur.
Laut WinSDK soll das euch eigentlich nicht aus der WinSpool.drv gelesen werden sondern aus der WinSpool.lib. Allerdings ist dies nicht möglich. Da ich diese nicht als DLL oder so laden kann. Und nach suchen auf meinem System war nur eine WinSpool.drv vorhanden. Aus diesem grund habe ich das versucht. Und als ich nur den Fehlercode Ungültiger Parameter zurückbekommen habe, dachte ich das es ja dann möglich sein müste.
Deine Code werde ich mal probieren. Ich melde mich dann auch gleich wenn ich etwas weis.
Und danke für deine Hilfe.
Cu
Neo
NeoInDerMATRIX - Do 20.01.05 23:05
Hi,
also ich habe es jetzt zum laufen gebracht. Auch wenn es leider nicht die Information bringt die ich gesucht habe. Diese Function Listet Drucker, Modem, und komischer weise TCP/IP Port.
Was bei Luckie gefehlt hat ist nur das beim zweiten aufruf ein speicherbereich vorhanden sein muss.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
| type TMONITOR_INFO_1 = record Name: PChar; end; PMONITOR_INFO_1 = ^TMONITOR_INFO_1;
function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer; cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean; stdcall; external 'WinSpool.drv' Name 'EnumMonitorsA';
procedure TForm1.Button1Click(Sender: TObject); var Needed : DWORD; Returned : DWORD; Monitors : Pointer; pWork : Pointer; i : Integer; begin Monitors := nil;
if (not EnumMonitors(nil, 1, Monitors, 0, Needed, Returned) and (GetLastError = ERROR_INSUFFICIENT_BUFFER)) then begin EnumMonitors(nil, 1, Monitors, Needed, Needed, Returned); GetMem(pWork, Needed); for i := 0 to Returned - 1 do begin ShowMessage(PMONITOR_INFO_1(pWork)^.Name); Inc(Integer(pWork), sizeof(TMONITOR_INFO_1)); end; FreeMem(pWork, Needed); end; end; |
So geht es dann.
Thx & Cu
Neo
Delete - Fr 21.01.05 14:31
Neo_in_der_MATRIX hat folgendes geschrieben: |
Was bei Luckie gefehlt hat ist nur das beim zweiten aufruf ein speicherbereich vorhanden sein muss. |
Ja, das ist mir gestern Nacht auch eingefallen. Ich ahtte imme rnoch die Netxxx-API Funktionen im Kopf, die diesen selber reservieren.
Allerdings würde ich es so machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
| type TMONITOR_INFO_1 = record Name: PChar; end; PMONITOR_INFO_1 = ^TMONITOR_INFO_1;
function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer; cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean; stdcall; external 'WinSpool.drv' Name 'EnumMonitorsA';
procedure TForm1.Button1Click(Sender: TObject); var Needed : DWORD; Returned : DWORD; Monitors : Pointer; pWork : Pointer; i : Integer; begin Monitors := nil; if (not EnumMonitors(nil, 1, Monitors, 0, Needed, Returned) and (GetLastError = ERROR_INSUFFICIENT_BUFFER)) then begin GetMem(Monitors, Needed); try EnumMonitors(nil, 1, Monitors, Needed, Needed, Returned); pWork := Monitors; for i := 0 to Returned - 1 do begin ShowMessage(PMONITOR_INFO_1(pWork)^.Name); Inc(Integer(pWork), sizeof(TMONITOR_INFO_1)); end; finally FreeMem(Monitors, Needed); end; end; end; |
Grund ist der: Die Informationen befinden sich im Speicherbereich von
Monitors. Jetzt muss ich diese Adresse aber inkrementieren. Bin ich am Ende angelangt, kenne ich die Startadresse nicht mehr. Gebe ich also
Monitors frei, gebe ich nicht den Speicher von Anfang an frei. Mit Einführung des
Arbeitszeigers pWork, mit dem ich dann die Informationen abrufe, kann ich selbigen inkrementieren. Der Zeiger
Monitors bleibt aber auf dem ersten Speicherbereich stehen und wenn ich dann
Monitors freigebe, habe ich den ganzen Speicherbereich wieder freigegeben.
Was mich jetzt bei dir etwas wundert: Du reservierst Speicher für
pWork:
Delphi-Quelltext
1:
| GetMem(pWork, Needed); |
aber keinen für
Monitors. Aber im Funktionsaufruf
Delphi-Quelltext
1:
| EnumMonitors(nil, 1, Monitors, Needed, Needed, Returned); |
füllst du selbigen. Arbeiten tust du dann aber wieder mit
pWork, nur wo weißt du
pWork den gefüllten Speicherbereich von
Monitors zu? So wie ich das sehe, ist es purer Zufall, dass dein Code funktioniert.
NeoInDerMATRIX - Fr 21.01.05 14:41
Ja ist egal,
ich danke dir auf jeden fall für deine Hilfe.
Cu
Neo
Delete - Fr 21.01.05 14:51
*push* Guck noch mal rein, habe noch was ergänzt.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!