從 C++ 向 C# 遷移
發(fā)布日期: 1/24/2005 | 更新日期: 1/24/2005
John Kennedy
Microsoft Corporation
下載
Road07102002-code.exe。
本頁(yè)內容
與生活中的許多事情一樣,有時(shí)要學(xué)習某些知識的唯一方式就是親自去嘗試。當然,也有一些很顯著(zhù)的例外。我可不建議通過(guò)這種方式去學(xué)習外科手術(shù)(哈哈),但是對于學(xué)習智能設備擴展 (SDE) 和用 C# 編寫(xiě)適用于 Pocket PC 的程序,這絕對是一個(gè)很好的方式。
誠然,我們會(huì )越來(lái)越多地接觸到 Microsoft .NET Compact Framework,不管是在本專(zhuān)欄還是在實(shí)際的開(kāi)發(fā)環(huán)節中,這一點(diǎn)不容置疑。更加不容置疑的是,C# 是 .NET Compact Framework 用得最多的一種語(yǔ)言。用 C# 開(kāi)發(fā)了一些程序之后,我對它的易用性、靈活性和優(yōu)雅得體有著(zhù)越來(lái)越深的印象。當然,當前發(fā)行的 Beta 版在某些地方還存在著(zhù)所謂的操作“欠佳”的情況,但這不久就會(huì )得到解決。我堅信,一旦您繼續了解一些新概念,您就會(huì )真正地喜歡使用 C# 和 .NET Compact Framework。
紙牌游戲
我們以前在本專(zhuān)欄中討論過(guò) XML Web 服務(wù),但有些讀者希望我能夠使用智能設備擴展來(lái)創(chuàng )建其他一些連接性不大的編程項目。并不是每個(gè)軟件都需要連接到 Internet,因此這個(gè)新平臺中有些很強大的功能往往會(huì )被忽視。
所以在本月的專(zhuān)欄中,我們將演練一下如何開(kāi)發(fā)一個(gè)適用于 Pocket PC 的更加傳統的應用程序 — 實(shí)際上是一個(gè)游戲,它采用 C# 編寫(xiě)并使用 .NET Compact Framework。使用 C# 進(jìn)行開(kāi)發(fā)與使用 eMbedded Visual C++ 進(jìn)行開(kāi)發(fā)之間存在著(zhù)一些很明顯的差異,對于在編寫(xiě)這個(gè)程序時(shí)所碰到的一些很明顯的問(wèn)題,我希望拿出來(lái)與大家分享一下。
所要討論的游戲非常簡(jiǎn)單。一個(gè)舊版本的紙牌匹配游戲 — Pelmanism。然而,要闡明一些重要的區別和方法還是很復雜的,所以即使您認為它很容易,也不妨試試。如果您要加載并試玩,可以下載源代碼。
這個(gè)游戲的設計十分簡(jiǎn)單,正如您在以下屏幕截圖中所看到的。(這些照片是我的團隊(即 Visual C++ 小組)的所有成員。您可能會(huì )認為,現在當我找他們要求拍照時(shí),他們會(huì )更加謹慎了。當然,我更愿意使用 Drew Barrymore 的照片,但有著(zhù)嚴格的流程……)。屏幕上有十六張紙牌,玩家通過(guò)點(diǎn)擊指示筆來(lái)“翻轉它們”。如果紙牌相匹配,它們就會(huì )從屏幕中消失。我將留給讀者一個(gè)練習 — 添加代碼以便統計翻轉次數、保存成績(jì)等等。是的,這表明我在偷懶。不過(guò)要知道,我也忙乎了一天呢!第一個(gè)人在問(wèn)我花多少時(shí)間在 Xbox 上玩 Halo 時(shí)懷著(zhù)一種很鄙夷的目光。
圖 1. 您知道,我被 Xbox 團隊逼著(zhù)討論這張圖的許可權。當然,實(shí)際上這是個(gè)謊言。
返回頁(yè)首圖形和 SDE
C# 程序與 eMbedded Visual C++ 的工作方式有著(zhù)很大的不同,它從 Visual Basic 繼承了窗體 的概念。從技術(shù)角度看,改變并不大,但我希望能夠引起您的注意。您可能也知道,窗體其實(shí)就是一個(gè)頁(yè)面,您可以在其中添加控件、顯示文本、從中接收屏幕點(diǎn)擊消息等等。當我們在 Visual Studio .NET 中創(chuàng )建一個(gè)默認項目時(shí),系統會(huì )自動(dòng)為我們提供一個(gè)默認窗體。
圖 2. 一個(gè)空白窗體,準備讓我們展現自己的想象力和才干。
您可以發(fā)現,窗體的左邊是一組控件,我們可以將它們拖放到窗體中,也就是拖放到我們的程序中。與使用 eMbedded Visual C++ 工具箱相比,您會(huì )發(fā)現,編輯器中控件的可視化外觀(guān)與因此而創(chuàng )建的源代碼之間的聯(lián)系更加緊密。試試一些控件并觀(guān)察代碼。Visual Studio 保持跟蹤的方式給人的印象很深。
一句話(huà)警告源代碼中有些地方不要手動(dòng)進(jìn)行更改。由于某種原因我忽視了這個(gè)告誡,當我在設計器中調整窗體時(shí)就丟失了代碼,所以要謹記。
可以在窗體中添加的一個(gè)控件是 PictureBox,這是一個(gè)顯示圖像的控件。我打算對游戲所顯示的每張紙牌都使用一個(gè) PictureBox。它與最初采用 C++ 編寫(xiě)這個(gè)程序的方式有所不同。如果用 C++ 創(chuàng )建,我就需要創(chuàng )建窗口(現在我們稱(chēng)之為窗體)并獲得 HDC(顯示上下文句柄),然后使用 BitBlt 將一大堆圖形數據變?yōu)閷?shí)際的圖形。這次,我打算使用十六個(gè) PictureBox 控件,并使用它們的方法來(lái)定義它們顯示什么圖像。您將會(huì )看到,這種方式是相當得體的。
當然,知道我們要顯示十六張紙牌,您可能會(huì )試著(zhù)將十六個(gè) PictureBox 拖到窗體中,然后調整它們的大小并將它們排列整齊。這是個(gè)好主意,但通過(guò)編程方式處理每個(gè)控件很快就會(huì )變成一項很瑣碎的事情。更好的做法是創(chuàng )建一組 PictureBox,然后使用索引對它們進(jìn)行處理,一會(huì )兒您將看到,我就是這樣做的。所以,盡管設計器十分有用,但我們并不一定要使用它來(lái)添加 PictureBox 控件。
讓我們來(lái)簡(jiǎn)單地看一些源代碼。C# 程序在大部分地方很像 C++ 程序。比如函數、if() 語(yǔ)句、do/while 和大量圓括號。然而,也有一些細微(而非很顯著(zhù))的區別。
舉一些基本的例子,比如很好而又老舊的 #define 語(yǔ)句。我如何向您說(shuō)明呢?它已經(jīng)過(guò)時(shí)了。當然,它也沒(méi)有完全過(guò)時(shí),只是做了點(diǎn)更改。在 C# 程序中,#define 只能用于創(chuàng )建標識符。您不能使用它來(lái)創(chuàng )建常量,比如 #define X_WIDTH 100。
了解這一點(diǎn)之后,我們再看一些數組聲明。需要二維整數數組嗎?不要再認為是 int grid[4][4];,而應該是 int[,] grid = new int[4,4] ; 。
了解此信息之后,您應該能夠明白游戲開(kāi)頭的這段代碼有何用處:
圖 3. 通過(guò)編程方式創(chuàng )建控件很容易,而且它們在編輯器中顯示了所有方法以提示您下一步做什么。
這段代碼聲明了一些數組:一個(gè)用于存儲玩紙牌時(shí)用到的 9 張不同的圖像,一個(gè)用于存儲可能存有紙牌的 16 個(gè)位置中的紙牌類(lèi)型,一個(gè)用于存儲 PictureBox 控件本身。
然后,我們按相同的方式處理所有這些 PictureBox 對象,創(chuàng )建它們、將它們添加到窗體中,并調整它們的大小和位置。請注意應用于每個(gè)對象的方法和屬性(例如 Location)如何通過(guò)句點(diǎn)與對象分開(kāi)。Visual Studio 集成開(kāi)發(fā)環(huán)境 (IDE) 非常智能,一旦您鍵入句點(diǎn),它就會(huì )彈出一個(gè)列表,其中包含您可以對這個(gè)對象執行的所有正確操作。這只是一個(gè)方面,說(shuō)明了 C# 讓人感到編寫(xiě)代碼是一件很愉快的事。
如果您也和我一樣,您就會(huì )喜歡在程序中添加 MessageBox 調用,以便隨時(shí)了解發(fā)生的事情。使用智能設備擴展也可以擁有這樣的能力:只需使用以下語(yǔ)法:
Messagebox.Show("Hello");
當然還有更多的選項,有關(guān)完整的列表,請參閱聯(lián)機幫助。
考慮圖像
想知道當我們玩紙牌時(shí)如何加載以顯示一些圖像嗎?我也很想知道,因為 .NET Compact Framework 缺少 .NET Framework 的一些功能,連我首選的方法都沒(méi)有。不過(guò)它仍然十分簡(jiǎn)單,如果您在通讀示例源代碼時(shí)稍加注意,就會(huì )發(fā)現它與 Image 對象有點(diǎn)關(guān)系。
下面是另一段代碼。這是一個(gè)函數,通過(guò)調用它,可以從磁盤(pán)(其實(shí)是內存,只要您明白我的意思)加載圖像,并將前面聲明的圖像數組中的元素分配給它。
圖 4. 從內存中加載圖像非常容易。
.bmp 文件是我在一個(gè)涂鴉程序中創(chuàng )建的圖像集合,并預先對它進(jìn)行縮放以適合 PictureBox 控件的大小。我習慣于使用 .bmp 格式,不過(guò)該控件也支持其他常見(jiàn)的文件格式。
我相信您已經(jīng)很熟悉 try/catch 異常處理了,它是一種可選方式,不過(guò)建議您養成使用它的習慣。如果圖像加載失敗,就會(huì )執行 catch() { } 中的代碼。這明顯能使代碼更加健壯可靠,不過(guò)如果能多做些事情(而不只是警告用戶(hù)程序將要終止),那就更有用了。
如果您使用小巧的 Pocket PC 模擬器(它附帶智能設備擴展)來(lái)試運行這個(gè)示例程序,您可能不知道如何將 .bmp 圖像文件從開(kāi)發(fā)用的計算機移到模擬的 Pocket PC 中。讓我告訴你吧,因為這個(gè)過(guò)程與早期的 Pocket PC 開(kāi)發(fā)工具相比有了一些更改 — 您一猜就知道我對它有很深的印象。
將文件復制到模擬器
1.
啟動(dòng)模擬器(如果尚未啟動(dòng))。
2.
從 Start 菜單中,選擇 Settings,然后選擇 System 選項卡。
3.
單擊 About,然后單擊 DeviceID 標簽。
4.
將設備名稱(chēng)從 Pocket_PC 改成其他的名稱(chēng)。
圖 5. 更改設備 ID,否則當模擬器與桌面計算機通信時(shí)會(huì )報錯。
5.
現在啟動(dòng) Pocket PC 上的文件瀏覽器程序。
6.
點(diǎn)擊網(wǎng)絡(luò )共享圖標。該圖標位于屏幕底部的最右邊。
7.
輸入通過(guò) LAN 訪(fǎng)問(wèn)您的計算機時(shí)所需的詳細信息。
8.
瀏覽至桌面計算機上的共享文件夾,然后選擇要復制的文件。
9.
點(diǎn)擊 Pocket PC 上的文件并按住不放。
注 模擬器存在一個(gè) bug,您可能需要按住鼠標鍵 30 秒鐘才會(huì )看到紅點(diǎn)以及隨后的彈出菜單。
10.
復制文件,返回到 Pocket PC 自己的目錄下并粘貼。
圖 6. 瀏覽至桌面計算機上的共享文件夾,然后復制文件并將其粘貼到您的(模擬的)Pocket PC。
這就是所有的步驟。
鄭重宣布,這就是這個(gè)小程序的全部?jì)热萘?。當然,我還添加了一些菜單,使用窗體設計器,要多簡(jiǎn)單就有多簡(jiǎn)單。有一件事令我考慮了許久,那就是如何處理用戶(hù)的指示筆點(diǎn)擊操作。
我對 Visual C++ 程序的理論分析是這樣的:占據整個(gè)屏幕并接受鼠標按下的消息,解出 X 和 Y 坐標,然后算出用戶(hù)點(diǎn)擊的紙牌。在這種情況下,每張紙牌都是一個(gè)控件,而每個(gè)控件都會(huì )單獨地響應鼠標按下的消息。我無(wú)法包含那種具有全局性質(zhì)的“點(diǎn)擊屏幕并獲得消息”代碼。
然而,為每個(gè)控件指定處理程序是很簡(jiǎn)單的。這就是源代碼的第一個(gè)代碼塊中的行:
this.pictureBox[x,y].Click += new System.EventHandler(this.UserTapsScreen);
您可以看到,我對每個(gè)控件都添加了相同的函數 (UserTapsScreen)。這明顯有個(gè)疑問(wèn),那就是“在該函數中,我如何知道消息由哪個(gè)控件發(fā)出?”以下就是實(shí)現這一點(diǎn)的源代碼:
private void UserTapsScreen(object sender, System.EventArgs e){int cardx = -1;int cardy = -1;// Find the card that send the messagefor (int x=0; x<4; x++)for (int y=0; y<4; y++)if (sender.Equals(pictureBox[x,y])){cardx = x;cardy = y;y=4;x=4;}...
請注意,這段代碼使用了傳遞給 UserTapsScreen 函數的 sender 參數的一個(gè)屬性,以及它的 Equals 方法。
返回頁(yè)首聲音效果
一個(gè)游戲要是沒(méi)有聲音效果那就毫無(wú)價(jià)值。這就是我們下個(gè)月要介紹的內容。同時(shí),請下載源代碼并試玩一下。如果您有任何問(wèn)題,請隨時(shí)
給我發(fā)送電子郵件。但是,如果您是專(zhuān)門(mén)發(fā)送垃圾郵件的公司,打算一天要給我發(fā)送十二次電子郵件來(lái)向我提供一些衣著(zhù)、電子和色情信息,那就另當別論了!
John Kennedy 白天是 Visual C++ 小組的技術(shù)作家/編程人員;而夜晚,他享受著(zhù) Pocket PC 開(kāi)發(fā)人員的秘密生活。
Larry Roof 創(chuàng )立了
larryroof.com,這是一家專(zhuān)門(mén)從事移動(dòng)項目咨詢(xún)和 eMbedded Visual Basic、智能設備擴展和 SQL Server CE 方面培訓的公司。