青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

穩定盈利的期貨交易方法-量化趨勢交易

alantop -專業量化投資者

愛好:量化投資,逆向工程,滲透
隨筆 - 595, 文章 - 0, 評論 - 921, 引用 - 0
數據加載中……

如何在MFC中打印CFormView?

MFC的打印是如何工作的?

Before we go further, we need to learn how OnPrintPreview and OnPrint work in MFC. Here is the scratch of the code.

  1. Calls OnPreparePrint to prompt dialog to setup actual printer and number of pages. Usually we will let MFC do the work for us here. But if you want to skip the dialog and setup printer DC directly, you’d better do it here or totally rewrite OnPrint/OnPrintPreview.
  2. Calls OnBeginPrint. If we can decide how many page we need to print, it is better to set the number of pages here if possible.
  3. Print each page in a loop.
    • In the loop, Calls OnPrepareDC. If you need to setup map mode and conversion ratio between logical pixel and physical pixel, such as like one inch in screen equals one inch in printer, you'd better do it here. One important thing to bear in mind is that if you can’t decide how many pages you need to print on step 2, you can still use CPrintInfo::m_bContinuePrinting member variable to terminate printing.
    • Calls OnPrint to do actually printing

打印CFormView有兩種方法:
1.Capturing screen image of CFormView.

Like injecting any code into a framework, first you need to know where to add your code. Such type of question is always the toughest one when programming in MFC. In this case, the question is when to grab the image. How about doing it in OnBeginPrint? Not bad idea at first glance. Well, it turns out there is catch here. As MFC prompts a window to emulate Printer DC in preview mode, you could end up capturing wrong image in this mode. It is better to do it in OnFilePrint and OnFilePrintPreview. The actual code looks like this:

void?CFormViewPrintView::_grapImage(?)?
{
????
//Grap?Image
????CPoint?oldPoint?=?GetScrollPosition(?);
????
//scroll?to?top?left?corner?as?CFormView?is?a?Scroll?view
????CPoint?pt(?0,?0?);
????
this->ScrollToPosition(?pt?);

????CClientDC?dc(
this);
????CRect?rect;
????
this->GetClientRect(?rect?);
????m_dib.Attach(?GDIUtil::GrabDIB(?
&dc,?rect?)?);

????ScrollToPosition(?oldPoint?);
}

void?CFormViewPrintView::OnFilePrintPreview()?
{
????
//?TODO:?Add?your?command?handler?code?here
????_grapImage(?);
????CFormView::OnFilePrintPreview()?;
}

void?CFormViewPrintView::OnFilePrint()?
{
????_grapImage(?);
????CFormView::OnFilePrint()?;
}

Hmm, what does the GDIUtil::GradDIB do? It grabs Bitmap from the screen and converts it to DIB. Why DIB, not Bitmap directly? A bitmap always depends on DC and screen DC is different than Printer DC. Without such conversion, we are under the mercy of Printer Driver. It may work fine in some printer, but badly on the other. Seen Roger Allen’s article on this.

Next, we need to deal with how to preserve something the same size as displayed on screen. Ever wondered why something turns terribly small when printing? Here is the reason, let’s say the resolution in printer is 600 pixel per inch, while we usually have 96 or 120 pixel per inch in the screen. If you simply print something “the same size” in pixel, it is not hard to imagine what will happen. That is also the reason why you should change font size when printing text. What we really want, is to print something the same size in inch, not pixel. “Point taken, but where to put the code of such conversion?” You ask yourself and realize this is the same old “where” question again. This can be done by overriding the method OnPrepareDC. What Microsoft really means by the name is “Setup map mode here if needed”. This is also the place to decide whether to terminate printing or not, if you haven’t figured out the number of printing pages previously. Our OnPrepareDC looks like this.

void?CFormViewPrintView::OnPrepareDC(CDC*?pDC,?
??????????????????????CPrintInfo
*?pInfo?/*?=?NULL?*/)
{
????
//?TODO:?Add?your?specialized?code?here?and/or?call?the?base?class
????if(?pInfo?)
????{
????????CClientDC?dc(?
this?);
????????pDC
->SetMapMode(MM_ANISOTROPIC);

????????CSize?sz(?dc.GetDeviceCaps(LOGPIXELSX),?
????????????????????dc.GetDeviceCaps(LOGPIXELSY)?);
????????pDC
->SetWindowExt(?sz?);
????????sz?
=?CSize(?pDC->GetDeviceCaps(LOGPIXELSX),
????????????????????????pDC
->GetDeviceCaps(LOGPIXELSY)?);
????????pDC
->SetViewportExt(?sz?);
????}
}

What does this code mean? It means one inch in screen, dc in this case, equals one inch in printer (could be pseudo one) and we don’t care about actual pixel size varies, say 120 ppi in screen vs 600 ppi in printer.

Last, the actual printing.

void?CFormViewPrintView::OnPrint(CDC*?pDC,?CPrintInfo*?pInfo)
{
????
//?TODO:?add?customized?printing?code?here
????if(?pInfo?==?NULL?)
????????
return;

????
if(?m_dib.GetHandle(?)?==?NULL?)
????????
return;
????{
????????
//Call?GlobalLock?in?constructor,?call?Unlock?when?exists?the?block
????????GLock?lock(?m_dib?);
????????BITMAPINFOHEADER?
*pBMI?=?(BITMAPINFOHEADER*)(LPVOID)lock;

????????
int?nColors?=?0;
????????
if(?pBMI->biBitCount?<=?8?)
????????????nColors?
=?(?1<<?pBMI->biBitCount?);

????????::StretchDIBits(?pDC
->GetSafeHdc(?),
????????pInfo
->m_rectDraw.left,?
????????pInfo
->m_rectDraw.top,
????????pBMI
->biWidth,
????????pBMI
->biHeight,
????????????????
0,?
????????????????
0,?
????????????????pBMI
->biWidth,
????????????????pBMI
->biHeight,
????????????????(LPBYTE)pBMI?
+?(pBMI->biSize?+?nColors?*?sizeof(RGBQUAD)),
????????????????(BITMAPINFO
*)pBMI,
????????????????DIB_RGB_COLORS,?
????????????????SRCCOPY);
????}
}

One thing to mention is that GLock in GUtil follows the same idea as AutoPtr in STD. I have no idea why Microsoft does right thing in CClientDC and CPaintDC, while turning blind when dealing something like GlobalLock/Unlock or the notorious SelectObject. How many times have we scratched our head to detect GDI object resource leak, only finding out that we select something in, but forget to select it out.

2.Another way WM_PRINT message
Ever heard of WM_PRINT message? It is not even in Visual C++ class wizard, but it seems promising everything we need for printing CFormView. Here is another way to print CFormView:

void?CFormViewPrint2View::_print(?)
{
????CRect?rect;
????
this->GetClientRect(?rect?);
????CDC?memDC;

????CClientDC?dc(?
this?);
????memDC.CreateCompatibleDC(?
&dc?);

????CBitmap?bitmap;
????bitmap.CreateCompatibleBitmap(?
&dc,?rect.Width(),?rect.Height()?);
????{
????????
//This?will?force?bitmap?selected?out?of?DC?when?exit?this?block
????????LocalGDI?local(?&memDC,?&bitmap?);
????????
this->Print(?&memDC,?PRF_ERASEBKGND|PRF_CLIENT|PRF_CHILDREN?);
????}
????m_dib.Attach(?GDIUtil::DDBToDIB(?bitmap?)?);
}

void?CFormViewPrint2View::OnFilePrintPreview()?
{
????
//?TODO:?Add?your?command?handler?code?here
????_print(?);
????CFormView::OnFilePrintPreview(?);
}

void?CFormViewPrint2View::OnFilePrint()?
{
????
//?TODO:?Add?your?command?handler?code?here
????_print(?);
????CFormView::OnFilePrint(?);
}


?

結論:

So, what is the strength and weakness of each method? The first one doesn’t care about how many individual child controls you have and how to print each of them on Printer, but it can only print visual part of the screen. While second one seems much better and cleaner than the first one, it even allows you to print all client area without displaying them on the screen. Unfortunately, there is a catch for it too. Some sub-classed Windows controls and user custom controls may forget to process WM_PRINT message at all, which is amazingly easy to implement if you can process WM_PAINT message.

posted on 2006-05-23 15:11 AlanTop 閱讀(1399) 評論(1)  編輯 收藏 引用 所屬分類: C++

評論

# re: 如何在MFC中打印CFormView?  回復  更多評論   

第二種方法打印出來的視圖就是空的,為什么我在上面畫的圖形都看不到呢?
2006-05-23 16:45 | byli
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲系列中文字幕| 欧美欧美全黄| 亚洲视屏一区| 午夜日本精品| 一区二区三区日韩欧美精品| 欧美亚洲色图校园春色| 一本色道久久综合亚洲精品按摩| 小辣椒精品导航| 亚洲主播在线观看| 蜜乳av另类精品一区二区| 欧美亚洲在线| 国产女主播一区二区三区| 一区二区三区四区五区精品| 亚洲精品免费在线观看| 欧美电影美腿模特1979在线看 | 亚洲国产精品视频一区| 国产亚洲精品自拍| 亚洲欧美中日韩| 午夜精品理论片| 国产精品美女999| 亚洲日本欧美日韩高观看| 国产日韩视频一区二区三区| 一区二区三区欧美| 欧美一级在线视频| 欧美日韩一区二区在线| 亚洲精品国精品久久99热| 亚洲美女中文字幕| 欧美成人一二三| 牛牛国产精品| 一区视频在线看| 欧美成人精品影院| 亚洲国产日韩一区| 一区二区三区精品国产| 欧美视频在线观看免费| 亚洲一区二区在线免费观看| 欧美一区二区三区喷汁尤物| 国产精品综合久久久| 午夜精品影院| 欧美高清在线视频| 一本色道久久99精品综合| 欧美涩涩视频| 亚洲小说欧美另类社区| 久久精品国产一区二区三| 黄色成人免费网站| 男人天堂欧美日韩| 宅男精品视频| 欧美一区二区三区成人| 尹人成人综合网| 欧美成人免费在线| 亚洲午夜电影| 欧美/亚洲一区| 亚洲午夜久久久久久久久电影院| 国产精品免费视频xxxx| 欧美在线视频a| 亚洲国语精品自产拍在线观看| 日韩午夜av| 国产精品乱人伦中文| 欧美一区二区三区视频免费| 另类天堂av| 亚洲一区二区三区在线观看视频 | 亚洲精品久久久久中文字幕欢迎你 | 亚洲国产婷婷香蕉久久久久久99| 亚洲午夜高清视频| 韩曰欧美视频免费观看| 欧美大成色www永久网站婷| 亚洲一区二区精品| 91久久精品国产| 亚洲欧美日韩系列| 亚洲全黄一级网站| 国产自产高清不卡| 欧美日韩一区二区国产| 久热精品视频在线免费观看| 制服丝袜激情欧洲亚洲| 欧美激情一区二区三区不卡| 午夜精品福利一区二区蜜股av| 精品成人a区在线观看| 欧美精品色网| 久久尤物视频| 亚洲欧美日韩系列| 日韩视频免费观看高清在线视频| 久久深夜福利免费观看| 小黄鸭视频精品导航| 亚洲激情电影在线| 狠狠色狠狠色综合人人| 国产乱码精品一区二区三区不卡| 欧美成人精品一区二区| 久久久久久夜| 欧美在线视频一区二区三区| 亚洲欧美成人一区二区三区| 日韩视频精品在线| 亚洲精品欧美在线| 亚洲日本在线观看| 欧美电影在线免费观看网站| 久久蜜桃资源一区二区老牛 | 99ri日韩精品视频| 红桃视频一区| 国内精品视频666| 国产精品捆绑调教| 国产精品xxxav免费视频| 欧美精品激情blacked18| 欧美大色视频| 欧美激情一区在线观看| 蜜臀久久99精品久久久久久9| 久久久久久免费| 久久国产精品高清| 久久精品三级| 麻豆亚洲精品| 美女精品一区| 免费看黄裸体一级大秀欧美| 久久久精品动漫| 久久综合九色99| 久久久久久久久久久久久久一区 | 亚洲一区二区欧美| 亚洲视屏一区| 午夜精品视频一区| 欧美一区二区在线看| 午夜亚洲福利在线老司机| 亚洲欧美视频一区| 久久成人精品视频| 久久激情婷婷| 欧美阿v一级看视频| 免费在线观看成人av| 欧美成人激情视频免费观看| 欧美国产日韩二区| 亚洲黄色一区| 亚洲午夜一区二区三区| 亚洲香蕉在线观看| 久久久99免费视频| 久久久久一本一区二区青青蜜月| 午夜一区二区三区在线观看| 久久精品伊人| 欧美国产日韩精品免费观看| 欧美色综合天天久久综合精品| 国产精品久久久爽爽爽麻豆色哟哟| 国产日韩一区二区三区| 亚洲欧洲在线观看| 亚洲夜间福利| 免费成人av| av不卡在线看| 欧美在线观看视频| 欧美激情视频一区二区三区在线播放 | 欧美日韩视频专区在线播放| 国产日韩在线看片| 91久久久在线| 欧美在线在线| 亚洲日本精品国产第一区| 亚洲欧美中文日韩在线| 久久久蜜臀国产一区二区| 欧美日韩国语| 激情av一区| 亚洲一区二区精品在线| 免费在线观看日韩欧美| 亚洲一区二区精品在线| 欧美丰满高潮xxxx喷水动漫| 国产精品视频免费观看www| 黄色在线一区| 香港久久久电影| 欧美v国产在线一区二区三区| 亚洲图片欧洲图片av| 久久三级福利| 国产欧美日韩免费| 亚洲乱码国产乱码精品精98午夜 | 久久综合精品一区| 国产日韩欧美一区在线| 在线综合+亚洲+欧美中文字幕| 久久久久亚洲综合| 亚洲视频一区在线观看| 欧美日韩高清一区| 一区视频在线播放| 久久精品国产亚洲精品| 亚洲手机成人高清视频| 久久综合色婷婷| 国内一区二区三区| 欧美一区二区三区精品电影| 日韩图片一区| 欧美激情第3页| 亚洲第一免费播放区| 久久伊人一区二区| 久久不射中文字幕| 国内在线观看一区二区三区| 午夜日韩激情| 午夜精品剧场| 国产欧美精品久久| 久久成人免费电影| 亚洲午夜av在线| 国产精品美女在线| 亚洲一区二区三区在线播放| 亚洲欧洲另类| 欧美日韩精品一二三区| 日韩一级精品| 日韩午夜激情电影| 欧美日韩视频| 午夜亚洲性色视频| 午夜视黄欧洲亚洲| 国产一区欧美日韩| 久久尤物视频| 久久免费视频在线观看| 亚洲欧洲在线看| 最新精品在线| 能在线观看的日韩av|