Canvas.TextOut() 點陣印表機列印位置會不對但雷射卻正確 |
答題得分者是:t27
|
cancer
高階會員 ![]() ![]() ![]() ![]() 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
各位好,一值都有這個問題,我的報表系統是自己寫的,所有文字都用 Canvas.TextOut() 輸出到印表機,用雷射印表機列印的話,跟預覽時的位置是相同的,但用點陣印表機列印的話,位置都往右往下偏離,X 和 Y 的值愈大,偏羞愈多,點聞印表機己很少人使用,但客戶的客戶偏偏就要提供底稿套表列印,不用點陣都不行。
很明顯,不能用預監時的 X,Y 值給 TextOut() 列印,因為印表機的解析度跟螢幕不同,必須先換算,換算方法很簡單,如下。 Windows 虛擬印表機解釋度是一/吋 96 點,螢幕的 Xm 要轉換為列印的 Xp,照比例算出來就好。 Xp := 印表機解析度 / 虛擬印表機解釋度度 * Xm; 假如 Xm = 500 虛擬印表機解釋度度 = 300 則 Xp = 300 / 96 * 500 = 1563 雷射的解析度都在 600 以上,都不會有問題,解析度低的,例如 300 或以下,列印位置總是往右往下偏,不知道是甚麼原因。 是不是有其他比較好的方法?我知道 Canvas 的 Dimension 單位,是可以更改的,預設是像素,好像可以改為吋、公分之類,這樣我就可以先把 Xp 除以 38 成為吋,再輸出。請問有人自己寫報表程式嗎?正確的做法是...? |
t27
中階會員 ![]() ![]() ![]() 發表:34 回覆:95 積分:90 註冊:2002-06-19 發送簡訊給我 |
這是以前在網路上找到的, 在雷射印表機 影印機 傳真機 試過都ok. 但沒在點矩陣印表機試過.
你參考試一試. 希望能有所幫助. 部分列印程式: function TPreviewPrinter.PrintRange(StartPage, StopPage: integer): boolean; var Page : integer; R : TRect; begin Screen.Cursor := crHourGlass; try Result := True; Printer.Orientation := Orientation; Printer.BeginDoc; Printer.Title := Title; InitPrinterVars(Printer.Handle); for Page := StartPage to StopPage do begin if Assigned(OnStatus) then OnStatus(Self, Format('Printing page %d', [Page]), Page, stPrinting); R := Rect(-offx,-offy,Printer.PageWidth,Printer.PageHeight); Printer.Canvas.StretchDraw(R, MetaFiles[Page]); if Page < StopPage then Printer.NewPage; end; Printer.EndDoc; if Assigned(OnStatus) then OnStatus(Self, 'Print Job Complete', -1, stPrintFinished); finally Screen.Cursor := crDefault; end; end;
procedure TPreviewPrinter.InitPrinterVars(hdc: THandle); var rate,hhh,vvv:double; begin hdc := Printer.Handle; if PaperSize <> Custom then begin ppix := GetDeviceCaps(hdc, LOGPIXELSX); ppiy := GetDeviceCaps(hdc, LOGPIXELSY); sizex := GetDeviceCaps(hdc, PHYSICALWIDTH); sizey := GetDeviceCaps(hdc, PHYSICALHEIGHT); if Units = unCentimeters then begin PaperLength := StrToFloat(Format('%8.1f',[sizex / ppix * INCH_TO_CM])); PaperWidth := StrToFloat(Format('%8.1f',[sizey / ppiy * INCH_TO_CM])); end; if Printer.Printers.Count = 0 then begin sizex := Round(8.5 * Screen.PixelsPerInch); sizey := Round(11 * Screen.PixelsPerInch); end; end else begin ppix := GetDeviceCaps(hdc, LOGPIXELSX); ppiy := GetDeviceCaps(hdc, LOGPIXELSY); if FUnits = unInches then begin sizex := round(PaperWidth * ppix); sizey := round(PaperLength * ppiy); end; if FUnits = unCentimeters then begin offx := GetDeviceCaps(hdc, PHYSICALOFFSETX); offy := GetDeviceCaps(hdc, PHYSICALOFFSETY); sizex := round(PaperWidth / INCH_TO_CM * ppix){ offx}; sizey := round(PaperLength / INCH_TO_CM * ppiy){ offy}; end; if Printer.Printers.Count = 0 then begin sizex := Round(8.5 * Screen.PixelsPerInch); sizey := Round(11 * Screen.PixelsPerInch); end; end; offx := GetDeviceCaps(hdc, PHYSICALOFFSETX); offy := GetDeviceCaps(hdc, PHYSICALOFFSETY); end;
編輯記錄
t27 重新編輯於 2011-12-29 23:36:34, 註解 無‧
|
cancer
高階會員 ![]() ![]() ![]() ![]() 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
|
cancer
高階會員 ![]() ![]() ![]() ![]() 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
t27 大,
原程式碼看不太懂,今天再看一次,看到了重點的 PHYSICALOFFSETX ,PHYSICALOFFSETY,和 -offx, -offy offx := GetDeviceCaps(hdc, PHYSICALOFFSETX); // 印表機預設偏移 offy := GetDeviceCaps(hdc, PHYSICALOFFSETY); ... R := Rect(-offx,-offy,Printer.PageWidth,Printer.PageHeight); // 用負數抵消偏移 Printer.Canvas.StretchDraw(R, forbiddenFiles[Page]);
試了一下兩支 pdf 虛擬印表機,一支列印位置正確,另一支仍是偏右偏下,原來是印表機預設的偏移值在搞鬼,正確的那一台偏移值都是零,另一即則是 75 和 75,怪不得上面的程式碼用 -offx 和 -offy 來抵消它們,修改了程式,算出列印的 X 和 Y 值後,分別加上負數的偏移值,就幾打都正確了,謝謝 t27 大。 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |