Лена |
Отправлено: 30.08.2006, 11:56 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
У меня есть метод одного из компонентов, который посылает свое содержимое на печать. Первый параметр принимает контекст устройства принтера. Как правильно получить контекст устройства?
XPrintMap->PrintMap(..., 0, 0, XPrintMap->Width,XPrintMap->Height);
Вместо многоточия должно быть из справки: hDC Printer device context.
Can be any device context.
|
|
Valdemar |
Отправлено: 30.08.2006, 12:28 |
|
Мастер участка
Группа: Участник
Сообщений: 433
|
Попробуйте Printer()->Handle |
|
Лена |
Отправлено: 30.08.2006, 15:38 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Не работает:
XPrintMap->PrintMap(Printer()->Handle ,0, 0, XPrintMap->Width,XPrintMap->Height);
[C++ Error] FPPreview.cpp(205): E2034 Cannot convert 'void *' to 'unsigned int'
[C++ Error] FPPreview.cpp(205): E2342 Type mismatch in parameter 'hDC' (wanted 'unsigned int', got 'void *')
|
|
Лена |
Отправлено: 30.08.2006, 15:44 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Так нет ошибки:
XPrintMap->PrintMap((int)Printer()->Handle,0, 0, XPrintMap->Width,XPrintMap->Height);
но ничего и не происходит... |
|
Valdemar |
Отправлено: 31.08.2006, 08:37 |
|
Мастер участка
Группа: Участник
Сообщений: 433
|
Можно еще так:
CODE | char pName[100], ADriver[100], APort[100];
int ADeviceMode;
Printer()->GetPrinterA(pName,ADriver, APort,ADeviceMode);
HANDLE hPrinter;
OpenPrinter(pName, &hPrinter, NULL); |
hPrinter будет Handle принтера по умолчанию. |
|
AVC |
Отправлено: 31.08.2006, 09:32 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Когда то делал эмулятор досовский печати. Выглядело так:
CODE |
bool __fastcall TF_DosPrint::Print (void)
{
AnsiString prnname = системное_имя_выбранного_пользователем_принтера;
// prn->GetPrinter(вот_это_device, driver, port, devmode);
AnsiString docname = Caption;
if (prnname.IsEmpty()) return false;
AnsiString text = FPrintText->Text;
if (text.IsEmpty()) return false;
DOC_INFO_1 doc_info_1;
doc_info_1.pDocName = docname.c_str();
doc_info_1.pOutputFile = NULL;
doc_info_1.pDatatype = NULL;
HANDLE phandle = 0;
DWORD tcou = text.Length();
DWORD pcou = 0;
bool ret = true;
try {
if (!OpenPrinter(prnname.c_str(), &phandle, NULL))
throw Exception("OpenPrinter");
if (!StartDocPrinter(phandle, 1, (LPBYTE)(&doc_info_1)))
throw Exception("StartDocPrinter");
if (!WritePrinter (phandle, text.c_str(), tcou, &pcou))
throw Exception("WritePrinter");
if (!EndDocPrinter(phandle))
throw Exception("EndDocPrinter");
} // try
catch (Exception &xcp)
{ text = AnsiString("Ошибка при вызове функции ") + xcp.Message;
ShowMessage(text);
ret = false;
}
if (phandle) ClosePrinter(phandle);
return ret;
}
|
То же самое, что предложил Valdemar
Отредактировано AVC — 31/08/2006, 08:45 |
|
Лена |
Отправлено: 31.08.2006, 10:52 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Что-то не получается. Параметры, которые требует PrintMap(unsigned int hDC, long X, long Y, long W, long H). В справе прилагается пример на VB:
CODE |
OBJECT.PrintMap (hDC x, y, w, h)
Part Description
OBJECT Represents a Map object.
hDC Printer device context. Can be any device context.
x Upper left corner X in HIMETRIC units.
y Upper left corner Y in HIMETRIC units.
w Width in HIMETRIC units.
h Height in HIMETRIC units.
Private Sub Command4_Click()
On Error GoTo ErrorHandler ` Set up error handler.
' coords must be in himetric
' print same size as on screen, in upper left of page
ScaleMode = 6 `set mode to mm
' there is no Printer.StartDoc method, it seems it is done
' implicitly when you use one of the printer.print methods
' so we need to print something before we print our map
' to start the page
Printer.CurrentX = 0
Printer.CurrentY = 0
Printer.Print " "
Map1.PrintMap Printer.hDC, 0, 0, Map1.Width * 100, _
Map1.Height * 100
Printer.NewPage ` Send new page.
Printer.EndDoc ` Printing is finished.
Exit Sub
|
У меня Map1 это XPrintMap. Я пишу так:
CODE |
char pName[100], ADriver[100], APort[100];
int ADeviceMode;
Printer()->GetPrinterA(pName,ADriver, APort,ADeviceMode); // Warning
HANDLE hPrinter;
OpenPrinter(pName, &hPrinter, NULL);
XPrintMap->PrintMap(hPrinter,0, 0, XPrintMap->Width,XPrintMap->Height); // Error
|
Получаю ошибки:
[C++ Warning] FPPreview.cpp(165): W8030 Temporary used for parameter 'ADeviceMode' in call to '_fastcall TPrinter::GetPrinterA(char *,char *,char *,unsigned int &)'
[C++ Error] FPPreview.cpp(170): E2034 Cannot convert 'void *' to 'unsigned int'
[C++ Error] FPPreview.cpp(170): E2342 Type mismatch in parameter 'hDC' (wanted 'unsigned int', got 'void *')
Если написать так:
XPrintMap->PrintMap((int)hPrinter,0, 0, XPrintMap->Width,XPrintMap->Height);
то:
[C++ Warning] FPPreview.cpp(165): W8030 Temporary used for parameter 'ADeviceMode' in call to '_fastcall TPrinter::GetPrinterA(char *,char *,char *,unsigned int &)'
Отредактировано Лена — 31/08/2006, 10:54 |
|
VTim |
Отправлено: 31.08.2006, 11:12 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 4
|
Тяжело смотреть на женские слезы ...
hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
//szPrinterName — Имя принтера из установленных, куда печатаем
...........
XPrintMap->PrintMap(hPrinterDC,0, 0, XPrintMap->Width,XPrintMap->Height);
...........
DeleteDC(hPrinterDC);
|
|
Лена |
Отправлено: 31.08.2006, 12:12 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Два вопроса:
1. Перед печатью я вызываю окно настроек принтера:
PrinterSetupDialog1->Execute(); (рис)
Как мне проинициализировать szPrinterName?
2. Чтобы не было ошибки, я пишу с (int):
XPrintMap->PrintMap((int)hPrinter,0, 0, XPrintMap->Width,XPrintMap->Height); без (int) получаю:
[C++ Error] FPPreview.cpp(175): E2034 Cannot convert 'void *' to 'unsigned int'
[C++ Error] FPPreview.cpp(175): E2342 Type mismatch in parameter 'hDC' (wanted 'unsigned int', got 'void *')
Правильно ли я добавляю (int), чтобы избежать этих ошибок? Такое привидение корректно в PrintMap?
Присоединить изображение
|
|
VTim |
Отправлено: 31.08.2006, 12:46 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 4
|
1. char szPrinterName[] = "Adobe PDF";
Для выбора из списка PrinterSetupDialog не годится, проще всего получить список установленных принтеров с помощью API EnumPrinters.
(Для NT чуть посложнее).
2. HDC hPrinterDC;
Приводить надо (если требуется) к типу для компонента PrintMap в соотв. с заголовочным файлом.
|
|
Лена |
Отправлено: 31.08.2006, 13:22 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Ошибки нет, но пока ничего не происходит:
void __fastcall TForm2::sBitBtn1Click(TObject *Sender)
{
char szPrinterName[] = "Adobe PDF";
HANDLE hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
XPrintMap->PrintMap((int)hPrinterDC,0, 0, XPrintMap->Width,XPrintMap->Height);
DeleteDC(hPrinterDC);
}
Буду разбираться.
Большое спасибо за консультации.
|
|
VTim |
Отправлено: 31.08.2006, 13:34 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 4
|
1. HANDLE hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
Это некорректный тип контекста, надо:
HDC hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
HANDLE и HDC разные вещи!
2. Не уверен, надо ли явно приводить к типу (int)?
3. Для отладки советовал бы попробовать вывод на обычный принтер, т.к. конверторы
и виртуальные принтеры имеют свои особенности, кроме того, возможно, компонент
поддерживает печать только на физическое устройство.
|
|
Grigoriy |
Отправлено: 31.08.2006, 13:36 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE (Лена @ 30/08/2006, 15:38) | Не работает:
XPrintMap->PrintMap(Printer()->Handle ,0, 0, XPrintMap->Width,XPrintMap->Height);
|
Нет.
Надо так писать
CODE |
TPrinter* printer1= Printer();//создаем объект класса TPrinter (экземпляр класса TPrinter)
//---------------
//ХЕНДЛ канвы объекта printer1 — это и есть хендл графического устройства WINDOWS для вывода на печать
XPrintMap->PrintMap(printer1->Canvas->Handle,0,0,
XPrintMap->Width,XPrintMap->Height);
//---------------
delete printer1;
|
ХЕНДЛ канвы объекта класса TPrinter является тем HDC графического устройства для печати.
К примеру хендл канвы формы
Form1->Canvas->Handle
это HDC графического устройства по выводу графики в окно,
и т.п.
|
|
Лена |
Отправлено: 31.08.2006, 14:09 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Если написать так:
char szPrinterName[] = "Adobe PDF";
HDC hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
XPrintMap->PrintMap((int)hPrinterDC,0, 0, XPrintMap->Width,XPrintMap->Height);
DeleteDC(hPrinterDC);
То ничего не происходит не печатает ни на виртуальный ни на реальный принтер.
Если написать так:
TPrinter* printer1= Printer();
XPrintMap->PrintMap((int)printer1->Canvas->Handle,0,0,XPrintMap->Width,XPrintMap->Height); // Без (int) вообще не компилируется.
delete printer1;
то исключение, которое на рисунке ниже.
Предварительно указала в окне PrinterSetupDialog1->Execute(); тип Adobe PDF. Получается, что Windows не воспринимает настройку в PrinterSetupDialog1->Execute();?
Присоединить изображение
|
|
VTim |
Отправлено: 31.08.2006, 14:26 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 4
|
<если написать так:
char szPrinterName[] = "Adobe PDF";
HDC hPrinterDC = CreateDC(NULL, szPrinterName, NULL, NULL);
XPrintMap->PrintMap((int)hPrinterDC,0, 0, XPrintMap->Width,XPrintMap->Height);
DeleteDC(hPrinterDC);
То ничего не происходит не печатает ни на виртуальный ни на реальный принтер.>
Здесь вывод происходит ТОЛЬКО на "Adobe PDF".
Вместо "Adobe PDF" надо подставить имя локального принтера, напр. "HP Laser Jet 1120" или др., как установлено в системе
|
|
Лена |
Отправлено: 31.08.2006, 14:56 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Я забыла выше написать, что пробовала:
char szPrinterName[] = "hp deskjet 940c";
предварительно назначив этот сетевой принтер по умолчанию. Нет, ничего не происходит — не печатает. Хотя из любой графической программы принтер печатает.
|
|
Grigoriy |
Отправлено: 31.08.2006, 15:16 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE (Лена @ 30/08/2006, 11:56) | Вместо многоточия должно быть из справки: hDC Printer device context.
Can be any device context. |
Тогда при чём здесь тип int, без которого "не компилируется", если должен быть тип HDC ?
|
|
Лена |
Отправлено: 31.08.2006, 15:25 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Без int ошибки:
[C++ Error] FPPreview.cpp(178): E2034 Cannot convert 'void *' to 'unsigned int'
[C++ Error] FPPreview.cpp(178): E2342 Type mismatch in parameter 'hDC' (wanted 'unsigned int', got 'void *')
Речь идет об компоненте ActiveX при интеграции в Builder он требует то что на рисунке ниже.
В справке есть пример для VB и для классического С++. Для С++ пример такой:
CODE |
// Map.PaperUnit Property
// Map.PrintMap Method
void CSampleProjectView::OnPrintMap(CDC* pDC,CPrintInfo* pInfo) {
try {
// get paper width in mm and convert to HIMETRIC (100th of a mm)
m_Map.SetPaperUnit(miUnitMillimeter);
double pw = m_Map.GetMapPaperWidth() * 100;
double ph = m_Map.GetMapPaperHeight()* 100;
m_Map.PrintMap((long)pDC->m_hDC,
pInfo->m_rectDraw.left,pInfo->m_rectDraw.
top,(long)pw,(long)ph);
} catch (COleDispatchException *e) {
e->ReportError();
e->Delete();
} catch (COleException *e) {
e->ReportError();
e->Delete();
}
}
|
Параметры ф-ции печати для Builder 6 на рисунке ниже:
Присоединить изображение
|
|
Лена |
Отправлено: 01.09.2006, 16:19 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Я вот новое исследование провела:
Написала код, который вроде работает. Возникает окно сохранения файла на диск, начинается печать (вижу в трее), но потом вываливается исключение. Рисунок прилагаю.
#include vcl/printers.hpp
Printer()->BeginDoc();
XPrintMap->PrintMap((int)Printer()->Handle,0, 0, 100,100);
Printer()->EndDoc();
Может это глюк компонента?
Отредактировано Лена — 01/09/2006, 16:20
Присоединить изображение
|
|
Лена |
Отправлено: 01.09.2006, 16:56 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Интересно, что ели печатать на реальный принтер, то исключения не выскакивает, а из принтера выходит чистый лист. |
|
E.S. |
Отправлено: 07.09.2006, 19:06 |
|
Не зарегистрирован
|
Нужно передавать не чистый контекст, а уже заполненный.
HDC hDC = GetDC( Form1->Handle );
// печатаем... на всякий случай в блоке try { ... }
ReleaseDC( Form1->Handle, hDC ); |
|
Лена |
Отправлено: 08.09.2006, 09:43 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
QUOTE (E.S. @ 07/09/2006, 19:06) | Нужно передавать не чистый контекст, а уже заполненный.
HDC hDC = GetDC( Form1->Handle );
// печатаем... на всякий случай в блоке try { ... }
ReleaseDC( Form1->Handle, hDC ); |
Спасибо, попробую.
Сейчас у меня код, который ниже. Он отлично работает для реального принтера. Для виртуального этот код, выводив в PDF файл только текст и то почему то без отступов (200,100), а строго в верхнем левом углу страницы файла PDF. BMP файл в виртуальном принтере тоже не печатается. Повторю, что код отлично работает для реального принтера:
CODE |
//печать на реальный принтер
void __fastcall TForm2::sButton2Click(TObject *Sender)
{
//код формирующий картунку bmp в Clipboard пропущен
//далее:
TClipboard *pCB = Clipboard();
if (pCB->HasFormat(CF_BITMAP))
{
Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
try
{
pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0);
Printer()->BeginDoc();
Printer()->Canvas->StretchDraw(Rect(200,200,XPrintMap->Width + 1800,XPrintMap->Height + 1800), pBitmap);
Printer()->Canvas->Font->Name = "Arial Cyr";
Printer()->Canvas->Font->Size = 10;
Printer()->Canvas->TextOut(200,100,"Фрагмент рисунка:");
Printer()->EndDoc();
}
catch (...)
{
sShowMessage("Не удалось распечатать");
}
delete pBitmap;
}
}
|
На виртуальный принтер получаю только текст из TextOut и без отсупов.
Цифру 1800 пришлось добавить, чтобы картинка была большая на листе A4. Без этой цифры печатается маленькой изображение. Хотя если вставить буфер обмена в любую графическую программу Photoshop и т .п. (см.рисунок) то видно что в буфере обмена нормальное большое изображение и печатается оно нормально из графической программы. Видимо в моем коде надо еще какие-то коэффициенты масштабирования предусмотреть, чтобы не писать подобранные наугад цифры 1800.
На рисунке реальное изображение которое поподает в буфер обмена. Мне же, приходиться в коде жестко добовлять цифру 1800 чтобы увидеть на бумаге похожие размеры:
Присоединить изображение
|
|
|