Новичок
Профиль
Группа: Участник
Сообщений: 22
Регистрация: 26.3.2011
Репутация: нет Всего: нет
|
Есть задача: сделать протоколирование печати, кто сколько и когда, и каких документов распечатал. Делаю через события FindFirstPrinterChangeNotification и FindNextPrinterChangeNotification. Пример взял с embarcadero developer network. При открытии формы делаю | Код | FMonitor:= TPBPrintersMonitor.Create(Self); //FMonitor.OnNewJob := JobNotification; FMonitor.OnJobComplete := JobNotification; FMonitor.Active := True;
|
Обработчик события, в котором в таблицу логов заносятся сведения о том, кто, когда и чего распечтал: | Код | procedure TfrmScanDocs.JobNotification(const jobinfo: TPBJobInformation); begin try if (jobinfo.Status = jsCompleted) or (jobinfo.Status = jsNew) or (jobinfo.Status = jsProcessing) or (jobinfo.Status = jsPaused) or (jobinfo.Status = jsResumed) then begin adcPdf.CommandText:= ' INSERT INTO ' + pDb + '..F010803 (kAction, id_Doc, u_Act, d_act)' + ' VALUES (''P'', ' + ExtractOnlyFileName(jobinfo.Document) + ', ''' + GetLogPol + ''', GetDate()) '; adcPdf.Execute; end; finally //FMonitor.Destroy; end; end;
|
Собственно, сама проблема: работает через раз, т.е. не у всех пользователей. Сначала грешил на сетевой принтер, однако не подтвердилось - у некоторых все отлично на сетевом пашет. Потом на Семерку - тоже мимо. В чем может быть проблема, может кто сталкивался? В полномочиях каких может? Из-за чего может не срабатывать событие? Среда: BDS 2006, СУБД - MS SQL 2008, метод доступа - ADO P.S. Вот код модуля с embarcadero: | Код | {$BOOLEVAL OFF}{Unit depends on shortcut boolean evaluation} Unit PBPrintersMonitorU; {$I JEDI.INC}
Interface
Uses Messages, Windows, SysUtils, Classes, Printers, COntnrs;
Type {: This enumeration describes a jobs status @enum jsNone no status has been assigned yet @enum jsNew the job has just been added to the printers queue @enum jsProcessing the job is being processed @enum jsPaused the jobs execution has been paused @enum jsResumed the jobs execution has been resumed, cannot detect that @enum jsAborted the job has been aborted, cannot detect that either @enum jsCompleted the job has successfully completed @enum jsError the job has run into an error condition @Desc Resumed and aborted jobs cannot be detected during the notification process, since this would require comparison with a previous state. } TPBJobStatus = (jsNone, jsNew, jsProcessing, jsPaused, jsResumed, jsAborted, jsCompleted, jsError );
{: This is a simple object used to transfer data about a job and the printer it is executing on to an event. } TPBJobInformation = class private FPrinterIndex: Integer; // index of printer in Printer.Printers FPrinterName : String ; // printers devicename FPrinterPort : String ; // printers port name FPrinterServer: String; // server name in case of network printer FPrinterShare: String; // share name in case of a network printer FComputer : String; // computer that originated the job FUser : String; // user that originated the job FDocument : String; // jobs document name FPages : Integer; // pages printed so far FTotalPages : Integer; // total pages in job FBytesPrinted: Cardinal; // bytes printed up to now FTotalbytes : Cardinal; // size of the job in bytes FJobID : Cardinal; // the ID of the job FStatus : TPBJobStatus; // the jobs status FCopies : Cardinal; // number of copies requested for job FOrientiation: TPrinterOrientation; // poLandscape or poPortrait public {: Create an instance and set its data values. } Constructor Create( aPrinterIndex: Integer; const aPrinterName, aPrinterPort, aPrinterServer, aPrinterShare: String );
{: Returns a deep copy of this object. } Function Clone: TPBJobInformation; property PrinterIndex : Integer read FPrinterIndex; property PrinterName : String read FPrinterName; property PrinterPort : String read FPrinterPort; property PrinterServer: String read FPrinterServer; property PrinterShare : String read FPrinterShare; property Computer : String read FComputer; property User : String read FUser; property Document : String read FDocument; property Pages : Integer read FPages; property TotalPages : Integer read FTotalPages; property BytesPrinted : Cardinal read FBytesPrinted; property TotalBytes : Cardinal read FTotalbytes; property JobID : Cardinal read FJobID; property Status : TPBJobStatus read FStatus; property Copies : Cardinal read FCopies; property Orientation : TPrinterOrientation read FOrientiation; End;
{: Prototype of an event used to pass job information to a client if TPBPrintersMonitor. @param aJobInformation holds the information about the job. This object remains property of the caller, the event handler must not free it! } TPBJobEvent = Procedure( const aJobinformation: TPBJobInformation ) of Object;
{: This class offers job monitoring functionality to clients. As it is now the object monitors all installed printers automatically, and there is no way to limit this to one particular printer. The client has to filter out the events of interest itself. Monitoring can be suspended and resumed via the Active property and is not done at design-time. } TPBPrintersMonitor = class(TComponent) private FInternalSyncHelper: HWND; // helper window used to sync to main thread FPendingNotifications: TThreadList; // queue of notifications to process FNotifiers: TObjectList; // list of notifier thread objects FActive: Boolean; // monitoring state FNewJobEvent: TPBJobEvent; // atached event handlers FJobChangeEvent: TPBJobEvent; FJobCompleteEvent: TPBJobEvent;
Procedure SetActive(const Value: Boolean); Procedure CreateNotifiers; protected {: Window function for the helper window, executes in the printer monitors thread, usually the main thread. } Procedure WndProc( Var msg: TMessage );
{: Event handler for the notifier threads, will execute in the calling threads context. @param aJobInformation contains the job information. The method makes a copy of this object for the internal use of the monitor. } Procedure JobNotification( const aJobinformation: TPBJobInformation );
{: Processes all pending notifications in the context of the printer monitors thread. } Procedure ProcessNotifications;
{: Fires the OnNewJob event, if a handler for it has been assigned. } Procedure DoNewJob( const aJobinformation: TPBJobInformation ); virtual;
{: Fires the OnJobChange event, if a handler for it has been assigned. } Procedure DoJobChange( const aJobinformation: TPBJobInformation ); virtual;
{: Fires the OnJobComplete event, if a handler for it has been assigned. } Procedure DoJobComplete( const aJobinformation: TPBJobInformation ); virtual; public Constructor Create( aOwner: TComponent ); override; Destructor Destroy; override; published property Active: Boolean read FActive write SetActive; property OnNewJob: TPBJobEvent read FNewJobEvent write FNewJobEvent; property OnJobChange: TPBJobEvent read FJobChangeEvent write FJobChangeEvent; property OnJobComplete: TPBJobEvent read FJobCompleteEvent write FJobCompleteEvent; end;
{: Exception class used to report monitor errors } EPBPrinterMonitorError = class( Exception );
Procedure Register;
Implementation
Uses WinSpool, SyncObjs {$IFNDEF DELPHI6_UP} , Forms {$ENDIF} ;
Procedure Register; Begin RegisterComponents('PBGoodies', [TPBPrintersMonitor]); End;
{$IFDEF DELPHI6_UP} // To remove deprecated warning Procedure RaiseLastWin32Error; Begin RaiseLastOSError; End; {$ENDIF}
Type {: This thread class will monitor the job queue of a single printer. On changes to a job or the queue an event is fired. The events handler has to make sure the processing it does is thread-safe. } TPBPrintMonitor = class( TThread ) private FJobInformation: TPBJobInformation; // contains info on monitored printer and last job change FPrinterHandle : THandle; // the printers API handle FWakeupEvent : TSimpleEvent; // used to wake thread when it is destroyed FRunning : Boolean; // flag set when thread reaches Execute FJobChangeEvent: TPBJobEvent; procedure HandleNotification(findhandle: THandle); // attached event handler protected Procedure Execute; override; Constructor InternalCreate; Procedure DoJobChange; virtual; Procedure Wakeup; public {: Do not use this constructor! @raises EPBPrinterMonitorError when called } Constructor Create( CreateSuspended: Boolean );
{: This class function is used to create an instance of the class to monitor a specific printer. @param index is the index of the printer to monitor in Printer.Printers @param onChangeJob is the callback to receive job notifications. @precondition 0 <= index < Printer.Printers.count @returns the created object, or Nil, if the printer information could not be obtained from the API. } class Function CreateMonitor( index: Integer; onChangeJob: TPBJobEvent ): TPBPrintMonitor;
{: Wakes the thread from the wait state, closes the printer handle. } Destructor Destroy; override;
property OnJobChange: TPBJobEvent read FJobChangeEvent write FJobChangeEvent; End;
{ TPBPrintMonitor —————————————————————————————————————————————————————}
Constructor TPBPrintMonitor.Create(CreateSuspended: Boolean); Begin raise EPBPrinterMonitorError.Create( 'Do not use this constructor to create instances of '+ 'TPBPrintMonitor, use the CreateMonitor method instead!' ); End;
{-- GetCurrentPrinterHandle -------------------------------------------} {: Retrieves the handle of the current printer @Returns an API printer handle for the current printer @Desc Uses WinSpool.OpenPrinter to get a printer handle. The caller takes ownership of the handle and <b>must</b> call ClosePrinter on it once the handle is no longer needed. Failing to do that creates a serious resource leak! <P> Requires Printers and WinSpool in the Uses clause. @Raises EWin32Error if the OpenPrinter call fails. }{ Created 30.9.2000 by P. Below -----------------------------------------------------------------------} Function GetCurrentPrinterHandle: THandle; Const Defaults: TPrinterDefaults = ( pDatatype : nil; pDevMode : nil; DesiredAccess : PRINTER_ACCESS_USE or PRINTER_ACCESS_ADMINISTER ); Var Device, Driver, Port : array[0..255] of char; hDeviceMode: THandle; Begin { GetCurrentPrinterHandle } Printer.GetPrinter(Device, Driver, Port, hDeviceMode); If not OpenPrinter(@Device, Result, @Defaults) Then RaiseLastWin32Error; End; { GetCurrentPrinterHandle }
{: Selects the printer by the passed index and tries to obtains its API handle and a number of information items on it. If this succeeds the thread is created, fed the obtained data, and its reference is returned. The thread is suspended. <br/> We trap any exceptions on the way and do not allow them to escape the function, instead Nil is returned as result. If the symbol DEBUG is defined a message box with the exception message will be shown, but program flow will still continue after that. <p/> WARNING! This function has a side effect! It will change the selected printer! The routine calling CreateMonitor is responsible for saving and restoring the previously selected printer, if that is required. This is an optimization, since in typical use CreateMonitor will be called for every printer in the list. } class Function TPBPrintMonitor.CreateMonitor(index: Integer; onChangeJob: TPBJobEvent): TPBPrintMonitor; Var printerhandle: THandle; pInfo: PPrinterInfo2; bytesNeeded: DWORD; Begin If (index < 0) or (index >= Printer.Printers.Count) Then raise EPBPrinterMonitorError.CreateFmt( 'TPBPrintMonitor.CreateMonitor: index %d is out of range. '+ 'Valid indices are %d..%d.', [index, 0, Printer.Printers.Count] );
Result := nil; printerhandle := 0; Try Printer.PrinterIndex := index; printerhandle := GetCurrentPrinterhandle; Winspool.GetPrinter( printerhandle, 2, Nil, 0, @bytesNeeded ); If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then RaiseLastWin32Error; pInfo := AllocMem( bytesNeeded ); Try If not Winspool.GetPrinter( printerhandle, 2, pInfo, bytesNeeded, @bytesNeeded ) Then RaiseLastWin32Error; Result := TPBPrintMonitor.InternalCreate; Try Result.FPrinterHandle := printerhandle; Result.FJobInformation := TPBJobInformation.Create( index, pInfo^.pPrinterName, pInfo^.pPortName, pInfo^.pServerName, pInfo^.pShareName ); Result.FJobChangeEvent := OnChangeJob; Except Result.FPrinterHandle := 0; // prevents ClosePrinter to be called twice FreeAndNil( Result ); raise; End; { Except } Finally FreeMem( pInfo ); End; Except On E: Exception Do Begin If printerhandle <> 0 Then ClosePrinter( printerhandle ); {$IFDEF DEBUG} If not (E Is EAbort) Then Begin S:= Format( 'TPBPrintMonitor.CreateMonitor raised an exception.'#13#10+ 'Exception class %s'#13#10'%s', [E.classname, E.Message] ); Windows.MessageBox( 0, Pchar(S), 'Error', MB_OK or MB_ICONSTOP ); End; { If } {$ENDIF} End; { On } End; { Except } End;
Destructor TPBPrintMonitor.Destroy; Begin If not Terminated Then Terminate; Wakeup; If FRunning and Suspended Then Resume; inherited; // will wait until the thread has died ClosePrinter( FPrinterHandle ); FJobInformation.Free; FWakeupEvent.Free; End;
Procedure TPBPrintMonitor.DoJobChange; Begin If Assigned( FJobChangeEvent ) Then FJobChangeEvent( FJobInformation ); End;
Procedure TPBPrintMonitor.HandleNotification( findhandle: THandle ); Var pni: PPrinterNotifyInfo; ChangeReason: Cardinal;
Function ReasonWas( flag: Cardinal ): Boolean; Begin Result := (flag and ChangeReason) <> 0; End; { ReasonWas }
Function FindJobStatus: TPBJobStatus; Var i: Integer; status: Cardinal;
Function StatusIs( flag: Cardinal ): Boolean; Begin Result := (flag and status) <> 0; End; { StatusIs }
Begin { FindJobStatus } Result := jsNone; If Assigned( pni ) Then For i:=0 To pni^.Count-1 Do If pni^.aData[i].Field = JOB_NOTIFY_FIELD_STATUS Then Begin status := pni^.aData[i].NotifyData.adwData[0]; If StatusIs( JOB_STATUS_PRINTED ) Then Result := jsCompleted Else If StatusIs( JOB_STATUS_DELETING ) Then Result := jsNone // we skip this case because we will get another notification for that Else If StatusIs( JOB_STATUS_SPOOLING or JOB_STATUS_PRINTING ) Then Result := jsProcessing Else If StatusIs( JOB_STATUS_ERROR or JOB_STATUS_OFFLINE or JOB_STATUS_PAPEROUT ) Then Result := jsError Else If StatusIs( JOB_STATUS_PAUSED ) Then Result := jsPaused; Break; End; { If } End; { FindJobStatus }
Procedure GetJobInformation; Function DataString( index: Integer ): String; Begin Result := Pchar( pni^.aData[index].NotifyData.Data.pBuf ) End; Function DataValue( index: Integer ): Cardinal; Begin Result := pni^.aData[index].NotifyData.adwData[0]; End; Function GetPrinterNumCopies(index: Integer):Cardinal; Begin result:=PDeviceMode( pni^.aData[index].NotifyData.Data.pBuf)^.dmCopies; End; Function GetPrinterOrientation(index: Integer):TPrinterOrientation; var Orientation: smallint; Begin Orientation:= PDeviceMode(pni^.aData[index].NotifyData.Data.pBuf)^.dmOrientation; Case orientation Of DMORIENT_PORTRAIT : result:=poPortrait; DMORIENT_LANDSCAPE: result:=poLandscape; Else result := poPortrait; Assert( false, 'Unknown value in dmOrientation'); End; End;
Var i: Integer; Begin { GetJobInformation } If not Assigned( pni) or (pni^.Count = 0) Then Exit; FJobInformation.FJobID := pni^.aData[0].Id; For i:=0 To pni^.Count-1 Do Case pni^.aData[i].Field Of JOB_NOTIFY_FIELD_MACHINE_NAME: FJobInformation.FComputer := Datastring(i); JOB_NOTIFY_FIELD_USER_NAME: FJobInformation.FUser := Datastring(i); JOB_NOTIFY_FIELD_DOCUMENT: FJobInformation.FDocument := Datastring(i); JOB_NOTIFY_FIELD_TOTAL_PAGES: FJobInformation.FTotalPages := Datavalue(i); JOB_NOTIFY_FIELD_TOTAL_BYTES: FJobInformation.FTotalbytes := Datavalue(i); JOB_NOTIFY_FIELD_BYTES_PRINTED: FJobInformation.FBytesPrinted := Datavalue(i); JOB_NOTIFY_FIELD_PAGES_PRINTED: FJobInformation.FPages := Datavalue(i); JOB_NOTIFY_FIELD_DEVMODE: Begin FJobInformation.FCopies:= GetPrinterNumCopies(i); FJobInformation.FOrientiation := GetPrinterOrientation(i); End; End; { Case } End; { GetJobInformation }
Begin { HandleNotification } If FindNextPrinterChangeNotification( findhandle, ChangeReason, nil, Pointer(pni) ) Then Try If ReasonWas( PRINTER_CHANGE_ADD_JOB ) Then FJobInformation.FStatus := jsNew Else If ReasonWas( PRINTER_CHANGE_DELETE_JOB ) Then FJobInformation.FStatus := jsCompleted Else If ReasonWas( PRINTER_CHANGE_SET_JOB ) Then FJobInformation.FStatus := FindJobStatus Else If ReasonWas( PRINTER_CHANGE_WRITE_JOB ) Then FJobInformation.FStatus := jsProcessing Else FJobInformation.FStatus := jsNone;
If FJobInformation.FStatus <> jsNone Then Begin GetJobInformation; DoJobChange; End; { If } Finally FreePrinterNotifyInfo( pni ); End; { Finally } End; { TPBPrintMonitor.HandleNotification }
Procedure TPBPrintMonitor.Execute; Const jobfields : Array [1..9] of Word = ( JOB_NOTIFY_FIELD_MACHINE_NAME, JOB_NOTIFY_FIELD_USER_NAME, JOB_NOTIFY_FIELD_DOCUMENT, JOB_NOTIFY_FIELD_TOTAL_PAGES, JOB_NOTIFY_FIELD_TOTAL_BYTES, JOB_NOTIFY_FIELD_BYTES_PRINTED, JOB_NOTIFY_FIELD_PAGES_PRINTED, JOB_NOTIFY_FIELD_STATUS, JOB_NOTIFY_FIELD_DEVMODE ); Var handles: packed Record findhandle, wakehandle: THandle; end; notifyOptions: PRINTER_NOTIFY_OPTIONS; notifyType: PRINTER_NOTIFY_OPTIONS_TYPE; retval: DWORD; Begin FRunning := True; If Terminated Then Exit; notifyOptions.Version := 2; notifyOptions.Count := 1; notifyOptions.Flags := PRINTER_NOTIFY_OPTIONS_REFRESH; notifyOptions.pTypes := @notifyType; FillChar( notifyType, sizeof( notifyType ), 0 ); notifyType.wType := JOB_NOTIFY_TYPE; notifyType.pFields := @jobfields; notifyType.Count := High( jobfields )- Low( jobfields ) + 1; handles.wakehandle := FWakeupEvent.Handle; handles.findhandle := FindFirstPrinterChangeNotification( Fprinterhandle, PRINTER_CHANGE_JOB, // we are only interested in job-related changes 0, @notifyoptions ); If handles.findhandle <> INVALID_HANDLE_VALUE Then Begin While not Terminated Do Begin retval := WaitForMultipleObjects( 2, @handles, false, INFINITE ); If not Terminated Then If retval = WAIT_OBJECT_0 Then try HandleNotification( handles.findhandle ) except // HandleNotifiaction will only ever raise assertions, // which the IDE debugger will trap for us end Else Break; End; { While } FindClosePrinterChangeNotification( handles.findhandle ); End { If } Else Begin {$IFDEF DEBUG} S:= 'FindFirstPrinterChangeNotification failed for printer '+ FJobInformation.FPrinterName+', the system error is'#13#10+ SysErrorMessage( GetLastError ); Windows.MessageBox( 0, Pchar(S), 'Error', MB_OK or MB_ICONSTOP ); {$ENDIF} End; { Else } End;
{: Create the thread suspended, create the wakeup event. } Constructor TPBPrintMonitor.InternalCreate; Begin inherited Create( true ); FWakeupEvent := TSimpleEvent.Create; End;
Procedure TPBPrintMonitor.Wakeup; Begin FWakeupEvent.SetEvent; End;
{ TPBJobInformation ———————————————————————————————————————————————————}
Function TPBJobInformation.Clone: TPBJobInformation; Begin Result := TPBJobInformation.Create( PrinterIndex, PrinterName, PrinterPort, PrinterServer, PrinterShare ); Result.FComputer := Computer; Result.FUser := User; Result.FDocument := Document; Result.FPages := Pages; Result.FTotalPages := TotalPages; Result.FbytesPrinted := BytesPrinted; Result.FTotalbytes := Totalbytes; Result.FJobID := JobID; Result.FStatus := Status; End;
Constructor TPBJobInformation.Create(aPrinterIndex: Integer; const aPrinterName, aPrinterPort, aPrinterServer, aPrinterShare: String ); Begin inherited Create; FPrinterIndex := aPrinterIndex; FPrinterName := aPrinterName; FPrinterPort := aPrinterPort; FPrinterServer := aPrinterServer; FPrinterShare := aPrinterShare; End;
{ TPBPrintersMonitor ———————————————————————————————————————————————————}
Const UM_JOBNOTIFICATION = WM_APP;
Constructor TPBPrintersMonitor.Create(aOwner: TComponent); Begin inherited; If not (csDesigning In ComponentState) Then Begin {$IFDEF DELPHI6_UP} FInternalSyncHelper := Classes.AllocateHWnd( WndProc ); {$ELSE} FInternalSyncHelper := Forms.AllocateHWnd( WndProc ); {$ENDIF} FPendingNotifications := TThreadList.Create; FNotifiers := TObjectList.Create( true ); // Owns the objects CreateNotifiers; End; { If } End;
Procedure TPBPrintersMonitor.CreateNotifiers; Var aNotifier: TPBPrintMonitor; i: Integer; oldIndex: Integer; Begin If Printer.Printers.Count > 0 Then Try oldindex := Printer.PrinterIndex; Try For i:= 0 To Printer.Printers.Count-1 Do Begin aNotifier := TPBPrintMonitor.CreateMonitor( i, JobNotification ); If Assigned( aNotifier ) Then FNotifiers.Add( aNotifier ); End; { For } Finally Printer.PrinterIndex := oldIndex; End; { Finally } Except // this is a crutch. If no default printer is defined accessing // PrinterIndex can cause an exception End; { Except } End;
Destructor TPBPrintersMonitor.Destroy; Begin FNotifiers.Free; FPendingNotifications.Free; {$IFDEF DELPHI6_UP} Classes.DeallocateHWnd( FInternalSyncHelper ); {$ELSE} Forms.DeallocateHWnd( FInternalSyncHelper ); {$ENDIF} inherited; End;
Procedure TPBPrintersMonitor.DoJobChange( const aJobinformation: TPBJobInformation); Begin If Assigned( FJobChangeEvent ) Then FJobChangeEvent( aJobinformation ); End;
Procedure TPBPrintersMonitor.DoJobComplete( const aJobinformation: TPBJobInformation); Begin If Assigned( FJobCompleteEvent ) Then FJobCompleteEvent( aJobinformation ); End;
Procedure TPBPrintersMonitor.DoNewJob( const aJobinformation: TPBJobInformation); Begin If Assigned( FNewJobEvent ) Then FNewJobEvent( aJobinformation ); End;
Procedure TPBPrintersMonitor.JobNotification( const aJobinformation: TPBJobInformation); {$IFDEF NO_MESSAGELOOP} Var res: Cardinal; {$ENDIF} Begin FPendingNotifications.Add( aJobinformation.Clone ); {$IFDEF NO_MESSAGELOOP} SendMessageTimeout( FInternalSyncHelper, UM_JOBNOTIFICATION, 0, 0, SMTO_NORMAL or SMTO_ABORTIFHUNG, 1000, res ); {$ELSE} PostMessage( FInternalSyncHelper, UM_JOBNOTIFICATION, 0, 0 ); {$ENDIF} End;
Procedure TPBPrintersMonitor.ProcessNotifications; Var items: TObjectList; list: TList; i: Integer; jobinfo: TPBJobInformation; Begin items := nil; list:= FPendingNotifications.LockList; Try If list.count > 0 Then Begin items:= TOBjectlist.Create; // owns its objects For i:=0 To list.Count-1 Do items.add( TObject( list[i] )); list.Clear; End; { If } Finally FPendingNotifications.UnlockList; End; { Finally } If Assigned( items ) Then Try For i:= 0 To items.count-1 Do Begin jobinfo:= TPBJobInformation( items[i] ); Case jobinfo.Status Of jsNew : DoNewJob( jobinfo ); jsCompleted : DoJobComplete( jobinfo ); Else DoJobChange( jobinfo ); End; { Case } End; { For } Finally items.Free End; { Finally } End;
Procedure TPBPrintersMonitor.SetActive(const Value: Boolean); Var i: Integer; Begin If FActive <> Value Then Begin FActive := Value; If not (csDesigning In ComponentState) Then For i:= 0 to FNotifiers.Count-1 Do If Value Then TPBPrintMonitor( FNotifiers[i] ).Resume Else TPBPrintMonitor( FNotifiers[i] ).Suspend; End; { If } End;
Procedure TPBPrintersMonitor.WndProc(var msg: TMessage); Begin If msg.Msg = UM_JOBNOTIFICATION Then ProcessNotifications Else msg.Result := DefWindowProc( FInternalSyncHelper, msg.Msg, msg.WParam, msg.LParam ); End;
end.
|
|