適用于:
Microsoft? eMbedded Visual C++? version 4.0
Microsoft? Windows? CE version 4.1
摘要:本文為熟悉 eMbedded Visual C++ 編程環(huán)境及創(chuàng)建應(yīng)用程序并將其下載到 Windows CE 4.1 仿真程序提供了逐步說明。本文共分為五個(gè)部分,每一部分都包含讀者可以完成的許多練習(xí)。完成所有這些步驟大約需要 60 分鐘。
從 Microsoft Download Center 下載 Windows CE 5.0 Embedded Development Labs.msi。
本頁內(nèi)容
第一部分:創(chuàng)建用于 Windows CE 4.1 仿真程序的 MFC 應(yīng)用程序
Microsoft? eMbedded Visual C++? 開發(fā)系統(tǒng)提供了一個(gè)與 Microsoft Visual C++ 6.0 版幾乎相同的編程環(huán)境。該環(huán)境及 Microsoft Windows? CE 的 Microsoft Win32? 應(yīng)用程序編程接口 (API) 使編寫基于 Windows CE 設(shè)備的應(yīng)用程序非常類似于編寫 Windows 桌面版應(yīng)用程序。
在本文的該部分中,將使用 Microsoft 基礎(chǔ)類 (MFC) 應(yīng)用程序向?qū)?chuàng)建一個(gè)應(yīng)用程序,您可以將該應(yīng)用程序下載到 Microsoft Windows CE .1 版仿真程序并在其上運(yùn)行。
在本文中,您可以點(diǎn)擊大多數(shù)縮略圖查看大圖像。
在該部分的練習(xí)中,您將執(zhí)行以下步驟:
? |
創(chuàng)建一個(gè)新的 Windows CE MFC 項(xiàng)目 |
? |
在平臺(tái)管理器中配置設(shè)置 |
? |
生成和部署第一個(gè)仿真程序應(yīng)用程序 |
要?jiǎng)?chuàng)建新的 Windows CE MFC 項(xiàng)目
1. |
啟動(dòng)eMbedded Visual C++。
eMbedded Visual C++ 的基本用戶界面如下圖所示。必要時(shí),先花幾分鐘時(shí)間瀏覽一下這些工具,再進(jìn)入下一個(gè)步驟。
在 File 菜單上,單擊 New。
|
2. |
在 New 對(duì)話框中,選擇 WCE MFC AppWizard (exe) 作為待創(chuàng)建項(xiàng)目。 |
3. |
在 Project name 框中,鍵入 Scribble |
4. |
在 Location 框中,輸入 C:\LABS\EVCBASIC。 |
5. |
對(duì)于 Windows CE,您不會(huì)像在 Intel x86 處理器中那樣受到限制。注意該對(duì)話框右下角的處理器列表。默認(rèn)情況下,所有的可用處理器都被選中。由于現(xiàn)在的目標(biāo)只是仿真程序,因此除 Win32 (WCE emulator) 之外,清除所有的復(fù)選框,如下圖所示。
|
6. |
單擊 OK 啟動(dòng)向?qū)А? |
7. |
在該向?qū)У牡谝豁撝校瑔螕?Single document,確保選定 Document/View Architecture support? 復(fù)選框,然后單擊 Next,如下圖所示。
選擇 Document/View Architecture support? 復(fù)選框?qū)⑹乖撓驅(qū)閼?yīng)用程序的主代碼創(chuàng)建兩個(gè)類。Document 類旨在保存和保持狀態(tài)(數(shù)據(jù)),而 View 類提供數(shù)據(jù)的圖形化表示形式。這是一種“一對(duì)多”關(guān)系,其中 Document 類可能具有多種相關(guān)視圖,每個(gè)視圖提供數(shù)據(jù)的一個(gè)不同的圖形因素。該體系結(jié)構(gòu)以數(shù)據(jù)為中心,因此,更改通知很簡(jiǎn)單,并且通過文檔集中進(jìn)行數(shù)據(jù)訪問和存儲(chǔ)。
|
8. |
在該向?qū)У南乱豁撝校A羲械哪J(rèn)選項(xiàng),然后單擊 Next,如下圖所示。
|
9. |
在該向?qū)У南乱豁撝校瑔螕?Next,如下圖所示。
|
10. |
在該向?qū)У南乱豁撝校瑔螕?Finish,如下圖所示。
|
11. |
出現(xiàn)摘要時(shí),單擊 OK 完成該向?qū)В缦聢D所示。
|
既然已經(jīng)完成該向?qū)В陀辛艘粋€(gè)可以部署到仿真程序并在其之上運(yùn)行的應(yīng)用程序,盡管它還不會(huì)做任何特別有趣的事情。
使用 Windows CE 的部分好處在于從許多設(shè)備中進(jìn)行選擇甚至生成自定義設(shè)備及其相關(guān) SDK 的靈活性。在使用 eMbedded Visual C++ 開發(fā)應(yīng)用程序時(shí),您必須配置平臺(tái)管理器以表明您希望將圖像下載到何種平臺(tái)和設(shè)備。在部署項(xiàng)目之前,請(qǐng)檢查平臺(tái)管理器的設(shè)置。
要配置平臺(tái)管理器
1. |
單擊 Build | Set Active Platform 菜單命令。 |
2. |
在對(duì)話框中,選擇 STANDARDSDK_410,然后單擊 OK,如下圖所示。
您也可以從 WCE 配置工具欄中選擇活動(dòng)平臺(tái)。
在這種情況下,您只能使用單個(gè)的平臺(tái)。如果您已經(jīng)安裝更多的 SDK,此處的列表將會(huì)增加。
|
3. |
單擊 Build | Set Active Configuration 菜單命令。 |
4. |
在對(duì)話框中,選擇 Scribble – Win32 (WCE emulator) Debug,然后單擊 OK,如下圖所示。
您也可以從 WCE 配置工具欄中選擇活動(dòng)配置。
對(duì)于在初始向?qū)ы撝羞x定的每種處理器類型,都會(huì)有兩種相關(guān)的項(xiàng)目配置:調(diào)試和發(fā)布。每種配置都包含諸如編譯、鏈接以及調(diào)試設(shè)置等信息。您可以通過 Build | Configurations 菜單創(chuàng)建其他配置或刪除現(xiàn)有配置。由于只選定了仿真程序處理器,因此,您只有兩種配置。
迄今為止,您已經(jīng)設(shè)置了相關(guān)的信息,用于為目標(biāo)設(shè)備環(huán)境生成正確的二進(jìn)制圖像。最后,您需要選擇在何處(是物理連接的設(shè)備還是仿真程序)放置輸出圖像。在本文中,您只有一個(gè)可用目標(biāo),這就是仿真程序。但是對(duì)于其他 CPU 類型,則有多個(gè)選擇。 |
5. |
在 WCE 配置工具欄上,選擇 STANDARDSDK_410 Emulator,如下圖所示。
|
現(xiàn)在,您就可以生成并部署第一個(gè)仿真程序應(yīng)用程序。在此步驟中,該仿真程序?qū)⒃谧烂嬗?jì)算機(jī)上啟動(dòng)。啟動(dòng)過程可能需要一點(diǎn)時(shí)間。
要生成和部署第一個(gè)仿真程序應(yīng)用程序。
1. |
單擊 Build | Build Scribble.exe 菜單命令生成應(yīng)用程序并將其下載到仿真程序中。
仿真程序應(yīng)當(dāng)啟動(dòng),然后,程序應(yīng)自動(dòng)地下載到仿真程序中。重新編譯和下載的鍵盤快速方式為 F7。
仿真程序屏幕應(yīng)當(dāng)如下圖所示。
現(xiàn)在,您需要啟動(dòng)應(yīng)用程序。 |
2. |
在仿真程序中,雙擊 My Computer 查看剛才下載的 Scribble.exe 應(yīng)用程序。下圖顯示 My Computer 的內(nèi)容。
|
3. |
雙擊 Scribble.exe。
應(yīng)用程序啟動(dòng),如下圖所示。
此時(shí),您擁有一個(gè)完整工作的應(yīng)用程序 ─ 盡管它不能做太多工作! |
4. |
單擊 File | Exit 退出該應(yīng)用程序,如下圖所示。
|
5. |
讓仿真程序繼續(xù)運(yùn)行并切換到 eMbedded Visual C++,準(zhǔn)備下一個(gè)練習(xí)。 |
第二部分:向應(yīng)用程序中添加鼠標(biāo)捕獲和手寫輸入繪圖
現(xiàn)在您需要向應(yīng)用程序中添加一些實(shí)際的功能。在該部分的練習(xí)中,您將添加來自手寫筆或鼠標(biāo)的數(shù)據(jù)的捕獲并將其繪制為屏幕上的手寫輸入。您需要探測(cè)手寫筆何時(shí)接觸屏幕、何時(shí)移動(dòng)以及何時(shí)離開屏幕。您將逐步生成這種功能,這樣就可以熟悉如何使用 MFC 向?qū)砑涌炀帉?Windows CE 代碼的速度,并充分利用開發(fā)人員可用的 MFC 體系結(jié)構(gòu)。
在該部分的練習(xí)中,您將執(zhí)行以下步驟:
? |
向 CScribbleView 類中添加狀態(tài)變量 |
? |
修改類構(gòu)造函數(shù) |
? |
向 CSCribbleView 類中添加 OnLButtonDown 方法啟動(dòng)手寫輸入捕獲 |
? |
向 CScribbleView 類中添加 OnLButtonUp 方法停止手寫輸入捕獲 |
? |
向 CScribbleView 類中添加 OnMouseMove 方法捕獲和繪制手寫輸入。 |
? |
編譯和測(cè)試應(yīng)用程序 |
要向 CScribbleView 類中添加狀態(tài)變量
1. |
在 eMbedded Visual C++ 左側(cè)窗格的底部,單擊 Class View 選項(xiàng)卡。 |
2. |
單擊 Scribble classes 行旁邊的加號(hào) (+) 展開應(yīng)用程序中的類列表。
該列表包含 5 個(gè)類,它們形成標(biāo)準(zhǔn) MFC Doc / View 應(yīng)用程序的模板。
Doc / View 應(yīng)用程序的設(shè)計(jì)將應(yīng)用程序分成 Document 類(保存數(shù)據(jù))和 View 類(向用戶呈現(xiàn)數(shù)據(jù)),如先前的練習(xí)所述。其他三個(gè)類 ─ App 類、MainFrame 類以及 AboutDlg 類 ─ 分別提供對(duì)應(yīng)用程序、應(yīng)用程序頂層窗口以及 About 對(duì)話框的支持。 |
3. |
右鍵單擊 CScribbleView 類,然后單擊 Add Member Variable,如下圖所示。
|
4. |
在 Variable Type 框中,鍵入 CPoint(這是一個(gè)簡(jiǎn)化 x 坐標(biāo)和 y 坐標(biāo)控制的 MFC 類)。 |
5. |
在 Variable Name 框中,鍵入 m_CurrentPoint |
6. |
在 Access 下面,單擊 Protected,如下圖所示。
一種很好的習(xí)慣是,通過使用 Protected 選項(xiàng)限制訪問來隱藏?cái)?shù)據(jù)成員。然后,類成員函數(shù)可以讀取和更新類的狀態(tài),但是外部函數(shù)和對(duì)象則不能。
m_CurrentPoint 變量保存最后一個(gè)繪圖點(diǎn),但是您還需要一個(gè)其他變量,來表明您是否處于繪圖狀態(tài)。 |
7. |
在 Add Member Variable 對(duì)話框中,單擊 OK。 |
8. |
右鍵單擊 CScribbleView 類,然后單擊 Add Member Variable。 |
9. |
在 Variable Type 框中,鍵入 bool |
10. |
在 Variable Name 框中,鍵入 m_InDraw |
11. |
在 Access 下面,單擊 Protected。
|
類向?qū)?duì) CScribbleView 的定義進(jìn)行編輯,向該類中添加變量。您將使用該變量來表明何時(shí)需要捕獲鼠標(biāo)輸入。
在使用類之前對(duì)其狀態(tài)進(jìn)行初始化始終是一種很好的習(xí)慣,因?yàn)橛嘘P(guān)構(gòu)造的成員數(shù)據(jù)中保存的值并不存在自動(dòng)保證。進(jìn)行該初始化的最佳位置是類的構(gòu)造函數(shù),而對(duì)于內(nèi)部數(shù)據(jù)類型,使用類初始化列表則是一種較好的習(xí)慣。
您需要查找類構(gòu)造函數(shù)并對(duì)其進(jìn)行修改以清除您的狀態(tài)。
要修改類構(gòu)造函數(shù)
1. |
在顯示項(xiàng)目的類視圖的左側(cè)窗格中,單擊 CScribbleView 旁邊的加號(hào) (+) 展開該類中方法和數(shù)據(jù)的列表。 |
2. |
雙擊帶有簽名 CScribbleView() 的類的默認(rèn)構(gòu)造函數(shù),如下圖所示。
該步驟打開 ScribbleView.cpp 文件并顯示以下構(gòu)造函數(shù)。
|
3. |
在大括號(hào) ({) 之前,添加以下代碼行。 : m_InDraw(false), m_CurrentPoint(0,0)
|
要向 CScribbleView 類中添加 OnLButtonDown 方法啟動(dòng)手寫輸入捕獲
1. |
右鍵單擊 CScribbleView 類,然后單擊 Add Windows Message Handler,如下圖所示。
|
2. |
在 New Windows messages/events 列表中,選擇 WM_LBUTTONDOWN,然后單擊 Add and Edit,如下圖所示。
該類向?qū)?WM_LBUTTONDOWN 函數(shù)原型添加到應(yīng)用程序中,并打開該新函數(shù)的編輯器。 |
3. |
替換注釋: // TODO: Add your message handler code here and/or call default
使用以下代碼: m_InDraw = true;
m_CurrentPoint = point;
前面的代碼設(shè)置類狀態(tài),表示正在繪圖并存儲(chǔ)手寫輸入的起始點(diǎn)。 |
要向 CScribbleView 類中添加 OnLButtonUp 方法停止手寫輸入捕獲
1. |
右鍵單擊 CScribbleView 類,然后單擊 Add Windows Message Handler。 |
2. |
在 New Windows messages/events 列表中,選擇 WM_LBUTTONUP,然后單擊 Add and Edit,如下圖所示。
類向?qū)?WM_LBUTTONUP 函數(shù)原型添加到應(yīng)用程序中,并打開該新函數(shù)編輯器。 |
3. |
替換注釋: // TODO: Add your message handler code here and/or call default
使用以下代碼: m_InDraw = false;
m_CurrentPoint = CPoint(0,0);
前面的代碼設(shè)置類狀態(tài),表示繪圖已經(jīng)停止,然后將當(dāng)前點(diǎn)設(shè)置為 0,0。該設(shè)置是表示不存在上一點(diǎn)的一個(gè)特殊位置。 |
要向 CScribbleView 類中添加 OnMouseMove 方法以捕獲并繪制手寫輸入
? |
右鍵單擊 CScribbleView 類,然后單擊 Add Windows Message Handler。 |
? |
在 New Windows messages/events 列表中,選擇 WM_MOUSEMOVE,然后單擊 Add and Edit,如下圖所示。
類向?qū)?WM_MOUSEMOVE 函數(shù)原型添加到應(yīng)用程序中,并打開該新函數(shù)編輯器。 |
? |
替換注釋: // TODO: Add your message handler code here and/or call default
使用以下代碼: if (m_InDraw)
{
if (point != m_CurrentPoint)
{
CPoint line[2];
line[0] = m_CurrentPoint;
line[1] = point;
m_CurrentPoint = point;
CDC* pDC = GetDC();
pDC->Polyline(line, 2);
ReleaseDC(pDC);
}
}
else
在該代碼中,有意沒有對(duì) else 語句進(jìn)行定義,因?yàn)橄驅(qū)傻拇a形成 else 語句。
前面的代碼檢查您處于捕獲模式(已經(jīng)調(diào)用 WM_LBUTTONDOWN),并檢查手寫筆已經(jīng)從之前的位置移動(dòng)。然后,它生成一個(gè)兩點(diǎn)數(shù)組 ─ 最近捕獲的點(diǎn)和最新捕獲的點(diǎn) ─ 并使用當(dāng)前窗口的設(shè)備上下文在它們之間繪制一條直線。
如果您不是處于繪圖模式,則將通過調(diào)用 else 語句中的生成代碼產(chǎn)生默認(rèn)的操作,如下所示。 CView::OnMouseMove (nFlags, point);
|
現(xiàn)在您可以再次測(cè)試應(yīng)用程序以確保所有功能都正確無誤。
要編譯和測(cè)試應(yīng)用程序
1. |
單擊 Build | Build Scribble.exe 菜單命令(或按 F7)來生成和下載該應(yīng)用程序。 |
2. |
更正任何編譯器錯(cuò)誤。 |
3. |
如果下載到仿真程序失敗,進(jìn)行檢查以確保您現(xiàn)在沒有運(yùn)行早期版本的 Scribble.exe。 |
4. |
如果應(yīng)用程序仍然在運(yùn)行,單擊 File | Exit 退出。 |
在新版本運(yùn)行后,您應(yīng)當(dāng)只能通過在仿真程序上使用鼠標(biāo)在應(yīng)用程序中繪制直線。注意您有一些不執(zhí)行任何操作的菜單命令,如果您在運(yùn)行 Scribble.exe 之前加載了另外的應(yīng)用程序并引起它重繪,則會(huì)丟失所有的直線信息。
記住在完成測(cè)試后退出應(yīng)用程序。
第三部分:修改應(yīng)用程序以存儲(chǔ)和重繪手寫輸入
現(xiàn)在,在重繪屏幕時(shí),直線數(shù)據(jù)丟失。您需要在 CScribbleDoc 類中添加存儲(chǔ)變量以存儲(chǔ)捕獲的數(shù)據(jù),并向 View 類中添加更多代碼以在適當(dāng)?shù)臅r(shí)刻調(diào)用這些方法。
在本部分的練習(xí)中,您將執(zhí)行以下步驟:
? |
向 CScribbleDoc 類中添加手寫輸入的類型定義 |
? |
向其他頭文件中添加引用 |
? |
使用 stdafx.h 生成預(yù)編譯頭 |
? |
向 CScribbleDoc 類中添加手寫輸入數(shù)據(jù)的存儲(chǔ) |
? |
向 CScribbleDoc 類中添加 GetFirstLine 方法 |
? |
向 CScribbleDoc 類中添加 GetNextLine 方法 |
? |
向 CScribbleDoc 類中添加 StartNewLine 方法 |
? |
向 CScribbleDoc 類中添加 AddPoint 方法 |
? |
為當(dāng)前直線向 CScribbleView 中添加存儲(chǔ)變量 |
? |
修改 CScribbleView::OnLButtonDown以引用 CScribbleDoc |
? |
修改 CScribbleView::OnMouseMove以引用 CScribbleDoc |
? |
向 CScribbleView::OnDraw 中添加實(shí)現(xiàn) |
? |
編譯和測(cè)試應(yīng)用程序 |
要向 CScribbleDoc 類中添加手寫輸入的類型定義
1. |
在 eMbedded Visual C++ 的左側(cè)窗格底部,單擊 Class View 選項(xiàng)卡。 |
2. |
右鍵單擊 CScribbleDoc 類,然后單擊 Go to Definition,如下圖所示。
|
3. |
在類定義 class CScribbleDoc : public CDocument 上面,添加以下兩行。 typedef CArray < CPoint,CPoint > SingleLine;
typedef CList < SingleLine *, SingleLine * > LineList;
您可以使用前面的定義把手寫輸入行作為點(diǎn)的集合,并引用手寫輸入行的集合。 |
CArray 和 CList 類需要默認(rèn)情況下沒有包括在內(nèi)的其他頭文件。為了能夠在整個(gè)項(xiàng)目中使用這些類,您需要在 stdafx.h 頭文件中添加對(duì)該頭文件的引用。
要添加對(duì)其他頭文件的引用
1. |
在 eMbedded Visual C++ 的左側(cè)窗格底部,單擊 File View 選項(xiàng)卡。 |
2. |
單擊 Scribble Files 行旁邊的加號(hào) (+) 展開項(xiàng)目中的文件組列表。 |
3. |
單擊 Header Files 行旁邊的加號(hào) (+) 展開應(yīng)用程序中使用的頭文件列表。
該列表將包含七個(gè)文件,它們形成標(biāo)準(zhǔn) MFC Doc / View 應(yīng)用程序的模板。 |
stdafx.h 文件用于生成預(yù)編譯頭,該預(yù)編譯頭將包括在項(xiàng)目中所有已編譯的文件中。它提供一種編譯項(xiàng)目中只使用一次的通用聲明和類型的方法,以加快生成過程速度。
要使用 stdafx.h 生成預(yù)編譯頭
1. |
右鍵單擊 stdafx.h file,然后單擊 Open,如下圖所示。
|
2. |
查找該行: #include // MFC core and standard components
只需在其下面添加該行: #include // MFC standard template classes
|
如您所見,View 類負(fù)責(zé)捕獲來自用戶的信息,并將其顯示在屏幕上。但是,Document 類負(fù)責(zé)存儲(chǔ)和訪問 View 類顯示的數(shù)據(jù)。此時(shí),還沒有存儲(chǔ)或保存數(shù)據(jù)。在以下的步驟中,您將添加為該點(diǎn)數(shù)據(jù)提供存儲(chǔ)的成員變量。
要向 CScribbleDoc 類中添加手寫輸入數(shù)據(jù)的存儲(chǔ)
1. |
在左側(cè)窗格中,選擇 Class View。 |
2. |
右鍵單擊 CScribbleDoc class,然后單擊 Add Member Variable,如下圖所示。
|
3. |
在 Variable Type 框中,鍵入 LineList |
4. |
在 Variable Name 框中,鍵入 m_LineInfo |
5. |
在 Access 下面,單擊 Protected,如下圖所示。
|
6. |
單擊 OK。 |
類向?qū)?duì) CScribbleDoc 類的類定義進(jìn)行編輯,將變量添加到該類中。由于該變量是一個(gè)保護(hù)變量,您需要添加訪問方法來設(shè)置和檢索該集合中的數(shù)據(jù)。
要向 CScribbleDoc 類中添加 GetFirstLine 方法
? |
在顯示類定義的左側(cè)窗格中,右鍵單擊 CScribbleDoc 類,然后單擊 Add Member Function。 |
? |
在 Function Type 框中,鍵入 const SingleLine * |
? |
在 Function Declaration 框中,鍵入 GetFirstLine (POSITION & pos) const,如下圖所示。
|
? |
單擊 OK。
類向?qū)г陬^文件中添加公共成員函數(shù)聲明,并在源文件中添加一個(gè)空的實(shí)現(xiàn)。然后,保留 ScribbleDoc.cpp 文件打開,現(xiàn)在就可以鍵入該方法的實(shí)現(xiàn)。 |
? |
將以下代碼添加到 GetFirstLine 方法的實(shí)現(xiàn)。 const SingleLine * RetVal = NULL;
pos = m_LineInfo.GetHeadPosition();
if (pos)
RetVal = m_LineInfo.GetAt(pos);
return RetVal;
|
要向 CScribbleDoc 類中添加 GetNextLine 方法
1. |
在顯示類定義的左側(cè)窗格中,右鍵單擊 CScribbleDoc 類,然后單擊 Add Member Function。 |
2. |
在 Function Type 框中,鍵入 const SingleLine * |
3. |
在 Function Declaration 框中,鍵入 GetNextLine ( POSITION & pos) const,如下圖所示。
|
4. |
單擊 OK。 |
5. |
鍵入 GetNextLine 方法的以下實(shí)現(xiàn)。 const SingleLine * RetVal = NULL;
if (pos)
RetVal = m_LineInfo.GetNext(pos);
return RetVal;
|
要向 CScribbleDoc 類中添加 StartNewLine 方法
? |
在顯示類定義的左側(cè)窗格中,右鍵單擊 CScribbleDoc 類,然后單擊 Add Member Function。 |
? |
在 Function Type 框中,鍵入 POSITION |
? |
在 Function Declaration 框中,鍵入 StartNewLine ( CPoint StartPoint ),如下圖所示。
|
? |
單擊 OK。 |
? |
鍵入 StartNewLine 方法的以下實(shí)現(xiàn)。 SingleLine * NewLine = new SingleLine();
NewLine->Add(StartPoint);
return m_LineInfo.AddTail(NewLine);
|
要向 CScribbleDoc 類中添加 AddPoint 方法
1. |
在顯示類定義的左側(cè)窗格中,右鍵單擊 CScribbleDoc 類,然后單擊 Add Member Function。 |
2. |
在 Function Type 框中,鍵入 bool |
3. |
在 Function Declaration 框中,鍵入 AddPoint ( POSITION pos, CPoint NewPoint ),如下圖所示。
|
4. |
單擊 OK。 |
5. |
鍵入 AddPoint 方法的以下實(shí)現(xiàn)。 SingleLine * WorkLine = m_LineInfo.GetAt(pos);
WorkLine->Add(NewPoint);
return true;
|
既然您擁有文檔中管理的數(shù)據(jù),則需要修改現(xiàn)有的視圖方法,從而在文檔中更新和存儲(chǔ)數(shù)據(jù)。您需要在視圖中使用新的類變量來標(biāo)識(shí)正在繪制的直線。
要為當(dāng)前直線向 CScribbleView 中添加存儲(chǔ)變量
1. |
在顯示類定義的左側(cè)窗格中,右鍵單擊 CScribbleView 類,然后單擊 Add Member Variable,如下圖所示。
|
2. |
在 Variable Type 框中,鍵入 POSITION |
3. |
在 Variable Name 框中,鍵入 m_CurrentPos |
4. |
在 Access 下,單擊 Protected,如下圖所示。
|
5. |
單擊 OK。 |
要修改 CScribbleView::OnLButtonDown以引用 CScribbleDoc
1. |
在顯示為 View 類定義的當(dāng)前成員列表的左側(cè)窗格中,雙擊 OnLButtonDown 方法,如下圖所示。
|
2. |
在調(diào)用基類 CView::OnLButtonDown(nFlags, point) 之前,對(duì)實(shí)現(xiàn)進(jìn)行修改,在該方法結(jié)尾添加如下代碼。 m_CurrentPos = GetDocument()->StartNewLine(point);
該步驟檢索與視圖相關(guān)的當(dāng)前文檔,并調(diào)用早先定義的 StartNewLine 方法。 |
現(xiàn)在您需要修改 OnMouseMove 方法。
要修改 CScribbleView::OnMouseMove以引用 CScribbleDoc
1. |
在顯示為 CScribbleView 類定義的當(dāng)前成員列表的左側(cè)窗格中,雙擊 OnMouseMove 方法轉(zhuǎn)到其實(shí)現(xiàn)。 |
2. |
對(duì)該實(shí)現(xiàn)進(jìn)行修改,緊接 ReleaseDC(pDC) 之后添加以下代碼。 GetDocument()->AddPoint(m_CurrentPos, point);
|
現(xiàn)在您擁有存儲(chǔ)在文檔中的點(diǎn)數(shù)據(jù),該數(shù)據(jù)在捕獲輸入時(shí)會(huì)正確地從 View 類中進(jìn)行更新。要做的下一個(gè)步驟是使該數(shù)據(jù)被擦除時(shí)可以在屏幕上重繪。要重繪該數(shù)據(jù),您需要修改 OnDraw 方法使客戶區(qū)為空白以及執(zhí)行其他操作。您將從文檔中記取每條直線,而且對(duì)于每條直線,要在直線上的各點(diǎn)之間繪制。
要將實(shí)現(xiàn)添加到 CScribbleView::OnDraw
1. |
在顯示為 CScribbleView 類定義的當(dāng)前成員列表的左側(cè)窗格中,雙擊 OnDraw 方法以轉(zhuǎn)到其實(shí)現(xiàn)。 |
2. |
替換以下行: // TODO: add draw code for native data here
使用該代碼: // Redraw the lines
POSITION WorkPos;
const SingleLine *WorkLine = GetDocument()->GetFirstLine(WorkPos);
while (NULL !=WorkLine)
{
// Build an array of points and draw them
if (0 ==WorkLine->GetSize())
break;
CPoint * PointArray = new CPoint [WorkLine->GetSize()];
for (int x = 0;x < WorkLine->GetSize();x++)
PointArray[x] = WorkLine->operator [] (x);
pDC->Polyline(PointArray, x);
delete [] PointArray;
PointArray = NULL;
WorkLine = GetDocument()->GetNextLine(WorkPos);
}
|
現(xiàn)在您就可以再次測(cè)試應(yīng)用程序以確保所有功能正確無誤。
要編譯和測(cè)試應(yīng)用程序
1. |
單擊 Build | Build Scribble.exe 菜單命令(或按 F7)生成并下載該應(yīng)用程序。 |
2. |
更正任何編譯器錯(cuò)誤。 |
3. |
如果下載到仿真程序失敗,檢查以確保您現(xiàn)在沒有運(yùn)行早期版本的 Scribble.exe。 |
4. |
如果應(yīng)用程序仍然在運(yùn)行,單擊 File | Exit 退出。 |
在運(yùn)行新版本后,您應(yīng)當(dāng)只能在仿真程序上使用鼠標(biāo)在應(yīng)用程序中繪制直線。對(duì)于該新版本,您可以啟動(dòng)其他應(yīng)用程序然后退出,查看 Scribble.exe 重繪其手寫輸入。
記住在完成測(cè)試之后退出應(yīng)用程序。
第四部分:探索 eMbedded Visual C++ 的調(diào)試功能
既然應(yīng)用程序可以進(jìn)行一些操作,而不僅僅是運(yùn)行向?qū)傻拇a,您就可以開始考慮 eMbedded Visual C++ 為設(shè)備和嵌入式解決方案的實(shí)際應(yīng)用程序開發(fā)人員提供的一些主要優(yōu)點(diǎn)。其中這些類型的解決方案明顯不同于桌面計(jì)算機(jī)開發(fā)的一個(gè)主要方面,就是提供了調(diào)試和診斷工具。桌面環(huán)境受益于大量將其本質(zhì)目標(biāo)定位于相同硬件、使用相同操作系統(tǒng)功能的開發(fā)人員,因此,在過去的幾年中,已經(jīng)創(chuàng)建了大量的工具以幫助進(jìn)行應(yīng)用程序開發(fā)。對(duì)于設(shè)備開發(fā)人員,該領(lǐng)域的工具則是鳳毛麟角。在本文的該部分中,您將使用 eMbedded Visual C++ 提供的一些工具。
迄今為止,您已經(jīng)使用 eMbedded Visual C++ 編譯應(yīng)用程序并將其下載到仿真程序中,然后直接在仿真程序中運(yùn)行該應(yīng)用程序。在本部分的練習(xí)中,您將執(zhí)行以下步驟:
? |
使用內(nèi)置調(diào)試器運(yùn)行應(yīng)用程序 |
? |
停止調(diào)試器 |
? |
測(cè)試斷點(diǎn) |
? |
添加監(jiān)視項(xiàng) |
? |
測(cè)試監(jiān)視項(xiàng) |
? |
訪問其他調(diào)試窗口 |
? |
在運(yùn)行時(shí)修改變量的值 |
要使用內(nèi)置調(diào)試器運(yùn)行應(yīng)用程序
? |
從 eMbedded Visual C++ 菜單中,單擊 Build | Start Debug | Go,如下圖所示。
您也可以按下 F5 執(zhí)行該命令。
|
調(diào)試器連接到仿真程序,檢查文件版本以及在仿真程序上啟動(dòng)應(yīng)用程序。eMbedded Visual C++ 環(huán)境切換到調(diào)試模式,并查找如下圖所示的內(nèi)容。
圖 1. eMbedded Visual C++ 環(huán)境中的調(diào)試模式
在該模式中,您可以從主應(yīng)用程序標(biāo)題欄查看當(dāng)前正在運(yùn)行的應(yīng)用程序。當(dāng)前的自動(dòng)變量位于窗口的左下側(cè)部分(在前面的圖形中沒有變量,因?yàn)閼?yīng)用程序正在運(yùn)行)。當(dāng)前的監(jiān)視變量位于窗口的右下側(cè)部分(在前面的圖形中沒有變量,因?yàn)闆]有選定任何變量)。
為了使用不同的選項(xiàng),您需要在某個(gè)位置停止調(diào)試器。要停止調(diào)試器,您可以使用 Build | Break 命令(如果沒有系統(tǒng)代碼正在運(yùn)行),或者您可以設(shè)置斷點(diǎn)并等待中斷事件發(fā)生。
要停止調(diào)試器
1. |
從菜單欄中,單擊 Edit | Breakpoints 加載斷點(diǎn)窗口,如下圖所示。
您也可以按下 ALT+F9 執(zhí)行該命令。
在 Breakpoints 對(duì)話框中,您可以從三種主要的表達(dá)式類別進(jìn)行中斷:從位置中斷(Location 選項(xiàng)卡);當(dāng)數(shù)據(jù)表達(dá)式評(píng)估為真時(shí)中斷(Data 選項(xiàng)卡);或者窗口過程檢索某個(gè) Windows 消息時(shí)中斷(Message 選項(xiàng)卡),這是前兩種類別的組合。在應(yīng)當(dāng)發(fā)生中斷時(shí),可能會(huì)使用該對(duì)話框來設(shè)置復(fù)雜條件。但是,注意使用數(shù)據(jù)表達(dá)式可能會(huì)嚴(yán)重地影響目標(biāo)環(huán)境的性能,因?yàn)樵诿總€(gè)指令后必須對(duì)該數(shù)據(jù)進(jìn)行評(píng)估。
在該過程中,您將根據(jù)位置來設(shè)置斷點(diǎn)。 |
2. |
在 Break at 框中,鍵入 CScribbleView::OnLButtonUp如下圖所示。
|
3. |
單擊 OK。 |
現(xiàn)在,您擁有一個(gè)斷點(diǎn)設(shè)置,在從窗口釋放鼠標(biāo)左按鈕時(shí),將會(huì)出現(xiàn)該斷點(diǎn)設(shè)置。在運(yùn)行應(yīng)用程序之前,在編輯器中將不會(huì)圖形化顯示有關(guān)一個(gè)方法的斷點(diǎn),因?yàn)樵谠摂帱c(diǎn)之前調(diào)試器無法解釋函數(shù)名。但是,您可以設(shè)置有關(guān)特定行的斷點(diǎn),該特定行將導(dǎo)致在編輯過程中顯示一個(gè)圖形化提示。F9 鍵是設(shè)置和清除基于位置的斷點(diǎn)的鍵盤快捷方式
現(xiàn)在您可以使用該應(yīng)用程序并查看斷點(diǎn)的工作。
要測(cè)試斷點(diǎn)
1. |
切換到仿真程序。 |
2. |
使用鼠標(biāo)在仿真程序中繪制一條直線,然后釋放鼠標(biāo)按鈕。
您將看到下圖所示的代碼。
在前面的圖示中,紅圈表示斷點(diǎn),黃色的箭頭顯示執(zhí)行的下一條語句。 |
在開發(fā)環(huán)境的左下側(cè)窗格中,現(xiàn)在您可以看到 Auto、Locals 以及 this 選項(xiàng)卡的相關(guān)數(shù)據(jù)。要添加監(jiān)視項(xiàng),您只需將它們從左下側(cè)窗格拖放到右下側(cè)窗格,或者也可以直接添加。下圖顯示 Auto 選項(xiàng)卡。
圖 2. 左下窗格中的 Auto 選項(xiàng)卡
要添加監(jiān)視項(xiàng)
? |
在 Auto 選項(xiàng)卡中,查找 m_InDraw,然后將其拖放到監(jiān)視窗格。 |
要查看監(jiān)視項(xiàng)如何工作,您可以單步執(zhí)行。
要測(cè)試監(jiān)視項(xiàng)
? |
從菜單欄中,單擊 Build | Step Over。
您也可以按下 F10 執(zhí)行該命令。
m_InDraw 的值變?yōu)?0 并出現(xiàn)紅色,表示它在最后的操作中發(fā)生了變化。 |
還有其他幾個(gè)有用的應(yīng)用程序調(diào)試窗口。
要訪問其他的調(diào)試窗口
? |
單擊 View | Debug Windows | Call Stack,如下圖所示。
|
查看調(diào)用堆棧、內(nèi)存、寄存器以及反匯編。注意仿真程序、寄存器和反匯編均為 x86 特性。對(duì)于其他處理器類型,您可以查看與目標(biāo) CPU 相關(guān)的寄存器以及顯示目標(biāo) CPU 指令集的反匯編。
現(xiàn)在您可以嘗試一些高級(jí)功能。
要在運(yùn)行時(shí)修改變量的值
1. |
單擊 Edit | Breakpoints 顯示斷點(diǎn)對(duì)話框。
您也可以按下 ALT+F9 執(zhí)行該命令。 |
2. |
單擊 Remove All 清除所有斷點(diǎn)。 |
3. |
單擊 OK。 |
4. |
單擊 Debug | Go 繼續(xù)運(yùn)行應(yīng)用程序,如下圖所示。
您也可以按下 F5 執(zhí)行該命令。
下一個(gè)步驟,您將設(shè)置有關(guān) OnMouseMove 方法的第一行的斷點(diǎn)。 |
5. |
在源代碼中向下滾動(dòng)幾行到 CScribbleView::OnMouseMove方法。 |
6. |
將插入符號(hào)放置到第一行 ─ if (m_InDraw) ─ 然后按下 F9 啟用斷點(diǎn)。 |
7. |
切換回仿真程序,并將鼠標(biāo)移動(dòng)到 Scribble 窗口上(無需按下鼠標(biāo)左鍵)。
如下圖所示,調(diào)試器應(yīng)當(dāng)在 OnMouseMove 方法設(shè)置斷點(diǎn)的第一行處中斷。黃色箭頭顯示當(dāng)前行。
現(xiàn)在,您將使用 QuickWatch 來查看 m_InDraw 的值并將該值更改為 True。 |
8. |
將插入符號(hào)放置到 m_InDraw 變量,然后單擊 Debug | Quick Watch 打開 QuickWatch 對(duì)話框(如下圖所示)。
您也可以按下 SHIFT+F9 執(zhí)行該命令。
|
9. |
在 Value 域中單擊,將值從 0 更改為 ,然后單擊 Recalculate。 |
10. |
單擊 Close。 |
11. |
從菜單中單擊 Debug | Step Over 移動(dòng)到下一個(gè)語句。
您也可以按下 F10 執(zhí)行該命令。
由于已經(jīng)動(dòng)態(tài)地更改了變量的值,因此您已經(jīng)更改了行為,這樣,現(xiàn)在調(diào)用繪圖代碼而不是將其忽略。 |
12. |
從菜單中單擊 Edit | Breakpoints 顯示 Breakpoints 對(duì)話框。
您也可以按下 ALT+F9 執(zhí)行該命令。 |
13. |
單擊 Remove All。 |
14. |
單擊 OK。 |
15. |
從菜單中單擊 Debug | Go 或按下 F5 繼續(xù)執(zhí)行。
現(xiàn)在,在您返回到仿真程序屏幕時(shí),移動(dòng)鼠標(biāo)將導(dǎo)致繪制手寫輸入,就像按下鼠標(biāo)按鈕一樣。 |
16. |
單擊 File | Exit 退出應(yīng)用程序并終止調(diào)試。 |
該操作完成第四部分和本文的主要活動(dòng)。如果還有時(shí)間,可以轉(zhuǎn)到第五部分。
第五部分:添加代碼保存和打開手寫輸入文檔
應(yīng)用程序中仍然有未使用的菜單命令。在本部分中,您將完成應(yīng)用程序,從而使它支持 File | Save As、File | New 和 File | Open 命令。
在本部分的練習(xí)中,您將執(zhí)行以下步驟:
? |
修改保存和打開的文件類型 |
? |
修改 File| New 行為以清除數(shù)據(jù)結(jié)構(gòu) |
? |
修改 File | Open 和 File | Save As 行為以對(duì)數(shù)據(jù)進(jìn)行系列化 |
? |
編譯和測(cè)試應(yīng)用程序 |
首先,您需要修改保存和打開模板,以識(shí)別與 scribble 數(shù)據(jù)相關(guān)的文件擴(kuò)展名。
要修改保存和打開的文件類型
1. |
在 eMbedded Visual C++ 左側(cè)窗格的底部,單擊 Resource 選項(xiàng)卡。 |
2. |
單擊 Scribble resources 行旁邊的加號(hào) (+),展開應(yīng)用程序中包含的資源列表。
該列表包含當(dāng)前項(xiàng)目中的七種類別的資源。 |
3. |
單擊 String Table 旁邊的加號(hào) (+),展開項(xiàng)目中的字符串表列表,如下圖所示。
|
4. |
雙擊 English (U.S.)。
第一項(xiàng)包含用于生成 doc/view 模板項(xiàng)的字符串。該字符串是一個(gè)特定的、由新行分隔的、包含七個(gè)子字符串標(biāo)識(shí)的格式字符串(按順序):Window Title、Document Name、File New name、filter name、filter extension、Registry file type ID 以及 Registry file type name。有關(guān)每個(gè)項(xiàng)的詳細(xì)描述,請(qǐng)參閱 CDocTemplate::GetDocString 在線文檔。 |
5. |
雙擊該項(xiàng)修改字符串表中 ID 為 IDR_MAINFRAME 和值為 128 的第一項(xiàng)。 |
6. |
將字符串更改為 Scribble\n\nScribble\nInk Doc (*.ink)\n.ink\nScribble.Document\nScribble Document,如下圖所示。
|
7. |
按下 ENTER 關(guān)閉對(duì)話框。 |
要修改 File | New 行為以清除數(shù)據(jù)結(jié)構(gòu)
1. |
在 eMbedded Visual C++ 左側(cè)窗格的底部,單擊 Class View 選項(xiàng)卡。 |
2. |
如果該類不可見,單擊 Scribble classes 行旁邊的加號(hào) (+)。 |
3. |
定位到 CScribbleDoc 并在必要時(shí)單擊加號(hào) (+) 將其展開。 |
4. |
雙擊 OnNewDocument 方法。 |
5. |
替換下面的行: // TODO: add reinitialization code here
// (SDI documents will reuse this document)
使用該代碼: // Clear the document contents
POSITION WorkPos = m_LineInfo.GetHeadPosition();
while (NULL !=WorkPos)
delete m_LineInfo.GetNext(WorkPos);
m_LineInfo.RemoveAll();
|
MFC 提供了一種可靠的結(jié)構(gòu)體系來簡(jiǎn)化應(yīng)用程序編寫。在編寫保存和打開例程時(shí)可以查看該好處的詳細(xì)示例。在此情況下,您只需修改文檔類的一個(gè)方法(Serialize 方法)。大多數(shù) MFC 基元都支持 Serialize 并使該任務(wù)更簡(jiǎn)單。
要修改 File | Save As 和 File | Open 行為以序列化數(shù)據(jù)
1. |
在文檔中向下滾動(dòng)定位到 Serialize 方法。 |
2. |
替換下面的行: // TODO: add storing code here
使用該代碼: ar << m_LineInfo.GetCount();
// Serialize the document contents
POSITION WorkPos = m_LineInfo.GetHeadPosition();
while (NULL !=WorkPos)
m_LineInfo.GetNext(WorkPos)->Serialize(ar);
替換下面的行: // TODO: add loading code here
使用該代碼: long ElementCount;
ar >> ElementCount;
for (long countPos = 0; countPos < ElementCount; countPos ++)
{
SingleLine * NewLine = new SingleLine();
NewLine->Serialize(ar);
m_LineInfo.AddTail(NewLine);
}
|
現(xiàn)在您就可以再次測(cè)試應(yīng)用程序,以確保所有功能正確無誤。
要編譯和測(cè)試應(yīng)用程序
1. |
單擊 Build | Build Scribble.exe 菜單命令(或按 F7)生成并下載應(yīng)用程序。 |
2. |
更正任何編譯器錯(cuò)誤。 |
3. |
如果下載到仿真程序失敗,進(jìn)行檢查以確保您現(xiàn)在沒有運(yùn)行早期版本的 Scribble.exe。 |
4. |
如果應(yīng)用程序仍然在運(yùn)行,單擊 File | Exit 退出。 |
運(yùn)行新版本之后,您應(yīng)當(dāng)能夠在屏幕上繪制手寫輸入,然后單擊 File | Save As 打開顯示保存選項(xiàng)的對(duì)話框。保存文件后,您可以單擊 File | New 清除內(nèi)容,然后單擊 File | Open 打開以前保存的繪圖。
記住完成測(cè)試后退出應(yīng)用程序。
小結(jié)
以下是本文所提供練習(xí)的小結(jié):
? |
創(chuàng)建了用于 Windows CE 4.1 仿真程序的 MFC 應(yīng)用程序 |
? |
向應(yīng)用程序中添加了鼠標(biāo)捕獲和手寫輸入繪圖 |
? |
修改了應(yīng)用程序以存儲(chǔ)和重繪手寫輸入 |
? |
探索了 eMbedded Visual C++ 的調(diào)試功能 |
? |
添加了保存和打開手寫輸入文檔的代碼 |
轉(zhuǎn)到原英文頁面