精華區beta C_and_CPP 關於我們 聯絡資訊
之前用wxWidgets寫過簡單的Dialog對話框,發覺好像沒有 用到很深奧的C++,多半是用到繼承和會寫簡單的class 就 好了,那MFC/.net 也差不多是這樣嗎? 我只是想把程式的 輸入和輸出改成視窗介面而已。 目前正在讀Ivor Horton寫的Visual C++教學手冊 ------------------------ 原諒我如果這是一個爛問題 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.229.79.23
HZYSoft:MFC 要會的和 wx 差不多,不用懂很多218.167.101.128 08/14
HZYSoft:這不是個爛問題,不過 MFC 是個爛 library218.167.101.128 08/14
khoguan:MS本身的產品(Office等等)也不用MFC開發220.130.208.168 08/14
renderer:那用什麼開發 ??? Win32 ??? 還是另有一套 ? 222.156.10.167 08/14
Qutineen:KFC? 219.68.79.162 08/14
windows2k:這不是肯德基 >< 220.130.43.108 08/14
OTP:請教一下Office不用MFC開發?那用什麼?...MFC哪裡爛?쐠 59.115.74.101 08/14
HZYSoft:Office 開始發展時 MFC 應該還沒出現218.167.101.128 08/14
OTP:那是用啥樣的編譯器阿?...是Borland的產品?....謝謝. 59.115.74.101 08/14
dybert:我覺的ivor horton那一本很ooxx..極不欣賞... 218.165.96.83 08/14
> -------------------------------------------------------------------------- < 作者: khoguan (Khoguan Phuann) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Sun Aug 14 16:24:22 2005 ※ 引述《bobhsiao (㊣小臃腫㊣)》之銘言: : 標題: 只想會使用MFC,C++大約要會到什麼程度? : 之前用wxWidgets寫過簡單的Dialog對話框,發覺好像沒有 : 用到很深奧的C++,多半是用到繼承和會寫簡單的class 就 : 好了,那MFC/.net 也差不多是這樣嗎? 我只是想把程式的 : 輸入和輸出改成視窗介面而已。 : 推 HZYSoft:MFC 要會的和 wx 差不多,不用懂很多 218.167.101.128 08/14 : 推 HZYSoft:這不是個爛問題,不過 MFC 是個爛 library 218.167.101.128 08/14 : 推 khoguan:MS本身的產品(Office等等)也不用MFC開發 220.130.208.168 08/14 : 推 renderer:那用什麼開發 ??? Win32 ??? 還是另有一套 ? 222.156.10.167 08/14 : 推 Qutineen:KFC? 219.68.79.162 08/14 : 推 windows2k:這不是肯德基 >< 220.130.43.108 08/14 : 推 OTP:請教一下Office不用MFC開發?那用什麼?...MFC哪裡爛?쐠 59.115.74.101 08/14 : 推 HZYSoft:Office 開始發展時 MFC 應該還沒出現 218.167.101.128 08/14 : 推 OTP:那是用啥樣的編譯器阿?...是Borland的產品?....謝謝. 59.115.74.101 08/14 嗯,沒想到引來一些回響 :-) 關於 MS 到底用什麼東東來開發 Office 以及它的各種重量級 產品這個問題呢?因為我之前想到這個問題,心裡很好奇,又 google 不出個所以然,所以就去 microsoft.public.vc.mfc 問人家,得到一個 blog link, 是一個 MS 的高階員工的 blog: MFC or WinForms: More Advice http://blogs.msdn.com/texblog/archive/2005/07/11/437750.aspx 節錄: So, what does MS use? Almost all current Microsoft products are written in VC++. Very few use MFC. Some newer projects are being done in C# and C++/CLI. I don't think it was ever a huge secret that MFC never caught on significantly within Microsoft. The Office apps would seem to have been the biggest candidates, but each is instead written with its own very specialized framework tailor made for the application. At any rate, that ship has sailed, and we're unlikely to see new Microsoft projects being written from the ground up in MFC. 所以答案就是「MS 內部自用的特製 framework」,當然 那也是建立於 Win32 API 上面的。 看來是因為那些產品很久之前就開始在開發了,那時的 MFC 完全不成熟,不堪用。一方面很可能也是 MFC 連 MS 本身的產品開發人員都不太欣賞吧 XD 到了這年頭,他們要用的話也是用 C# 和 C++/CLI 了。 至於類似 Delphi/BCB 那種「拉一拉點一點填一填就OK」 的迷人 RAD 環境,VC++ .NET 2003 才開始出現(C# 早一年) 但至今市面上的中文書仍然絕少對此著墨。現在 VC++ 2005 又快要推出了,這方面似乎又有增強,但究竟能不能和 早已極成熟的 Delphi/BCB 比呢?還請有經驗的大大們 解惑。 -------------- ※ 編輯: khoguan 來自: 220.130.208.168 (08/14 16:36)
OTP:請教一下VC++和MFC不依樣喔?!....:P 59.115.74.101 08/14
UNARYvvv:VC跟MFC性質不同 一樓這樣比很奇怪 61.70.137.117 08/14
※ 編輯: khoguan 來自: 220.130.208.168 (08/14 16:47)
OTP:sorry啦...小妹我之前是買VC++的光碟片... 59.115.74.101 08/14
LPH66:這個回答有點無言..應該說MFC是VC++內附的library 219.84.44.21 08/14
LPH66:只不過並不一定要在寫視窗程式時用MFC罷了 219.84.44.21 08/14
sheauren:IDE平台跟framework不好比較... 220.131.39.200 08/15
> -------------------------------------------------------------------------- < 作者: HZYSoft (PCMan 2004) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Sun Aug 14 23:03:42 2005 ※ 引述《khoguan (Khoguan Phuann)》之銘言: : ※ 引述《bobhsiao (㊣小臃腫㊣)》之銘言: : : 標題: 只想會使用MFC,C++大約要會到什麼程度? : : 之前用wxWidgets寫過簡單的Dialog對話框,發覺好像沒有 : : 用到很深奧的C++,多半是用到繼承和會寫簡單的class 就 : : 好了,那MFC/.net 也差不多是這樣嗎? 我只是想把程式的 : : 輸入和輸出改成視窗介面而已。 : : 推 HZYSoft:MFC 要會的和 wx 差不多,不用懂很多 218.167.101.128 08/14 : : 推 HZYSoft:這不是個爛問題,不過 MFC 是個爛 library 218.167.101.128 08/14 : : 推 khoguan:MS本身的產品(Office等等)也不用MFC開發 220.130.208.168 08/14 : : 推 renderer:那用什麼開發 ??? Win32 ??? 還是另有一套 ? 222.156.10.167 08/14 : : 推 Qutineen:KFC? 219.68.79.162 08/14 : : 推 windows2k:這不是肯德基 >< 220.130.43.108 08/14 : : 推 OTP:請教一下Office不用MFC開發?那用什麼?...MFC哪裡爛?쐠 59.115.74.101 08/14 : : 推 HZYSoft:Office 開始發展時 MFC 應該還沒出現 218.167.101.128 08/14 : : 推 OTP:那是用啥樣的編譯器阿?...是Borland的產品?....謝謝. 59.115.74.101 08/14 : 嗯,沒想到引來一些回響 :-) : 關於 MS 到底用什麼東東來開發 Office 以及它的各種重量級 : 產品這個問題呢?因為我之前想到這個問題,心裡很好奇,又 : google 不出個所以然,所以就去 microsoft.public.vc.mfc : 問人家,得到一個 blog link, 是一個 MS 的高階員工的 blog: : MFC or WinForms: More Advice : http://blogs.msdn.com/texblog/archive/2005/07/11/437750.aspx : 節錄: : So, what does MS use? : Almost all current Microsoft products are written in VC++. : Very few use MFC. Some newer projects are being done in C# : and C++/CLI. : I don't think it was ever a huge secret that MFC never caught : on significantly within Microsoft. The Office apps would seem : to have been the biggest candidates, but each is instead written : with its own very specialized framework tailor made for the : application. At any rate, that ship has sailed, and we're : unlikely to see new Microsoft projects being written from : the ground up in MFC. : 所以答案就是「MS 內部自用的特製 framework」,當然 : 那也是建立於 Win32 API 上面的。 M$ Office 不使用 MFC,甚至完全不使用 Windows Common controls 連各種 control 都是用 Win32 API 自己重新硬幹一套,他應該是有自己的 library。 所以 Office 裡面的各種視窗元件在其他程式都不容易找到,因為 Windows 沒內建 MFC 早期是個完全不堪用而且 bug 極多的產品,事實上連 MFC 1.0 在開發時 因為 Afx 小組把他搞得太過複雜效率又差,連 M$ 內部的人員也無法使用 早期可說完全是個失敗品。 Office 出生的時候應該還沒有 MFC 吧,且當時的 MFC 也不堪用,不用他很正常。 至於 compiler,M$ 的一些產品還是用 Microsoft C++ 也不是用 Visual C++ 編譯。 而 M$ Visual C++ 在 5.0 之前編譯器品質也很糟糕 後期因為大量挖角 Borland 等其他公司的台柱,因此突飛猛進,但是 VC 6.0 仍然 是個糟糕的產品,因為對 C++ 標準符合度極差。 直到近期因為 M$ 延攬 C++ 標準 委員會的人,這個長久的問題才開始改善。 這也解釋了為何 MFC 是最爛的選擇, 因為早期的 MFC 發展時,C++ 也還不成熟, VC++ 也不成熟,因此依靠一些 不標準的語法,和完全違反現代 C++ 特性的方法,來讓 MFC 運作,因此,MFC 無法 在任何除VC++之外的編譯器上編譯,除了 Borland (Borland 的編譯器必須要打開 特殊選項來相容 MFC,才有辦法使用,預設是無法編譯),以及 Intel C++ compiler (Intel C++ Compiler 設計成相容 VC++ 且搭配 VC++ 使用) 以外,因此,MFC 是個 號稱使用 C++,卻根本無法在標準 C++ 和一般 C++ compiler 下使用的產品。 另外,MFC 在物件導向的使用上也相當失敗,基本上只是把 Windows API 加上一層 包裝,增加更多 overhead,卻沒有好用到哪裡去。 只允許單一繼承,並且使用大量難用 且相當畸形的 C 語言巨集來實做 RTTI 和 template (這是因為 MFC 開始發展時 C++ 還沒有 template 和 RTTI )。又因為歷史因素,為了符合 Win32 API 的使用習慣 所有的命名規則還是使用惡名昭彰的匈牙利命名法,並且名稱都和 Win32 API 一致 大多數 C++ 物件和其 method 也幾乎和 Win 32 API 是一對一對應,形同沒有封裝 此外,網路功能的嚴重缺乏更是離譜,其內建的 CSocket 甚至無法在 multi-threading 下正常使用,一使用就當機,不但功能簡陋,更是難以擴充使用。 而為了歷史包袱, 在 2005 年的今天,MFC 內部仍然充滿了大量 for Windows 3.1 的程式碼 即使自 5.0 版之後的 VC++ 早就不支援編譯 Win 3.1 的程式。 個人用了好幾年 MFC 以及其他 GUI library 之後,最後得到的結論就是: 在即將邁入 2006 年的今天,如果你還在想學 MFC,你一定是瘋了! 順道一提,M$ 也是有用 MFC 開發軟體的,例如 FrontPage Express 大概沒人記得這個失敗的網頁編輯軟體,那是當年跟 Internet Explorer 4.0 包在一起的精簡版網頁編輯軟體,不曾聽說過有誰用過 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.231.53.110
bobhsiao:給我們一盞明燈吧~騙吃騙喝還是要靠微軟的..= = 61.229.79.23 08/14
renderer:大大可以順道評一下 Qt wxWidgets GTK 嗎 感謝 61.228.220.61 08/14
OTP:HZYSoft是台灣軟體業之寶.....佩服 59.115.72.14 08/15
Neo1978:請問匈牙利命名法有什麼缺點? 61.224.207.59 08/15
> -------------------------------------------------------------------------- < 作者: HZYSoft (PCMan 2004) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Wed Aug 17 23:46:48 2005 ※ 引述《HZYSoft (PCMan 2004)》之銘言: : 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? : 時間: Sun Aug 14 23:03:42 2005 : <deleted /> : : -- : ※ 發信站: 批踢踢實業坊(ptt.cc) : ◆ From: 61.231.53.110 簡單回一下以下推文 : 推 bobhsiao:給我們一盞明燈吧~騙吃騙喝還是要靠微軟的..= = 61.229.79.23 08/14 既然是這樣叫微軟給你明燈吧,要死忠追隨微軟可能學 C# + .net 會比較好 : 推 renderer:大可以順道評一下 Qt wxWidgets GTK 嗎 感謝 61.228.220.61 08/14 我等一下另開標題貼一篇 GUI toolkit 的評論,請參閱 : 推 OTP:HZYSoft是台灣軟體業之寶.....佩服 59.115.72.14 08/15 你搞錯了,我不是軟體業的,我只是業餘自己好玩偶爾寫寫小程式。 板上有很多台灣軟體業之寶,小弟不敢班門弄斧 : 推 Neo1978:請問匈牙利命名法有什麼缺點? 61.224.207.59 08/15 多很多綴字,又不好看又不好記打起來又麻煩,在現代 IDE 輔助下,實用性並不高。 舉例,有個變數 Var 型態是 Long Pointer to a Zero-terminated String,那你就必須 在變數名稱前面加上 lpsz,變成 lpszVar,凡是遇到 long pointer 變數,命名一律 必須前綴 LP,於是傳統採匈牙利命名的 Win32 SDK 程式中到處都充滿 LP。 Handle of WiNDow 這個型別,就必須命名為 HWND,這類變數有時得前綴 hwnd, 這樣很難記又沒意義,又降低可讀性,在現代的程式已經沒有實用價值了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.129.59.3 > -------------------------------------------------------------------------- < 作者: pcjustin (駱駝) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Thu Aug 18 14:43:39 2005 : : 推 Neo1978:請問匈牙利命名法有什麼缺點? 61.224.207.59 08/15 : 多很多綴字,又不好看又不好記打起來又麻煩,在現代 IDE 輔助下,實用性並不高。 : 舉例,有個變數 Var 型態是 Long Pointer to a Zero-terminated String,那你就必須 : 在變數名稱前面加上 lpsz,變成 lpszVar,凡是遇到 long pointer 變數,命名一律 : 必須前綴 LP,於是傳統採匈牙利命名的 Win32 SDK 程式中到處都充滿 LP。 : Handle of WiNDow 這個型別,就必須命名為 HWND,這類變數有時得前綴 hwnd, : 這樣很難記又沒意義,又降低可讀性,在現代的程式已經沒有實用價值了。 可以請HZYSoft幫我們介紹一些命名的好方法 我一直以為匈牙利命名是好方法 一一" 看來被我一些windows的書騙了 還特別去學了一下 只是後來發現命名規則好麻煩 最後只學了一些簡易的 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 219.91.83.151
StubbornLin:有人說它是惡魔的禮物= =" 是不是我不知道XD 59.116.64.30 08/18
khoguan:請先看一下 9257 篇,謝謝。220.130.208.168 08/18
khoguan:Oh, no! 噓錯了,對不起。我是要噓下一篇。220.130.208.168 08/18
sekya:Orz 我看成9527... 59.104.35.143 08/18
> -------------------------------------------------------------------------- < 作者: UNARYvvv (有趣生活) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Thu Aug 18 15:34:08 2005 ※ 引述《pcjustin (駱駝)》之銘言: : : 多很多綴字,又不好看又不好記打起來又麻煩,在現代 IDE 輔助下,實用性並不高。 : : 舉例,有個變數 Var 型態是 Long Pointer to a Zero-terminated String,那你就必須 : : 在變數名稱前面加上 lpsz,變成 lpszVar,凡是遇到 long pointer 變數,命名一律 : : 必須前綴 LP,於是傳統採匈牙利命名的 Win32 SDK 程式中到處都充滿 LP。 : : Handle of WiNDow 這個型別,就必須命名為 HWND,這類變數有時得前綴 hwnd, : : 這樣很難記又沒意義,又降低可讀性,在現代的程式已經沒有實用價值了。 : 可以請HZYSoft幫我們介紹一些命名的好方法 : 我一直以為匈牙利命名是好方法 一一" : 看來被我一些windows的書騙了 : 還特別去學了一下 : 只是後來發現命名規則好麻煩 : 最後只學了一些簡易的 或許可以先看看這篇文章 (分別是 中文 & 英文) http://chinesetrad.joelonsoftware.com/Articles/Wrong.html http://www.joelonsoftware.com/articles/Wrong.html -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.70.137.117
HZYSoft:推,謝謝你提供的連結,好文! 140.129.59.3 08/18
pcjustin:push,借轉 219.91.94.217 08/18
godfat:我也討厭 exception handling T-T 61.224.46.135 08/26
> -------------------------------------------------------------------------- < 作者: renderer (rendering) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Fri Aug 19 23:57:32 2005 ※ 引述《HZYSoft (PCMan 2004)》之銘言: : -- : ※ 發信站: 批踢踢實業坊(ptt.cc) : ◆ From: 61.231.53.110 : 推 bobhsiao:給我們一盞明燈吧~騙吃騙喝還是要靠微軟的..= = 61.229.79.23 08/14 : 推 renderer:大大可以順道評一下 Qt wxWidgets GTK 嗎 感謝 61.228.220.61 08/14 : 推 OTP:HZYSoft是台灣軟體業之寶.....佩服 59.115.72.14 08/15 : 推 Neo1978:請問匈牙利命名法有什麼缺點? 61.224.207.59 08/15 匈牙利命名法最大的缺點是,現今它沒有任何基於必要性的優點,以至於它所有缺點 的負分加起來,就差不多是它的總得分。 變數的型別是什麼,從變數的定義就看得出來了,何必要把型別縮寫加在變數上呢? 可能需要它的理由是 「找不到變數定義」 如 global 變數,不知道它被定義在哪一個檔案,又沒有 IDE 的時候。 「懶得找變數定義」 對於一個千百行的函式,你不會想中途看到一半,時常要 Scroll 到前面去 看變數定義,尤其是 C 程式。 「猜不到變數型別是什麼」 以前的變數命名比較短,如 kn,猜都猜不出來可能的型別是什麼。 然而,現在的程式寫作習慣改變了,尤其是 C++ 或說物件導向的程式寫作。 「容易知道變數被定義在哪裏」 物件導向程式寫作有一個重要的認知是:物必有主。一個變數一定會有個主。 global 變數不被鼓勵使用,而以 class static member 取代之,你很容易 知道他被定義在哪裏。 「變數定義就在旁邊而已,不必你找」 小函式的使用被鼓勵,對於一個 20 行內的函式,你絕對看得到變數定義。 對於大一點的函式, C++ 讓你可以在變數使用的前一刻宣告即可,這種寫作 方式也被鼓勵。對於一個不認識的變數,它的定義就在前幾行而已。 「猜得到變數型別是什麼」 完整的變數命名被鼓勵,加上物件導向的特性,很容易猜得出變數型別。 如視窗 window.height 會是一個 unsigned int。 man.height 大概就是一個 float 了。 所以基本上,匈牙利命名法在現在已經沒有任何基於必要性的優點了。 匈牙利命名法的缺點是: 「好煩」 我已經知道這個變數是 int 了,為什麼程式碼到處都在說它是 int 。 「不清爽」 vector.x 不是很好嗎,為什麼要寫 vVector.fx。 「變數改型別的時候怎麼辦」 變數改變型別是有可能的,如果一個變數分佈在 20 個檔案,最起碼要改 20 次。當然,有好的開發環境可能會方便一點。如果是發佈給人家用的 API 呢,改變型別縮寫,鐵定會被客戶抱怨一下。 「五技而窮」 基於物件導向,以及程式規模愈來愈大,大量的自定型別被定義,如何去為這 些型別找個容易識別的縮寫呢? 「以理類推,函式前面也要加回傳型別的縮寫呀,這樣才統一呀!!!」 如果變數前面要加型別縮寫才行,那為什麼有回傳值的函式不用,總是要平等 對待呀。如 fsqrt(),man.fGetHeight()。天阿!應該沒有人會這樣子用。一 個無法貫徹於各種情況的風格,可能不是一個好的風格。 「難以為多型物件命名」 如 Man* mnRenderer = new Programmer; 好 還是 Man* pgmRenderer = new Programmer; 好 在物件導向程式寫作裏,一個變數的角色與行為,會比它的型別來得重要。 「無法用於泛型程式寫作」 如 template<class TYPE> class Vector { public: TYPE x; TYPE y; TYPE z; }; 這裏的 x,y,z 前面要加什麼縮寫好? ... 結論是,匈牙利命名法還真奇怪,不過它也許有它的時代意義。 另外,像是 g_XXX , m_XXX 也是沒有必要的。 「g_XXX」 程式裏不太應該要有 global 變數,放到 class static member,g_ 就用不 上了。如 Man::Count,你一定知道它是一個唯一的變數。 「m_XXX」 m_XXX 也是沒有必要的,如: vector.m_x; m_ 是個贅字,"." 本身就說出 x 是它的 member 了。 另外 void Vector::operator = (const Vector& b) { this->x = b.x; this->y = b.y; this->z = b.z; } 是比下面的寫法來得對稱的: void Vector::operator = (const Vector& b) { m_x = b.m_x; m_y = b.m_y; m_z = b.m_z; } m_ 唯一有用的是在 member function 裏,然而加 this-> 就好了。 this-> 是語言提供的本尊原生寫法,另立主張,有人喜歡,有人不喜歡, 這樣就不好了。 另外,應該讓 class 的使用者使用乾淨的介面, vector.m_x,其實是多給 使用者麻煩。考慮使用者的方便,會比讓自己方便來得重要。 建議參考 Java Convention http://java.sun.com/docs/codeconv/ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.228.217.108 ※ 編輯: renderer 來自: 61.228.217.108 (08/20 00:11)
UNARYvvv:(兩行推文完全消失><) 61.70.137.117 08/20
UNARYvvv:老實說我假如看到 man.height 這個東西 61.70.137.117 08/20
UNARYvvv:會想到用 unsigned char..畢竟 0~255 夠了..XDD 61.70.137.117 08/20
renderer:呵呵 那我舉例不當 ..XDD 61.228.217.108 08/20
> -------------------------------------------------------------------------- < 作者: powerair (max) 看板: C_and_CPP 標題: Re: 只想會使用MFC,C++大約要會到什麼程度? 時間: Mon Dec 12 13:34:47 2005 ※ 引述《HZYSoft (PCMan 2004)》之銘言: : : 推 Neo1978:請問匈牙利命名法有什麼缺點? 61.224.207.59 08/15 : 多很多綴字,又不好看又不好記打起來又麻煩,在現代 IDE 輔助下,實用性並不高。 : 舉例,有個變數 Var 型態是 Long Pointer to a Zero-terminated String,那你就必須 : 在變數名稱前面加上 lpsz,變成 lpszVar,凡是遇到 long pointer 變數,命名一律 : 必須前綴 LP,於是傳統採匈牙利命名的 Win32 SDK 程式中到處都充滿 LP。 : Handle of WiNDow 這個型別,就必須命名為 HWND,這類變數有時得前綴 hwnd, : 這樣很難記又沒意義,又降低可讀性,在現代的程式已經沒有實用價值了。 很抱歉挖出這麼久以前的po文來回 小弟剛來這 難免要先考古一番 看到匈牙利命名法 想到曾在課堂上聽老師提過 找到了一篇關於匈牙利命名法的文(其實是在為匈牙利命名法平反) 文章內提到 匈牙利命名法分為 "應用"與"系統"匈牙利命名法 被鞭的大都是系統匈牙利命名法(也就是HZYSoft大大所舉的例子) 而當初匈牙利命名法被Simonyi(M$ Word團隊裡的人)提出時本意並非為此 讓錯的程式看得出錯 作者: 周思博 (Joel Spolsky) http://chinesetrad.joelonsoftware.com/Articles/Wrong.html -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.229.162.149
UNARYvvv:話說當時我的 9284 就是 po 出這個連結回 HZY 大大啊..XD 12/12 21:05
UNARYvvv:9284 篇 12/12 21:06
> -------------------------------------------------------------------------- < 作者: purpose (purpose) 看板: C_and_CPP 標題: Re: [問題] mfc不知如何下手 時間: Thu Apr 7 06:39:04 2011 ※ 引述《steven70101 (老人)》之銘言: : 最近剛入公司,要學習MFC的用法 : c++跟win32 api都是略懂(程式越學越不敢說懂...) : 有用 win32 api 寫出俄羅斯方塊的經驗 : 遊戲畫面 : http://ppt.cc/QY_N : 但是現在在看MFC時有種找不到下手點的感覺 : 會按照範例寫出最基本的一個空視窗 : 也看了另一個範例教你怎麼拉功能表 : 但是看了看卻忽然感覺,那我應該怎麼下筆囧 : 是用那基本的空視窗在新增 .rc 然後去拉嗎? : 那程式碼部分應該怎麼寫? 我也是新手,提供一點看法。 不管怎麼教、怎麼學 MFC,有些最基本的東西都要掌握住。 要搞懂什麼是 Dialog-Based,什麼是 SDI、MDI。 因為每次開新的 MFC 專案,第一個要選的就是這件事情。 可以先從既有的軟體去比較,如果這個軟體跟你要寫的類似,那再分析它是 用 Dialog 還是 SDI 或 MDI 寫。 如果對方也用 MFC 寫,又有 Open Source 那你當然直接開他的 .sln 看最快。 版友之前貼過的,比較知名的 MFC 開源專案: http://www.codeproject.com/KB/cpp/OpenSource_VC_MFC.aspx MFC 裡有很多比較方便的功能,都得使用 DOC/VIEW 才有。 換言之,至少得選 SDI、MDI 專案才能使用這些功能。 問題是 Dialog 一開始就能用拖曳的方式加入控件 (or Control or 控制項), 而 SDI 與 MDI 一開始沒地方加! 這是一個常見問題。 解決的方法是開 SDI 專案時,自己更改設定,把 View 類從預設的繼承自 CView 改成繼承自 CFormView。 那這個 SDI 的客戶區就會跟 Dialog 一樣,隨便你用滑鼠拖曳去添加控件了。 當你拖曳好軟體介面後,接下來要考慮的兩件事,來決定程式碼怎麼寫: 1. 要處理哪些事件 為什麼需要處理事件,這理由就不需要多談。 當使用者敲下某個鍵盤按鍵,Windows 會告知發生 "WM_KEYDOWN" 給有 focus 的視窗。 然後看此視窗的決定,是要如何處理掉此事件。 如果該視窗選擇「不處理」,那就「到此為止」。這是由 Windows 定下的規則。 可是 MFC 對於 message 的傳遞有自己的路線,不再死守 Windows 規定。 (進階版的事件處理) 如果是 DOC/VIEW 程式,則會看有 focus 的視窗打不打算處理這個 "WM_KEYDOWN", 這個 focus 視窗通常是第一線的 View 類視窗。 如果 View 類不處理,那麼就將訊息轉送給 Doc 類。 如果 Doc 類又不想處理,那就再轉交給框架視窗 (CFrameWnd), 而框架視窗又不想處理,就交給 CWinApp 類。 比如針對一個 F7 按鍵,我們可以在這幾個 class 裡,都分別寫好對於 F7 的 事件處理程式碼。 等事件真的發生時,再從目前的程式狀態,去決定要交給哪個 class 負責。 2. 現有的圖形介面,是否需要修改 主要的問題通常在控件上。也就是所謂的 "Custom Control" 議題。 舉例來說,控件裡最強大、最麻煩的 List Control,預設的 Report 型態下, 每個 item 的背景顏色固定只有一種。 如果想要單數 item 背景是白色,雙數 item 的背景是紅色,那就要自己改寫。 對於 Win32 API 開發者而言,熟悉的方案就是用 "SubClassing" 解決。 MFC 也有 SubClassing,只是跟 Win32 不完全等價。 前者是改掉 WndClass,後者是改掉真的 C++ Class。 Edit 控件之所以是 Edit,是因為在 CreateWindow() 時,其 WndClass 參數選擇 了一個叫 Edit 的 WndClass。 又每個已經對 OS 註冊過的 WndClass 都有自己獨一無二的 WndProc 函數。 已經註冊完畢的 WndClass,就已經將 WndProc 寫死掉,沒辦法修改內容。 所以 Win32 API 開發者們,會在 CreateWindow() 建立過控件後,再這樣做: oldWndProc = SetWindowLong(目標視窗的 hWnd, GWL_WNDPROC, 自訂的新 WndProc); 此時雖然偵測目標視窗的 WndClass 還是沒有改變,但是其 WndProc 已經在 Runtime 被修改成自訂的版本了。然後在自訂的新 WndProc 裡,再用 switch 挑選出想要 自己處理的訊息,改寫訊息處理程式碼後,將其它不打算改的狀況都丟給: CallWindowProc(oldWndProc, 目標視窗的 hWnd, uMsg, wParam, lParam); 參考資料: http://msdn.microsoft.com/en-us/library/bb773183.aspx 回到前面提的 List Control,其 WndClass 叫 SysListView32,如果依造 Win32 API 開發者的那套 SubClassing 機制,那就是要改寫 WM_PAINT 的處理程式碼。 改寫 WM_PAINT 的工作量非常非常大,於是 Windows 又提供了新的機制,用來針對 想要 "Custom Control" 的開發者,主要有兩個: Owner Draw Custom Draw 參考資料:http://msdn.microsoft.com/en-us/library/ms364048.aspx 不是每個控件都有提供上面這兩個機制,但至少 SysListView32 有提供。 其想法是,整個控件的外框繪製還是由 SysListView32 的既有 WM_PAINT 去 處理,但是內部每個 item 的繪製工作就不管了。一律傳送通告訊息給父視窗, 當父視窗收到後,再去手動取得 DC 手動用 GDI 函數畫 item。所以我們想要拿單數、 雙數的 item 有不同背景色,就可以這樣做。 這裡的父視窗顯然就是控件的 Owner,所以才叫 Owner Draw。 至於 Custom Draw 當成新版的 Owner Draw 就好,同樣也是由控件發送通告訊息, 去告知控件的父視窗,目前準備要繪製哪個 item,由你負責繪製用的程式碼吧! 這兩個做法是不牽涉到 SubClassing 的,因為父視窗通常就是我們軟體的視窗, 其 WndClass (WndProc) 本來就是全新自訂的。 ### MFC 的 SubClassing 已經不需要 SetWindowLong 再 CallWindowProc 了。 一些都以 C++ 類別為核心。 以 Edit Control 為例,當在對話方塊拉好一個 Edit 控件,然後在上面按右鍵, 選擇『加入變數』。 最右邊 (VC 2008 為例) 會有個「類別」,如果選擇 Value,且「變數型別」 為 CString,則表示將這個 Edit 控件跟一個 CString 物件綁定。 每當執行 UpdateData() 後,螢幕畫面上的字就會跟 CString 物件的值同步。 如果『加入變數』時,選擇「類別 = Control」,這時候「變數型別」就是一個關鍵, 當你選擇預設的 CEdit,變數名稱叫 myedit,那你只是多了一個 CEdit myedit, 可以方便你寫 myedit.SetWindowText() 這類操作,該控件的 WndProc 還是沒有改變。 因為 MFC 一切都是以類別為單位,所以要先用 class view 或者你用 VC6 就是用 什麼類別精靈?先去新增一個 CMyEdit 類別,並繼承自 CEdit。 然後在「加入變數」設定「變數型別」時,選擇 CMyEdit,不要選 CEdit。 就這樣選完後,MFC 就自動幫你做好 SubClassing 工作了。 比如在父視窗的 class 裡幫你加入資料成員 CMyEdit myed; 的程式碼,會自動產生。 所以 MFC 再怎麼爛,還是比直接寫 Win32 API 方便、快速一點。 就算退一萬步,你也還是能夠掛著 MFC 的皮,去搞 Win32 API 那套 SubClassing。 當新增好 CMyEdit 後,因為這個 class 是你建的,所以愛怎麼改就怎麼改吧, 不會像 CEdit 的程式碼一樣,都已經被寫死。 繼續回去用 List Control 當 "Custome Control" 例子,假設已經新增 好 CMyListCtrl mylist。 首先在 class view (類別檢視) 點選 CMyListCtrl 讓他維持選中的狀態, 然後打開「屬性視窗」,會有幾個分頁。 如果選「事件」分頁,表示你要處理來自 CMyListCtrl 的子視窗發來的通告訊息。 以此例來說只有 CMyDialog 才有可能擁有子視窗,所以這裡不用碰。 如果選「覆寫」(override),就是改寫 CMyListCtrl 裡的一些虛擬函數。 因為 MFC 在每個控件都有額外設計一些虛擬函數,你首先要知道他們的功能, 才需要考慮要不要做 override。不知道功能的就不要動,不會影響整個程式。 像 PreSubClassWindow 這個虛擬函數,因為前面的 SubClassing 動作都是由 MFC 自動 處理。如果想要在 SubClassing 之前,做一些額外的動作,就可以在這裡進行。 舉例來說,原本按照預設值,控件都是自己 Draw 外觀,你必須明確加上 Style 告知說你想要做 Owner Draw,則控件才會在某些時段,準備資料傳送通告訊息給父 視窗說,該輪到你 Draw 內容了。這就可以在 PreSubClassWindow 去更改 Style: void CMyListCtrl::PreSubclassWindow() { // 加入下面這個 Style,才能使 List Control 進入 Owner Draw 模式 this->ModifyStyle(0,LVS_OWNERDRAWFIXED); CListCtrl::PreSubclassWindow(); } 如果選「訊息」(message),那就是主要的處理重點。 比如選 WM_PAINT,那就真的整個 List Control 的繪製工作都可以由你來寫。 如果我們 SubClassing 之後想要讓 List Control 做 Owner Draw,則要注意 這裡不是去寫一個處理 WM_DRAWITEM 的處理函數,去動 CMyListCtrl::OnDrawItem() 是錯誤的。這樣寫表示當 List Control 的子視窗想要做 Owner Draw 並且送來通告 訊息時,做為父視窗的 CMyListCtrl 去幫他畫。 所以應該改用 CMyListCtrl 的父視窗,或者用 MFC 的術語講,就是改用其父類別 CMyDialog 去處理,即 CMyDialog::OnDrawItem()。 但是這個方法有個缺點,就是 CMyListCtrl 會跟 CMyDialog 綁死。 你下次開的 MFC 專案時,為了重複使用這次的有 Owner Draw 功能的 List Control, 那你就要把 CMyListCtrl 跟 CMyDialog 都複製過去。 所以 MFC 有另外一個方案,就是做 override,改寫掉 CMyListCtrl::DrawItem() 這個虛擬函數。把想要做的 Owner Draw 程式碼都寫在裡面就好。 下次開新專案時,只要把這個 CMyListCtrl 複製過去,設定好加入變數的 MFC SubClassing 動作,不用寫一行程式碼,就可以重複使用。 : 因為之前 api 有提供基本空視窗的程式碼 : 然後我要抓啥資料或是多啥功能就是去寫程式就好 : 結果MFC的工具書裡面一堆圖反而讓我無所適從無法下手(汗) 書就前篇講的《Programming Windows with MFC》 雖然很舊,但重要觀念都有講。其他書我也看了一些,雖然可能細節寫得更詳細, 或者中文書看起來比較快,但是在教導觀念的部份,還是這本好。 另外補充一點,雖然現在版本的 MFC Class Hierarchy Chart 都大到誇張,小螢幕 的根本不能一次看完,還是可以找 VC6 比較小的圖,盡量讓自己可以隨時打開來看, 或者印出來看,怎樣都好。 因為大家的記憶都有限,不可能記住 MFC 每個類別的功能,一定是用到時再查。 比如想到要做工具列,那工具列的可能英文是什麼?想好後,開這張圖,去查 toolbar 相關的類別,並看與他相關的父類、子類是什麼。 以 CView 來說,如果你看過他的 Hierarchy Chart,就知道還有很多子類,有些 可以支援捲軸的一些功能,有些可以像 Dialog 一樣拖曳控件上去。 而 CView 僅只是最垃圾,功能最少的那種。你沒這樣查圖,一直用最基本的類別 只會覺得,怎麼什麼東西都沒有!