Windows上の任意のプリンターに任意の文字列を正確に印刷する方法についてネットを検索して数日後、最終的にこのコードを思いつきました。
LPBYTE pPrinterEnum;
DWORD pcbNeeded, pcbReturned;
PRINTER_INFO_2 *piTwo = NULL;
HDC printer;
EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,NULL,0,&pcbNeeded,&pcbReturned);
pPrinterEnum = new BYTE[pcbNeeded];
if (!EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,pPrinterEnum,pcbNeeded,&pcbNeeded,&pcbReturned)) {
qDebug() << "In Print, could not enumerate printers";
} else {
piTwo = ((PRINTER_INFO_2*)pPrinterEnum);
for (int i = 0; i < pcbReturned; i++) {
QString name = QString::fromWCharArray(piTwo[i].pPrinterName);
if (this->m_printer_path == name) {
const WCHAR * driver = L"WINSPOOL\0";
printer = CreateDC(NULL,piTwo[i].pPrinterName,NULL,NULL);
}
}
}
if (printer == 0) {
qDebug() << "No Printer HDC";
return;
} else {
qDebug() << "Printer seems okay!";
}
qDebug() << "Starting Document";
DOCINFO di;
memset( &di, 0, sizeof( di ) );
di.cbSize = sizeof( di );
WCHAR * text = new WCHAR[ba.length()];
QString(ba).toWCharArray(text);
StartDoc(printer,&di);
qDebug() << "Writing text";
TextOut(printer,0, 0, text, ba.length());
qDebug() << "Text Written";
EndPage(printer);
qDebug() << "Page ended";
DeleteDC(printer);
qDebug() << "DC Deleted";
基本的な注意事項:
1) QPrinter を使用できません。あとがきではなく、生のテキストを書く必要があります。2) プリンターの名前はユーザーが設定するまでわかりません。印刷する文字列のサイズは、ユーザーが作成するまでわかりません。
追加情報:
a) プリンターは動作します。メモ帳、Chrome、ほぼすべてのものから必要なプリンターに印刷できます。b) どんなハックでも喜んで実装します。テキストファイルに書き込んでコピーコマンドを発行するようなものは機能しないようです。つまり、デバイスの初期化に失敗したというエラーが発生します。
これは動作します: notepad /P Documents/test_print.txt これは動作しません: copy Documents\test_print.txt /D:EPSON_TM_T20 copy Documents\test_print.txt /D \MYCOMPUTER\epson_tm_t20 (アクセスが拒否され、プリンターが共有されます) print Documents \test_print.txt (デバイスを初期化できません)
コマンドラインからテキストファイルを印刷するための推奨される方法をほぼすべて試しましたが、うまくいきません。インストール、ドライバーの再インストール、プリンターの追加、ポートをいじって、すべてやり直しました。
明らかに、経験不足のために私が見逃しているWindows印刷についての簡単なことがあります。
私が達成したいことは次のとおりです。
1) 最良のシナリオ (テキストをプリンターに直接書き込む) 2) 2 番目に優れたシナリオ (テキストをファイルに書き込み、プログラムを実行して印刷する)
プログラムはエンドユーザー向けであるため、エンドユーザーのためにこれを自動的に行う方法を見つける必要があるため、powershell からコマンド obscure_configuration を実行した後、タブ 36 のチェックボックス a をクリックすることは期待できません。
どんな助けでも大歓迎です。
/ジェイソン
アップデート
これは、QByteArray の内容をサーマル プリンターに出力する作業コードです。
qDebug() << "Executing windows code";
BOOL bStatus = FALSE;
DOC_INFO_1 DocInfo;
DWORD dwJob = 0L;
DWORD dwBytesWritten = 0L;
HANDLE hPrinter;
wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;
qDebug() << "opening printer";
bStatus = OpenPrinter(name,&hPrinter, NULL);
if (bStatus) {
qDebug() << "Printer opened";
DocInfo.pDocName = L"My Document";
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = L"RAW";
dwJob = StartDocPrinter( hPrinter, 1, (LPBYTE)&DocInfo );
if (dwJob > 0) {
qDebug() << "Job is set.";
bStatus = StartPagePrinter(hPrinter);
if (bStatus) {
qDebug() << "Writing text to printer";
bStatus = WritePrinter(hPrinter,ba.data(),ba.length(),&dwBytesWritten);
EndPagePrinter(hPrinter);
} else {
qDebug() << "could not start printer";
}
EndDocPrinter(hPrinter);
qDebug() << "closing doc";
} else {
qDebug() << "Couldn't create job";
}
ClosePrinter(hPrinter);
qDebug() << "closing printer";
} else {
qDebug() << "Could not open printer";
}
if (dwBytesWritten != ba.length()) {
qDebug() << "Wrong number of bytes";
} else {
qDebug() << "bytes written is correct " << QString::number(ba.length()) ;
}
注: Skizz に謝罪する義務があります。彼が書いた内容は、根本的な問題のデバッグに実際に役立ちました。QByteArray 内の文字は、プリンター用に特別に事前にフォーマットされています。問題は、いくつかの NULL バイトが含まれていることです。それらをプリンターに送信しようとすると、TextOut がテキストを切り捨て、最初の数行だけを印刷します。回答で示唆されているように、WritePrinter を使用すると、null バイトが無視され、void * と長さが受け入れられ、すべてがそこに置かれます。
さらに、PrintDlg の使用を推奨する彼の応答は、正しいプリンター HDC を取得するために機能しました。問題は、ユーザーが最初にプリンターを 1 回選択し、その後、印刷するため、印刷するたびに選択する必要がないことです。たくさんあります(これは販売時点管理です)。
文字列名からプリンター HDC を取得する際の問題は、すべての重要な NULL バイトを wchar_* に追加しなかったことが原因で、次の方法で解決されました。
wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;
上記の m_printer_path は、プリント マネージャーから取得したプリンターの名前の文字列表現です。
文字列にはプリンターに必要なすべてのフォーマットが含まれているため、改行やフォーマットについて心配する必要はありません。
この質問に対する 3 つの回答はすべて、実際に最終的な実用的なソリューションを実装するのに非常に役立ちました。私は各回答に賛成票を投じました。