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

            幽魂國(guó)度

             

            2010年3月29日

            CDC類(lèi)對(duì)象的行為函數(shù)

            (1)、常用的繪畫(huà)成員函數(shù):
                 SetPixel():用指定的顏色在指定的坐標(biāo)畫(huà)一個(gè)點(diǎn),返回值為RGB顏色值;
                                    函數(shù)原型 COLORREF SetPixel( int x, int y, COLORREF crColor );
                                                      COLORREF
            SetPixel( POINT point, COLORREF crColor );
                 MoveTo():移動(dòng)當(dāng)前位置到指定的坐標(biāo),返回值為以前位置的坐標(biāo);
                                    函數(shù)原型  CPoint MoveTo( int x, int y );
                                                      
            CPoint MoveTo( POINT point );
                 LineTo():從當(dāng)前位置到指定位置畫(huà)一條直線(xiàn),成功返回非0;
                                    函數(shù)原型  BOOL LineTo( int x, int y ); 
                                                      BOOL LineTo( POINT point );
                 Polyline():從當(dāng)前位置,繪畫(huà)多條曲線(xiàn),成功返回非0;
                                    函數(shù)原型 BOOL Polyline( LPPOINT lpPoints, int nCount/*數(shù)目*/ );
                 Rectangle():根據(jù)指定參數(shù)繪制一個(gè)矩形,成功返回非0;
                                    函數(shù)原型  BOOL Rectangle( int x1, int y1, int x2, int y2 );
                                                      B
            OOL Rectangle( LPCRECT lpRect );
                 Ellipse(): 根據(jù)指定的矩形繪制一個(gè)內(nèi)切橢圓,成功返回非0;
                                    函數(shù)原型 BOOL Ellipse( int x1, int y1, int x2, int y2 );
                                                     
            BOOL Ellipse( LPCRECT lpRect );
                 DrawIcon():在指定位置畫(huà)一個(gè)圖標(biāo),成功返回非0;
                                    函數(shù)原型 BOOL DrawIcon( int x, int y, HICON hIcon );
                                                      BOOL DrawIcon( POINT point, HICON hIcon );
            (2)、有關(guān)文本處理的常用函數(shù):
                 TextOut():在函數(shù)參數(shù)指定的位置顯示文本串。
                                    函數(shù)原型 virtual BOOL TextOut( int x, int y, LPCTSTR lpszString, int nCount );
                                                      BOOL TextOut( int x, int y, const CString& str );
                 DrawText():在函數(shù)參數(shù)指定的矩形區(qū)域內(nèi)顯示文本串。
                                    函數(shù)原型 virtual int DrawText( LPCTSTR lpszString, int nCount, LPRECT lpRect, UINT nFormat /*類(lèi)型*/);
                                                     
            int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );
                 SetTextColor():設(shè)置顯示文本的顏色,返回當(dāng)前文本RGB顏色值;
                                     函數(shù)原型 virtual COLORREF SetTextColor( COLORREF crColor );
                
            GetTextColor():獲得當(dāng)前文本顏色; 函數(shù)原型 COLORREF GetTextColor( ) const;
                 SetBkColor():設(shè)置顯示文本的背景顏色,返回當(dāng)前文本背景RGB顏色值;
                                     函數(shù)原型 virtual COLORREF SetBkColor( COLORREF crColor );
                 GetBkColor():獲得當(dāng)前文本背景顏色; 函數(shù)原型 COLORREF GetBkColor( ) const;
                 SetBkMode():設(shè)置文本的背景模式,返回當(dāng)前背景模式值;
                                     函數(shù)原型 int SetBkMode( int nBkMode /*模式*/); TRANSPARENT透明,OPAQUE 不透明  
                 GetBkMode():獲得當(dāng)前文本背景模式; 函數(shù)原型 int GetBkMode( ) const;
                
            SetTextAlign():設(shè)置顯示文本的對(duì)齊方式,成功返回非0;
                                      函數(shù)原型  UINT SetTextAlign( UINT nFlags );
                 GetTextAlign():獲得文本的對(duì)齊方式,函數(shù)原型 UINT GetTextAlign( ) const;

            posted @ 2010-03-29 22:15 峰 閱讀(869) | 評(píng)論 (1)編輯 收藏

            2010年1月21日

            如何實(shí)現(xiàn)屬性表單

            概述:創(chuàng)建一個(gè)屬性表單,首先創(chuàng)建一個(gè)CPropertySheet對(duì)象;為每一個(gè)屬性表單創(chuàng)建一個(gè)CPropertyPage對(duì)象,在CPropertySheet類(lèi)中;在CPropertySheet類(lèi)的構(gòu)造函數(shù)中添加AddPage函數(shù)添加每個(gè)屬性頁(yè);最后在菜單函數(shù)中調(diào)用DoModal函數(shù)來(lái)顯示一個(gè)靜態(tài)屬性表單。屬性頁(yè)
            是被添加屬性表單的,也就是說(shuō),屬性表單是屬性頁(yè)的父窗口。因此,可以通過(guò)GetParent()函數(shù)獲得屬性頁(yè)父窗口的指針,即屬性表單的
            指針,但要經(jīng)過(guò)類(lèi)型轉(zhuǎn)換
            步驟:
            1、創(chuàng)建一個(gè)或多個(gè)屬性頁(yè),基類(lèi)為CPropertyPage。
            class CPropSet1 : public CPropertyPage
            {
            // Dialog Data
             //{{AFX_DATA(CPropSet1)
              enum { IDD = IDD_PROP_SET1 };
              int  m_MAXVALUEX2;
              int  m_MINVALUEX2;
             //}}AFX_DATA
            }
            2、建立CProp表單:基類(lèi)為CPropertySheet。
            CPropSheet::CPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
             :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
            {
               AddPage(&m_propSet1); //決定page順序
               AddPage(&m_propSet2);
            }
            3、菜單函數(shù):
            void CDataView::OnPropsheet()
            {
             // TODO: Add your command handler code here
               CPropSheet propSheet("參數(shù)設(shè)置"); //表單名稱(chēng),其他為缺省變量
             
               propSheet.m_propSet1.m_MAXVALUEX2=m_XValueMax;
               propSheet.m_propSet1.m_MINVALUEX2=m_XValueMin;
             
             if( IDOK==propSheet.DoModal())
             {
                m_ChartCtrl1.EnableRefresh(false);
                m_XValueMax=propSheet.m_propSet1.m_MAXVALUEX2;
                m_XValueMin=propSheet.m_propSet1.m_MINVALUEX2;
                m_ChartCtrl1.GetBottomAxis()->SetMinMax(m_XValueMin,m_XValueMax);
                m_ChartCtrl1.EnableRefresh(true);
             }
            }
            4、建立向?qū)В?br>首先在調(diào)用屬性表單對(duì)象的DoModal函數(shù)之前,調(diào)用SetWizardMode函數(shù)。
                propSheet.SetWizardMode();
            然后通過(guò)SetWizardButtons函數(shù)設(shè)置向?qū)?duì)話(huà)框上的按鈕。
             ((CPropSheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);
             ((CPropSheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
             ((CPropSheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);

            注意點(diǎn):需改文字種類(lèi)和類(lèi)型。

            posted @ 2010-01-21 19:46 峰 閱讀(905) | 評(píng)論 (0)編輯 收藏

            2009年12月31日

            實(shí)現(xiàn)簡(jiǎn)單打印預(yù)覽功能

            打印預(yù)覽實(shí)現(xiàn)流程:
                 首先調(diào)用CFormView::OnFilePrintPreview,再依次調(diào)用自己的所重寫(xiě)的虛函數(shù)OnPreparePrinting(CPrintInfo* pInfo)、OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)、OnPrint(CDC* pDC, CPrintInfo* pInfo)、CFormView::OnPrint(pDC, pInfo);,當(dāng)關(guān)閉打印預(yù)覽時(shí)調(diào)用OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)  ,結(jié)束打印。
            部分代碼:
              ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
              BOOL CElectronValveView::OnPreparePrinting(CPrintInfo* pInfo)
            {
             // default preparation
              pInfo->SetMinPage(1); //設(shè)置打印文件起始頁(yè) 
              pInfo->SetMaxPage(1); //設(shè)置打印文件終止頁(yè)
              return   DoPreparePrinting(pInfo);

            void CElectronValveView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
            {
             // TODO: add extra initialization before printing
              m_ChartCtrl.GetBottomAxis()->GetGrid()->SetColor(BlackColor);//設(shè)置柵格顏色為黑色,不然打印的時(shí)候太淡
              m_ChartCtrl.GetLeftAxis()->GetGrid()->SetColor(BlackColor);
            }
            void CElectronValveView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
            {
             // TODO: add cleanup after printing
             m_ChartCtrl.GetBottomAxis()->GetGrid()->SetColor(BlueColor);//恢復(fù)顏色,不然控件中也是這個(gè)顏色了。
             m_ChartCtrl.GetLeftAxis()->GetGrid()->SetColor(BlueColor);
            }
            void CElectronValveView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
            {
             // TODO: add customized printing code here
             CMainFrame* pMain=(CMainFrame *)AfxGetApp()->m_pMainWnd 
             CDC *pCurrentDC = GetDC();        // will have dimensions of the client area
             CSize PaperPixelsPerInch(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
             //獲得打印紙?jiān)O(shè)備每英寸的像素?cái)?shù),應(yīng)該是一樣的。
                CSize ScreenPixelsPerInch(pCurrentDC->GetDeviceCaps(LOGPIXELSX), pCurrentDC->GetDeviceCaps(LOGPIXELSY));
             //應(yīng)該是獲得屏幕的每英寸的像素?cái)?shù),應(yīng)該是一樣的
             
             CSize m_PaperSize,m_LogicalPageSize;
             m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
             //把紙張所得的像素對(duì)應(yīng)的屏幕大小得到。
             m_LogicalPageSize.cx = ScreenPixelsPerInch.cx * m_PaperSize.cx / PaperPixelsPerInch.cx * 3 / 4;
             m_LogicalPageSize.cy = ScreenPixelsPerInch.cy * m_PaperSize.cy / PaperPixelsPerInch.cy * 3 / 4;
             
             //這里必須這樣設(shè),是為了和ChartCtrl中的打印對(duì)應(yīng)起來(lái)。
                pDC->SetMapMode(MM_ANISOTROPIC);
                pDC->SetWindowExt(m_LogicalPageSize);
                pDC->SetViewportExt(m_PaperSize);    
                pDC->SetWindowOrg(0, 0);   
             
             CRect rcClient,rcClient1;
             GetClientRect(&rcClient1); //得到的仍然是打印預(yù)覽顯示客戶(hù)區(qū)的大小
             rcClient=pInfo->m_rectDraw;//打印紙的客戶(hù)區(qū)
             double ratioX,ratioY;
             ratioX=(double)rcClient.right/(double)rcClient1.Width();
             ratioY=(double)rcClient.bottom/(double)rcClient1.Height();
             int nWid,left,right;
             CFont *pOldFont;
             CFont fnBig,fnBig1;
             CPen Pen,*OldPen;
             
             //畫(huà)主框
             Pen.CreatePen(PS_SOLID,2,RGB(0,0,0));
             OldPen=pDC->SelectObject(&Pen);
             pDC->Rectangle(20,20,m_LogicalPageSize.cx-20,m_LogicalPageSize.cy-20);
             pDC->SelectObject(OldPen);

             //畫(huà)標(biāo)題欄
             pDC->MoveTo(20,60);
             pDC->LineTo(m_LogicalPageSize.cx-20,60);
             pDC->MoveTo(20,85);
             pDC->LineTo(m_LogicalPageSize.cx-20,85);
             pDC->SelectObject(&Pen);
             pDC->MoveTo(20,110);
             pDC->LineTo(m_LogicalPageSize.cx-20,110);
             pDC->SelectObject(OldPen);
             pDC->MoveTo(196,60); 
             pDC->LineTo(196,110);
             pDC->MoveTo(390,60); 
             pDC->LineTo(390,110);

             //畫(huà)結(jié)果欄
             pDC->MoveTo(20,430); 
             pDC->LineTo(m_LogicalPageSize.cx-20,430);
             pDC->MoveTo(85,430); 
             pDC->LineTo(85,470);//測(cè)量結(jié)果1分界線(xiàn)豎線(xiàn)
             pDC->MoveTo((m_LogicalPageSize.cx-85-100)/4+85,430);//開(kāi)啟響應(yīng)時(shí)間分界線(xiàn) 
             pDC->LineTo((m_LogicalPageSize.cx-85-100)/4+85,470);
             pDC->MoveTo((m_LogicalPageSize.cx-85-100)/4*2+85,430); 
             pDC->LineTo((m_LogicalPageSize.cx-85-100)/4*2+85,470);
             pDC->MoveTo((m_LogicalPageSize.cx-85-100)/4*3+85,430); 
             pDC->LineTo((m_LogicalPageSize.cx-85-100)/4*3+85,470);
             pDC->MoveTo((m_LogicalPageSize.cx-85-100)/4*4+85,430); 
             pDC->LineTo((m_LogicalPageSize.cx-85-100)/4*4+85,470);
             pDC->MoveTo(20,450); 
             pDC->LineTo(m_LogicalPageSize.cx-20,450);
             pDC->SelectObject(&Pen);
             pDC->MoveTo(20,470); 
             pDC->LineTo(m_LogicalPageSize.cx-20,470); 
             pDC->SelectObject(OldPen);

              //寫(xiě)標(biāo)題
             fnBig.CreatePointFont(200,"黑體",pDC);
             pOldFont=pDC->SelectObject(&fnBig);
             
             nWid=rcClient1.Width();
             left=rcClient1.left;
             right=rcClient1.right;
             pDC->SetTextAlign(TA_CENTER);
             pDC->TextOut(m_LogicalPageSize.cx/2,30,"XXX性能測(cè)試報(bào)告");
             fnBig.DeleteObject();
             fnBig.CreatePointFont(110,"宋體",pDC);
             pOldFont=pDC->SelectObject(pOldFont);
             pOldFont=pDC->SelectObject(&fnBig);
             pDC->SetTextAlign(TA_LEFT);
             pDC->TextOut(25,67,"產(chǎn)品名稱(chēng):"+pMain->m_strProductName);
             pDC->TextOut(25,92,"產(chǎn)品圖號(hào):"+pMain->m_strProductPictureNo);
             pDC->TextOut(201,67,"檢測(cè)時(shí)間:"+pMain->m_strMeasureTime0);
             pDC->TextOut(201,92,"生產(chǎn)廠(chǎng)家:"+pMain->m_strProductFactory);
             pDC->TextOut(395,67,"產(chǎn)品編號(hào):"+pMain->m_strProductBianHao);
             pDC->TextOut(395,92,"檢 驗(yàn) 員:"+pMain->m_strMeasurerName);

             CString aa;
             aa.Format("%d(ms)",m_iPreviousTime1);
             fnBig.DeleteObject();
             fnBig.CreatePointFont(85,"宋體",pDC);
             pDC->SelectObject(&fnBig);
             pDC->TextOut(25,420,"預(yù)置電信號(hào)時(shí)間:"+aa);
             aa.Format("%d",m_iCurveNumber1);
             pDC->TextOut(150,420,"曲線(xiàn)數(shù)量:"+aa);
             fnBig1.CreatePointFont(100,"宋體",pDC);
             pOldFont=pDC->SelectObject(&fnBig1);
             pDC->TextOut(25,455,"測(cè)試結(jié)果"); 
             pDC->TextOut(90,435,"開(kāi)啟響應(yīng)時(shí)間(ms)");
             pDC->TextOut(120,455,m_strOpenResponseTime);
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4+85+5,435,"開(kāi)啟換向時(shí)間(ms)");
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4+85+5+30,455,m_strOpenInvertTime);
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4*2+85+5,435,"關(guān)閉響應(yīng)時(shí)間(ms)");
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4*2+85+5+30,455,m_strCloseResponseTime);
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4*3+85+5,435,"關(guān)閉換向時(shí)間(ms)");
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4*3+85+5+30,455,m_strCloseInvertTime); 
             pDC->TextOut((m_LogicalPageSize.cx-85-100)/4*4+85+10,435,"檢測(cè)結(jié)論");
             
             //最后一欄
             fnBig.DeleteObject();
             fnBig.CreatePointFont(130,"宋體",pDC);
             pDC->SelectObject(&fnBig);
             pDC->TextOut(m_LogicalPageSize.cx-180,m_LogicalPageSize.cy-20-20,"審核:");
             pDC->SetTextAlign(TA_LEFT);

             CPoint offset(16,110);
             m_ChartCtrl.Print1(offset,pDC,pInfo,0);//調(diào)用chart類(lèi)來(lái)畫(huà)表格和曲線(xiàn)
             fnBig.DeleteObject();

             CFormView::OnPrint(pDC, pInfo);
            }
            本程序利用ChartCtrl來(lái)實(shí)現(xiàn)繪制表格和曲線(xiàn)。

            posted @ 2009-12-31 15:26 峰 閱讀(1260) | 評(píng)論 (0)編輯 收藏

            2009年12月30日

            簡(jiǎn)述如何實(shí)現(xiàn)簡(jiǎn)單預(yù)覽

            步驟1:添加新類(lèi)CDIBStatic,類(lèi)型為MFC Class,基類(lèi)為CStatic。
            步驟2:在工程中加入CPictureObj.h和CPictureObj.cpp,及CIstream.h和CIstream.cpp。
            步驟3:在類(lèi)CDIBStatic加入頭文件#include "PictureObj.h",添加變量CPictureObj* m_pPicObj;,用于讀取和顯示。CPictureObj中封裝了IPicture接口。
            步驟4:新建一Dialog,加入控件picture,類(lèi)型為MFC Class,基類(lèi)為CfileDlg。
            部分代碼:
            CDIBStatic源代碼:
            OOL CDIBStatic::LoadDib(LPCTSTR lpszFileName)//讀取
            {
             try//利用try語(yǔ)句當(dāng)文件第一次打開(kāi)時(shí)lpszFileName會(huì)出錯(cuò),在catch中捕獲將其設(shè)置為NULL
            lpszFileName = lpszFileName;
              // 確保文件存在并能打開(kāi)
              CFile file(lpszFileName, CFile::modeRead);
              file.Close();

            // 創(chuàng)建圖像顯示的對(duì)象并讀入圖像文件
              m_pPicObj = new CPictureObj;
              if(!m_pPicObj->Load(lpszFileName))
              {
               // 讀入文件失敗,清除對(duì)象
               m_pPicObj = NULL;
               delete m_pPicObj;
               // 清除顯示的圖像并顯示錯(cuò)誤提示
               PaintDib(IsValidDib());
               return FALSE;
              }
              PaintDib(IsValidDib());
              return TRUE;
             }
             catch (CFileException* e)
             {
              m_lpszFileName = NULL;
              PaintDib(IsValidDib());
              e->Delete();
              return FALSE;
             }
            }

            void CDIBStatic::PaintDib(BOOL bDibValid)//顯示
            {
             ASSERT_VALID(this);
             ClearDib(); // 清除以前的圖像
              
             CRect PaintRect;
             // 獲得顯示區(qū)域
             GetClientRect(&PaintRect);   
             PaintRect.InflateRect(-1, -1);
             CClientDC dc(this);

             if (bDibValid && m_bPreview)
             {
              CSize size = m_pPicObj->GetSize(&dc);
              int nDestX, nDestY, nDestWidth, nDestHeight;
              if ((DWORD)size.cx < (DWORD)PaintRect.Width() && (DWORD)size.cy < (DWORD)PaintRect.Height())
              { // 圖像尺寸小于顯示區(qū)域?qū)D像顯示在中間
               nDestX = PaintRect.left + (PaintRect.Width() - size.cx)/2;
               nDestY = PaintRect.top + (PaintRect.Height() - size.cy)/2;
               nDestWidth = size.cx;
               nDestHeight = size.cy;
              }
              else
              { // 圖像尺寸大于顯示區(qū)域,進(jìn)行比例縮放
               if ((PaintRect.Width()/(float)size.cx) <= (PaintRect.Height()/(float)size.cy))
               { // 寬度限制
                nDestWidth = PaintRect.Width();
                nDestHeight = (nDestWidth*size.cy) / size.cx;
                nDestX = PaintRect.left;
                nDestY = PaintRect.top + (PaintRect.Height() - nDestHeight) /2;
               }
               else
               { // 高度限制  
                nDestHeight = PaintRect.Height();
                nDestWidth = (nDestHeight*size.cx) / size.cy;
                nDestX = PaintRect.left + (PaintRect.Width() - nDestWidth) /2;
                nDestY = PaintRect.top;
               }
              }

              // 獲得圖像的顯示位置和大小
              CRect RectDest(nDestX, nDestY, nDestX+nDestWidth, nDestY+nDestHeight);
              // 顯示圖像
              m_pPicObj->Draw(&dc,&RectDest,&RectDest);
              // 給圖像加一外框
              CBrush*  pOldBrush  = (CBrush*)dc.SelectStockObject(NULL_BRUSH);  
              dc.Rectangle(RectDest);
              if(NULL != pOldBrush)  { dc.SelectObject(pOldBrush);  }
             }
             else
             {
              // 顯示錯(cuò)誤提示信息
              CString strText = "不能識(shí)別的文件格式!";
              if( m_lpszFileName == NULL || strlen(m_lpszFileName) <= 0 )
              {
               strText = "沒(méi)有選擇文件!";
              }
              if( !m_bPreview )
              {
               strText = "";
              }
              dc.DrawText(strText, strText.GetLength(), &PaintRect, DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_END_ELLIPSIS);
             }
              
             return;
            }

            HBRUSH CDIBSatic::CtlColor(CDC* pDC, UINT nCtlColor)//用于重繪
            {
             // TODO: Change any attributes of the DC here
             PaintDib(IsValidDib());
             return (HBRUSH)GetStockObject(NULL_BRUSH);
            }
            BOOL IsValidDib() const { return (m_pPicObj && m_pPicObj->m_pPict); }
            void CDIBSatic::ClearDib()//清除圖片
            {
             ASSERT_VALID(this);
             
             CClientDC dc(this);
             CRect rectPaint;
               
             GetClientRect(&rectPaint);   
             rectPaint.InflateRect(-1,-1);
                
             CBrush* pBrushWhite; //白畫(huà)刷
             pBrushWhite = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
               
             dc.FillRect(&rectPaint, pBrushWhite);
            }
            void RemoveDib() { m_lpszFileName = NULL; delete m_pPicObj; m_pPicObj = NULL; PaintDib(IsValidDib()); }
             void SetPreview(BOOL bPreview) { m_bPreview = bPreview; PaintDib(IsValidDib()); }
            CPreviewFileDlg源代碼:
            BOOL CPreviewFileDlg::OnInitDialog()
            {
             CFileDialog::OnInitDialog();
             m_DIBStaticCtrl.SubclassDlgItem(IDC_IMAGE, this);
             CWnd* pParent = GetParent();
             CRect rcParent;
             pParent->GetClientRect(&rcParent);
             CRect rcPrev;
             GetDlgItem(IDC_PREVIEW)->GetClientRect(&rcPrev); //復(fù)選框
             CRect rc;
             m_DIBStaticCtrl.GetClientRect(&rc);
             int height = rc.Height();
             rc.top = rcPrev.bottom - 10;//圖像框設(shè)置
             rc.bottom = rc.top + height ;
             rc.left = 50;
             rc.right = rcParent.Width() - rc.left;
             m_DIBStaticCtrl.MoveWindow(&rc, true);

             GetDlgItem(IDC_PREVIEW)->SendMessage(BM_SETCHECK, (m_bPreview) ? 1 : 0);
             
             return TRUE;  // return TRUE unless you set the focus to a control
                           // EXCEPTION: OCX Property Pages should return FALSE
            }
            void CPreviewFileDlg::OnFileNameChange()
            {
             CFileDialog::OnFileNameChange();
             if (m_bPreview)
             {
              m_DIBStaticCtrl.SetPreview(m_bPreview);//顯示圖片
              m_DIBStaticCtrl.LoadDib(GetPathName()); //加載
             }

            }//當(dāng)點(diǎn)擊文件時(shí)調(diào)用
            void CPreviewFileDlg::OnFolderChange()
            {
             CFileDialog::OnFolderChange();
             m_DIBStaticCtrl.RemoveDib();//清除
            }
            菜單欄源代碼:
            void CPreviewDlg::OnPreview()
            {
             // TODO: Add extra validation here
                static char BASED_CODE szFilter[] = "Bitmap(*.bmp)|*.bmp|JPEG(*.jpg)|*.jpg|GIF(*.gif)|*.gif|WMF(*.wmf)|*.wmf|ICON(*.ico)|*.ico||";
             CString strDefName;

             char szPath[MAX_PATH];//最大目錄大小
             
                CPreviewFileDlg FileDlg(TRUE,"*.*",NULL,
                                    OFN_FILEMUSTEXIST|OFN_NONETWORKBUTTON|
                                    OFN_PATHMUSTEXIST,szFilter);
             FileDlg.m_ofn.lpstrInitialDir = szPath;
                if( FileDlg.DoModal() != IDOK )
              return;

                // To get the selected file's path and name
                CString strFileName;
                strFileName = FileDlg.GetPathName();

                if(strFileName.IsEmpty())
                {
              return;
             }
            }

            posted @ 2009-12-30 21:03 峰 閱讀(610) | 評(píng)論 (0)編輯 收藏

            2009年12月3日

            淺談malloc()和free()

             

            一、malloc()free()的基本概念以及基本用法:

            1、函數(shù)原型及說(shuō)明:

            void *malloc(long NumBytes)

            該函數(shù)分配了NumBytes個(gè)字節(jié),并返回了指向這塊內(nèi)存的指針。如果分配失敗,則返回一個(gè)空指針(NULL)。

            關(guān)于分配失敗的原因,應(yīng)該有多種,比如說(shuō)空間不足就是一種。

            void free(void *FirstByte)

            該函數(shù)是將之前用malloc分配的空間還給程序或者是操作系統(tǒng),也就是釋放了這塊內(nèi)存,讓它重新得到自由。

            2、函數(shù)的用法:

                  其實(shí)這兩個(gè)函數(shù)用起來(lái)倒不是很難,也就是malloc()之后覺(jué)得用夠了就甩了它把它給free()了,舉個(gè)簡(jiǎn)單例子:

            程序代碼:

                     // Code...

                     float *YValue;

                     YValue=(float *)malloc(DataNumberMax*sizeof(float));  //動(dòng)態(tài)分配內(nèi)存

                     if (NULL == YValue)   exit (1);

                     gets(YValue);

                     // code...

                     free(YValue);

                     YValue= NULL;

                     // code...

                 就是這樣!當(dāng)然,具體情況要具體分析以及具體解決。比如說(shuō),你定義了一個(gè)指針,在一個(gè)函數(shù)里申請(qǐng)了一塊內(nèi)存然后通過(guò)函數(shù)返回傳遞給這個(gè)指針,那么也許釋放這塊內(nèi)存這項(xiàng)工作就應(yīng)該留給其他函數(shù)了。

            3、關(guān)于函數(shù)使用需要注意的一些地方:

            A、申請(qǐng)了內(nèi)存空間后,必須檢查是否分配成功。

            B、當(dāng)不需要再使用申請(qǐng)的內(nèi)存時(shí),記得釋放;釋放后應(yīng)該把指向這塊內(nèi)存的指針指向NULL,防止程序后面不小心使用了它。

            C、這兩個(gè)函數(shù)應(yīng)該是配對(duì)。如果申請(qǐng)后不釋放就是內(nèi)存泄露;如果無(wú)故釋放那就是什么也沒(méi)有做。釋放只能一次,如果釋放兩次及兩次以上會(huì)出現(xiàn)錯(cuò)誤(釋放空指針例外,釋放空指針其實(shí)也等于啥也沒(méi)做,所以釋放空指針釋放多少次都沒(méi)有問(wèn)題)。

            D、雖然malloc()函數(shù)的類(lèi)型是(void *),任何類(lèi)型的指針都可以轉(zhuǎn)換成(void *),但是最好還是在前面進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,因?yàn)檫@樣可以躲過(guò)一些編譯器的檢查。

            二、malloc()到底從哪里得來(lái)了內(nèi)存空間:

             

            1 malloc()到底從哪里得到了內(nèi)存空間? 答案是從堆里面獲得空間。也就是說(shuō)函數(shù)返回的指針是指向堆里面的一塊內(nèi)存。操作系統(tǒng)中有一個(gè)記錄空閑內(nèi)存地址的鏈表。當(dāng)操作系統(tǒng)收到程序的申請(qǐng)時(shí),就會(huì)遍歷該鏈表,然后就尋找第一個(gè)空間大于所申請(qǐng)空間的堆結(jié)點(diǎn),然后就將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將該結(jié)點(diǎn)的空間分配給程序。就是這樣!

            2什么是堆:堆是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒(méi)有分配的空間,局部堆就是用戶(hù)分配的空間。堆在操作系統(tǒng)對(duì)進(jìn)程 初始化的時(shí)候分配,運(yùn)行過(guò)程中也可以向系統(tǒng)要額外的堆,但是記得用完了要還給操作系統(tǒng),要不然就是內(nèi)存泄漏。

                什么是棧:棧是線(xiàn)程獨(dú)有的,保存其運(yùn)行狀態(tài)和局部自動(dòng)變量的。棧在線(xiàn)程開(kāi)始的時(shí)候初始化,每個(gè)線(xiàn)程的棧互相獨(dú)立。每個(gè)函數(shù)都有自己的棧,棧被用來(lái)在函數(shù)之間傳遞參數(shù)。操作系統(tǒng)在切換線(xiàn)程的時(shí)候會(huì)自動(dòng)的切換棧,就是切換SS/ESP寄存器。棧空間不需要在高級(jí)語(yǔ)言里面顯式的分配和釋放。

                通過(guò)上面對(duì)概念的描述,可以知道:

                棧是由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量的值等。操作方式類(lèi)似于數(shù)據(jù)結(jié)構(gòu)中的棧。

                堆一般由程序員分配釋放,若不釋放,程序結(jié)束時(shí)可能由OS回收。注意這里說(shuō)是可能,并非一定。所以我想再?gòu)?qiáng)調(diào)一次,記得要釋放!

            所以,舉個(gè)例子,如果你在函數(shù)上面定義了一個(gè)指針變量,然后在這個(gè)函數(shù)里申請(qǐng)了一塊內(nèi)存讓指針指向它。實(shí)際上,這個(gè)指針的地址是在棧上,但是它所指向的內(nèi)容卻是在堆上面的!這一點(diǎn)要注意!所以,再想想,在一個(gè)函數(shù)里申請(qǐng)了空間后,比如說(shuō)下面這個(gè)函數(shù):

            程序代碼:

                // code...

                    void Function(void)

                    {

                     char *p = (char *)malloc(100 * sizeof(char));

                 }

                就這個(gè)例子,千萬(wàn)不要認(rèn)為函數(shù)返回,函數(shù)所在的棧被銷(xiāo)毀指針也跟著銷(xiāo)毀,申請(qǐng)的內(nèi)存也就一樣跟著銷(xiāo)毀了!這絕對(duì)是錯(cuò)誤的!因?yàn)?strong>申請(qǐng)的內(nèi)存在堆上,而函數(shù)所在的棧被銷(xiāo)毀跟堆完全沒(méi)有啥關(guān)系。所以,還是那句話(huà):記得釋放!

             

            3free()到底釋放了什么

                free()釋放的是指針指向的內(nèi)存!注意!釋放的是內(nèi)存,不是指針!這點(diǎn)非常非常重要!指針是一個(gè)變量,只有程序結(jié)束時(shí)才被銷(xiāo)毀。釋放了內(nèi)存空間后,原來(lái)指向這塊空間的指針還是存在!只不過(guò)現(xiàn)在指針指向的內(nèi)容的垃圾,是未定義的,所以說(shuō)是垃圾。因此,前面我已經(jīng)說(shuō)過(guò)了,釋放內(nèi)存后把指針指向NULL,防止指針在后面不小心又被解引用了。非常重要啊這一點(diǎn)!

             

            三、malloc()以及free()的機(jī)制:

                事實(shí)上,仔細(xì)看一下free()的函數(shù)原型,也許也會(huì)發(fā)現(xiàn)似乎很神奇,free()函數(shù)非常簡(jiǎn)單,只有一個(gè)參數(shù),只要把指向申請(qǐng)空間的指針傳遞

             

            free()中的參數(shù)就可以完成釋放工作!這里要追蹤到malloc()的申請(qǐng)問(wèn)題了。申請(qǐng)的時(shí)候?qū)嶋H上占用的內(nèi)存要比申請(qǐng)的大。因?yàn)槌龅目臻g是用來(lái)記錄對(duì)這塊內(nèi)存的管理信息。

            malloc()申請(qǐng)的空間實(shí)際我覺(jué)得就是分了兩個(gè)不同性質(zhì)的空間。一個(gè)就是用來(lái)記錄管理信息的空間,另外一個(gè)就是可用空間了。而用來(lái)記錄管理信息的實(shí)際上是一個(gè)結(jié)構(gòu)體。在C語(yǔ)言中,用結(jié)構(gòu)體來(lái)記錄同一個(gè)對(duì)象的不同信息是

            下面看看這個(gè)結(jié)構(gòu)體的原型:

            程序代碼:

                struct mem_control_block {

                 int is_available;     //這是一個(gè)標(biāo)記?

                 int size;             //這是實(shí)際空間的大小

                 };

                對(duì)于size,這個(gè)是實(shí)際空間大小。這里其實(shí)我有個(gè)疑問(wèn),is_available是否是一個(gè)標(biāo)記?因?yàn)槲铱戳?/span>free()的源代碼之后對(duì)這個(gè)變量感覺(jué)有點(diǎn)納悶(源代碼在下面分析)。這里還請(qǐng)大家指出!

                所以,free()就是根據(jù)這個(gè)結(jié)構(gòu)體的信息來(lái)釋放malloc()申請(qǐng)的空間!而結(jié)構(gòu)體的兩個(gè)成員的大小我想應(yīng)該是操作系統(tǒng)的事了。但是這里有一個(gè)問(wèn)題,malloc()申請(qǐng)空間后返回一個(gè)指針應(yīng)該是指向第二種空間,也就是可用空間!不然,如果指向管理信息空間的話(huà),寫(xiě)入的內(nèi)容和結(jié)構(gòu)體的類(lèi)型有可能不一致,或者會(huì)把管理信息屏蔽掉,那就沒(méi)法釋放內(nèi)存空間了,所以會(huì)發(fā)生錯(cuò)誤!(感覺(jué)自己這里說(shuō)的是廢話(huà))

             

                好了!下面看看free()的源代碼,我自己分析了一下,覺(jué)得比起malloc()的源代碼倒是容易簡(jiǎn)單很多。只是有個(gè)疑問(wèn),下面指出!

            程序代碼:

                // code...

               

                    void free(void *ptr) 

                 {

                         struct mem_control_block *free;

                         free = ptr - sizeof(struct mem_control_block);

                         free->is_available = 1;

                         return;

                 }

                看一下函數(shù)第二句,這句非常重要和關(guān)鍵。其實(shí)這句就是把指向可用空間的指針倒回去,讓它指向管理信息的那塊空間,因?yàn)檫@里是在值上減去了一個(gè)結(jié)構(gòu)體的大小!后面那一句free->is_available = 1;我有點(diǎn)納悶!我的想法是:這里is_available應(yīng)該只是一個(gè)標(biāo)記而已!因?yàn)閺倪@個(gè)變量的名稱(chēng)上來(lái)看,is_available 翻譯過(guò)來(lái)就是“是可以用”。不要說(shuō)我土!我覺(jué)得變量名字可以反映一個(gè)變量的作用,特別是嚴(yán)謹(jǐn)?shù)拇a。這是源代碼,所以我覺(jué)得絕對(duì)是嚴(yán)謹(jǐn)?shù)模。∵@個(gè)變量的值是1,表明是可以用的空間!只是這里我想了想,如果把它改為0或者是其他值不知道會(huì)發(fā)生什么事?!但是有一點(diǎn)我可以肯定,就是釋放絕對(duì)不會(huì)那么順利進(jìn)行!因?yàn)檫@是一個(gè)標(biāo)記!

             

                當(dāng)然,這里可能還是有人會(huì)有疑問(wèn),為什么這樣就可以釋放呢??我剛才也有這個(gè)疑問(wèn)。后來(lái)我想到,釋放是操作系統(tǒng)的事,那么就free()這個(gè)源代碼來(lái)看,什么也沒(méi)有釋放,對(duì)吧?但是它確實(shí)是確定了管理信息的那塊內(nèi)存的內(nèi)容。所以,free()只是記錄了一些信息,然后告訴操作系統(tǒng)那塊內(nèi)存可以去釋放,具體怎么告訴操作系統(tǒng)的我不清楚,但我覺(jué)得這個(gè)已經(jīng)超出了我這篇文章的討論范圍了。

             

                那么,我之前有個(gè)錯(cuò)誤的認(rèn)識(shí),就是認(rèn)為指向那塊內(nèi)存的指針不管移到那塊內(nèi)存中的哪個(gè)位置都可以釋放那塊內(nèi)存!但是,這是大錯(cuò)特錯(cuò)!釋放是不可以釋放一部分的!首先這點(diǎn)應(yīng)該要明白。而且,從 free()的源代碼看,ptr只能指向可用空間的首地址,不然,減去結(jié)構(gòu)體大小之后一定不是指向管理信息空間的首地址。所以,要確保指針指向可用空間的首地址!
            程序代碼:
            float *YValuePoint;
            while ( !feof(file) && i<DataNumberMax)  //讀數(shù)
              {
               fscanf(file,"%f ",&data);      
               YValue[i]=data;
               sum+=YValue[i];
               pLineSerie->AddPoint(XValue++,YValue[i]);
               i++;
              }
              average=sum/DataNumberMax;
              max=*YValue;
              min=*(YValue+2);
             YValuePoint=YValue; //保存首地址
              for(int j=0;j<DataNumberMax;j++)
              {
                  if(max <* YValue)
               {
                    max =* YValue;
               }
               else
               {
                if(min > *YValue)  min = *YValue;
               }
               YValue++;              //YValue地址值+1
              }

              free(YValuePoint);  //釋放內(nèi)存,釋放從該內(nèi)存空間的首地址開(kāi)始

            posted @ 2009-12-03 11:50 峰 閱讀(403) | 評(píng)論 (0)編輯 收藏

            2009年11月28日

            鉤子

                 摘要: HHOOK SetWindowsHookEx(                                    //裝載一個(gè)...  閱讀全文

            posted @ 2009-11-28 16:01 峰 閱讀(1429) | 評(píng)論 (0)編輯 收藏

            2009年11月22日

            指針的指針

            指向另一指針的指針:轉(zhuǎn)自風(fēng)過(guò)無(wú)痕博客
             

            一. 回顧指針概念:
            早在本系列第二篇中我就對(duì)指針的實(shí)質(zhì)進(jìn)行了闡述。今天我們又要學(xué)習(xí)一個(gè)叫做指向另一指針地址的指針。讓我們先回顧一下指針的概念吧!
            當(dāng)我們程序如下申明變量:
            short int i;
            char a;
            short int * pi;
            程序會(huì)在內(nèi)存某地址空間上為各變量開(kāi)辟空間,如下圖所示。
            內(nèi)存地址→6     7      8     9     10     11    12    13     14    15
            -------------------------------------------------------------------------------------
            …  |     |      |      |      |      |       |      |      |      |  
            -------------------------------------------------------------------------------------
                |short int i |char a|      |short int * pi|
            圖中所示中可看出:
            i 變量在內(nèi)存地址5的位置,占兩個(gè)字節(jié)。
            a變量在內(nèi)存地址7的位置,占一個(gè)字節(jié)。
            pi變量在內(nèi)存地址9的位置,占兩個(gè)字節(jié)。(注:pi 是指針,我這里指針的寬度只有兩個(gè)字節(jié),32位系統(tǒng)是四個(gè)字節(jié))
            接下來(lái)如下賦值:
            i=50;
            pi=&i;
            經(jīng)過(guò)上在兩句的賦值,變量的內(nèi)存映象如下:
            內(nèi)存地址→6     7      8     9     10     11    12    13      14     15
            --------------------------------------------------------------------------------------
            …  |    50      |      |      |    6         |      |      |       |  
            --------------------------------------------------------------------------------------
                |short int i |char a|      |short int * pi|
            看到?jīng)]有:短整型指針變量pi的值為6,它就是I變量的內(nèi)存起始地址。所以,這時(shí)當(dāng)我們對(duì)*pi進(jìn)行讀寫(xiě)操作時(shí),其實(shí)就是對(duì)i變量的讀寫(xiě)操作。如:
            *pi=5;   //就是等價(jià)于I=5;

            二. 指針的地址與指向另一指針地址的指針
            在上一節(jié)中,我們看到,指針變量本身與其它變量一樣也是在某個(gè)內(nèi)存地址中的,如pi的內(nèi)存起始地址是10。同樣的,我們也可能讓某個(gè)指針指向這個(gè)地址。
            看下面代碼:
            short int * * ppi;    //這是一個(gè)指向指針的指針,注意有兩個(gè)*號(hào)
            ppi=pi
            第一句:short int * * ppi;——申明了一個(gè)指針變量ppi,這個(gè)ppi是用來(lái)存儲(chǔ)(或稱(chēng)指向)一個(gè)short int * 類(lèi)型指針變量的地址。
            第二句:&pi那就是取pi的地址,ppi=pi就是把pi的地址賦給了ppi。即將地址值10賦值給ppi。如下圖:
            內(nèi)存地址→6     7      8     9     10     11    12    13       14    15
            ------------------------------------------------------------------------------------
            …  |    50     |      |      |      6       |       10      |      |  
            ------------------------------------------------------------------------------------
                |short int i|char a|      |short int * pi|short int ** ppi|
            從圖中看出,指針變量ppi的內(nèi)容就是指針變量pi的起始地址。于是……
            ppi的值是多少呢?——10。
            *ppi的值是多少呢?——6,即pi的值。
            **ppi的值是多少呢?——50,即I的值,也是*pi的值。
            呵呵!不用我說(shuō)太多了,我相信你應(yīng)明白這種指針了吧!

            三. 一個(gè)應(yīng)用實(shí)例
            1. 設(shè)計(jì)一個(gè)函數(shù):void find1(char array[], char search, char * pi)
            要求:這個(gè)函數(shù)參數(shù)中的數(shù)組array是以0值為結(jié)束的字符串,要求在字符串a(chǎn)rray中查找字符是參數(shù)search里的字符。如果找到,函數(shù)通過(guò)第三個(gè)參數(shù)(pa)返回值為array字符串中第一個(gè)找到的字符的地址。如果沒(méi)找到,則為pa為0。
            設(shè)計(jì):依題意,實(shí)現(xiàn)代碼如下。
            void find1(char array[] , char search, char * pa)
            {
               int i;
               for (i=0;*(array+i)!=0;i++)
               {
                  if (*(array+i)==search)
                  {
                    pa=array+i
                    break;
                  }
                  else if (*(array+i)==0)
                  {
                    pa=0;
                    break;
                  }
               }
            }
            你覺(jué)得這個(gè)函數(shù)能實(shí)現(xiàn)所要求的功能嗎?
            調(diào)試:
            我下面調(diào)用這個(gè)函數(shù)試試。
            void main()
            {
              char str[]={“afsdfsdfdf\0”};  //待查找的字符串
              char a=’d’;   //設(shè)置要查找的字符
              char * p=0;  //如果查找到后指針p將指向字符串中查找到的第一個(gè)字符的地址。
              find1(str,a,p);  //調(diào)用函數(shù)以實(shí)現(xiàn)所要操作。
              if (0==p )
              {
                 printf (“沒(méi)找到!\n”);//1.如果沒(méi)找到則輸出此句
              }
              else
              {
                 printf(“找到了,p=%d”,p);  //如果找到則輸出此句
              }
            }
            分析:
            上面代碼,你認(rèn)為會(huì)是輸出什么呢?
            運(yùn)行試試。
            唉!怎么輸出的是:沒(méi)有找到!
            而不是:找到了,……。
            明明a值為’d’,而str字符串的第四個(gè)字符是’d’,應(yīng)該找得到呀!
            再看函數(shù)定義處:void find1(char array[] , char search, char * pa)
            看調(diào)用處:find1(str,a,p);
            依我在第五篇的分析方法,函數(shù)調(diào)用時(shí)會(huì)對(duì)每一個(gè)參數(shù)進(jìn)行一個(gè)隱含的賦值操作。
            整個(gè)調(diào)用如下:
               array=str;
               search=a;
               pa=p;    //請(qǐng)注意:以上三句是調(diào)用時(shí)隱含的動(dòng)作。
               int i;
               for (i=0;*(array+i)!=0;i++)
               {
                  if (*(array+i)==search)
                  {
                    pa=array+i
                    break;
                  }
                  else if (*(array+i)==0)
                  {
                    pa=0;
                    break;
                  }
               }
            哦!參數(shù)pa與參數(shù)search的傳遞并沒(méi)有什么不同,都是值傳遞嘛(小語(yǔ):地址傳遞其實(shí)就是地址值傳遞嘛)!所以對(duì)形參變量pa值(當(dāng)然值是一個(gè)地址值)的修改并不會(huì)改變實(shí)參變量p值,因此p的值并沒(méi)有改變(即p的指向并沒(méi)有被改變)。
            (如果還有疑問(wèn),再看一看《函數(shù)參數(shù)的傳遞》了。)
            修正:
            void find2(char [] array, char search, char ** ppa)
            {
               int i;
               for (i=0;*(array+i)!=0;i++)
               {
                  if (*(array+i)==search)
                  {
                    *ppa=array+i
                    break;
                  }
                  else if (*(array+i)==0)
                  {
                    *ppa=0;
                    break;
                  }
               }
            }
            主函數(shù)的調(diào)用處改如下:
              find2(str,a,&p);  //調(diào)用函數(shù)以實(shí)現(xiàn)所要操作。
            再分析:
            這樣調(diào)用函數(shù)時(shí)的整個(gè)操作變成如下:
               array=str;
               search=a;
               ppa=&p;    //請(qǐng)注意:以上三句是調(diào)用時(shí)隱含的動(dòng)作。
               int i;
               for (i=0;*(array+i)!=0;i++)
               {
                  if (*(array+i)==search)
                  {
                    *ppa=array+i
                    break;
                  }
                  else if (*(array+i)==0)
                  {
                    *ppa=0;
                    break;
                  }
               }
            看明白了嗎?
            ppa指向指針p的地址。
            對(duì)*ppa的修改就是對(duì)p值的修改。
            下面看一下指向指針變量的指針變量怎樣正確引用。
            用指向指針的指針變量訪(fǎng)問(wèn)一維和二維數(shù)組。

            #include<stdio.h>
            #include<stdlib.h>
            main()
            {
            int a[3],b[2][2],*p1,*p2,**p3,i,j;

            printf("請(qǐng)輸入一維數(shù)組的值:\n");
            for(i=0;i<3;i++)
            scanf("%d",&a[i]);/*一維數(shù)組的輸入*/

            printf("請(qǐng)輸入二維數(shù)組的值:\n");
            for(i=0;i<2;i++)
            for(j=0;j<2;j++)
            scanf("%d",&b[i][j]);/*二維數(shù)組輸入*/

            printf("用指針輸出一維數(shù)組:\n");
            for(p1=a,i=0;i<3;i++)     /* 用指針輸出一維數(shù)組*/
            {
                printf("%4d",*(p1+i));
            }
            printf("\n");

            printf("用指向指針的指針變量輸出一維數(shù)組(1):\n");
            for(p1=a,p3=&p1,i=0;i<3;i++)
            printf("%4d",*(*p3+i));/*用指向指針的指針變量輸出一維數(shù)組*/
            printf("\n");
            printf("用指向指針的指針變量輸出一維數(shù)組(2):\n");
            for(p1=a;p1-a<3;p1++)/*用指向指針的指針變量輸出一維數(shù)組*/
            {
            p3=&p1;
            printf("%4d",**p3);
            }
            printf("\n");

            printf("用指針輸出二維數(shù)組:\n");
            for(i=0;i<2;i++)   /*用指針輸出二維數(shù)組*/
            {
               p2=b[i] ;
               for(int j=0;j<2;j++)
              {
                printf("%4d",*(p2+j)) ;
              }
            }
            printf("\n");

            printf("用指向指針的指針變量輸出二維數(shù)組(1):\n");
            for(i=0;i<2;i++)/*用指向指針的指針變量輸出二維數(shù)組*/
            {
            p2=b[i];
            p3=&p2;
            for(j=0;j<2;j++)
            printf("%4d",*(*p3+j));

            利用指向指針的指針變量對(duì)二維字符數(shù)組的訪(fǎng)問(wèn)。

            #include<stdio.h>
            #include<stdlib.h>
            main()
            {
            int i;
            char * ptr;
            static char c[][16]={"clanguage","fox","computer","homepage"};
            /*二維字符數(shù)組*/
            static char *cp[]={c[0],c[1],c[2],c[3]};/*指針數(shù)組*/
            static char **cpp;/*指向字符指針的指針變量*/
            cpp=cp;/*將指針數(shù)組的首地址傳遞給指向字符指針的指針變量*/


            for(i=0;i<4;i++)/*按行輸出字符串*/
            printf("%s\n",*cpp++);
            printf("-----------\n");

            for(i=0;i<4;i++)/*按行輸出字符串*/
            {
            cpp=&cp[i];
            printf("%s\n",*cpp);
            }
            printf("-----------\n");

             
             for(i=0;i<4;i++)
             {
                ptr=c[i];
                printf("%s",ptr);
                printf("\n");
             }
             

            }

            }
            printf("\n");

             printf("用指向指針的指針變量輸出二維數(shù)組(2):\n");
            for(i=0;i<2;i++)/*用指向指針的指針變量輸出二維數(shù)組*/
            {
            p2=b[i];
            for(p2=b[i];p2-b[i]<2;p2++)
            {
            p3=&p2;
            printf("%4d",**p3);
            }
            printf("\n");
            }

            }

            posted @ 2009-11-22 22:31 峰 閱讀(356) | 評(píng)論 (0)編輯 收藏

            2009年11月21日

            C++中的接口與實(shí)現(xiàn)

                    所謂接口繼承,就是派生類(lèi)只繼承函數(shù)的接口,也就是聲明;而實(shí)現(xiàn)繼承,就是派生類(lèi)同時(shí)繼承函數(shù)的接口和實(shí)現(xiàn)。
                   我們都很清楚C++中有幾個(gè)基本的概念,虛函數(shù)、純虛函數(shù)、非虛函數(shù)。
                   虛函數(shù)
                   C++實(shí)現(xiàn)運(yùn)行中的多態(tài)性是通過(guò)虛函數(shù)實(shí)現(xiàn)的,而虛函數(shù)必須存在于繼承環(huán)境下。
                   因此,虛函數(shù)是指一個(gè)類(lèi)中你希望進(jìn)行重載的成員函數(shù),當(dāng)你用一個(gè)基類(lèi)指針或引用指向一個(gè)繼承類(lèi)對(duì)象的時(shí)候,你調(diào)用一個(gè)虛函數(shù),實(shí)際調(diào)用的是繼承類(lèi)的成員函數(shù)。虛函數(shù)用來(lái)表現(xiàn)基類(lèi)和派生類(lèi)的成員函數(shù)之間的一種關(guān)系。虛函數(shù)的定義在基類(lèi)中進(jìn)行,在需要定義為虛函數(shù)的成員函數(shù)的聲明前冠以關(guān)鍵字,如 virtual void func() 。 基類(lèi)中的某個(gè)成員函數(shù)被聲明為虛函數(shù)后,此虛函數(shù)就可以在一個(gè)或多個(gè)派生類(lèi)中被重新定義. 在派生類(lèi)中重新定義時(shí),其函數(shù)原型,包括返回類(lèi)型、函數(shù)名、參數(shù)個(gè)數(shù)、參數(shù)類(lèi)型及參數(shù)的先后順序,都必須與基類(lèi)中的原型完全相同。
                    虛函數(shù)是重載的一種表現(xiàn)形式,是一種動(dòng)態(tài)的重載方式。
                   只有類(lèi)的普通成員函數(shù)可以定義為虛函數(shù),全局函數(shù)及靜態(tài)成員函數(shù)(類(lèi)擁有)不能聲明為虛函數(shù)。
                   純虛函數(shù):
                    純虛函數(shù)在基類(lèi)中沒(méi)有定義且只能在基類(lèi)中定義,但未給出具體的函數(shù)定義體(實(shí)現(xiàn)),它們被初始化為0。任何用純虛函數(shù)派生的類(lèi),都要自己提供該函數(shù)的具體實(shí)現(xiàn)。
                     定義純虛函數(shù):virtual void func() = 0;
                     定義了純虛函數(shù)的類(lèi)被稱(chēng)之為抽象類(lèi)。抽象類(lèi)定義一族派生類(lèi)的共同接口,而接口的完整實(shí)現(xiàn),即純虛函數(shù)的函數(shù)體,由派生類(lèi)自己定義。
            例://class Shape
                   public:
                             virtual void area()=0; // 純虛函數(shù)
                    //class Tringle : public Shape  //公有繼承
                   public:
                            void area() {//}                /接口與實(shí)現(xiàn)
                     抽象類(lèi)可以有多個(gè)純虛函數(shù),也可以定義其他虛函數(shù)。若派生類(lèi)沒(méi)有重新定義純虛函數(shù),那么該派生類(lèi)也稱(chēng)之為純虛函數(shù)。
                     純虛函不需要定義其實(shí)際操作,它的存在只是為了在派生類(lèi)中被重新定義,只是提供一個(gè)多態(tài)接口
                   非虛函數(shù)
                   一般成員函數(shù),無(wú)virtual關(guān)鍵字修飾。
                    至于為什么要定義這些函數(shù),我們可以將虛函數(shù)、純虛函數(shù)和非虛函數(shù)的功能與接口繼承實(shí)現(xiàn)繼承聯(lián)系起來(lái):
                     如前所述,聲明一個(gè)純虛函數(shù)(pure virtual)的目的是為了讓派生類(lèi)只繼承函數(shù)接口,也就是上面說(shuō)的接口繼承。
                    純虛函數(shù)一般是在不方便具體實(shí)現(xiàn)此函數(shù)的情況下使用。也就是說(shuō)基類(lèi)無(wú)法為繼承類(lèi)規(guī)定一個(gè)統(tǒng)一的缺省操作,但繼承類(lèi)又必須含有這個(gè)函數(shù)接口,并對(duì)其分別實(shí)現(xiàn)。但是,在C++中,我們是可以為純虛函數(shù)提供定義的,只不過(guò)這種定義對(duì)繼承類(lèi)來(lái)說(shuō)沒(méi)有特定的意義。因?yàn)槔^承類(lèi)仍然要根據(jù)各自需要實(shí)現(xiàn)函數(shù)。
                    通俗說(shuō),純虛函數(shù)就是要求其繼承類(lèi)必須含有該函數(shù)接口,并對(duì)其進(jìn)行實(shí)現(xiàn)。是對(duì)繼承類(lèi)的一種接口實(shí)現(xiàn)要求,但并不提供缺省操作,各個(gè)繼承類(lèi)必須分別實(shí)現(xiàn)自己的操作。
                    聲明非純虛函數(shù)(impure virtual)的目的是讓繼承類(lèi)繼承該函數(shù)的接口和缺省實(shí)現(xiàn)。
                    與純虛函數(shù)唯一的不同就是其為繼承類(lèi)提供了缺省操作,繼承類(lèi)可以不實(shí)現(xiàn)自己的操作而采用基類(lèi)提供的默認(rèn)操作。
                    聲明非虛函數(shù)(non-virtual)的目的是為了令繼承類(lèi)繼承函數(shù)接口及一份強(qiáng)制性實(shí)現(xiàn)。
                    相對(duì)于虛函數(shù)來(lái)說(shuō),非虛函數(shù)對(duì)繼承類(lèi)要求的更為嚴(yán)格,繼承類(lèi)不僅要繼承函數(shù)接口,而且也要繼承函數(shù)實(shí)現(xiàn)。也就是為繼承類(lèi)定義了一種行為。
             總結(jié)
                    純虛函數(shù):要求繼承類(lèi)必須含有某個(gè)接口,并對(duì)接口函數(shù)實(shí)現(xiàn)。
                    虛函數(shù):繼承類(lèi)必須含有某個(gè)接口,可以自己實(shí)現(xiàn),也可以不實(shí)現(xiàn),而采用基類(lèi)定義的缺省實(shí)現(xiàn)。
                    非虛函數(shù):繼承類(lèi)必須含有某個(gè)接口,必須使用基類(lèi)的實(shí)現(xiàn)。
                     一個(gè)C++類(lèi)有著兩個(gè)重要的方面:用于描述行為的公共接口,以及行為的私有實(shí)現(xiàn)。
                   大多數(shù)的繼承都是公有繼承:派生類(lèi)繼承了基類(lèi)的接口和實(shí)現(xiàn)。不過(guò),我們也可以進(jìn)行有選擇的繼承,即派生類(lèi)可以只繼承接口或?qū)崿F(xiàn)。私有基類(lèi),只繼承實(shí)實(shí)現(xiàn),沒(méi)有接口;公有繼承基類(lèi),繼承接口,但繼承的實(shí)現(xiàn)可能是不完整的或不存在的(純虛函數(shù))。
             例:
            我們可以用函數(shù):
             Triangle t;
             t.area();
            我們只是使用了其接口,但具體的實(shí)現(xiàn)可以不知道。void area() {......}

            posted @ 2009-11-21 20:20 峰 閱讀(1650) | 評(píng)論 (0)編輯 收藏

            繼承簡(jiǎn)介

                通過(guò)繼承機(jī)制,可以利用已有的數(shù)據(jù)類(lèi)型來(lái)定義新的數(shù)據(jù)類(lèi)型。所定義的新的數(shù)據(jù)類(lèi)型不僅擁有新定義的成員,而且還同時(shí)擁有舊的成員。我們稱(chēng)已存在的用來(lái)派生新類(lèi)的類(lèi)為基類(lèi),又稱(chēng)為父類(lèi)。由已存在的類(lèi)派生出的新類(lèi)稱(chēng)為派生類(lèi),又稱(chēng)為子類(lèi)。
                在C++語(yǔ)言中,一個(gè)派生類(lèi)可以從一個(gè)基類(lèi)派生,也可以從多個(gè)基類(lèi)派生。從一個(gè)基類(lèi)派生的繼承稱(chēng)為單繼承;從多個(gè)基類(lèi)派生的繼承稱(chēng)為多繼承。
            例:

            #include <iostream.h>
            class Metal
            {
            public:
             unsigned atomicNumber;
             float atomicWeight;
             float pricePerounce;
            public:
             Metal( unsigned Number=0,
                     float Weight=0.000000,
                     float Perounce=0.000000)
             {
             atomicNumber=Number;
             atomicWeight=Weight;
             pricePerounce=Perounce;
             }
             ~Metal() {}
                unsigned GetNumber(void) {return atomicNumber;}  //內(nèi)聯(lián)函數(shù)
                float GetWeight(void) {return atomicWeight;}
                float Getprice(void) {return pricePerounce;}
             virtual void output()
             {
              cout << "The atomic weight =" << atomicWeight << endl;
              cout << "The atomic number =" << atomicNumber << endl;
              cout << "Price per ounce =" << pricePerounce << endl;
             }
            };

            class Pb : public Metal  //公有繼承,單繼承
            {
            public:
             Pb (unsigned Number=82,float Weight=207,float Perounce=0.01):Metal(Number,Weight,Perounce) {}
             //子類(lèi)構(gòu)造首先調(diào)用基類(lèi)構(gòu)造函數(shù)
            };

            class Au : public Metal
            {
            public:
             Au (unsigned Number=79,float Weight=196.9665,float Perounce=450.75):Metal(Number,Weight,Perounce) {}
             Au (Pb& lemp)  //拷貝函數(shù)
             {
                   atomicNumber=lemp.GetNumber()-3;
                   atomicWeight=lemp.GetWeight()-10.2335;
                   pricePerounce=lemp.Getprice()+450.74;
             }
            };

            void main ()
            {
                Pb m;
             Au n=m;     //拷貝
             n.output();
            }

            注:

              派生類(lèi)的三種繼承方式:公有繼承(public)、私有繼承(private)、保護(hù)繼承(protected)是常用的三種繼承方式:
                    公有繼承時(shí),水平訪(fǎng)問(wèn)和垂直訪(fǎng)問(wèn)對(duì)基類(lèi)中的公有成員不受限制;
                    私有繼承時(shí),水平訪(fǎng)問(wèn)和垂直訪(fǎng)問(wèn)對(duì)基類(lèi)中的公有成員也不能訪(fǎng)問(wèn);
                    保護(hù)繼承時(shí),對(duì)于垂直訪(fǎng)問(wèn)同于公有繼承,對(duì)于水平訪(fǎng)問(wèn)同于私有繼承。
                    對(duì)于基類(lèi)中的私有成員,只能被基類(lèi)中的成員函數(shù)和友元函數(shù)所訪(fǎng)問(wèn),不能被其他的函數(shù)訪(fǎng)問(wèn)。
                    如果通過(guò)公有繼承來(lái)產(chǎn)生基類(lèi),那么這個(gè)派生類(lèi)應(yīng)該是其基類(lèi)的特化。
                    如果派生類(lèi)之間的區(qū)別在于屬性,則用數(shù)據(jù)成員來(lái)表示;如果在于行為,則用虛函數(shù)來(lái)表示。

               任何一個(gè)類(lèi)都可以派生出一個(gè)新類(lèi),派生類(lèi)也可以再派生出新類(lèi)。

             

            posted @ 2009-11-21 10:58 峰 閱讀(298) | 評(píng)論 (0)編輯 收藏

            2009年11月19日

            如何設(shè)置按鈕控件點(diǎn)擊彈出新菜單欄

            函數(shù)介紹:CButtonST應(yīng)用
            DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bRepaint)
            {
             
            HINSTANCE hInstResource = NULL;

             // Destroy any previous menu
             if (m_hMenu)
             {
                     ::DestroyMenu(m_hMenu);
                     m_hMenu = NULL;
                     m_hParentWndMenu = NULL;
                     m_bMenuDisplayed = FALSE;
             } // if

             // Load menu
             if (nMenu)
             {
              // Find correct resource handle
              hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nMenu), RT_MENU);
              // Load menu resource
              m_hMenu = ::LoadMenu(hInstResource, MAKEINTRESOURCE(nMenu));
              m_hParentWndMenu = hParentWnd;
              // If something wrong
              if (m_hMenu == NULL) return BTNST_INVALIDRESOURCE;
             } // if

             // Repaint the button
                 if (bRepaint)  Invalidate();

                 return BTNST_OK;
            } // End of SetMenu

            DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bWinXPStyle, UINT nToolbarID, CSize sizeToolbarIcon, COLORREF crToolbarBk, BOOL bRepaint)    //除前兩個(gè)參數(shù),其他參數(shù)都有初始值
            {
             BOOL bRetValue = FALSE;

             // Destroy any previous menu
             if (m_menuPopup.m_hMenu)
             {
                m_menuPopup.DestroyMenu();
                m_hParentWndMenu = NULL;
                m_bMenuDisplayed = FALSE;
             } // if

             // Load menu
             if (nMenu)
             {
                 m_menuPopup.SetMenuDrawMode(bWinXPStyle);
              // Load menu
                 bRetValue = m_menuPopup.LoadMenu(nMenu);
              // If something wrong
              if (bRetValue == FALSE) return BTNST_INVALIDRESOURCE;

              // Load toolbar
              if (nToolbarID)
              {
               m_menuPopup.SetBitmapBackground(crToolbarBk);
               m_menuPopup.SetIconSize(sizeToolbarIcon.cx, sizeToolbarIcon.cy);

               bRetValue = m_menuPopup.LoadToolbar(nToolbarID);
               // If something wrong
               if (bRetValue == FALSE)
               {
                m_menuPopup.DestroyMenu();
                return BTNST_INVALIDRESOURCE;
               } // if
              } // if

              m_hParentWndMenu = hParentWnd;
             } // if

             // Repaint the button
             if (bRepaint) Invalidate();

             return BTNST_OK;
            } // End of SetMenu

            通過(guò)#ifdef BTNST_USE_BCMENU  來(lái)判斷選擇哪個(gè)函數(shù)。

            程序過(guò)程:
               頭文件:
            CButtonST m_btnHelp;
               源文件:
            1)在當(dāng)前對(duì)話(huà)類(lèi)的初始化函數(shù)中添加:
            OnInitDialog()
             m_btnHelp.SetIcon(IDI_HELP, (int)BTNST_AUTO_GRAY);           //設(shè)置圖標(biāo),未點(diǎn)擊時(shí)變灰
             m_btnHelp.SetTooltipText(_T("Help"));                                             //輸出文字
            #ifdef BTNST_USE_BCMENU
             m_btnHelp.SetMenu(IDR_MENU, m_hWnd);                                  //點(diǎn)擊時(shí)彈出菜單欄
            #else
             m_btnHelp.SetMenu(IDR_MENU, m_hWnd);
            #endif
            2)設(shè)置控件交換信息:
            DoDataExchange(CDataExchange* pDX)函數(shù)中
             DDX_Control(pDX,IDC_BUTTON1,m_btnHelp);  //輸出
            3)新菜單欄響應(yīng)函數(shù):
            新建一菜單欄:IDR_MENUNEW,設(shè)置為POP-UP;
            設(shè)置子菜單:IDR_ITEM1.點(diǎn)擊ClassWizard,選擇當(dāng)前文檔類(lèi)點(diǎn)擊ON_COMMAND設(shè)置響應(yīng)函數(shù)。

            posted @ 2009-11-19 14:03 峰 閱讀(782) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題  下一頁(yè)

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            91精品国产91久久久久福利| 久久国产乱子伦精品免费强| 亚洲国产成人精品女人久久久| 青青热久久国产久精品| 亚洲AV日韩AV天堂久久| 久久九九青青国产精品| 婷婷久久综合九色综合九七| 久久偷看各类wc女厕嘘嘘| 久久精品99无色码中文字幕| 久久99热这里只频精品6| 久久久久久久综合日本亚洲| 亚洲精品tv久久久久| 久久久久久免费一区二区三区| 久久精品中文无码资源站| 中文字幕成人精品久久不卡 | 一级女性全黄久久生活片免费| 精品国产青草久久久久福利| 99久久国产综合精品麻豆| 国产精品激情综合久久 | 粉嫩小泬无遮挡久久久久久| 亚洲国产成人久久笫一页 | 婷婷久久综合| 久久久精品视频免费观看| 2021久久国自产拍精品| 国产亚洲精品久久久久秋霞 | 99久久伊人精品综合观看| 无码日韩人妻精品久久蜜桃 | 欧美久久一级内射wwwwww.| 久久久国产精品福利免费 | 色狠狠久久AV五月综合| 亚洲国产精品无码久久久久久曰 | 久久精品国产WWW456C0M| 精品一区二区久久| 色综合久久综精品| 久久免费国产精品一区二区| 青青青国产精品国产精品久久久久 | 久久精品国产99国产精品导航| 欧美精品丝袜久久久中文字幕| 精品国产91久久久久久久a| 精品久久久无码中文字幕天天| 国产成人久久久精品二区三区|