Stampa e output PDF nelle applicazioni aziendali Windows — come scegliere tra System.Drawing.Printing, WPF e librerie di report
· Go Komura · CSharp, .NET, WinForms, WPF, Stampa, PDF, Report, Sviluppo Windows, Consulenza tecnica
La stampa in un’applicazione aziendale Windows non si risolve con «disegniamo qualcosa con PrintDocument». Le interruzioni di pagina non funzionano, i margini slittano, l’anteprima non coincide con l’output reale, oppure compare una finestra di stampa anche se si desidera soltanto un PDF: questi problemi nascono quasi sempre dall’implementazione senza comprendere il meccanismo di stampa.
Questo articolo organizza quattro opzioni — System.Drawing.Printing di WinForms, FlowDocument/FixedDocument di WPF, librerie per l’output PDF e report tramite Excel/Word — dal punto di vista della scelta in base ai requisiti.
1. La conclusione prima di tutto
- Per elenchi semplici o per estendere asset WinForms esistenti,
PrintDocumentè sufficiente. L’impaginazione ripete l’eventoPrintPagefinchéHasMorePagesnon diventafalse; se lo si dimentica, le pagine successive alla seconda non vengono stampate. 12 - Il DPI di stampa non è il DPI dello schermo.
PageSettings.PrinterResolutionrappresenta la risoluzione della stampante, mentre i margini sono composti daPageSettings.HardMarginX/HardMarginY— area fisicamente non stampabile della stampante — eMargins— margini logici indicati dall’applicazione. Riutilizzare direttamente le coordinate dello schermo provoca disallineamenti per la differenza di DPI e sistemi di coordinate. 345 - In WPF il percorso di stampa standard di Windows è diviso in un percorso GDI e uno XPS. Le applicazioni WPF usano originariamente il percorso XPS; inviando a una stampante senza XPSDrv l’output viene convertito automaticamente in GDI. 67
- I documenti WPF hanno filosofie diverse:
FlowDocumentper contenuto fluido eFixedDocumentper layout fisso.FlowDocumentprivilegia la leggibilità e viene rimpaginato in base a dimensioni della finestra e risoluzione, mentreFixedDocumentprivilegia la fedeltà sul dispositivo di visualizzazione e stampa. 89 - In WPF carta e vassoio si specificano con
PrintDialogePrintTicket/PrintQueue. Prima di stampare è buona pratica convalidare e unire la richiesta alle capacità reali della stampante conPrintQueue.MergeAndValidatePrintTicket. 1011 - Microsoft Print to PDF è un driver di stampa pensato per operazioni interattive. È una coda di stampa e un pacchetto driver inclusi nel sistema; in genere chiede il percorso di salvataggio a ogni esecuzione, quindi non è adatto a batch non presidiati. 12
- Microsoft non supporta né consiglia l’automazione COM di Office da server o servizi. Office è stato progettato per desktop interattivi e profili utente; in ambienti non presidiati o non interattivi può comportarsi in modo instabile o bloccarsi. 13
- I servizi Windows operano nella sessione 0, quindi non possono mostrare finestre di dialogo né dipendere dalla stampante predefinita legata alla sessione dell’utente. Considerare questo confine fin dall’inizio quando si progetta una stampa residente. 14
- Non liberare oggetti GDI (handle) in processi di lunga durata può raggiungere il limite per processo e causare arresti. Il limite è finito e regolabile con
GDIProcessHandleQuota; non è possibile allocare all’infinito. 15
Tabella decisionale: requisito × mezzo
| Requisito | Mezzo adatto | Motivo |
|---|---|---|
| Stampare pochi elenchi o documenti semplici (WinForms) | PrintDocument |
Sono sufficienti le classi standard e si riutilizzano gli asset di disegno GDI+ esistenti |
| Report con molte linee, più formati carta o layout complesso | Libreria di report oppure layout fisso con FixedDocument |
Calcolo di coordinate, paginazione e composizione giapponese in proprio sono costosi |
| Stampa batch massiva senza operatore | PrintDocument.Print() programmatico / invio diretto a XpsDocumentWriter |
Deve completarsi senza finestre e senza dipendere dalla stampante predefinita |
| Serve solo salvare PDF senza stampare | Generare direttamente PDF con una libreria | Non dipende da finestra di stampa, stampante predefinita o stato dello spooler |
| Anteprima obbligatoria e importante flusso interno di verifica | PrintPreviewDialog (WinForms), DocumentViewer (WPF) |
È possibile usare direttamente la UI standard di verifica prima della stampa |
| Riutilizzare template Excel esistenti | Generazione diretta con Open XML SDK o automazione COM limitata | Riutilizza gli asset, ma COM va evitato nei servizi residenti |
Vediamo ora i dettagli.
2. Il minimo indispensabile sulla stampa Windows
L’architettura di stampa Windows è formata dallo spooler e dai driver delle singole stampanti. L’applicazione chiama funzioni indipendenti dal dispositivo e può inviare lavori a destinazioni molto diverse: stampanti laser, plotter vettoriali, stampanti raster o fax. 16
Esistono due percorsi principali di stampa.
- Percorso GDI. Quando stampa un’app Win32 GDI, il motore grafico GDI mette le istruzioni di disegno nello spooler come EMF (enhanced metafile) oppure le rende direttamente in un’immagine stampabile insieme al driver. Le app WinForms tradizionali passano da qui. 166
- Percorso XPS. È il percorso per driver basati su XPS (XML Paper Specification). Le app WPF lo usano originariamente e inviano documenti XPS allo spooler. Se la stampante non usa un driver XPSDrv, i dati vengono convertiti automaticamente in GDI prima dell’invio. 67
Perché schermo e stampa differiscono. La causa più comune è confondere i DPI. Il Graphics dello schermo lavora di norma attorno a 96 DPI, quello della stampante alla risoluzione indicata da PageSettings.PrinterResolution, spesso attorno a 600 DPI. 3 Passare al Graphics di stampa coordinate in pixel calcolate per lo schermo farà disegnare molto più piccolo — o, con altra configurazione, più grande — del previsto. In stampa è sicuro costruire le coordinate in centesimi di pollice o misure fisiche (millimetri/pollici), senza dipendere dalla risoluzione di Graphics.
Un altro punto facilmente trascurato è l’area fisicamente non stampabile della stampante. Molte stampanti non possono stampare alcuni millimetri dal bordo della carta. Il vincolo è disponibile con PageSettings.HardMarginX/HardMarginY, descritto dalla documentazione come margini fisici impostati dalla stampante. 4 I margini logici dell’app sono PageSettings.Margins (un pollice per lato per impostazione predefinita); anche portandoli a zero, non è possibile stampare dentro l’hard margin. 5 Molti difetti del tipo «ho impostato margine zero, ma il bordo viene tagliato o spostato» derivano dall’ignorare questo margine fisico.
3. WinForms: uso pratico di System.Drawing.Printing
La stampa WinForms è costruita attorno a PrintDocument: si crea il documento, si impostano PrinterSettings e DefaultPageSettings, si esegue il disegno nell’evento PrintPage e si avvia la stampa con Print(). 1
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
public sealed class ReportPrinter
{
// Dati da stampare. Si presuppone una riga di dettaglio del documento per ogni riga.
private readonly IReadOnlyList<string> _lines;
private int _lineIndex;
public ReportPrinter(IReadOnlyList<string> lines) => _lines = lines;
public void Print(string printerName)
{
using var document = new PrintDocument();
document.DocumentName = "Dettagli dell'ordine";
if (!string.IsNullOrEmpty(printerName))
{
document.PrinterSettings.PrinterName = printerName;
}
// Con un nome di stampante sconosciuto, qui il risultato risulta false (non adatto a rilevare lo stato offline).
if (!document.PrinterSettings.IsValid)
{
throw new InvalidOperationException(
$"La stampante specificata non è stata trovata: {printerName}");
}
_lineIndex = 0;
document.PrintPage += Document_PrintPage;
document.Print();
}
private void Document_PrintPage(object? sender, PrintPageEventArgs e)
{
// MarginBounds è l'area di disegno disponibile che tiene conto dei margini logici (Margins).
// PageBounds copre l'intero foglio; il contenuto può essere tagliato anche disegnando all'interno del margine hardware.
using var font = new Font("Segoe UI", 10);
float lineHeight = font.GetHeight(e.Graphics);
float y = e.MarginBounds.Top;
while (_lineIndex < _lines.Count)
{
if (y + lineHeight > e.MarginBounds.Bottom)
{
// Questa pagina termina qui. Poiché ci sono altri dati, si continua alla pagina successiva.
e.HasMorePages = true;
return;
}
e.Graphics.DrawString(_lines[_lineIndex], font, Brushes.Black,
e.MarginBounds.Left, y);
y += lineHeight;
_lineIndex++;
}
// Sono state disegnate tutte le righe; questa è l'ultima pagina.
e.HasMorePages = false;
}
}
Il caso tipico del difetto «non esce la seconda pagina» è dimenticare di impostare esplicitamente HasMorePages a false — il valore predefinito è false — oppure sbagliare una condizione e uscire lasciandolo sempre false. L’evento PrintPage si ripete fino a quando la proprietà diventa false; prima di impostarla, verificare esplicitamente se rimangono righe da disegnare. 12 Per applicare impostazioni diverse per pagina, come formato o orientamento, usare anche l’evento QueryPageSettings insieme a PrintPage.
Il caso tipico di «margini spostati» è costruire le coordinate partendo da e.Graphics.VisibleClipBounds o e.PageBounds, ignorando MarginBounds — area che riflette il margine logico — e HardMarginX/HardMarginY — vincolo fisico. 4 In particolare una stampante di sviluppo può avere hard margin piccolo e nascondere il problema, mentre un modello presso il cliente può averlo maggiore e tagliare righe o campi. La verifica su più modelli è una fase facile da omettere.
Per offrire un’anteprima, assegnare lo stesso PrintDocument alla proprietà Document di PrintPreviewDialog: la logica di PrintPage viene riutilizzata senza modifiche. 1 Per cambiare output in base alla risoluzione, ottenere le scelte da PrinterSettings.PrinterResolutions e assegnarle a PageSettings.PrinterResolution. 3
4. WPF: FlowDocument / FixedDocument e PrintDialog
In WPF la scelta tra FlowDocument e FixedDocument dipende dalla natura del documento.
FlowDocument. È un documento che ridispone dinamicamente il contenuto in base a variabili di esecuzione quali dimensione della finestra o impostazioni dei font, privilegiando la leggibilità. Include ricerca, paginazione e cambio di modalità di visualizzazione. 8FixedDocument. È un documento WYSIWYG in cui l’applicazione controlla completamente il layout, privilegiando la fedeltà su dispositivi di visualizzazione e stampa. È adatto quando serve riproducibilità elevata. 9
Per un report interno che privilegia la leggibilità scegliere FlowDocument; per documenti o etichette in cui posizione di linee e campi deve restare fissata al pixel, scegliere FixedDocument.
La stampa di base usa System.Windows.Controls.PrintDialog, una classe WPF distinta da System.Windows.Forms.PrintDialog. 10
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
public static class FlowDocumentPrinter
{
public static void Print(FlowDocument document, string jobName)
{
var printDialog = new PrintDialog();
// Stampare solo se l'utente ha premuto OK.
if (printDialog.ShowDialog() != true)
{
return;
}
// FlowDocument usa presupposti diversi per la dimensione della pagina in visualizzazione e in stampa, quindi
// adeguare dimensioni e margini del contenuto stampato all'area stampabile della stampante.
var paginator = ((IDocumentPaginatorSource)document).DocumentPaginator;
paginator.PageSize = new Size(
printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
printDialog.PrintDocument(paginator, jobName);
}
}
Per specificare con precisione formato carta, vassoio e fronte-retro usare PrintQueue e PrintTicket/PrintCapabilities. PrintTicket descrive l’istruzione del lavoro, PrintCapabilities le funzioni realmente supportate dalla stampante; è buona pratica unire e convalidare la richiesta con valori validi della stampante usando PrintQueue.MergeAndValidatePrintTicket. 711
using System.Linq;
using System.Printing;
public static class DuplexPrintTicketBuilder
{
public static PrintTicket BuildDuplexTicket(PrintQueue printQueue)
{
PrintCapabilities capabilities = printQueue.GetPrintCapabilities();
// Verificare in anticipo se la stampante supporta la stampa fronte-retro (rilegatura sul lato lungo).
bool supportsDuplex = capabilities.DuplexingCapability
.Contains(Duplexing.TwoSidedLongEdge);
var requestedTicket = new PrintTicket();
if (supportsDuplex)
{
requestedTicket.Duplexing = Duplexing.TwoSidedLongEdge;
}
// Unire al PrintTicket predefinito dell'utente soltanto la richiesta di stampa fronte-retro.
// Gli elementi non supportati vengono sostituiti automaticamente con valori validi.
ValidationResult result = printQueue.MergeAndValidatePrintTicket(
printQueue.UserPrintTicket, requestedTicket);
return result.ValidatedPrintTicket;
}
}
Se un report a layout fisso viene costruito con FixedDocument e inviato direttamente sul percorso XPS, il lavoro viene aggiunto a PrintQueue con Write/WriteAsync di XpsDocumentWriter. Per una stampante senza XPSDrv avviene internamente la conversione automatica in GDI, quindi il chiamante non deve preoccuparsi del percorso. 7
5. Alternative per l’output PDF
Il requisito «voglio produrre un PDF» cambia la progettazione secondo quale dei tre significati si intenda.
- Come estensione della stampa, è sufficiente che l’utente possa scegliere manualmente il salvataggio PDF.
- Si vuole generare PDF dall’applicazione passando dalla finestra di stampa.
- Non si stamperà affatto: si vogliono produrre in massa soltanto file PDF in un batch non presidiato.
Microsoft Print to PDF serve ai casi 1 e 2. È una funzione inclusa da Windows 10, formata da coda di stampa e pacchetto driver, visibile all’app come una normale stampante. 12 Tuttavia presuppone un comportamento interattivo che chiede il nome del file a ogni stampa; anche ufficialmente i controlli sono forniti solo come gestione della coda e del pacchetto driver. 12 Non è progettato per il caso 3, nel quale si fissa un percorso e si producono PDF silenziosamente in quantità. In tale caso è più naturale usare una libreria che generi PDF direttamente senza passare dalla pipeline di stampa.
Per scegliere una libreria PDF, prima di raccomandare un prodotto specifico è utile ordinare i requisiti aziendali secondo questi criteri.
| Criterio | Cosa verificare |
|---|---|
| Licenza | OSS (MIT/Apache oppure GPL/AGPL) o commerciale. Distribuendo o vendendo l’app all’esterno, verificare nelle fonti primarie — testo della licenza e sito ufficiale del fornitore — che obbligo di apertura del codice, condizioni di ridistribuzione e uso commerciale non siano in conflitto con la propria forma di distribuzione |
| Font giapponesi | Supporto per subset embedding dei font giapponesi, assenza di mojibake su macchine prive del font e, se necessario al business, scrittura verticale e varianti IVS |
| Funzioni per report | Definizione basata su template, barcode/QR, firma elettronica, PDF/A per conservazione a lungo termine e facilità di trasferire il layout dei report cartacei esistenti |
| Dipendenze e ambiente | Funzionamento su server senza GUI (Windows Server, container), dipendenze da librerie native ed esperienza in .NET Core/.NET fuori da Framework |
| Prestazioni | Uso della memoria nella generazione batch di molte pagine o lavori e comportamento con generazione parallela |
Le condizioni di licenza cambiano per prodotto e versione. Prima dell’adozione verificare sempre la documentazione ufficiale o il testo stesso della licenza. Qui non viene consigliata alcuna libreria o prodotto specifico: vengono mostrati soltanto criteri di confronto.
6. L’alternativa dei report tramite Excel / Word
Quando esiste già un report gestito con un template Excel, può essere più realistico riutilizzare quell’asset invece di ricreare tutto da zero. Ci sono due approcci principali.
- Generare o modificare direttamente xlsx/docx con Open XML SDK e simili. Poiché non avvia l’eseguibile di Excel/Word ma legge e scrive direttamente il formato file ZIP + XML, funziona stabilmente anche sul server. È adatto a mantenere linee e formattazione del template inserendo solo valori; i dettagli sono organizzati in “Come costruire l’output di report Excel: COM/Open XML/template”.
- Controllare il vero
Excel.Applicationcon Excel COM Interop. È scelto quando si devono riutilizzare fogli esistenti con macro o ricalcoli complessi, ma è frequente il problema che EXCEL.EXE resti attivo per riferimenti COM non liberati. Misure e criteri sono trattati in “Il problema di EXCEL.EXE che rimane usando Excel da C#”.
Il punto importante è che Microsoft dichiara ufficialmente che l’automazione Office lato server o da servizio Windows non è consigliata né supportata. Le app Office sono progettate per desktop interattivo e profilo di utente connesso; in ambiente non presidiato/non interattivo possono essere instabili o andare in deadlock. 13 Anche le normali EULA non prevedono di offrire ai clienti funzionalità Office tramite automazione lato server. 13
Perciò, integrando l’output di report in un servizio residente o in un job batch, anche se si riusa un template Excel, è più sicuro evitare di avviare Excel.exe a runtime tramite COM Interop e preferire la generazione diretta di file con Open XML SDK. Se COM Interop è indispensabile, una separazione realistica è eseguirlo come app residente — non servizio — in una sessione utente interattiva connessa.
7. Insidie pratiche
Stampa da un servizio Windows e sessione 0
Non sono rare le richieste di incorporare la stampa in un servizio residente, ma i servizi Windows operano nella sessione 0. Da Windows Vista la sessione 0 è riservata a servizi e processi non associati a utenti interattivi ed è separata dalla sessione dell’utente. 14 Per questa separazione, anche se il servizio mostra una finestra di dialogo l’utente non la vedrà; codice che attende input utente — per esempio una finestra di stampa — può sembrare bloccato. 14
Un’altra insidia pratica è la visibilità di stampanti di rete o stampanti mappate per utente. Una stampante di rete connessa dall’utente è spesso visibile nella sua sessione interattiva, ma non necessariamente da un contesto diverso come il processo del servizio nella sessione 0. Per un processo residente che stampa, verificare fin dall’inizio quali stampanti siano visibili a quale account e sessione. La separazione delle sessioni è trattata in “Come comprendere l’isolamento delle sessioni Windows”, mentre le basi di implementazione e operatività dei servizi sono in “Come creare e gestire servizi Windows”.
Stampante assente o offline
Se si assegna a PrinterSettings.PrinterName un nome inesistente oppure si esegue in un ambiente senza stampante predefinita, il tentativo di stampa può produrre un’eccezione o un fallimento. Come minimo convalidare prima con PrinterSettings.IsValid e progettare tentativi e notifiche di errore assumendo che la stampa possa fallire. Se una stampante di rete è temporaneamente offline, il lavoro può restare nello spooler senza output reale; non terminare la verifica a «l’invio è riuscito», ma controllare lo stato del job quando necessario.
Il rischio di dipendere dalla stampante predefinita
Un’implementazione che non specifica PrinterSettings.PrinterName e dipende sempre dalla “stampante predefinita” accumula rischi nel tempo. L’utente può cambiare stampante predefinita o un portatile può cambiarla in un’altra sede, inviando documenti importanti a una destinazione non voluta. Per report aziendali importanti, conservare esplicitamente il nome della stampante di destinazione nella configurazione o in una schermata di impostazioni, così da non essere trascinati dai cambiamenti della predefinita.
Perdite di handle GDI durante l’esecuzione prolungata
Se nel codice di stampa non si liberano con certezza tramite using o Dispose() risorse GDI/GDI+ come Graphics, Font, Brush e Pen, dopo un’esecuzione prolungata gli handle GDI si esauriscono e le chiamate di disegno iniziano a fallire. Gli handle hanno un limite predefinito per processo, una risorsa finita regolabile da 256 a 65.536 tramite GDIProcessHandleQuota nel Registro. 15 Più frequentemente stampa un’app residente, più è probabile che questa perdita emerga solo in produzione. Un’indagine e un metodo di isolamento concreti sono spiegati nel caso di crash prolungato di una telecamera industriale dovuto a perdita di handle.
Articoli correlati
- Come costruire l’output di report Excel: COM/Open XML/template
- Il problema di EXCEL.EXE che rimane usando Excel da C#: rilascio dei riferimenti COM e scelta della sostituzione
- Come creare e gestire servizi Windows: da Task Scheduler alla trasformazione di BackgroundService in servizio
- Come comprendere l’isolamento delle sessioni Windows: Session 0, RDP ed esecuzione simultanea di più utenti
- Indagine sui crash prolungati di una telecamera industriale: perdita di handle
Aree di consulenza correlate
KomuraSoft LLC offre consulenza tecnica sulla progettazione delle funzioni di stampa e output di report nelle applicazioni aziendali Windows, sul rifacimento di report che riusa asset Excel esistenti e sulla progettazione di stampa/output da servizi residenti.
Riferimenti
-
Microsoft Learn, PrintDocument Class. Sul ruolo di
PrintDocument— impostareDocumentNameePrinterSettingse avviare la stampa conPrint()— e sull’indicazione di usare lo spazio dei nomiSystem.Printingper stampare da WPF. ↩ ↩2 ↩3 ↩4 -
Microsoft Learn, PrintPageEventArgs.HasMorePages Property. Sul valore predefinito
falsee sulla ripetizione dell’eventoPrintPagefino a quando questa proprietà èfalse. ↩ ↩2 -
Microsoft Learn, PageSettings.PrinterResolution Property. Sul fatto che la risoluzione di stampa predefinita della pagina sia la risoluzione predefinita della stampante e che le scelte siano ottenibili da
PrinterSettings.PrinterResolutions. ↩ ↩2 ↩3 -
Microsoft Learn, PageSettings.HardMarginX Property. Sul fatto che l’hard margin rappresenti il margine fisico impostato dalla stampante. ↩ ↩2 ↩3
-
Microsoft Learn, PageSettings.Margins Property. Sui margini predefiniti di un pollice per lato e sul calcolo dell’area stampabile insieme a
Boundsnell’eventoPrintPage. ↩ ↩2 -
Microsoft Learn, Windows Print Path Overview. Sui due percorsi principali in Windows: GDI per app Win32 e XPS per WPF o XPS Print API. ↩ ↩2 ↩3
-
Microsoft Learn, Printing documents overview. Sul percorso XPS WPF, la stampa base con
PrintDialog, quella avanzata conPrintTicket/PrintCapabilities/PrintQueue/XpsDocumentWritere la conversione automatica in GDI per stampanti senza XPSDrv. ↩ ↩2 ↩3 ↩4 -
Microsoft Learn, Flow Document Overview. Sul fatto che
FlowDocumentridisponga il contenuto secondo variabili quali dimensione della finestra e risoluzione, privilegiando la leggibilità. ↩ ↩2 -
Microsoft Learn, FixedDocument Class. Sul fatto che
FixedDocumentprivilegi una riproduzione WYSIWYG fedele per display e stampa, con filosofia diversa daFlowDocument. ↩ ↩2 -
Microsoft Learn, PrintDialog Class. Sul fatto che
System.Windows.Controls.PrintDialogcompongaPrintTicketePrintQueuein base all’input utente e sia distinto daSystem.Windows.Forms.PrintDialog. ↩ ↩2 -
Microsoft Learn, How to: Validate and Merge PrintTickets. Sulla verifica delle capacità con
PrintQueue.GetPrintCapabilitiese l’unione/convalida della richiesta conMergeAndValidatePrintTicket. ↩ ↩2 -
Microsoft Learn, RemoveMPDW. Su Microsoft Print to PDF come optional feature installata per impostazione predefinita e gestita/rimossa come coda di stampa e pacchetto driver. ↩ ↩2 ↩3
-
Microsoft Support, Considerations for server-side Automation of Office. Sul fatto che Microsoft non consigli né supporti l’automazione Office da applicazioni client non presidiate/non interattive, comprese ASP/ASP.NET/DCOM/servizi NT, e che Office presupponga desktop interattivo e profilo utente. ↩ ↩2 ↩3
-
Microsoft Learn, Service Changes for Windows Vista - Session 0 Isolation. Sul fatto che da Windows Vista la sessione 0 sia riservata a servizi e app non associate a utenti interattivi e che i servizi non possano mostrare direttamente finestre di dialogo. ↩ ↩2 ↩3
-
Microsoft Learn, GDI Objects. Sul fatto che gli handle GDI abbiano un limite per processo e che
GDIProcessHandleQuotaconsenta di regolarlo fra 256 e 65.536. ↩ ↩2 -
Microsoft Learn, Introduction to printing. Sull’architettura di stampa Windows formata da spooler e driver, e sull’invio delle istruzioni di disegno Win32 GDI come EMF allo spooler. ↩ ↩2
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Individuare con PerfView e dotnet-trace la causa di un rallentamento — introduzione pratica all'analisi delle prestazioni .NET
Quando un'app aziendale è lenta, satura la CPU o si blocca, quale strumento usare e cosa osservare? Questa guida spiega la divisione dei ...
Oltre appsettings.json — Guida pratica alla gestione della configurazione nelle applicazioni aziendali Windows (impostazioni per ambiente, segreti e percorsi di scrittura)
Uno sguardo pratico alla gestione della configurazione nelle applicazioni aziendali Windows: stratificazione di appsettings.json, scelta ...
Introduzione al registro eventi di Windows e a ETW — usare per le app aziendali i meccanismi standard del sistema operativo
La vostra app aziendale Windows usa soltanto file di log? Registro eventi ed ETW sono registrazioni visibili a un livello diverso, per il...
Google Ads BtoB con un budget ridotto — come progettare e gestire una routine settimanale efficace con poche decine di migliaia di yen al mese
Guida pratica a Google Ads per aziende BtoB che vogliono iniziare con poche decine di migliaia di yen al mese. Illustra il funzionamento ...
Far comparire il sito nelle ricerche con il nome della zona — guida pratica alla SEO locale per PMI (pagine per area e Google Business Profile)
Per le PMI il cui sito non compare nelle ricerche «nome della zona + settore». L'articolo illustra l'ordine con cui migliorare la SEO loc...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Thread UI e timer
Thread UI WPF / WinForms, flussi asincroni, Dispatcher e progettazione dei timer.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
La progettazione e l'implementazione di funzionalità di stampa e output PDF nelle applicazioni aziendali rientrano nelle consulenze sullo sviluppo di applicazioni Windows.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- Devo usare PrintDocument o la stampa WPF?
- Se l'interfaccia è WinForms, la scelta naturale è PrintDocument; se è WPF, FlowDocument o FixedDocument. Non è necessario mescolare tecnologie: il criterio pratico è seguire il framework della UI dell'applicazione esistente. Se si sceglie WPF per un nuovo progetto, conviene decidere in anticipo se il report è soprattutto a flusso libero o a layout fisso e scegliere di conseguenza FlowDocument o FixedDocument.
- Conviene acquistare una libreria di report?
- Quando è elevato il costo di realizzare internamente con GDI+/WPF report complessi con molte linee, più formati carta, incorporamento di font giapponesi o scrittura verticale, il costo di una libreria di report è spesso inferiore. Per un semplice elenco A4, PrintDocument o FixedDocument realizzato in casa può essere sufficiente. È più sicuro valutare prima la complessità dei requisiti.
- È possibile generare solo PDF senza usare la stampa?
- Sì. Il PDF è solo uno dei formati di output; la generazione diretta con una libreria PDF che non dipenda dalla finestra di stampa o dalla stampante predefinita è spesso più adatta a elaborazioni batch e automazione. Microsoft Print to PDF è un driver pensato per operazioni interattive e non è indicato per creare PDF senza intervento umano.
- Si possono supportare anche stampanti per etichette o ricevute?
- È possibile, ma non sempre come semplice estensione di PrintDocument o FixedDocument. Molte stampanti per etichette hanno un proprio linguaggio di comandi o SDK e vengono controllate attraverso un percorso diverso dalla stampa standard Windows. Iniziare verificando se il modello si comporta come un normale driver Windows oppure richiede un SDK dedicato.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.
Link pubblici