1 / 59

Creating Single Document Interface Applications

Creating Single Document Interface Applications. 建立單一文件介面的應用程式. Doc/View 架構. 在視窗應用程式中 , 資料的顯示與儲存係使用 Doc/View 的架構 Doc 物件用於管理視窗程式的資料儲存 View 物件則負責將 Doc 儲存的資料正確地顯示在視窗中 一個完整的視窗應用程式必需具備以下類別 App 類別 ( 應用程式類別 ) Frame 類別 ( 視窗框架類別 ) Document 類別 ( 文件類別 ) View 類別 ( 流覽類別 ).

evette
Télécharger la présentation

Creating Single Document Interface Applications

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Creating Single Document Interface Applications 建立單一文件介面的應用程式

  2. Doc/View架構 • 在視窗應用程式中, 資料的顯示與儲存係使用Doc/View的架構 • Doc物件用於管理視窗程式的資料儲存 • View物件則負責將Doc儲存的資料正確地顯示在視窗中 • 一個完整的視窗應用程式必需具備以下類別 • App類別(應用程式類別) • Frame類別(視窗框架類別) • Document類別(文件類別) • View類別(流覽類別)

  3. Creating An SDI Application • 利用AppWizard產生基本應用程式架構 • 應用程式類型 • 文件樣版字串:應用程式所要產生文件的副檔名(specifying the document file extension) • 副檔名:dhc • 產生的類別:指定View類別的基底類別 • 選取CView

  4. Creating a line class • MFC(Microsoft Foundation Class)中並沒有line object class,僅有Point Object class(CPoint) • 在「類別檢視」中利用精靈加入類別 • 類別型態請選「泛用C++類別」, • 在精靈對話方塊中: • 類別名稱:Cline • 基底類別:Cobject • 繼承模式:Public

  5. Creating a line class • 在類別中加入兩個CPoint物件變數,用於儲存線的兩點,存取模式為private • CPoint m_ptFrom; • CPoint m_ptTo; • 建立帶有兩個輸入參數的建構函式 • CLine(CPoint ptFrom, CPoint ptTo); • 用於設定m_ptFrom及m_ptTo這兩個成員資料的初始值

  6. Add Draw Function • 加入一個Function 到Cline類別中,存取模式為public • void Cline::Draw(CDC* pDC) • 加入以下程式碼到Function中,實際執行在文件視窗畫線的功能 • pDC->MoveTo(m_ptFrom); • pDC->LineTo(m_ptTo);

  7. 在文件類別中加入相關的成員變數 • 宣告儲存CLine Object的陣列 • 利用精靈加在Document類別中 • 型別為CObArray • 可動態配置Array的空間以儲存使用者所畫的線段 • 可用來儲存繼承自CObject的物件(參考下頁的Array classes) • 名稱為m_oaLines • 存取模式為private

  8. The Array Classes • CArray:A template class for creating your own array class • CByteArray:An array of Byte data types • CDWordArray:An array of DWORD data types. • CObArray:An array of classes derived from the Cobject base class • CPtrArray:An array of pointers(to any object or data type) • CStringArray:An array of Cstring objects • CUIntArray:An array of UNIT data types(unsigned integers) • CWordArray:An array of WORD data types

  9. 在文件類別中加入相關的成員函式 • 函式功能 • Getting the from and to points • Creating a new line object • Adding it to the object array • 函式定義內容 • 名稱:AddLine • 傳回值型態:Cline * • 傳入參數:CPoint ptFrom, CPoint ptTo

  10. AddLine 函式內容 CLine *pLine=NULL; try { pLine = new CLine(ptFrom, ptTo); //Create a CLine object m_oaLines.Add(pLine); //Add the new line to the object array SetModifiedFlag(); //Mark the document as dirty } catch(CMemoryException* perr) { AfxMessageBox("Out of Memory", MB_ICONSTOP|MB_OK); if (pLine) { delete pLine; //delete it pLine = NULL; } perr->Delete(); //Delete the exception object } return pLine;

  11. 用法: Place a try section around the code that might have problem The try section should always be followed by one or more catch sections If a problem occurs during the code in the try section, the program immediately jumps to the catch sections 捕捉程式執行時的錯誤並加以處理 try { … } catch { … }

  12. 將Line Class的定義內容加到doc類別中 • 編輯SDISquigDoc.h(SDISquig為專案名稱) • 加入#include "Line.h “ • 原因:SDISquigDoc.cpp 有建立Line 物件 • 至此可先編譯程式

  13. 在Doc類別中加入「Getting the Line Count」功能 • 在Doc類別中加入函式 • 名稱為GetLineCount • 存取模式為public • 傳回值型態為int,沒有輸入參數 • 在函式中加入以下程式碼: • return (int)m_oaLines.GetCount() ;

  14. 在Doc類別中加入「Retrieving a Specific Line」功能 • 在Doc類別中加入函式 • 名稱為GetLine • 存取模式為public • 傳回值型態為Cline* • 一個輸入參數 • int iIndex • 在函式中加入以下程式碼: • return (CLine*)m_oaLines[iIndex];

  15. Showing the Users • We have already built the capability into the document class to hold the drawing. • Now we need to add the functionality to the view object to read the user’s drawing input and to draw the image.

  16. Add a member variable to the View class 以記錄前一次按下Mouse的位置 • Add a member variable to the View class • Type: CPoint • Name: m_ptPrevPos • Access: private

  17. Adding the Mouse Events • 叫出View的快顯功能表並選取屬性指令,為以下事件建立事件程序 • WM_LBUTTONDOWN • WM_LBUTTONUP • WM_MOUSEMOVE

  18. 在CSDISquigView::LButtonDown()中加入以下程式碼 在CSDISquigView::LButtonUp中加入以下程式碼 WM_LBUTTONDOWN及WM_LBUTTONUP事件程序 if (GetCapture()==this) ReleaseCapture(); SetCapture(); m_ptPrevPos=point;

  19. WM_MOUSEMOVE事件程序 • 在CSDISquigView::OnMouseMove中加入以下程式碼: if ((nFlags & MK_LBUTTON)==MK_LBUTTON) { if (GetCapture()==this) { CClientDC dc(this); CLine *pLine=GetDocument()->AddLine(m_ptPrevPos, point); pLine->Draw(&dc); m_ptPrevPos=point; } }

  20. 在View class的OnDraw函式加入以下程式碼 • The function OnDraw is called whenever the image presented to users needs to be redrawn • 加入以下程式碼到OnDraw中 int iCount = pDoc->GetLineCount(); if (iCount) { int iPos; CLine *pLine = NULL; for (iPos=0; iPos < iCount ; iPos++) { pLine = pDoc->GetLine(iPos); pLine->Draw(pDC); } }

  21. Deleting the Current Drawing • SDI應用程式的DOC類別的基底類別為CDocument,此類別中有一個DeleteContens成員函式,在需要清除目前視窗內容時(如使用者開新檔案)將自動呼叫該函式。 • 在SDI的Doc類別中,覆寫上述函式 • 對Doc類別按右鍵並選取屬性 • 在屬性視窗中按覆寫鈕 • 選取DeleteContents • 將下一張投影片的程式碼加到DeleteContents函式中

  22. Deleting the Current Drawing //Get the number of lines in the object array int iCount = (int)m_oaLines.GetCount(); int iPos; try { if (iCount) { //Loop through the array , deleting each object for (iPos=0; iPos < iCount ; iPos++) delete (CLine*)m_oaLines.GetAt(iPos); //Reset the array m_oaLines.RemoveAll(); } } catch (CMemoryException* perr) { //Display a message for the user, giving him or her the bad news perr->ReportError(); //Delete the exception object perr->Delete(); }

  23. Saving and Restoring • There are two parts of serialization • When application data is stored on the system drive in the form of a file, it’s called serialization. • When the application state is restored from the file , it’s called deserialization. • Serialization in Visual C++ is accomplished through the Archive class

  24. The serialization function • When an application is reading or writing a file , the document object’s Serialize function is called .

  25. Saving and Restoring the Drawing • Find the serialization function in the doc class, 加入以下程式碼: //Pass the serialization on to the object array; m_oaLines.Serialize(ar);

  26. Saving and Restoring the Drawing • Add a new function to the Line class(存取模式為public), 先加到.cpp • 加函式原型定義到.h中 void Serialize(CArchive &ar); void CLine::Serialize(CArchive &ar) { CObject::Serialize(ar); if (ar.IsStoring()) //writing ar << m_ptFrom << m_ptTo; else ar >> m_ptFrom >> m_ptTo; //reading }

  27. Saving and Restoring the Drawing • VC++ must be told that a class should be serializable.To do this: • Open the Cline header file • Add DECLARE_SERIAL(CLine) just after the first line of the class definition. • (Line.h) class CLine : • public CObject • Open the source code file • Add IMPLEMENT_SERIAL (CLine, CObject, 1) just before the class constructor • (Line.cpp) #include "line.h" • 保留預設的建構函式(沒有輸入參數)

  28. ID_COLOR_BLACK ID_COLOR_BLUE ID_COLOR_GREEN ID_COLOR_CYAN ID_COLOR_RED ID_COLOR_MAGENTA ID_COLOR_YELLOW ID_COLOR_WHITE Caption:&Black Modifying the Menu

  29. Adding Color the the Cline Class • Add another member variable to the Cline class to hold the color of each line private: COLORREF m_crColor; • Modify the class constructor(.cpp及.h) CLine::CLine(CPoint ptFrom, CPoint ptTo, COLORREF crColor) { //設定兩個成員資料的初值 m_ptFrom = ptFrom; m_ptTo=ptTo; m_crColor=crColor; }

  30. Adding color the Cline Class • Modify the Draw function to use the specified color void CLine::Draw(CDC* pDC) { //Create a pen CPen lpen(PS_SOLID, 1, m_crColor); //Set the new pen as the drawing object CPen* pOldPen = pDC->SelectObject(&lpen); //Draw the line pDC->MoveTo(m_ptFrom); pDC->LineTo(m_ptTo); //Reset the previous pen pDC->SelectObject(pOldPen); }

  31. Adding color the Cline Class • Modify the Serialize function to save and restore the color information void CLine::Serialize(CArchive &ar) { CObject::Serialize(ar); if (ar.IsStoring()) //writing ar << m_ptFrom << m_ptTo << m_crColor; else ar >> m_ptFrom >> m_ptTo>>m_crColor; //reading }

  32. Adding color to the Document • Add a member variable to hold the current color,存取模式為private. UINT m_nColor; • Add a color table to convert color IDs into RGB values,存取模式為public static const COLORREF m_crColors[8];

  33. Adding color to the Document • Add the Color Table specification to the source code ,加在END_MESSAGE_MAP()之後 const COLORREF CSDISquigDoc::m_crColors[8]={ RGB(0, 0, 0), //Black RGB(0, 0, 255), //Blue RGB(0, 255, 0), //Green RGB(0, 255, 255), //Cyan RGB(255, 0, 0), //Red RGB(255, 0, 255), //Magenta RGB(255, 255, 0), //Yellow RGB(255, 255, 255), //White };

  34. Adding color to the Document • 在OnNewDocument()中加入以下指令, 以設定顏色初始值 m_nColor=0; • Modify the AddLine function pLine = new CLine(ptFrom, ptTo, m_crColors[m_nColor] );

  35. Adding color to the Document • Adding a function to return the current color,存取模式為public UINT CSDISquigDoc::GetColor(void) { //Return the current color return ID_COLOR_BLACK+m_nColor; }

  36. 為Color 的相關指令加事件處理程式 void CSDISquigDoc::OnColorBlack() { // TODO: 在此加入您的命令處理常式程式碼 //Set the current color to black m_nColor = ID_COLOR_BLACK - ID_COLOR_BLACK; } void CSDISquigDoc::OnUpdateColorBlack(CCmdUI *pCmdUI) { // TODO: 在此加入您的命令更新 UI 處理常式程式碼 //Determine if the Black menu entry should be checked pCmdUI->Enable(); pCmdUI->SetCheck(GetColor()==ID_COLOR_BLACK?1:0); }

  37. 為Color 的相關指令加事件處理程式 void CSDISquigDoc::OnColorBlue() { // TODO: 在此加入您的命令處理常式程式碼 m_nColor = ID_COLOR_BLUE - ID_COLOR_BLACK; } void CSDISquigDoc::OnUpdateColorBlue(CCmdUI *pCmdUI) { // TODO: 在此加入您的命令更新 UI 處理常式程式碼 pCmdUI->Enable(); pCmdUI->SetCheck(GetColor()==ID_COLOR_BLUE?1:0); }

  38. 加入顏色工具列 • 程序如slide39~slide41 • 將每一個工具按鈕的ID設成和Color底下的功能指令ID一樣 • 每一個工具按鈕的色彩如slide33, 調整方式為選取快顯功能表裡的「調整色彩」指令。 • 每一個工具按鈕的prompt 屬性值 • textOfStatusBar\ntextOfButton

  39. 修改或建立應用程式的工具列 • 在CMainFrame 類別中加入對應的宣告及程式碼: • 在MainFrm.h中宣告工具列物件變數 • CToolBar m_wndColorBar;

  40. 10-3 修改或建立應用程式的工具列 • 在MainFrm.C的OnCreate函式中,加入對應程式碼: • 呼叫CToolBar ::CreateEx函式建立工具列 • 呼叫CToolBar ::LoadToolBar函式載入工具列資源 • 呼叫CToolBar ::EnableDocking函式設定工具列可停泊在視窗的位置 • 呼叫CFrameWnd:: EnableDocking函式設定視窗框架可供停泊工具列的位置 • 呼叫CFrameWnd::DockControlBar將工具列停泊在視窗框架中。

  41. 10-3 修改或建立應用程式的工具列 • 一些設定工具列形式的選項 • CBRS_ALIGN_TOP:將工具列停留在視窗框架的上端 • CBRS_ALIGN_BOTTOM:將工具列停留在視窗框架的下端 • CBRS_ALIGN_LEFT:將工具列停留在視窗框架的左端 • CBRS_ALIGN_RIGHT:將工具列停留在視窗框架的右端 • CBRS_ALIGN_ANY:工具列可停留在視窗框架的任何一端 • CBRS_BORDER_TOP:在工具列的頂端建立外框 • CBRS_BORDER_BOTTOM:在工具列的下端建立外框 • CBRS_BORDER_LEFT:在工具列的左端建立外框 • CBRS_BORDER_RIGHT:在工具列的右端建立外框 • CBRS_FLYBY:當滑鼠游標停留在工具按鈕上方時,將在狀態列顯示該按鈕的說明。

  42. Adding width to the line class • Add another member variable to the Cline class to hold the width of each line private: UINT m_lnWidth; • Modify the class constructor(.cpp及.h) CLine::CLine(CPoint ptFrom, CPoint ptTo,COLORREF crColor, UINT lnWidth) { //設定兩個成員資料的初值 m_ptFrom = ptFrom; m_ptTo=ptTo; m_crColor=crColor; m_lnWidth=lnWidth; }

  43. Adding width to the line class • Modify the Draw function to use the specified width void CLine::Draw(CDC* pDC) { //Create a pen CPen lpen(PS_SOLID,m_lnWidth, m_crColor); //Set the new pen as the drawing object CPen* pOldPen = pDC->SelectObject(&lpen); //Draw the line pDC->MoveTo(m_ptFrom); pDC->LineTo(m_ptTo); //Reset the previous pen pDC->SelectObject(pOldPen); }

  44. Adding width to the line class • Modify the Serialize function to save and restore the width information CObject::Serialize(ar); if (ar.IsStoring()) //writing ar << m_ptFrom << m_ptTo << m_crColor << m_lnWidth; else //reading ar >> m_ptFrom >> m_ptTo >> m_crColor >> m_lnWidth;

  45. Adding width to the Document • Add a member variable to hold the current width,存取模式為private. UINT m_nWidth; • Add a width table to convert width IDs into width values,存取模式為public static const UINT m_lnWidths[5];

  46. Adding width to the Document • Add the WidthTable specification to the source code ,加在END_MESSAGE_MAP()之後 Const UINT CSDISquigDoc::m_lnWidths[5]={ 1, //VeryThin 8, //Thin 16, //Medium 24, //Thick 32, //Very Thick };

  47. Adding Width to the Document • 在OnNewDocument()中加入以下指令, 以設定線條粗細初始值 m_nWidth=0; • Modify the AddLine function pLine = new CLine(ptFrom, ptTo, m_crColors[m_nColor], m_lnWidths[m_nWidth]);

  48. Adding width to the Document • Adding a function to return the current width,存取模式為public UINT CSDISquigDoc::GetWidth(void) { //Return the current width return ID_WIDTH_VERYTHIN+m_nWidth; }

  49. Modifying the Menu • ID_WIDTH_VERYTHIN • ID_WIDTH_THIN • ID_WIDTH_MEDIUM • ID_WIDTH_THICK • ID_WIDTH_VERYTHICK

  50. 為Width 的相關指令加事件處理程式 void CSDISquigDoc::OnWidthVerythin() { // TODO: 在此加入您的命令處理常式程式碼 //Set the current width to very thin m_nWidth = ID_WIDTH_VERYTHIN - ID_WIDTH_VERYTHIN; } void CSDISquigDoc::OnUpdateWidthVerythin(CCmdUI *pCmdUI) { // TODO: 在此加入您的命令更新 UI 處理常式程式碼 //Determine if the Very Thin menu entry should be checked pCmdUI->Enable(); pCmdUI->SetCheck(GetWidth()==ID_WIDTH_VERYTHIN?1:0); }

More Related