Announcement

Collapse
No announcement yet.

Druckauftraege erkennen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Druckauftraege erkennen

    Hallo<p>

    ich suche ein Ereignis bzw. eine Message WM_??? die beim Ausdruck eines Dokumentes gleich welcher Art entsteht. <br>
    Vielleicht koennte dies auch ueber eine Spooler-Funktion erfolgen ? <br>

    Wer weiss Rat.<br>
    Gruss und Dank<br>
    Dietmar

  • #2
    Hallo,

    das folgende Beispiel demonstriert, wie man im eigenen Programm den Drucker-Spooler abfragen kann:
    <pre>
    unit GetPrintPoolerInfoFrm;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    private
    { Private-Deklarationen }
    public
    { Public-Deklarationen }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.DFM}

    uses WinSpool, Printers;

    procedure TForm1.Button1Click(Sender: TObject);
    const
    MaxJobs = 1024;
    type
    TArrayofJobs = array[1..1024] of TJobInfo2;
    var
    iNumJobs : Integer;
    dwNeed : DWORD;
    dwReturned : DWORD;
    i : Integer;
    szDevice : array[0..255] of char;
    szDriver : array[0..255] of char;
    szPort : array[0..255] of char;
    hPrinter : THandle;
    hDeviceMode : THandle;
    pBuffer : Pointer;
    sWindir : String;
    begin
    Printer.PrinterIndex := -1;
    Printer.GetPrinter(szDevice, szDriver, szPort, hDeviceMode);
    if not WinSpool.OpenPrinter(@szDevice, hPrinter, nil) then
    Exit;
    ListBox1.Items.Clear;
    GetPrinter(hPrinter, 2, nil, 0, @dwNeed);
    GetMem(pBuffer, dwNeed);
    if GetPrinter(hPrinter, 2, pBuffer, dwNeed, @dwNeed) then
    with ListBox1.Items do begin
    if TPrinterInfo2A(pBuffer^).pServerName <> nil then
    Add('pServerName='+TPrinterInfo2A(pBuffer^).pServe rName);
    if TPrinterInfo2A(pBuffer^).pPrinterName <> nil then
    Add('pPrinterName='+TPrinterInfo2A(pBuffer^).pPrin terName);
    end;
    ...
    EnumJobs(hPrinter, 0, iNumJobs, 2, nil, 0, dwNeed, dwReturned);
    GetMem(pBuffer, dwNeed);
    if EnumJobs(hPrinter, 0, iNumJobs, 2, pBuffer, dwNeed, dwNeed,dwReturned) then
    begin
    ListBox1.Items.Add('enumjobs ='+inttostr(dwReturned));
    for i := 1 to dwReturned do
    with ListBox1.Items do begin
    Add('----------------------------------');
    Add('JobId='+inttostr(TArrayofJobs(pBuffer^)[i].JobId));
    if TarrayofJobs(pBuffer^)[i].pPrinterName <> nil then
    Add('pPrinterName='+TarrayofJobs(pBuffer^)[i].pPrinterName);
    if TarrayofJobs(pBuffer^)[i].pMachineName <> nil then
    Add('pMachineName='+TarrayofJobs(pBuffer^)[i].pMachineName);
    if TarrayofJobs(pBuffer^)[i].pUserName <> nil then
    Add('pUserName='+TarrayofJobs(pBuffer^)[i].pUserName);
    if TarrayofJobs(pBuffer^)[i].pDocument <> nil then
    Add('pDocument='+TarrayofJobs(pBuffer^)[i].pDocument);
    if TarrayofJobs(pBuffer^)[i].pDatatype <> nil then
    Add('pDatatype='+TarrayofJobs(pBuffer^)[i].pDatatype);
    if TarrayofJobs(pBuffer^)[i].pStatus <> nil then
    Add('pStatus='+TarrayofJobs(pBuffer^)[i].pStatus);
    if TarrayofJobs(pBuffer^)[i].pStatus <> nil then
    Add('pStatus='+TarrayofJobs(pBuffer^)[i].pStatus);
    Add('Size='+Inttostr(TarrayofJobs(pBuffer^)[i].Size));
    Add('Status='+Inttostr(TarrayofJobs(pBuffer^)[i].Status));
    Add('Priority='+Inttostr(TarrayofJobs(pBuffer^)[i].Priority));
    Add('Position='+Inttostr(TarrayofJobs(pBuffer^)[i].Position));
    Add('TotalPages='+Inttostr(TarrayofJobs(pBuffer^)[i].TotalPages));
    Add('PagesPrinted='+Inttostr(TarrayofJobs(pBuffer^ )[i].PagesPrinted));
    ...
    Add(sWindir + Format('%-0.5d.SPL',[TArrayofJobs(pBuffer^)[i].JobId]));
    Add('JobID=' + IntToStr(TArrayofJobs(pBuffer^)[i].JobId));
    SetJob(hPrinter, TArrayofJobs(pBuffer^)[i].JobId, 0, nil, JOB_CONTROL_CANCEL)
    end;
    end;
    FreeMem(pBuffer, dwNeed);
    WinSpool.ClosePrinter(hPrinter);
    end;

    end.
    </pre&gt

    Comment


    • #3
      Hallo Andreas, <p>

      vielen Dank fuer die schnelle Antwort. <br>
      Das Beispiel funktioniert - aber ich muss jedesmal den Button druecken um etwas abzufangen (Infos zu bekommen).<br>
      Oder anders gesagt, ich muss ueber einen Timer staendig pollen.<br>
      Besser waere eine "Message", das ich mit einer HOOK-Funktionen abfangen koennte. Dann kann ich besser <br>
      auf einen Ereignis reagieren. <br>
      Ich habe heute eine "WM_SpoolerStatus" gefunden die aber nicht reagiert<br>

      Gruss und Dank <br>
      Dietma

      Comment


      • #4
        Aber, das Prinzip ist recht einfach. Es scheint so, als ob Du die Win32.hlp hast, also ... als erstes wird mit

        FindFirstPrinterChange()

        ein Change-Handle initialisiert, daß man dann mit

        FindNextPrinterChange()

        abfragt.

        Ciao, Ass

        Comment


        • #5
          bitte um schnelle antwort, herr kosch. es genau das was ich brauche, doch es funktioniert in meiner application nicht. mach ich was falsch???? eigentlich kann mann da ja nichts falsch machen, oder!?
          bekomme unter anderem die meldung : inumjobs konnte wahrscheinlich nicht initialisiet werden.
          warum haben sie die ... gesetzt. hat das etwas zu sagen?
          vielen dank im vorraus

          Comment


          • #6
            Hallo,

            im <b>Download</b>-Ordner (Entwickler Forum | Delphi | Download) habe ich ein Beispielprojekt abgelegt, dass neben dem Zustand des Druckerspoolers auch alle noch anstehenden Druckaufträge der Warteschlange auflistet.

            Getestete Konfiguration: Windows NT4; Netzwerkdrucker (Drucker am NT-Server angeschlossen)

            Comment


            • #7
              Hallo Andreas,

              ich habe Deinem Programm eine Zeile hinzugefügt:

              Add('pPrinterStatus='+IntToStr(TPrinterInfo2A(pBuf fer^).Status));

              um den Status anzeigen zu lassen, der laut PRINTER_INFO_2 übergeben wird. Es ist jedoch egal, ob der Drucker online, offline, einen paper jam hat oder in einem Erdloch wegen akuter Wutausbrüche begraben wurde. Ich erhalte immer den Rückgabewert "0".
              Ich habe sowohl unter Win95 einen Netzwerkdrucker als auch unter NT4 (SP5) einen lokalen Drucker an LPT1 angesprochen. Das Resultat war immer das gleiche. Ist es überhaupt möglich, den Status abzufragen (und zwar nicht nur in der MS Theorie sondern auch in der Praxis ;-).

              Gruß aus Hamburg
              Thorste

              Comment


              • #8
                Wenn es der Drucker-Treiber so will, ja

                Comment


                • #9
                  Hallo Andreas,
                  ich habe es sowohl mit einem HPLaserjet 4000, einem Deskjet 2000C und einem Canon BJ4300 ausprobiert. Da es bei keinem funktioniert, vermute ich doch eher, daß die entsprechende API Funktion nicht richtig funktioniert. Kriegst Du denn den Status richtig angezeigt, wenn der Drucker online oder offline ist, wenn kein Papier eingelegt ist oder der Papierschacht offen ist?

                  Gruß aus Hamburg

                  Thorste

                  Comment


                  • #10
                    Hallo Andreas, hallo Thorsten,

                    der Status-Wert der PRINTER_INFO_2 - Struktur aus WINSPOOL ändert sich lediglich wenn der entsprechende Drucker auf "Offline arbeiten" oder "Drucker anhalten" gesetzt wird. (siehe Systemsteuerung + rechte Maustaste auf den Drucker). Ansonsten liefert dies Funktion immer 0. (egal welcher Druckertreiber angesprochen wird). Auch die Funktion "EnumJobs" aus WINSPOOL bringt hier leider nichts. Bis heute habe ich auch noch keine Möglichkeit gefunden, den Druckerstatus zu ermitteln.

                    Sagt mir Bescheid, wenn Ihr eine Lösung gefunden habt.

                    Branc

                    Comment


                    • #11
                      Hallo Branco,

                      die Einstellungen aus der WINSPOOL geben ja letztendlich auch nur lokale Eigenschaften wieder und sagen nichts über den physikalischen Zustand aus.
                      Für WIN 95 ist die einzige von M$ zur Verfügung gestellte Struktur der PRINTER_INFO_2, welcher den physikalischen Status des Druckers und nicht des Treibers zurückgibt. Für NT und W2K gibt es zusätzlich die PRINTER_INFO_6 Struktur, die den Status zurückgibt. (Nützt mir nur soviel wie der berühmte Reissack, der in China umfällt ;-)

                      Ich habe den MS SDK Support zu dem Thema befragt und um Antwort gebeten, ob der Rückgabewert 0 (-idle-) ein Bug ist. Die Antwort lautet:
                      "Thank you for bringing this problem in the Platform SDK to our attention. We will correct this for a further release."

                      Alles klar? Wann und ob für WIN95 noch ein weiteres Release kommen mag, wissen wohl nur Gott und Billy Boy.

                      Gruß aus Hamburg

                      Thorste

                      Comment


                      • #12
                        Hallo Thorsten,

                        ist mir bis jetzt noch nicht aufgefallen, daß unter NT eine PRINTER_INFO_6 vorhanden ist, da ich immer nur in der Hilfe zu "GetPrinter" nachgesehen habe und dort steht für NT nur 1 bis 5. Habe jetzt mal bei "SetPrinter" gekuckt..... naja

                        hast Du es schon getestet unter NT mit PRINTER_INFO_6 ? Funktioniert es ? (kaum vorstellbar)

                        Gruß aus Marburg

                        Branc

                        Comment


                        • #13
                          Hallo Branco,

                          ich habe es unter W2K getestet, indem ich einfach im Quellcode von Andreas die GetPrinter Zeilen ersetzt habe durch

                          GetPrinter(hPrinter, 6, nil, 0, @dwNeed);<P>
                          GetMem(pBuffer, dwNeed);<p>
                          if GetPrinter(hPrinter, 6, pBuffer, dwNeed, @dwNeed) then<p>
                          ListBox1.Items.Add('Status='+IntToStr(TPrinterInfo 6(pBuffer^).dwStatus));<p>
                          end;<p>

                          Leider hat es nicht funktioniert. Der Rückgabewert ist immer noch 0. Vielleicht läuft es ja unter NT. Habe ich aber zur Zeit nicht zur Verfügung :-(
                          Ich bleibe aber am Ball.

                          Gruß aus Hamburg

                          Thorste

                          Comment


                          • #14
                            Hallo,

                            ich habe endlich oder auch leider, gefunden, was wir suchen (naja, zumindest in dieser Diskussion). In der MS Knowledge Base unter www.microsoft.com findet sich unter dem Suchbegriff Q160129 ein Artikel, welcher folgende Summary hat:

                            "The status of printers and print jobs are updated by the Win32 Spooler during the despool of a print job. At all other times, when that printer is not despooling and reports no state information, the printer is considered to be ready and idle. "

                            Es scheint also nicht möglich, den Status im Voraus abzufragen.

                            Davon ist aber wohl nur der Status betroffen. Für alles andere gibt es einen Artikel unter

                            http://dev-developer.earthweb.com/visualdev/0001_vol10_5/0001_bridgvb.html

                            Gruß aus Hamburg

                            Thorste

                            Comment

                            Working...
                            X