http://support.microsoft.com/kb/129860
如何使用来自 Rich Edit 控件的内置打印功能
打印 Rich Edit 控件包括标准的打印 API 的使用以及两个 Rich Edit 控件邮件,EM _ FORMATRANGE 和 EM_DISPLAYBAND。 可以由其自身或结合 EM_DISPLAYBAND 邮件使用 EM _ FORMATRANGE 消息。 本文结尾处包含下面是代码示例演示了这些信息的使用情况的。
EM _ FORMATRANGE
此消息用于设置为打印机 DC 文本的格式,并可以选择向打印机发送输出。
wParam 参数,此邮件的是一个 Boolean 类型的值的值,,指示在文本应呈现 (打印) 到打印机。 零值仅在文本格式,非 0 的值将文本的格式设置和将其呈现到打印机时。
此邮件的 lParam 参数是一个指针 FORMATRANGE 结构。 此结构需要向控件发送邮件前填写。
FORMATRANGE 成员
HDC hdc-包含设备上下文 (DC) 向呈现,如果 wParam 参数为零。 在输出实际发送到此 DC。
HDC hdcTarget-包含设备上下文格式,这通常是 hdc 成员相同,但可以不同。 例如,如果您创建了一个打印预览模块 hdc 成员就是在其中查看输出,和 hdcTarget 成员是 DC 打印机窗口的 DC。
矩形 rc-包含向呈现区域。 此成员包含文本格式设置为适合,和随后打印该矩形。 它还包含页边距,页眉和页脚,等的空间。 在发送邮件后可能会更改 rc.bottom 成员。 如果更改它必须指定不打印部分行中仍包含指定的文本的可以原始矩形的界限内适合该最大矩形。 可能需要打印每个页面后重设此值。 以缇为单位给出这些维度。
矩形 rcPage-包含呈现设备的整个区域。 可以使用 GetDeviceCaps() 函数来获取此区域。 以缇为单位给出这些维度。
CHARRANGE chrg-包含要打印的字符区域。 将 chrg.cpMin 设置为 0 和 chrg.cpMax 为-1 可打印所有字符。
从 EM _ FORMATRANGE 返回的值是在下一页上第一个字符的索引。 如果在打印多个页应设置 chrg.cpMin 为该值发送下一条 EM _ FORMATRANGE 消息之前。
完成打印时必须将此消息发送到控件其中 wParam = 0 且 lParam = NULL 以释放由控件的信息缓存。
EM_DISPLAYBAND
如果您使用 EM _ FORMATRANGE 消息将 wParam 参数 0,然后可以使用 EM_DISPLAYBAND 邮件要将输出发送到该打印机。
此消息的 wParam 参数未使用,并且应该 0。
此邮件的 lParam 参数是一个指针矩形结构。 此矩形结构是要显示区域和通常是 FORMATRANGE 结构 EM _ FORMATRANGE 消息中使用的 rc 成员相同但可以不同。 是例如矩形不相同如果采用打印页的某些部分,或正在使用内置的边距。
只应在以前的 EM _ FORMATRANGE 消息后使用此信息。
示例代码
void Print(HDC hPrinterDC, HWND hRTFWnd) { FORMATRANGE fr; int nHorizRes = GetDeviceCaps(hPrinterDC, HORZRES), nVertRes = GetDeviceCaps(hPrinterDC, VERTRES), nLogPixelsX = GetDeviceCaps(hPrinterDC, LOGPIXELSX), nLogPixelsY = GetDeviceCaps(hPrinterDC, LOGPIXELSY); LONG lTextLength; // Length of document. LONG lTextPrinted; // Amount of document printed. // Ensure the printer DC is in MM_TEXT mode. SetMapMode ( hPrinterDC, MM_TEXT ); // Rendering to the same DC we are measuring. ZeroMemory(&fr, sizeof(fr)); fr.hdc = fr.hdcTarget = hPrinterDC; // Set up the page. fr.rcPage.left = fr.rcPage.top = 0; fr.rcPage.right = (nHorizRes/nLogPixelsX) * 1440; fr.rcPage.bottom = (nVertRes/nLogPixelsY) * 1440; // Set up 1" margins all around. fr.rc.left = fr.rcPage.left + 1440; // 1440 TWIPS = 1 inch. fr.rc.top = fr.rcPage.top + 1440; fr.rc.right = fr.rcPage.right - 1440; fr.rc.bottom = fr.rcPage.bottom - 1440; // Default the range of text to print as the entire document. fr.chrg.cpMin = 0; fr.chrg.cpMax = -1; // Set up the print job (standard printing stuff here). ZeroMemory(&di, sizeof(di)); di.cbSize = sizeof(DOCINFO); if (*szFileName) di.lpszDocName = szFileName; else { di.lpszDocName = "(Untitled)"; // Do not print to file. di.lpszOutput = NULL; } // Start the document. StartDoc(hPrinterDC, &di); // Find out real size of document in characters. lTextLength = SendMessage ( hRTFWnd, WM_GETTEXTLENGTH, 0, 0 ); do { // Start the page. StartPage(hPrinterDC); // Print as much text as can fit on a page. The return value is // the index of the first character on the next page. Using TRUE // for the wParam parameter causes the text to be printed. #ifdef USE_BANDING lTextPrinted = SendMessage(hRTFWnd, EM_FORMATRANGE, FALSE, (LPARAM)&fr); SendMessage(hRTFWnd, EM_DISPLAYBAND, 0, (LPARAM)&fr.rc); #else lTextPrinted = SendMessage(hRTFWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr); #endif // Print last page. EndPage(hPrinterDC); // If there is more text to print, adjust the range of characters // to start printing at the first character of the next page. if (lTextPrinted < lTextLength) { fr.chrg.cpMin = lTextPrinted; fr.chrg.cpMax = -1; } } while (lTextPrinted < lTextLength); // Tell the control to release cached information. SendMessage(hRTFWnd, EM_FORMATRANGE, 0, (LPARAM)NULL); EndDoc (hPrinterDC); }