Scanner de codes-barres USB en C# : Créez une application de numérisation complète
Les lecteurs de codes-barres USB se connectent aux applications C# comme des périphériques d'entrée clavier standard, envoyant les données scannées sous forme de caractères saisis suivis d'une pression sur la touche Entrée. Ce comportement de ce clavier HID simplifie l'intégration : votre application reçoit les entrées de texte sans qu'aucun pilote ou SDK spécial ne soit requis. IronBarcode traite ces données brutes pour valider les formats, extraire les données structurées et générer des codes-barres de réponse, transformant ainsi un simple événement de numérisation en un pipeline de données complet pour la gestion des stocks, les points de vente au détail et les systèmes de suivi logistique.
Les activités de vente au détail, d'entreposage et de fabrication dépendent toutes d'une lecture rapide et précise des codes-barres. Lorsqu'un développeur connecte un scanner USB à une application Windows Forms ou WPF, le scanner se comporte de la même manière qu'un clavier : les données arrivent dans une zone de texte, et appuyer sur Entrée signale qu'un code-barres complet a été reçu. Le défi n'est pas de recueillir les données ; Le traitement se déroule correctement. Le système de validation de codes-barres d'IronBarcode vérifie l'intégrité du format, extrait des champs tels que les numéros de lot ou les identifiants d'application GS1 et peut générer immédiatement un nouveau code-barres en réponse.
Ce guide vous accompagne pas à pas dans la création d'une application de lecture de codes-barres USB en C# prête pour la production. Vous installerez la bibliothèque, capturerez les données du scanner, validerez les formats de codes-barres, générerez les étiquettes de réponse et assemblerez un processeur à file d'attente pour un volume élevé de données. Chaque section comprend un code complet et exécutable ciblant .NET 10 avec un style d'instruction de niveau supérieur lorsque cela est approprié.
Comment les scanners de codes-barres USB fonctionnent-ils avec C# ?
Pourquoi le mode Wedge du clavier HID simplifie-t-il l'intégration ?
La plupart des lecteurs de codes-barres USB sont livrés configurés par défaut en mode clavier HID. Lorsque vous branchez un tel appareil sur un ordinateur Windows, le système d'exploitation l'enregistre à la fois comme un périphérique de stockage USB (pour la configuration) et comme un clavier (pour la saisie de données). Lorsqu'un code-barres est scanné, l'appareil traduit la valeur décodée du code-barres en frappes de clavier et les envoie à la fenêtre d'application qui a le focus, en ajoutant un retour chariot à la fin.
Du point de vue d'un développeur C#, cela signifie qu'il n'est pas nécessaire d'utiliser les kits de développement logiciel (SDK) des fournisseurs, les bibliothèques COM ou les API USB spécifiques. Un simple contrôle TextBox avec un gestionnaire d'événement KeyDown suffit pour la saisie. Le principal défi d'intégration consiste à distinguer les données saisies par scanner de la véritable saisie au clavier. Les scanners délivrent généralement tous les caractères en un laps de temps très court — souvent moins de 50 millisecondes — tandis que la frappe humaine répartit les frappes sur des centaines de millisecondes. Le déclenchement temporel de la rafale est un moyen fiable de filtrer les frappes accidentelles.
Les scanners de qualité professionnelle prennent également en charge les modes série (RS-232 ou port COM virtuel) et USB HID direct, ce qui vous offre un meilleur contrôle sur les caractères de préfixe/suffixe et les déclencheurs de numérisation. Le modèle d'interface ci-dessous gère les deux cas :
public interface IScannerInput
{
event EventHandler<string> BarcodeScanned;
void StartListening();
void StopListening();
}
public class KeyboardWedgeScanner : IScannerInput
{
public event EventHandler<string> BarcodeScanned;
private readonly TextBox _inputBox;
private readonly System.Windows.Forms.Timer _burstTimer;
private readonly System.Text.StringBuilder _buffer = new();
public KeyboardWedgeScanner(TextBox inputBox)
{
_inputBox = inputBox;
_burstTimer = new System.Windows.Forms.Timer { Interval = 80 };
_burstTimer.Tick += OnBurstTimeout;
_inputBox.KeyPress += OnKeyPress;
}
private void OnKeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
_burstTimer.Stop();
string value = _buffer.ToString().Trim();
_buffer.Clear();
if (value.Length > 0)
BarcodeScanned?.Invoke(this, value);
}
else
{
_buffer.Append(e.KeyChar);
_burstTimer.Stop();
_burstTimer.Start();
}
e.Handled = true;
}
private void OnBurstTimeout(object sender, EventArgs e)
{
_burstTimer.Stop();
_buffer.Clear(); // incomplete burst -- discard
}
public void StartListening() => _inputBox.Focus();
public void StopListening() => _inputBox.Enabled = false;
}
public class SerialPortScanner : IScannerInput
{
public event EventHandler<string> BarcodeScanned;
private readonly System.IO.Ports.SerialPort _port;
public SerialPortScanner(string portName, int baudRate = 9600)
{
_port = new System.IO.Ports.SerialPort(portName, baudRate);
_port.DataReceived += OnDataReceived;
}
private void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string data = _port.ReadLine().Trim();
if (data.Length > 0)
BarcodeScanned?.Invoke(this, data);
}
public void StartListening() => _port.Open();
public void StopListening() => _port.Close();
}
public interface IScannerInput
{
event EventHandler<string> BarcodeScanned;
void StartListening();
void StopListening();
}
public class KeyboardWedgeScanner : IScannerInput
{
public event EventHandler<string> BarcodeScanned;
private readonly TextBox _inputBox;
private readonly System.Windows.Forms.Timer _burstTimer;
private readonly System.Text.StringBuilder _buffer = new();
public KeyboardWedgeScanner(TextBox inputBox)
{
_inputBox = inputBox;
_burstTimer = new System.Windows.Forms.Timer { Interval = 80 };
_burstTimer.Tick += OnBurstTimeout;
_inputBox.KeyPress += OnKeyPress;
}
private void OnKeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
_burstTimer.Stop();
string value = _buffer.ToString().Trim();
_buffer.Clear();
if (value.Length > 0)
BarcodeScanned?.Invoke(this, value);
}
else
{
_buffer.Append(e.KeyChar);
_burstTimer.Stop();
_burstTimer.Start();
}
e.Handled = true;
}
private void OnBurstTimeout(object sender, EventArgs e)
{
_burstTimer.Stop();
_buffer.Clear(); // incomplete burst -- discard
}
public void StartListening() => _inputBox.Focus();
public void StopListening() => _inputBox.Enabled = false;
}
public class SerialPortScanner : IScannerInput
{
public event EventHandler<string> BarcodeScanned;
private readonly System.IO.Ports.SerialPort _port;
public SerialPortScanner(string portName, int baudRate = 9600)
{
_port = new System.IO.Ports.SerialPort(portName, baudRate);
_port.DataReceived += OnDataReceived;
}
private void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string data = _port.ReadLine().Trim();
if (data.Length > 0)
BarcodeScanned?.Invoke(this, data);
}
public void StartListening() => _port.Open();
public void StopListening() => _port.Close();
}
Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.IO.Ports
Public Interface IScannerInput
Event BarcodeScanned As EventHandler(Of String)
Sub StartListening()
Sub StopListening()
End Interface
Public Class KeyboardWedgeScanner
Implements IScannerInput
Public Event BarcodeScanned As EventHandler(Of String) Implements IScannerInput.BarcodeScanned
Private ReadOnly _inputBox As TextBox
Private ReadOnly _burstTimer As Timer
Private ReadOnly _buffer As New StringBuilder()
Public Sub New(inputBox As TextBox)
_inputBox = inputBox
_burstTimer = New Timer With {.Interval = 80}
AddHandler _burstTimer.Tick, AddressOf OnBurstTimeout
AddHandler _inputBox.KeyPress, AddressOf OnKeyPress
End Sub
Private Sub OnKeyPress(sender As Object, e As KeyPressEventArgs)
If e.KeyChar = ChrW(Keys.Enter) Then
_burstTimer.Stop()
Dim value As String = _buffer.ToString().Trim()
_buffer.Clear()
If value.Length > 0 Then
RaiseEvent BarcodeScanned(Me, value)
End If
Else
_buffer.Append(e.KeyChar)
_burstTimer.Stop()
_burstTimer.Start()
End If
e.Handled = True
End Sub
Private Sub OnBurstTimeout(sender As Object, e As EventArgs)
_burstTimer.Stop()
_buffer.Clear() ' incomplete burst -- discard
End Sub
Public Sub StartListening() Implements IScannerInput.StartListening
_inputBox.Focus()
End Sub
Public Sub StopListening() Implements IScannerInput.StopListening
_inputBox.Enabled = False
End Sub
End Class
Public Class SerialPortScanner
Implements IScannerInput
Public Event BarcodeScanned As EventHandler(Of String) Implements IScannerInput.BarcodeScanned
Private ReadOnly _port As SerialPort
Public Sub New(portName As String, Optional baudRate As Integer = 9600)
_port = New SerialPort(portName, baudRate)
AddHandler _port.DataReceived, AddressOf OnDataReceived
End Sub
Private Sub OnDataReceived(sender As Object, e As SerialDataReceivedEventArgs)
Dim data As String = _port.ReadLine().Trim()
If data.Length > 0 Then
RaiseEvent BarcodeScanned(Me, data)
End If
End Sub
Public Sub StartListening() Implements IScannerInput.StartListening
_port.Open()
End Sub
Public Sub StopListening() Implements IScannerInput.StopListening
_port.Close()
End Sub
End Class
Le minuteur de rafale intégré au clavier est un détail essentiel. Il se réinitialise à chaque frappe et ne se déclenche que si aucun caractère n'est enregistré, ce qui signifie que les utilisateurs de clavier qui tapent lentement verront leurs saisies incomplètes rejetées plutôt que traitées comme un scan de code-barres.
Comment gérez-vous plusieurs marques de scanners ?
Dans les environnements Enterprise , on trouve fréquemment un mélange de scanners Honeywell, Zebra (anciennement Symbol/Motorola) et Datalogic sur le même étage. Chaque fournisseur possède ses propres caractères de terminaison par défaut, ses débits de transmission et ses conventions de préfixe/suffixe. Un modèle de configuration assure la flexibilité de votre application :
public class ScannerConfiguration
{
public string ScannerType { get; set; } = "KeyboardWedge";
public string PortName { get; set; } = "COM3";
public int BaudRate { get; set; } = 9600;
public string Terminator { get; set; } = "\r\n";
public bool EnableBeep { get; set; } = true;
public Dictionary<string, string> BrandSettings { get; set; } = new();
public static ScannerConfiguration GetHoneywellConfig() => new()
{
ScannerType = "Serial",
BaudRate = 115200,
BrandSettings = new Dictionary<string, string>
{
{ "Prefix", "STX" },
{ "Suffix", "ETX" },
{ "TriggerMode", "Manual" }
}
};
public static ScannerConfiguration GetZebraConfig() => new()
{
ScannerType = "KeyboardWedge",
BrandSettings = new Dictionary<string, string>
{
{ "ScanMode", "Continuous" },
{ "BeepVolume", "High" }
}
};
}
public class ScannerConfiguration
{
public string ScannerType { get; set; } = "KeyboardWedge";
public string PortName { get; set; } = "COM3";
public int BaudRate { get; set; } = 9600;
public string Terminator { get; set; } = "\r\n";
public bool EnableBeep { get; set; } = true;
public Dictionary<string, string> BrandSettings { get; set; } = new();
public static ScannerConfiguration GetHoneywellConfig() => new()
{
ScannerType = "Serial",
BaudRate = 115200,
BrandSettings = new Dictionary<string, string>
{
{ "Prefix", "STX" },
{ "Suffix", "ETX" },
{ "TriggerMode", "Manual" }
}
};
public static ScannerConfiguration GetZebraConfig() => new()
{
ScannerType = "KeyboardWedge",
BrandSettings = new Dictionary<string, string>
{
{ "ScanMode", "Continuous" },
{ "BeepVolume", "High" }
}
};
}
Option Strict On
Public Class ScannerConfiguration
Public Property ScannerType As String = "KeyboardWedge"
Public Property PortName As String = "COM3"
Public Property BaudRate As Integer = 9600
Public Property Terminator As String = vbCrLf
Public Property EnableBeep As Boolean = True
Public Property BrandSettings As Dictionary(Of String, String) = New Dictionary(Of String, String)()
Public Shared Function GetHoneywellConfig() As ScannerConfiguration
Return New ScannerConfiguration() With {
.ScannerType = "Serial",
.BaudRate = 115200,
.BrandSettings = New Dictionary(Of String, String) From {
{"Prefix", "STX"},
{"Suffix", "ETX"},
{"TriggerMode", "Manual"}
}
}
End Function
Public Shared Function GetZebraConfig() As ScannerConfiguration
Return New ScannerConfiguration() With {
.ScannerType = "KeyboardWedge",
.BrandSettings = New Dictionary(Of String, String) From {
{"ScanMode", "Continuous"},
{"BeepVolume", "High"}
}
}
End Function
End Class
Le stockage de ces configurations dans un fichier de paramètres ou une base de données permet au personnel de l'entrepôt de changer de modèle de scanner sans nécessiter de redéploiement. Le champ ScannerType détermine quelle implémentation de IScannerInput est instanciée au démarrage.
Comment installer IronBarcode dans un projet C# ?
Quelle est la méthode la plus rapide pour ajouter IronBarcode via NuGet?
Ouvrez la console du Package Manager dans Visual Studio et exécutez :
Install-Package BarCode
Vous pouvez également utiliser l'interface de ligne de commande .NET :
dotnet add package BarCode
Ces deux commandes téléchargent la version actuelle depuis NuGet et ajoutent la référence d'assembly à votre fichier projet. La bibliothèque cible .NET Standard 2.0 et fonctionne donc avec .NET Framework 4.6.2 à .NET 10 sans aucun module de compatibilité supplémentaire.
Après l'installation, définissez votre clé de licence avant d'appeler une méthode IronBarcode . Pour le développement et l'évaluation, une clé d'essai gratuite est disponible sur la page de licences IronBarcode :
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
Pour les déploiements conteneurisés, IronBarcode fonctionne avec Docker sous Linux , et pour les fonctions cloud, il prend en charge AWS Lambda et Azure Functions .
Comment valider les codes-barres scannés avec IronBarcode?
Quelle est la bonne approche pour la vérification du format ?
IronBarcode prend en charge plus de 30 symbologies de codes-barres, notamment Code 128 , EAN-13 , Code 39 , les codes QR et Data Matrix . Pour les applications de scanner USB, le modèle de validation réencode la chaîne scannée sous forme d'image de code-barres et la relit immédiatement via le décodeur. Cet aller-retour confirme que la chaîne est une valeur valide pour le format déclaré :
public class BarcodeValidator
{
public async Task<ValidationResult> ValidateAsync(string scannedText, BarcodeEncoding preferredFormat = BarcodeEncoding.Code128)
{
var result = new ValidationResult { RawInput = scannedText };
try
{
var barcode = BarcodeWriter.CreateBarcode(scannedText, preferredFormat);
var readResults = await BarcodeReader.ReadAsync(barcode.ToBitmap());
if (readResults.Any())
{
var first = readResults.First();
result.IsValid = true;
result.Format = first.BarcodeType;
result.Value = first.Value;
result.Confidence = first.Confidence;
}
else
{
result.IsValid = false;
result.Error = "No barcode could be decoded from the scanned input.";
}
}
catch (Exception ex)
{
result.IsValid = false;
result.Error = ex.Message;
}
return result;
}
}
public record ValidationResult
{
public string RawInput { get; init; } = "";
public bool IsValid { get; set; }
public BarcodeEncoding Format { get; set; }
public string Value { get; set; } = "";
public float Confidence { get; set; }
public string Error { get; set; } = "";
}
public class BarcodeValidator
{
public async Task<ValidationResult> ValidateAsync(string scannedText, BarcodeEncoding preferredFormat = BarcodeEncoding.Code128)
{
var result = new ValidationResult { RawInput = scannedText };
try
{
var barcode = BarcodeWriter.CreateBarcode(scannedText, preferredFormat);
var readResults = await BarcodeReader.ReadAsync(barcode.ToBitmap());
if (readResults.Any())
{
var first = readResults.First();
result.IsValid = true;
result.Format = first.BarcodeType;
result.Value = first.Value;
result.Confidence = first.Confidence;
}
else
{
result.IsValid = false;
result.Error = "No barcode could be decoded from the scanned input.";
}
}
catch (Exception ex)
{
result.IsValid = false;
result.Error = ex.Message;
}
return result;
}
}
public record ValidationResult
{
public string RawInput { get; init; } = "";
public bool IsValid { get; set; }
public BarcodeEncoding Format { get; set; }
public string Value { get; set; } = "";
public float Confidence { get; set; }
public string Error { get; set; } = "";
}
Imports System
Imports System.Linq
Imports System.Threading.Tasks
Public Class BarcodeValidator
Public Async Function ValidateAsync(scannedText As String, Optional preferredFormat As BarcodeEncoding = BarcodeEncoding.Code128) As Task(Of ValidationResult)
Dim result As New ValidationResult With {.RawInput = scannedText}
Try
Dim barcode = BarcodeWriter.CreateBarcode(scannedText, preferredFormat)
Dim readResults = Await BarcodeReader.ReadAsync(barcode.ToBitmap())
If readResults.Any() Then
Dim first = readResults.First()
result.IsValid = True
result.Format = first.BarcodeType
result.Value = first.Value
result.Confidence = first.Confidence
Else
result.IsValid = False
result.Error = "No barcode could be decoded from the scanned input."
End If
Catch ex As Exception
result.IsValid = False
result.Error = ex.Message
End Try
Return result
End Function
End Class
Public Class ValidationResult
Public Property RawInput As String = ""
Public Property IsValid As Boolean
Public Property Format As BarcodeEncoding
Public Property Value As String = ""
Public Property Confidence As Single
Public Property Error As String = ""
End Class
Pour les codes-barres GS1-128 utilisés dans les applications de chaîne d'approvisionnement, la chaîne scannée inclut des préfixes d'identificateur d'application entre parenthèses tels que (01) pour le GTIN et (17) pour la date d'expiration. IronBarcode analyse ces identificateurs d'application automatiquement lorsque vous spécifiez BarcodeEncoding.GS1_128.
Quelle logique de somme de contrôle EAN-13 les développeurs doivent-ils implémenter ?
Les applications de point de vente doivent souvent vérifier indépendamment les chiffres de contrôle EAN-13 avant de transmettre la valeur à une base de données de prix. La somme de contrôle de type Luhn pour EAN-13 alterne les valeurs 1 et 3 sur les 12 premiers chiffres :
public static bool ValidateEan13Checksum(string value)
{
if (value.Length != 13 || !value.All(char.IsDigit))
return false;
int sum = 0;
for (int i = 0; i < 12; i++)
{
int digit = value[i] - '0';
sum += (i % 2 == 0) ? digit : digit * 3;
}
int expectedCheck = (10 - (sum % 10)) % 10;
return expectedCheck == (value[12] - '0');
}
public static bool ValidateEan13Checksum(string value)
{
if (value.Length != 13 || !value.All(char.IsDigit))
return false;
int sum = 0;
for (int i = 0; i < 12; i++)
{
int digit = value[i] - '0';
sum += (i % 2 == 0) ? digit : digit * 3;
}
int expectedCheck = (10 - (sum % 10)) % 10;
return expectedCheck == (value[12] - '0');
}
Public Shared Function ValidateEan13Checksum(value As String) As Boolean
If value.Length <> 13 OrElse Not value.All(AddressOf Char.IsDigit) Then
Return False
End If
Dim sum As Integer = 0
For i As Integer = 0 To 11
Dim digit As Integer = AscW(value(i)) - AscW("0"c)
sum += If(i Mod 2 = 0, digit, digit * 3)
Next
Dim expectedCheck As Integer = (10 - (sum Mod 10)) Mod 10
Return expectedCheck = (AscW(value(12)) - AscW("0"c))
End Function
Ce contrôle purement logique s'exécute avant l'encodage afin d'éviter la surcharge liée à la génération d'images aller-retour pour chaque scan dans un environnement de vente au détail à volume élevé. Selon la spécification GS1 , l'algorithme de chiffre de contrôle est identique pour UPC-A (12 chiffres) lorsque vous supprimez le zéro initial.
Comment générer des codes-barres de réponse à partir de données scannées ?
Quand une application doit-elle créer de nouveaux codes-barres après une numérisation ?
Un schéma courant dans la réception en entrepôt est le flux de travail " scan et réétiquetage " : un article entrant porte un code-barres fournisseur (souvent EAN-13 ou ITF-14), et le système de gestion d'entrepôt doit imprimer une étiquette interne Code 128 avec ses propres codes d'emplacement et de lot. Les fonctionnalités de génération d'IronBarcode gèrent cela en quelques lignes :
public class InventoryLabelGenerator
{
private readonly string _outputDirectory;
public InventoryLabelGenerator(string outputDirectory)
{
_outputDirectory = outputDirectory;
Directory.CreateDirectory(_outputDirectory);
}
public async Task<string> GenerateLabelAsync(string internalCode, string locationCode)
{
string fullCode = $"{internalCode}|{locationCode}|{DateTime.UtcNow:yyyyMMdd}";
// Primary Code 128 label for scanners
var linearBarcode = BarcodeWriter.CreateBarcode(fullCode, BarcodeEncoding.Code128);
linearBarcode.ResizeTo(500, 140);
linearBarcode.SetMargins(12);
linearBarcode.AddAnnotationTextAboveBarcode(fullCode);
linearBarcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black);
// QR code companion for mobile apps
var qrCode = BarcodeWriter.CreateQrCode(fullCode);
qrCode.ResizeTo(200, 200);
qrCode.SetMargins(8);
string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
string pngPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.png");
string pdfPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.pdf");
await Task.Run(() =>
{
linearBarcode.SaveAsPng(pngPath);
linearBarcode.SaveAsPdf(pdfPath);
});
return pngPath;
}
}
public class InventoryLabelGenerator
{
private readonly string _outputDirectory;
public InventoryLabelGenerator(string outputDirectory)
{
_outputDirectory = outputDirectory;
Directory.CreateDirectory(_outputDirectory);
}
public async Task<string> GenerateLabelAsync(string internalCode, string locationCode)
{
string fullCode = $"{internalCode}|{locationCode}|{DateTime.UtcNow:yyyyMMdd}";
// Primary Code 128 label for scanners
var linearBarcode = BarcodeWriter.CreateBarcode(fullCode, BarcodeEncoding.Code128);
linearBarcode.ResizeTo(500, 140);
linearBarcode.SetMargins(12);
linearBarcode.AddAnnotationTextAboveBarcode(fullCode);
linearBarcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black);
// QR code companion for mobile apps
var qrCode = BarcodeWriter.CreateQrCode(fullCode);
qrCode.ResizeTo(200, 200);
qrCode.SetMargins(8);
string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
string pngPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.png");
string pdfPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.pdf");
await Task.Run(() =>
{
linearBarcode.SaveAsPng(pngPath);
linearBarcode.SaveAsPdf(pdfPath);
});
return pngPath;
}
}
Imports System.IO
Imports System.Threading.Tasks
Public Class InventoryLabelGenerator
Private ReadOnly _outputDirectory As String
Public Sub New(outputDirectory As String)
_outputDirectory = outputDirectory
Directory.CreateDirectory(_outputDirectory)
End Sub
Public Async Function GenerateLabelAsync(internalCode As String, locationCode As String) As Task(Of String)
Dim fullCode As String = $"{internalCode}|{locationCode}|{DateTime.UtcNow:yyyyMMdd}"
' Primary Code 128 label for scanners
Dim linearBarcode = BarcodeWriter.CreateBarcode(fullCode, BarcodeEncoding.Code128)
linearBarcode.ResizeTo(500, 140)
linearBarcode.SetMargins(12)
linearBarcode.AddAnnotationTextAboveBarcode(fullCode)
linearBarcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black)
' QR code companion for mobile apps
Dim qrCode = BarcodeWriter.CreateQrCode(fullCode)
qrCode.ResizeTo(200, 200)
qrCode.SetMargins(8)
Dim timestamp As String = DateTime.UtcNow.ToString("yyyyMMddHHmmss")
Dim pngPath As String = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.png")
Dim pdfPath As String = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.pdf")
Await Task.Run(Sub()
linearBarcode.SaveAsPng(pngPath)
linearBarcode.SaveAsPdf(pdfPath)
End Sub)
Return pngPath
End Function
End Class
L'enregistrement au format PDF est particulièrement utile pour les imprimantes d'étiquettes qui acceptent les fichiers PDF en entrée via un partage réseau. Vous pouvez également exporter au format SVG pour obtenir des étiquettes thermiques vectorielles de haute qualité, ou exporter sous forme de flux d'octets pour l'envoyer directement à une API d'imprimante d'étiquettes.
IronBarcode prend en charge une personnalisation de style étendue, notamment les couleurs personnalisées, les ajustements de marge , les superpositions de texte lisibles par l'homme et, pour les codes QR, l'intégration de logos pour les étiquettes mobiles marquées de la marque.




