Strona 1 z 1

[BC++] Zmiana formatu wydruku

Nowy postNapisane: czwartek, 8 stycznia 2009, 12:04
przez ivinnie
Witam,
mam problem z ustawieniem formatu drukowanej strony. Program generuje mi wydruk standardowo w formacie A4, nie wiem co nalezy wpisac aby wydruk generowany byl w formacie B5. Uzywam Turbo C++ 2006, opieralem sie na poradniku z tej strony.
Moze nalezy cos w tym zmienic ? :
Kod: Zaznacz cały
   Printer()->Orientation = poPortrait;
   Printer()->BeginDoc(); //POCZATEK DRUKOWANIA
   int margLeft = 100;
   int margTop = 100;
   int x = Printer()->PageWidth; //<< 595;  // długość strony B5 182mm 176 w PUNKTACH 498 ale nie drukuje poprawnie z tymi wartosciami
   int y = Printer()->PageHeight; //<< 841; // wysokość strony B5 257mm 250 w PUNKTACH 708.


Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: czwartek, 8 stycznia 2009, 14:10
przez Cyfrowy Baron
Wyboru formatu papieru dokonujesz w sterowniku drukarki, gdyż klasa TPrinter nie zawiera funkcji umożliwiających zmianę tegoż formatu.
Do wywołania sterownika drukarki możesz wykorzystać komponent PrinterSetupDialog

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: środa, 21 stycznia 2009, 11:42
przez ivinnie
Czy jest mozliwe aby na drukarkach roznych firm wydruk wygladal inaczej ? Piszac program uzywalem wirtualnej drukarki CutePDF do biezacego sprawdzania czy wszystko jest tak jak chcialem - drukarka drukowala do formatu XPS, po skonczeniu programu przelaczylem sie na 2 system operacyjny z zainstalowana drukarka HP 1410 na ktorej wydruk wygladal tak samo jak w pliku XPS (nie drukowalem pliku XPS), a u innej osoby z drukarka Epson C86 sa male roznice w wydruku. Co moze byc tego powodem ?

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: środa, 21 stycznia 2009, 13:35
przez Cyfrowy Baron
To jest możliwe, gdyż sterowniki drukarki używają różnych zaawansowanych form wydruku. Np. drukarki HP mają funkcję ICM umożliwiającą ustalenie sposobu drukowania grafiki. Poza tym dochodzi kwestia rozdzielczości drukowania, jeżeli w swoim programie zdefiniowałeś jedną stała rozdzielczość wydruku, to na drukarce na której jest ustawiona domyślna rozdzielczość wydruku na 300 dpi wydruk będzie wyglądał trochę inaczej niż na drukarce z domyślną rozdzielczością ustawioną na 600 dpi.
Kolejna kwestia, to, że nie wszystkie drukarki muszą obsługiwać specyfikację i posiadać sterowniki XPS, aczkolwiek ta specyfikacja jest wspierana przez firmy Canon, Epson, HP, Ricoh, Xerox.
Plik XPS jest archiwum w formacie ZIP (zmień rozszerzenie na ZIP a się przekonasz ), który zawiera pliki składające się na dokument, między innymi plik XML dla każdej strony, zagnieżdżone obrazy i czcionki, a także informacje Digital Rights Management.
Nad tym wszystkim można zapanować i zaprogramowań tak aplikację, żeby wydruki były identycznie (lub niezauważalnie różne) niezależnie od drukarki, ale to wymaga stworzenia w programie dość skomplikowanych algorytmów.

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: poniedziałek, 26 stycznia 2009, 13:55
przez ivinnie
Pomyslalem troche nad tym co mi napisales, probowalem z tym zawalczyc, ale troche to zbyt skomplikowane - na pewno mozna prosciej niz pisac algorytm do rozprowania XPSa i ustawiania jego wlasciwosci wg drukarki.
Sprobowalem napisac mala funkcje do zmiany DEVMODE drukarki - czesciowo to dziala (moge zmienic orientacje papieru itp, jednak chyba za bardzo nie dziala zmiana DPI) - na razie testuje to na wirtualnej drukarce, niestety wiekszosc helpow w necie jest pisana pod Delphi.
Funkcja wyglada tak:
Kod: Zaznacz cały
void Standaryzuj()
{
const int CCHBINNAME=24;
Char cPort[1024],cDevice[1024],cDriver[1024];
THandle hDeviceMode;

// setting printer
char PrinterName;
int vPrinterIndex = Printer()->Printers->IndexOf(PrinterName);
if(vPrinterIndex<0)
   vPrinterIndex = 0;

Printer()->PrinterIndex = vPrinterIndex;

Printer()->GetPrinter(cDevice,cDriver,cPort,hDeviceMode);
DEVMODE *DevMode = (DEVMODE*)GlobalLock(reinterpret_cast<HGLOBAL>(hDeviceMode));
AnsiString vDevice = cDevice;
AnsiString vPort = cPort;

DevMode->dmFields |= DM_DEFAULTSOURCE|DM_ORIENTATION|DM_SCALE;

DevMode->dmOrientation = DMORIENT_PORTRAIT;
DevMode->dmScale = 100; //czy to odpowiada za DPI ?

int BinNo = static_cast<int>(DeviceCapabilities(vDevice.c_str(),vPort.c_str(),DC_BINNAMES,NULL,NULL));
if(BinNo>0)
{
   int LenCCHBINNAME = 1+(BinNo*CCHBINNAME);
   char *cPaperNames = new char[LenCCHBINNAME];
   memset(cPaperNames,'\0',LenCCHBINNAME);
   WORD *wBins = new WORD[BinNo];

   DevMode->dmDefaultSource = DMBIN_AUTO;
   delete []cPaperNames;
   delete []wBins;
}else{
   DevMode->dmDefaultSource = DMBIN_AUTO;
   Printer()->SetPrinter(cDevice,cDriver,cPort,hDeviceMode);
   ::GlobalUnlock(reinterpret_cast<HGLOBAL>(hDeviceMode));
}

Moglbys mi podpowiedziec jak dobrac sie do DPI ? Czy tylko parametr DPI sie liczy przy drukowaniu?

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: poniedziałek, 26 stycznia 2009, 15:13
przez Cyfrowy Baron
DPI to kwestia algorytmu przeliczającego w programie. Przykład takiego przeliczania znajdziesz w serwisie Cyfrowy Baron w dziale: porady -> StringGrid -> Drukowanie zawartości tabeli StringGrid.

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: poniedziałek, 26 stycznia 2009, 21:35
przez ivinnie
Dzieki - przetestowalem twoja porade, pogrzebalem jeszcze troche po sieci na temat DEVMODE i znalazlem cos takiego:
DevMode->dmYResolution = 600;
Specifies the y-resolution, in dots per inch, of the printer. If the printer initializes this member, the dmPrintQuality member specifies the x-resolution, in dots per inch, of the printer.


Jeszcze tego nie stestowalem na innej drukarce niz HP, ale wydaje mi sie ze o to chodzilo.

Na stronie z MS doczytalem jeszcze ze nalezy zmienic rowniez wartosc dmPrintQuality czyli:
DevMode->dmYResolution = DevMode->dmPrintQuality = 600;

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: czwartek, 29 stycznia 2009, 15:25
przez Cyfrowy Baron
Chodzi pewnie Tobie o coś takiego:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap *Bmp = new Graphics::TBitmap();
Bmp->Assign(Image1->Picture->Bitmap); // Image musi zawierać bitmapę, jeżeli nie należy dokonać konwersji


THandle hDeviceMode;
PDeviceMode   DevMode;

char   *ADevice,   *ADriver,   *APort;
ADevice =new   char[100];
ADriver =new   char[100];
APort   =new   char[100];

Printer()->GetPrinter(ADevice,   ADriver,   APort, hDeviceMode);
DevMode   =(_devicemodeA*)   GlobalLock((void   *)hDeviceMode);

DevMode->dmFields = DevMode->dmFields | DM_DEFAULTSOURCE;
DevMode->dmFields = DevMode->dmFields | DM_ORIENTATION;
DevMode->dmFields = DevMode->dmFields | DM_SCALE;
DevMode->dmFields = DevMode->dmFields | DM_PRINTQUALITY;
DevMode->dmFields = DevMode->dmFields | DM_YRESOLUTION;

DevMode->dmPaperSize = DMPAPER_A5;

DevMode->dmOrientation = DMORIENT_PORTRAIT;
DevMode->dmYResolution = 600; //<-- brak zastosowania
DevMode->dmPrintQuality = DMRES_LOW;
DevMode->dmScale = 100; // <- brak zastosowania
Printer()->SetPrinter(ADevice,   ADriver,   APort, hDeviceMode);

Printer()->BeginDoc();

int x = Printer()->PageWidth;  // długość strony.
int y = Printer()->PageHeight; // wysokość strony.

int width;
int height;

if((x / Bmp->Width) < (y / Bmp->Height))
{
  width = Bmp->Width * ((x / Bmp->Width) + 0.5);
  height = Bmp->Height * ((x / Bmp->Width) + 0.5);
}
else
{
  height = Bmp->Height * ((y / Bmp->Height) + 0.5);
  width = Bmp->Width * ((y / Bmp->Height) + 0.5);
}

Printer()->Canvas->CopyRect(Rect(10, 10, width, height), Bmp->Canvas, Rect(0, 0, Bmp->Width, Bmp->Height)); // <- tutaj Image

Printer()->Canvas->Brush->Style = bsClear; // usuwanie tła spod tekstu - tło przeźroczyste
Printer()->Canvas->TextOut(100, 200, Label1->Caption); // <-- tutaj Label->Caption

Printer()->EndDoc();
delete Bmp;
}
//---------------------------------------------------------------------------


Struktura DEVMODE ma zastosowanie nie tylko przy drukowaniu, ale również przy wyświetlaniu grafiki na ekranie monitora, dlatego nie wszystkie elementy tej struktury mają zastosowanie przy drukowaniu i tak dmYResolution, dmScale nie mają zastosowania w odniesieniu do drukarki lecz ekranu.
Za rozdzielczość wydruku odpowiada DevMode->dmPrintQuality, która może przyjmować cztery zdefiniowane wartości:

DMRES_HIGH
DMRES_MEDIUM
DMRES_LOW
DMRES_DRAFT

nie ma możliwości określenia jawnie rozdzielczości wydruku.
W odniesieniu do mojej drukarki te pre-definiowane właściwości mają następujące odpowiedniki:

DMRES_HIGH - najlepsza (600 dpi)
DMRES_MEDIUM - normalna (600 dpi)
DMRES_LOW - szybka zwykła (300 dpi)
DMRES_DRAFT - szybka robocza (300 dpi)

brak tutaj jednak jednego odpowiednika: Maksymalna (1200 dpi).

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: niedziela, 8 lutego 2009, 18:10
przez ivinnie
Dzieki za odpowiedzi - podziele sie moimi spostrzezeniami:
Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_LOW;

to ustawienie powoduje, ze wydruk jest powiekszony (300DPI)
Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_MEDIUM;

To ustawienie powoduje, ze wydruk jest taki jak powinien (600DPI)
Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_LOW;
DevMode->dmYResolution = DevMode->dmPrintQuality = 600;

To ustawienie powoduje, ze wydruk jest taki jak powinien -> 'na sile' ustawione 600DPI.
Przy ustawieniach DMRES_LOW, DMRES_MEDIUM, DMRES_HIGH drukarka szybciej lub wolniej drukuje, natomiast dopisana druga linijka ustawia pozadana rodzielczosc drukowania.
Przetestowane na 2 roznych drukarkach.

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: poniedziałek, 9 lutego 2009, 10:52
przez Cyfrowy Baron
Nie wiem jakiej drukarki używasz, ale u mnie na HP to:

Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_LOW;
DevMode->dmYResolution = DevMode->dmPrintQuality = 600;


sprawia tylko, że drukarka drukuje w najniższej rozdzielczości.

A co do tego:

Przy ustawieniach DMRES_LOW, DMRES_MEDIUM, DMRES_HIGH drukarka szybciej lub wolniej drukuje, natomiast dopisana druga linijka ustawia pozadana rodzielczosc drukowania.
Przetestowane na 2 roznych drukarkach.


Nie jest prawdą, jeżeli drukarka drukuje szybciej to robi to w mniejszej rozdzielczości, a wolniej w większej rozdzielczości, przynajmniej u mnie tak jest, co odpowiada temu co pisałem wcześniej:


Za rozdzielczość wydruku odpowiada DevMode->dmPrintQuality, która może przyjmować cztery zdefiniowane wartości:

DMRES_HIGH
DMRES_MEDIUM
DMRES_LOW
DMRES_DRAFT

nie ma możliwości określenia jawnie rozdzielczości wydruku.




Odsyłam do pliku pomocy BCB, tam masz to dokładnie opisane. Sugeruję, żebyś dokładniej przeprowadził testy, jak tak zrobiłem w każdej możliwej konfiguracji.



W kwestii drukowania wolniej-szybciej. Jak to jest u mnie.
Drukarka ma dwa tryby drukowania karetka z tuszem drukuje przy przesuwaniu do przodu i przy powrocie w 300 dpi - bardzo szybko, karetka drukuje tylko przy przesuwaniu do przodu, wraca na pusto przy 300 dpi - szybko, oraz karetka z tuszem drukuje przy przesuwaniu do przodu i przy powrocie w 600 dpi - wolno, karetka drukuje tylko przy przesuwaniu do przodu, wraca na pusto przy 600 dpi - bardzo wolno. Istnieje jeszcze piąty tryb 1200 dpi w którym karetka drukuje tylko przy przesuwaniu do przodu i jest to tryb najwolniejszy. Większośc modeli drukarek z którymi się zetknąłem mają tylko cztery tryby drukowania.

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: piątek, 13 lutego 2009, 13:02
przez ivinnie
Używam również HP. Rozchodzi mi się o sam wydruk, lepiej zobrazuje to screen:
http://www.imagic.pl/public/pview/258493/druki.jpg
Na górze grafiki jest powiększony wyjściowy druk przy ustawieniu tylko DMRES_LOW.
Na dole grafiki jest prawidłowy rozmiar wydrukowanej grafiki przy dodaniu tylko linijki jak na obrazku.

Patrząc na te wydruki wywnioskowałem, że ustawienie DevMode->dmPrintQuality = 600; powoduje prawidłowe drukowanie, chyba inne parametry nie wpływają na wielkość drukowanej grafiki, nie wyobrażam sobie pisania funkcji standaryzującej wydruk dla każdej dostępnej na rynku drukarki.

Re: [BC++] Zmiana formatu wydruku

Nowy postNapisane: piątek, 13 lutego 2009, 13:18
przez Cyfrowy Baron
Ja czytałem pliki pomocy dla środowiska CodeGear RAD Studio C++ Builder 2007, to co napisałem wcześniej zaczerpnąłem właśnie z pliku pomocy, a co do tego jak drukuje u mnie drukarka zaczerpnąłem oczywiście z własnej obserwacji.

Stosowałem u siebie takie rozwiązanie:

Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_LOW;
DevMode->dmYResolution = DevMode->dmPrintQuality = 600;


i u mnie nie daje żadnej zmiany w stosunku do takiego:

Kod: Zaznacz cały
DevMode->dmPrintQuality = DMRES_LOW;