按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
其中前三个参数分别是与打印机有关的信息字符串,可以从WIN。INI 的【windows 】section
中获得,各以逗号分隔,例如:
device=HP LaserJet 4P/4MP;HPPCL5E;LPT1:
代表三项意义:
Print Driver = HP LaserJet 4P/4MP
Print Type = HPPCL5E
Print Port = LPT1:
SDK 程序中对于打印所需做的努力,最低限度到此为止。显然,困难度并不高,但是其
中尚未参杂对打印机的控制,而那是比较麻烦的事儿。换句话说我们还得考虑「分页」
的问题。以文字为例,我们必须取得一页(一张纸)的大小,以及字形的高度,从而计
算扣除留白部份之后,一页可容纳几行:
TEXTMETRIC TextMetric;
int LineSpace;
int nPageSize;
int LinesPerPage;
GetTextMetrics(hPr; &TextMetric); //取得字形数据
LineSpace = TextMetric。tmHeight + TextMetric。tmExternalLeading; // 计算字高
nPageSize = GetDeviceCaps(hPr; VERTRES); // 取得纸张大小
LinesPerPage = nPageSize / LineSpace 1; // 一页容纳多少行
然后再以循环将每一行文字送往打印机:
Escape (hPr; STARTDOC; 4; 〃PrntFile text〃; (LPSTR) NULL);
CurrentLine = 1;
for (。。。) {
。。。 // 取得一行文字,放在char pLine'128' 中,长度为LineLength。
664
…………………………………………………………Page 727……………………………………………………………
第 12 章 列印與預樱А�
TextOut (hPr; 0; CurrentLine*LineSpace; (LPSTR)pLine; LineLength);
if (++CurrentLine 》 LinesPerPage ) {
CurrentLine = 1; //重设行号
IOStatus = Escape (hPr; NEWFRAME; 0; 0L; 0L); //换页
if (IOStatus 《 0 || bAbort)
break;
}
}
if (IOStatus 》= 0 && !bAbort) {
Escape (hPr; NEWFRAME; 0; 0L; 0L);
Escape (hPr; ENDDOC; 0; 0L; 0L);
}
其中的Escape 用来传送命令给打印机(打印机命令一般称为escape code ),它是一个
Windows API 函数。
打印过程中我们还应该提供一个中断机制给使用者。Modeless 对话框可以完成此一使
命,我们可以让它出现在打印过程之中。这个对话框应该在打印程序开始之前先做起来,
外形类似图12…1d:
HWND hPrintingDlgWnd; // 这就是【Printing】对话框
FARPROC lpPrintingDlg; // 【Printing】对话框的窗口函数
lpPrintingDlg = MakeProcInstance(PrintingDlg; hInst);
hPrintingDlgWnd = CreateDialog (hInst; 〃PrintingDlg〃; hWnd; lpPrintingDlg);
ShowWindow (hPrintingDlgWnd; SW_NORMAL);
负责此一中断机制的对话框函数很简单,只检查【OK 】钮有没有被按下,并据以改变
bAbort 的值:
int FAR PASCAL PrintingDlg (HWND hDlg; unsigned msg; WORD wParam; LONG lParam)
{
switch(msg) {
case WM_MAND:
return (bAbort = TRUE);
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg; IDCANCEL));
SetDlgItemText(hDlg; IDC_FILENAME; FileName);
return (TRUE);
}
return (FALSE);
}
665
…………………………………………………………Page 728……………………………………………………………
第篇 深入 MFC 程式設計
从应用程序的眼光来看,这样就差不多了。然而资料真正送到打印机上,还有一大段曲
折过程。每一个送往打印机DC 的绘图动作,其实都只被记录为metafile (注)储存在
你的TEMP 目录中。当你调用Escape(hPr ; NEWFRAME; 。。。),打印机驱动程序(。DRV)
会把这些metafile 转换为打印机语言(control sequence 或Postscript ),然后通知GDI 模
组,由GDI 把它储存为~SPL 文件,也放在TEMP 目录中,并删除对应之metafile 。之
后,GDI 模块再送出消息给打印管理器Print Manager ,由后者调用Openm、
Writem 等低阶通讯函数(也都是Windows API 函数),把打印机命令传给打印机。
整个流程请参考图12…3。
注:metafile 也是一种图形记录规格,但它记录的是绘图动作,不像bitmap 记录的是真
正的图形资料。所以播放metafile 比播放bitmap 慢,因为多了一层绘图函数解读动作;
但它的大小比bitmap 小很多。用在有许多四形、圆形、工程几何图形上最为方便。
这个曲折过程之中就产生了一个问题。~SPL 这种文件很大,如果你的TEMP 目录空间
不够充裕,怎么办?如果Printer Manager 把积存的~SPL 内容消化掉后能够空出足够磁
碟空间的话,那么GDI 模块就可以下命令(送消息)给Printer Manager ,先把积存的
~SPL 档处理掉。问题是,在Windows 3。x 之中,我们的程序此刻正忙着做绘图动作,
GDI 没有机会送消息给Printer Manager (因为Windows 3。x 是个非强制性多任务系统) 。
解决方法是你先准备一个callback 函数,名称随你取,通常名为AbortProc :
FARPROC lpAbortProc;
lpAbortProc = MakeProcInstance(AbortProc; hInst);
Escape(hPr; SETABORTPROC; NULL; (LPSTR)(long)lpAbortProc; (LPSTR)NULL);
GDI 模块在执行Escape(hPr ; NEWFRAME。。。) 的过程中会持续调用这个callback 函数,想
办法让你的程序释放出控制权:
int FAR PASCAL AbortProc(hDC hPr; int Code)
{
MSG msg;
while (!bAbort && PeekMessage(&msg; NULL; NULL; NULL; TRUE))
if (!IsDialogMessage(hAbortDlgWnd; &msg)) {
TranslateMessage(&msg);
666
………………………………………………