Announcement

Collapse
No announcement yet.

Hook programmieren

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

  • Hook programmieren

    Ich bin auf der Suche nach einer Lösung für folgende Problematik: Jedesmal wenn der Anwender unter NT oder 2000 in irgendeinem Programm eine Printfunktion benutzt, sollen alle Druckereinstellungen und die zu druckende Seitenzahl, Uhrzeit, etc. sowie über ein Popupwindow Zusatzinformationen in einer Datenbank gespeichert werden. Wie kann ich eine solche Funktionalität realisieren?

  • #2
    Hallo,

    man könnte den <b>Drucker-Spooler</b> über die Win32-API-Funktion <b>EnumJobs</b> abfragen und so die hinzugefügten Druckaufträge auslesen. Damit man rechtzeitig "zum Schuss" kommt, hilft die API-Funktion <b>FindFirstPrinterChangeNotification</b> weiter, denn hier kann über das Flag <b>PRINTER_CHANGE_JOB</b> das Hinzufügen eines neuen Druck-Jobs als Grund für die Benachrichtigung angefordert werden. Über die API-Funktion <b>GetJob</b> können die Detail (Seitenanzahl etc.) zu einem vorgefundenen Druckauftrag ermittelt werden.

    Das folgende Beispiel demonstriert das Aulesen des Spoolers:
    <pre>
    uses WinSpool, Printers;
    ...
    ...
    ...
    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));
    with TArrayofJobs(pBuffer^)[i].Submitted do
    begin
    Add('Submited wYear='+Inttostr(wYear));
    Add('Submited wMonth='+Inttostr(wMonth));
    Add('Submited wDayOfWeek='+Inttostr(wDayOfWeek));
    Add('Submited wDay='+Inttostr(wDay));
    Add('Submited wHour='+Inttostr(wHour));
    Add('Submited wMinute='+Inttostr(wMinute));
    Add('Submited wMinute='+Inttostr(wSecond));
    Add('Submited wMilliseconds='+Inttostr(wMilliseconds));
    end;
    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;
    </pre&gt

    Comment


    • #3
      Hallo Herr Kosch,

      vielen Dank für die Hilfestellung, aber als API-Einsteiger habe ich doch noch so meine Probleme. Ich habe versuch zunächst über OpenPrinter ein Handle für einen installierten Drucker zu bekommen und dann mit diesem handle FindFirstPrinter... zu benutzen, aber dann hänge ich in der Luft, wie kann ich feststellen ob ein neuer Printjob anliegt, und wie kann ich das für jeden Drucker der im System installiert ist feststellen?

      Gruß Ingo Janse

      Comment


      • #4
        Hallo,

        die Win32-API-Funktion FindFirstPrinterChangeNotification erzeugt ein <b>Benachrichtigungs-Objekt</b> und liefert ein <b>Handle</b> darauf zurück. Somit kann man die API-Funktion <b>WaitForSingleObject</b> auf die Lauer legen, um im eigenen Programm auf das Auslösen dieses Ereignisses reagieren zu können. Damit das eigene Programm aber nicht einfriert, muss dazu ein zweiter Thread abgespaltet werden.

        Zu FindFirstPrinterChangeNotification habe ich leider kein Beispiel am Lager, aber in meinem Buch <i>Delphi Win32-Lösungen</i> ist ein Beispielprojekt (DDWIN.DPR), das in einem zweiten Thread über WaitForSingleObject die Debug-Informationen des Betriebssystems auswertet (auch hier kommt ein Benachrichtigungsobjekt zum Einsatz). Dieses Grundgerüst kann auch für FindFirstPrinterChangeNotification verwendet werden.

        In der Hilfe zum <b>Microsoft Platform SDK</b> sowie in der <b>MSDN Library</b> sind weitere umfangreiche Infos zu finden. Falls die MSDN-CDROMs nicht zur Verfügung stehen, würde ich mein Glück zuerst unter http://msdn.microsoft.com/default.asp versuchen

        Comment

        Working...
        X