• <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>
            穩(wěn)定盈利的期貨交易方法-量化趨勢交易

            alantop -專業(yè)量化投資者

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

            如何在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 閱讀(1395) 評論(1)  編輯 收藏 引用 所屬分類: C++

            評論

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

            第二種方法打印出來的視圖就是空的,為什么我在上面畫的圖形都看不到呢?
            2006-05-23 16:45 | byli
            久久久久99精品成人片试看| 7777精品伊人久久久大香线蕉| 影音先锋女人AV鲁色资源网久久| 2021久久精品免费观看| 国产精品乱码久久久久久软件| 久久久亚洲AV波多野结衣| 91久久婷婷国产综合精品青草| 亚洲成色999久久网站| 国产精品青草久久久久福利99 | 无码国内精品久久人妻| 精品久久久久久久| 亚洲欧美国产日韩综合久久 | 久久精品成人免费网站| 欧美与黑人午夜性猛交久久久 | 久久亚洲色一区二区三区| 久久久久人妻一区精品色| 日本亚洲色大成网站WWW久久| 久久99久久99精品免视看动漫| 国产精品美女久久久久AV福利| 亚洲AV日韩AV永久无码久久| 精品国产一区二区三区久久蜜臀| 一本色道久久综合狠狠躁| 久久久无码精品亚洲日韩软件| 7777久久亚洲中文字幕| 综合人妻久久一区二区精品 | 久久精品水蜜桃av综合天堂| 久久久久久久综合综合狠狠| 精品久久一区二区三区| 久久夜色精品国产噜噜噜亚洲AV| 亚洲欧美成人久久综合中文网| 久久中文字幕视频、最近更新| 久久99精品久久久久久| 久久精品国产亚洲AV电影| 亚洲第一极品精品无码久久| 精品国产99久久久久久麻豆 | 久久久久亚洲AV成人网| 国产精品99久久久久久宅男| 7国产欧美日韩综合天堂中文久久久久| 久久久久亚洲av无码专区| 99久久夜色精品国产网站| 日产精品久久久久久久|