VC打印动态强制分页(换页) 调试时,不知道为什么调用EndPage()返回都是-1(按照MSDN是失败),但是预览结果实际上是换了新页的。这又是为什么? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 另外,看到一个帖子中的函数 //换页 OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { if(pDC->IsPrinting()) { int originy=... //当前页的原点y值它通常=每页高度*(pInfo->m_nCurPage-1); //然后再设置当前页原点 pDC->SetViewportOrg(0,originy); //在此你也可以是别的处理换页的方式 } ... } 红色这句是不是说,虽然打印御览是分页显示的,但实际上VC的处理却是连续的页面,因此如果在需要分页的地方将y值修改为下一页的值,即不会再被最后页的内容覆盖了?如:第一页打印开始Y=100;第二页打印开始Y=100+页面高度;第N页打印开始Y=100+(N-1)*页面高度;对吗? 我们以前打印报表数据都是用excel的模版实现的,还没有遇到类似的问题。帮你顶。 附上你的OnPreparePrinting(),OnBeginPrinting(),OnPrint()完整代码啊,你这样说得太模糊了,都不知道你要表达什么意思。OnPrint()是根据你前面设置的页数来打印的,重复调用至打印完毕。打印预览就是你OnDraw()所画的情况,所以每次都画到最后,在OnPrint里一般是要根据你打印的页的高度来重绘的。 BOOL CXXView::OnPreparePrinting(CPrintInfo* pInfo){ if(pInfo){ if( pInfo->m_bPreview == TRUE ) { //Preview CWnd *pWnd = GetParentFrame(); if( pWnd != NULL ){ //make resize possible LONG lResult = ::GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE); lResult |= (WS_THICKFRAME | WS_MAXIMIZEBOX); ::SetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE, lResult); //Max window pWnd->ShowWindow(SW_SHOWMAXIMIZED); } } } // default preparation return DoPreparePrinting(pInfo);}void CXXView::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo){ //创建字体 //创建pen用来画表格的线}void CXXView::OnEndPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/){ m_PrintFont.DeleteObject(); m_PrintPen.DeleteObject();}void CXXView::OnPrint(CDC *pDC, CPrintInfo *pInfo){ static i = 0; if(pDC && pInfo) { //Set the new font CFont *pOriginalFont = pDC->SelectObject(&m_PrintFont); CPen *pOriginalPen = pDC->SelectObject(&m_PrintPen); PrintDispatch(pDC, pInfo); //Set the original font pDC->SelectObject(pOriginalFont); pDC->SelectObject(pOriginalPen); }}void PrintDispatch(CDC *pDC, CPrintInfo *pInfo){ // start printing position UINT x = pageInfo.xStart; UINT y = pageInfo.yStart; for(int i = 0; i < prtTableSize; i++) { printTable[i]->PrintTable(&x, &y, pDC, pInfo); }}其中printTable是我定义的一个类的数组,他的成员函数PrintTable负责打印这个类所封装的数据,并且判断需要换页时就换页操作也就是说,由于很难算出总共能打印多少页所以,我想只调用OnPrint/PrintDispatch一次,即能打印出所有可能的分页(包括header/footer)而不是先安排好每页都打什么,算出总页数,在循环调用多次OnPrint 在OnBeginPrinting 统计出你的页数 int nTotalRowHeight = 0; int nNumPages = 1; for (int row = 0; row < RowCount; row++) { nTotalRowHeight += RowHeight(row);//每行的高度 if (nTotalRowHeight > m_nPageHeight) { nNumPages++; nTotalRowHeight = RowHeight(row); } } // Set up the print info pInfo->SetMaxPage(nNumPages); pInfo->m_nCurPage = 1; 在OnPrint打印的时候 // Set the page map mode to use GridCtrl units, and setup margin pDC->SetMapMode(MM_ANISOTROPIC); pDC->SetWindowExt(m_LogicalPageSize); pDC->SetViewportExt(m_PaperSize); pDC->SetWindowOrg(-LEFT_MARGIN*m_CharSize.cx, 0);// int nTotalRowHeight = 0; UINT nNumPages = 1; int nCurrPrintRow = 1;////找到本页的行号 while (nCurrPrintRow < RowCount && nNumPages < pInfo->m_nCurPage) { nTotalRowHeight += RowHeight(nCurrPrintRow); if (nTotalRowHeight > m_nPageHeight) { nNumPages++; if (nNumPages == pInfo->m_nCurPage) break; nTotalRowHeight = RowHeight(nCurrPrintRow); } nCurrPrintRow++; } if (nCurrPrintRow >= RowCount) return; BOOL bFirstPrintedRow = TRUE; CRect rect; rect.bottom = -1; while (nCurrPrintRow < RowCount) { rect.top = rect.bottom+1; rect.bottom = rect.top + RowHeight(nCurrPrintRow) - 1; if (rect.bottom > m_nPageHeight) break; // 跳出循环 rect.right = -1; ///打印的内容 nCurrPrintRow++; bFirstPrintedRow = FALSE; } // 设置下一页 pDC->SetWindowOrg(0,0); 是的,你需要先統計出你要打印的頁數啊。在OnPreparePrinting()中調用pInfo->SetMaxPage(nMaxPage)設置打印頁數。DoPreparePrinting(pInfo)后出現預覽對話框,你可以看到你設置的打印頁數。你可以選擇打印多少頁到多少頁。然后在OnBeginPrinting()中可以得到真實打印的頁數,pInfo->SetMaxPage(pInfo->GetToPage()-pInfo->GetFromPage() + 1)。OnPrint()根據你設置的頁數會自動調用多少次以打印各頁,在OnPrint()中你只需繪制當前頁就好了啊。自定義繪制當前頁PrintDispatch(pDC, pInfo->m_nCurPage - 1)。 嗯,看来我对OnPrint函数理解错误了,开始因为觉得针对自己的项目如果在打印前算出总共能打印多少页,很麻烦,就想着如果能够实现每个打印子任务可以根据当前打印的状态来判断是否该换页等操作就好了,就想当然的以为只要调用OnPrint一次,其他交给下面处理,当时还尝试着修改pInfo-> m_nCurPage等参数来控制换页,呵呵。看来是我调查出了大问题,没有好好理解这种机制。不过我还是有点不甘心,虽然按照MFC的这种打印机制我前面的做法是错误的,但是对于我这种懒人,我觉得应该还是会有些情况下,先算出MaxPage很麻烦(如规则太多,行列变化情况很多——〉打印页统计复杂),因此要是能将打印任务交给下面自行处理,就方便多了,呵呵,当然那时可能就不用MFC的这种规则了。不知道有没有我说的这种实现方法,大家知道的话,麻烦给指个方向:) 求救一个小问题 奇怪的异常?如何解决? 一个VC的问题:怎样给命名管道传递第一个参数? 一个long左移32位,为什么得到的是其本身 如何利用VC抓取屏幕生成一张位图? 请问如何获取窗口和视图的指针!在线等! 安装程序的问题 错误信息解释,散分 微软刚刚向法院上交了WINXP的源代码。WINXP竟然是用BASIC语言写的! 一个无法捕获的异常,非高手勿进,只有20分 松下PLC串口编程之16进制高低位互换问题 台湾电脑科学界的叫法和大陆不一样.
//换页
OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if(pDC->IsPrinting())
{
int originy=...
//当前页的原点y值它通常=每页高度*(pInfo->m_nCurPage-1);
//然后再设置当前页原点
pDC->SetViewportOrg(0,originy);
//在此你也可以是别的处理换页的方式
}
...
} 红色这句是不是说,虽然打印御览是分页显示的,但实际上VC的处理却是连续的页面,因此如果在需要分页的地方将y值修改为下一页的值,即不会再被最后页的内容覆盖了?
如:
第一页打印开始Y=100;
第二页打印开始Y=100+页面高度;
第N页打印开始Y=100+(N-1)*页面高度;
对吗?
{
if(pInfo){
if( pInfo->m_bPreview == TRUE ) {
//Preview
CWnd *pWnd = GetParentFrame();
if( pWnd != NULL ){
//make resize possible
LONG lResult = ::GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE);
lResult |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
::SetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE, lResult); //Max window
pWnd->ShowWindow(SW_SHOWMAXIMIZED);
}
}
}
// default preparation
return DoPreparePrinting(pInfo);
}void CXXView::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo)
{
//创建字体
//创建pen用来画表格的线
}
void CXXView::OnEndPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/)
{
m_PrintFont.DeleteObject();
m_PrintPen.DeleteObject();
}
void CXXView::OnPrint(CDC *pDC, CPrintInfo *pInfo)
{
static i = 0;
if(pDC && pInfo)
{
//Set the new font
CFont *pOriginalFont = pDC->SelectObject(&m_PrintFont);
CPen *pOriginalPen = pDC->SelectObject(&m_PrintPen); PrintDispatch(pDC, pInfo); //Set the original font
pDC->SelectObject(pOriginalFont);
pDC->SelectObject(pOriginalPen);
}
}
void PrintDispatch(CDC *pDC, CPrintInfo *pInfo)
{
// start printing position
UINT x = pageInfo.xStart;
UINT y = pageInfo.yStart; for(int i = 0; i < prtTableSize; i++)
{
printTable[i]->PrintTable(&x, &y, pDC, pInfo);
}
}
其中printTable是我定义的一个类的数组,他的成员函数PrintTable负责打印这个类所封装的数据,并且判断需要换页时就换页操作
也就是说,由于很难算出总共能打印多少页
所以,我想只调用OnPrint/PrintDispatch一次,即能打印出所有可能的分页(包括header/footer)
而不是先安排好每页都打什么,算出总页数,在循环调用多次OnPrint
int nTotalRowHeight = 0;
int nNumPages = 1;
for (int row = 0; row < RowCount; row++)
{
nTotalRowHeight += RowHeight(row);//每行的高度
if (nTotalRowHeight > m_nPageHeight) {
nNumPages++;
nTotalRowHeight = RowHeight(row);
}
}
// Set up the print info
pInfo->SetMaxPage(nNumPages);
pInfo->m_nCurPage = 1;
在OnPrint打印的时候
// Set the page map mode to use GridCtrl units, and setup margin
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(m_LogicalPageSize);
pDC->SetViewportExt(m_PaperSize);
pDC->SetWindowOrg(-LEFT_MARGIN*m_CharSize.cx, 0);
//
int nTotalRowHeight = 0;
UINT nNumPages = 1;
int nCurrPrintRow = 1;//
//找到本页的行号
while (nCurrPrintRow < RowCount && nNumPages < pInfo->m_nCurPage)
{
nTotalRowHeight += RowHeight(nCurrPrintRow);
if (nTotalRowHeight > m_nPageHeight) {
nNumPages++;
if (nNumPages == pInfo->m_nCurPage) break;
nTotalRowHeight = RowHeight(nCurrPrintRow);
}
nCurrPrintRow++;
}
if (nCurrPrintRow >= RowCount) return; BOOL bFirstPrintedRow = TRUE;
CRect rect;
rect.bottom = -1;
while (nCurrPrintRow < RowCount)
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + RowHeight(nCurrPrintRow) - 1; if (rect.bottom > m_nPageHeight) break; // 跳出循环 rect.right = -1;
///打印的内容
nCurrPrintRow++;
bFirstPrintedRow = FALSE;
} // 设置下一页
pDC->SetWindowOrg(0,0);
不知道有没有我说的这种实现方法,大家知道的话,麻烦给指个方向:)