• <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>

            我住包子山

            this->blog.MoveTo("blog.baozishan.in")

            VC++編程內(nèi)幕學(xué)習(xí)心得(2)--下

            接著上回開始

            書上的第二個例子

            直接貼我略加修改的代碼,后面附有注釋:

            void Cfont2View::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)

            {//想說的是OnPrepareDC在每次調(diào)用OnDraw之前調(diào)用,可在里面進行初始化的一些操作

                CRect clientRect;

               

                GetClientRect(clientRect);

                pDC->SetMapMode(MM_ANISOTROPIC);//橫豎比恒定的可變比例映射

                pDC->SetWindowExt(400,450);//窗口范圍固定,視口范圍如下,因此圖像(文字)會根據(jù)視口范圍改變比例

                pDC->SetViewportExt(clientRect.right, -clientRect.bottom);//原書第二參數(shù)為正,我這里用負數(shù),為了和標(biāo)準(zhǔn)MM_TWIPSx,y方向?qū)ι?/span>,x+,y-;

                CPoint pt = pDC->GetViewportOrg();

                ASSERT(pt.x==0&&pt.y==0);//pDC->SetViewportOrg(0,0);//原書上這樣寫,應(yīng)該有點多余,因為初始原點就是0,0;

                CView::OnPrepareDC(pDC, pInfo);

            }

            void Cfont2View::OnDraw(CDC* pDC)

            {//OnDraw函數(shù)基本沒有變,只是用了一個nPos來一直計算新的字串位置

                CFont fontT1,fontT2,fontT3,fontT4;

                CFont * pOldFont = NULL;

                TEXTMETRIC tm;

                int nPos = 0;

                fontT1.CreateFont(50,0,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,

                    DEFAULT_PITCH|FF_SWISS, TEXT("Arail"));

                pOldFont = pDC->SelectObject(&fontT1);

                pDC->TextOut(0,nPos,TEXT("This is Arial, default width"));

                pDC->GetTextMetrics(&tm);

                nPos-=tm.tmHeight+tm.tmExternalLeading;//找到下一個串的y坐標(biāo)

                fontT2.CreateFont(50,0,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,

                    DEFAULT_PITCH|FF_MODERN, TEXT("Courier"));

                pDC->SelectObject(&fontT2);

                pDC->TextOut(0,nPos,TEXT("This is Courier, default width"));

                pDC->GetTextMetrics(&tm);

                nPos-=tm.tmHeight+tm.tmExternalLeading;

                fontT3.CreateFont(50,10,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,

                    DEFAULT_PITCH|FF_ROMAN, TEXT("Courier"));

                pDC->SelectObject(&fontT3);

                pDC->TextOut(0,nPos,TEXT("This is generic Roman, variable width"));

                pDC->GetTextMetrics(&tm);

                nPos-=tm.tmHeight+tm.tmExternalLeading;

                    fontT4.CreateFont(50,0,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,

                    DEFAULT_PITCH|FF_MODERN, TEXT("LinePrinter"));

                pDC->SelectObject(&fontT4);

                pDC->TextOut(0,nPos,TEXT("This is LinePrinter, default width"));

                pDC->GetTextMetrics(&tm);

                nPos-=tm.tmHeight+tm.tmExternalLeading;

                fontT5.CreateFont(50,0,0,0,400,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,

                    DEFAULT_PITCH|FF_MODERN, TEXT("Consolas"));

                pDC->SelectObject(&fontT5);

                pDC->TextOut(0,nPos,TEXT("Consolas Fonts, recommand by VS2005 official"));

                pDC->SelectObject((CFont*)pOldFont);

             

                Cfont2Doc* pDoc = GetDocument();

                ASSERT_VALID(pDoc);

                if (!pDoc)

                    return;

                // TODO: 在此處為本機數(shù)據(jù)添加繪制代碼

            }

            這個例子大概就是這樣,截圖放出:

            clip_image002

            看著這個例子覺得字很丑,于是稍微改了一下背景色跟字體,一下就好看多了,呵呵,代碼很簡單.需要在OnDraw或者OnPrepareDC中畫黑色背景,畫字體用CDC::SetBkMode設(shè)置透明背景,然后CDC::SetTextColor設(shè)置字體顏色為00FF00就可以了,呵呵

            clip_image004

            接下來就是一個關(guān)于深入了解ScrollView的一個例子(第三個例子)

            這個例子建立時記得讓ViewCScrollView中繼承

            修改OnInitialUpdate()函數(shù)

            void CgdiView::OnInitialUpdate()

            {

                CScrollView::OnInitialUpdate();

             

                CSize sizeTotal(800,1050);

                CSize sizePage(sizeTotal.cx/2,sizeTotal.cy/2);

                CSize sizeLine(sizeTotal.cx/50,sizeTotal.cy/50);

                SetScrollSizes(MM_LOENGLISH, sizeTotal,sizePage,sizeLine);

            }

            對于CScrollView類我仍然有一些疑惑,自己未能解決.在設(shè)置了ScrollSize以后,仍然可以將view拉長導(dǎo)致超出ScrollSize,這樣不會顯示滾動條,我試了半天也沒有解決問題,真的不知道該怎么辦..問題還是留在這里

            其他實現(xiàn)如下:

            View頭文件添加:

            private:

                const CSize m_sizeEllipse;

                CPoint m_pointTopLeft;//橢圓外切矩形左上角坐標(biāo)

                CSize m_sizeOffset;//鼠標(biāo)初始點中橢圓時與橢圓外切矩形左上角的偏移

            BOOL m_bCaptured;//鼠標(biāo)按下的標(biāo)志

            Cpp文件實現(xiàn):

            void CgdiView::OnDraw(CDC* pDC)

            {

                CBrush brushHatch(HS_DIAGCROSS,RGB(255,0,0));//0xFF0000

                CPoint point(0,0);

                pDC->LPtoDP(&point);

                pDC->SetBrushOrg(point);//繪制畫刷的原點,如果不這樣寫,當(dāng)滾動條滾動時,默認繪制原點會變?yōu)楫?dāng)前區(qū)域的坐上點坐標(biāo)

                pDC->SelectObject(&brushHatch);

                pDC->Ellipse(CRect(m_pointTopLeft,m_sizeEllipse));

                TRACE(TEXT("%d %d\n"),m_pointTopLeft.x,m_pointTopLeft.y);

                pDC->SelectStockObject(BLACK_BRUSH);

                pDC->Rectangle(100,-100,200,-200);//這個矩形為了方便查看重繪矩形,當(dāng)重繪時候矩黑色矩形部分會出現(xiàn)閃爍

                CgdiDoc* pDoc = GetDocument();

                ASSERT_VALID(pDoc);

                if (!pDoc)

                    return;

            }

            void CgdiView::OnLButtonDown(UINT nFlags, CPoint point)

            {

                CRect rectEllipse(m_pointTopLeft, m_sizeEllipse);

                CRgn circle;

             

                CClientDC dc(this);

                OnPrepareDC(&dc);

                dc.LPtoDP(rectEllipse);

                circle.CreateEllipticRgnIndirect(rectEllipse);

                if(circle.PtInRegion(point))

                {

                    SetCapture();

                    m_bCaptured = TRUE;

                    CPoint pointTopLeft(m_pointTopLeft);

                    dc.LPtoDP(&pointTopLeft);

                    m_sizeOffset = point - pointTopLeft;

                    SetCursor(LoadCursor(NULL,IDC_CROSS));

                }

                CScrollView::OnLButtonDown(nFlags, point);

            }

             

            void CgdiView::OnLButtonUp(UINT nFlags, CPoint point)

            {

                if(m_bCaptured)

                {

                    ReleaseCapture();

                    m_bCaptured = FALSE;

                }

                CScrollView::OnLButtonUp(nFlags, point);

            }

             

            void CgdiView::OnMouseMove(UINT nFlags, CPoint point)

            {

                if(m_bCaptured)

                {

                    CClientDC dc(this);

                    OnPrepareDC(&dc);

                    CRect rectOld(m_pointTopLeft, m_sizeEllipse+CSize(1,-1));

                    dc.LPtoDP(rectOld);

                    InvalidateRect(rectOld, TRUE);

                    m_pointTopLeft = point - m_sizeOffset;

                    dc.DPtoLP(&m_pointTopLeft);//注意這里有取地址而CRect沒有,是因為CRect類定義了一個隱式轉(zhuǎn)換,轉(zhuǎn)換成LPRECT,CPoint沒定義

                    CRect rectNew(m_pointTopLeft, m_sizeEllipse);

                    dc.LPtoDP(rectNew);

                    InvalidateRect(rectNew,TRUE);

                }

                CScrollView::OnMouseMove(nFlags, point);

            }

             

            以下則是位圖的基本學(xué)習(xí)

            這一節(jié)講位圖

            關(guān)于創(chuàng)建設(shè)備無關(guān)位圖DIB.

            關(guān)于DIB最好的資料是MSDN的幫助.

            Windows 的兩種位圖:GDI位圖,DIB.

            GDI位圖由MFC庫中的CBitmap類表示.GDI位圖對象中有一個相關(guān)聯(lián)的windows數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)由windowsGDI模塊來維護,它是設(shè)備相關(guān)的.應(yīng)用程序可以得到GDI位圖數(shù)據(jù)的一份拷貝,但其中每一位的安排完全依賴顯示設(shè)備.設(shè)備依賴的限制就是無法通過調(diào)制解調(diào)器,磁盤傳遞這樣的位圖..

            操縱CBitmap跟其他GDI對象是一樣的簡單..

            但是MFC并沒有封裝DIB,所以需要用SDK的東西來使用DIB.原始使用DIB我覺得是一件很麻煩的事情,你需要了解一些系統(tǒng)調(diào)色板之類的知識,有些Directx的書上ms有寫.讀取一個位圖文件需要先知道他的各種信息,之后根據(jù)信息為它建立大小合適的結(jié)構(gòu)存放他的位圖信息,根據(jù)這些為位圖設(shè)定位圖的調(diào)色版,在繪制位圖時有可能需要把位圖調(diào)色板讓系統(tǒng)使用,之后再恢復(fù)成原始的調(diào)色板,很多很復(fù)雜的操作..但是,這本書的作者提供給我們了一個他寫的CDib,降低了開發(fā)的難度,節(jié)省了時間,網(wǎng)上ms有很多CDib的類:

            我將附上去它的整個代碼部分,如果能研究好了這部分內(nèi)容應(yīng)該會有很大提高,目前我還沒研究太好..只是大概有那么點概念

            頭文件直接貼在這兒

            // cdib.h declaration for Inside Visual C++ CDib class

             

            #ifndef _INSIDE_VISUAL_CPP_CDIB

            #define _INSIDE_VISUAL_CPP_CDIB

             

            class CDib : public CObject

            {

                enum Alloc {noAlloc, crtAlloc, heapAlloc};

                DECLARE_SERIAL(CDib)

            public:

                LPVOID m_lpvColorTable;

                HBITMAP m_hBitmap;

                LPBYTE m_lpImage;  // starting address of DIB bits

                LPBITMAPINFOHEADER m_lpBMIH; //  buffer containing the BITMAPINFOHEADER

            private:

                HGLOBAL m_hGlobal; // For external windows we need to free;

                                   //  could be allocated by this class or allocated externally

                Alloc m_nBmihAlloc;

                Alloc m_nImageAlloc;

                DWORD m_dwSizeImage; // of bits -- not BITMAPINFOHEADER or BITMAPFILEHEADER

                int m_nColorTableEntries;

               

                HANDLE m_hFile;

                HANDLE m_hMap;

                LPVOID m_lpvFile;

                HPALETTE m_hPalette;

            public:

                CDib();

                CDib(CSize size, int nBitCount);    // builds BITMAPINFOHEADER

                ~CDib();

                int GetSizeImage() {return m_dwSizeImage;}

                int GetSizeHeader()

                    {return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;}

                CSize GetDimensions();

                BOOL AttachMapFile(const char* strPathname, BOOL bShare = FALSE);

                BOOL CopyToMapFile(const char* strPathname);

                BOOL AttachMemory(LPVOID lpvMem, BOOL bMustDelete = FALSE, HGLOBAL hGlobal = NULL);

                BOOL Draw(CDC* pDC, CPoint origin, CSize size);  // until we implemnt CreateDibSection

                HBITMAP CreateSection(CDC* pDC = NULL);

                UINT UsePalette(CDC* pDC, BOOL bBackground = FALSE);

                BOOL MakePalette();

                BOOL SetSystemPalette(CDC* pDC);

                BOOL Compress(CDC* pDC, BOOL bCompress = TRUE); // FALSE means decompress

                HBITMAP CreateBitmap(CDC* pDC);

                BOOL Read(CFile* pFile);

                BOOL ReadSection(CFile* pFile, CDC* pDC = NULL);

                BOOL Write(CFile* pFile);

                void Serialize(CArchive& ar);

                void Empty();

               

                BOOL CDib::DrawDib(CDC* pDC, CPoint origin, CSize size);

            private:

                void DetachMapFile();

                void ComputePaletteSize(int nBitCount);

                void ComputeMetrics();

            };

            #endif // _INSIDE_VISUAL_CPP_CDIB

            兩個構(gòu)造函數(shù):

            CDib();

            CDib(CSize size, int nBitCount);    // builds BITMAPINFOHEADER

            第一個沒有參數(shù)的構(gòu)造函數(shù)建立一個空的DIB對象,用來從文件或內(nèi)存載入DIB.

            第二個帶有高寬,顏色位數(shù)的構(gòu)造函數(shù),可以用它的CreateSection,得到DIBSection.

            其他Public的成員函數(shù):

            BOOL AttachMapFile(const char* strPathname, BOOL bShare = FALSE);

            BOOL AttachMemory(LPVOID lpvMem, BOOL bMustDelete = FALSE, HGLOBAL hGlobal = NULL);

            從內(nèi)存映射文件讀出位圖/從內(nèi)存地址,有可能需要用全局句柄(HGLOBAL)讀出位圖

            BOOL Compress(CDC* pDC, BOOL bCompress = TRUE); // FALSE means decompress

            壓縮,解壓縮位圖

            BOOL CopyToMapFile(const char* strPathname);

            建立一個映射文件把當(dāng)前DIB內(nèi)容復(fù)制過去,當(dāng)文件對象關(guān)閉時(CDib對象析構(gòu))真正寫入文件..

            ...省略很多函數(shù)說明,有問題可以查書,呵呵,下面介紹應(yīng)用CDib的方法

             

            注意要鏈接"VFW32.lib,因為在CDib中有(#include <vfw.h>)

            使用CDib的方法:

            調(diào)用Draw之前需要做的

            m_pDib->UsePalette(pDC); // could be in palette msg handler

            CSize sizeDib = m_pDib->GetDimensions();

            pDC->StretchBlt(0, 0, sizeDib.cx, sizeDib.cy, &m_dcMem,

                            0, 0, sizeToDraw.cx, sizeToDraw.cy, SRCCOPY);

            DIB的例子在下面:

            建立工程使用的是CScrollView視圖,

                CDib m_dibFile;

                CDib m_dibResource;

            兩個成員函數(shù),分別從資源文件載入位圖和從(映射)文件載入位圖

            void CEx06dView::OnInitialUpdate()//初始化滾動條跟映射模式,載入資源視圖

            {

                CScrollView::OnInitialUpdate();

                CSize sizeTotal(30000, 40000); // 30-by-40 cm

                CSize sizeLine = CSize(sizeTotal.cx / 100, sizeTotal.cy / 100);

                SetScrollSizes(MM_HIMETRIC, sizeTotal, sizeTotal, sizeLine);

             

                LPVOID lpvResource = (LPVOID) ::LoadResource(NULL,

                    ::FindResource(NULL, MAKEINTRESOURCE(IDB_GOHAN),

                                   RT_BITMAP));

                m_dibResource.AttachMemory(lpvResource); // no need for

                                                         //  ::LockResource

                CClientDC dc(this);

                TRACE("bits per pixel = %d\n", dc.GetDeviceCaps(BITSPIXEL));

             

            }

            OnDraw函數(shù),使用了兩個dib類型,第一個用SDK,StretchDIBits繪制圖像,第二個用CDib類型繪制圖像

            void CEx06dView::OnDraw(CDC* pDC)

            {

                CEx06dDoc* pDoc = GetDocument();

                BeginWaitCursor();

                m_dibResource.UsePalette(pDC); // should be in palette

                m_dibFile.UsePalette(pDC);     //  message handlers, not here

                pDC->TextOut(0, 0,

                    "Press the left mouse button here to load a file.");

                CSize sizeResourceDib = m_dibResource.GetDimensions();

                sizeResourceDib.cx *= 30;

                sizeResourceDib.cy *= -30;

                //m_dibResource.Draw(pDC, CPoint(0, -800), sizeResourceDib);

                pDC->SetStretchBltMode(COLORONCOLOR);

                StretchDIBits(pDC->GetSafeHdc(),0,-800,sizeResourceDib.cx,sizeResourceDib.cy,0,0,sizeResourceDib.cx/30,sizeResourceDib.cy/-30,

                    m_dibResource.m_lpImage,(LPBITMAPINFO)m_dibResource.m_lpBMIH, DIB_RGB_COLORS, SRCCOPY);

                CSize sizeFileDib = m_dibFile.GetDimensions();

                sizeFileDib.cx *= 30;

                sizeFileDib.cy *= -30;

                m_dibFile.Draw(pDC, CPoint(1800, -800), sizeFileDib);

                EndWaitCursor();

             

            }

            鼠標(biāo)左鍵點擊事件,你可以使用MEMORY_MAPPED_FILES宏定義,這時候用的是內(nèi)存映射文件,否則使用的就是文件,對應(yīng)的CDib方法分別為AttachMapFile, Read..

            //#define MEMORY_MAPPED_FILES

            void CEx06dView::OnLButtonDown(UINT nFlags, CPoint point)

            {

                CFileDialog dlg(TRUE, "bmp", "*.bmp");

                if (dlg.DoModal() != IDOK) {

                    return;

                }

            #ifdef MEMORY_MAPPED_FILES

                if (m_dibFile.AttachMapFile(dlg.GetPathName(),

                        TRUE) == TRUE) { // share

                    Invalidate();

                }

             #else

                CFile file;

                file.Open(dlg.GetPathName(), CFile::modeRead);

                if (m_dibFile.Read(&file) == TRUE) {

                    Invalidate();

                }

            #endif // MEMORY_MAPPED_FILES

                CClientDC dc(this);

                m_dibFile.SetSystemPalette(&dc);

            }

            clip_image006

            對于調(diào)色板的使用我并沒有很好的掌握,之后還會看看,如果想差不多會再補上,明天加上最后一小節(jié).

            posted on 2007-12-08 18:04 Gohan 閱讀(2028) 評論(2)  編輯 收藏 引用 所屬分類: MFC/SDK

            Feedback

            # re: VC++編程內(nèi)幕學(xué)習(xí)心得(2)--下 2007-12-08 18:15 Gohan

            http://www.shnenglu.com/Files/gohan/CDIB.rar
            CDIB類下載,包括cpp文件跟頭文件  回復(fù)  更多評論   

            # re: VC++編程內(nèi)幕學(xué)習(xí)心得(2)--下 2007-12-18 21:35 秦歌

            頂一下  回復(fù)  更多評論   

            久久精品蜜芽亚洲国产AV| 国产成人精品久久一区二区三区av| 久久久久久久久66精品片| 久久精品青青草原伊人| 99久久免费国产特黄| 欧美激情精品久久久久久| 久久午夜羞羞影院免费观看| 很黄很污的网站久久mimi色| 欧美日韩精品久久免费| 久久免费线看线看| 久久人人爽人人爽人人片AV麻烦| 日韩欧美亚洲综合久久影院d3| 国产欧美久久久精品影院| 国产精品久久久久久福利漫画| 欧美亚洲国产精品久久| 国产精品日韩深夜福利久久| 久久久av波多野一区二区| 欧美精品一区二区久久| 久久久久免费精品国产| 人妻少妇久久中文字幕| 狠狠色丁香久久婷婷综合蜜芽五月 | 欧美喷潮久久久XXXXx| 国产视频久久| 色综合久久天天综合| 久久66热人妻偷产精品9| 久久久久免费精品国产| 久久强奷乱码老熟女网站| 99精品伊人久久久大香线蕉| 99久久人妻无码精品系列| 99蜜桃臀久久久欧美精品网站| 欧美激情精品久久久久久久| 精品久久久无码中文字幕天天| 久久久久一区二区三区| 久久精品国产久精国产| 2021少妇久久久久久久久久| 久久夜色精品国产噜噜噜亚洲AV| 久久久久久久女国产乱让韩| 99蜜桃臀久久久欧美精品网站| 亚洲人成无码网站久久99热国产 | 伊人 久久 精品| 亚洲国产精品综合久久网络|