如之前講的,字太多很累,而且這裡是草稿,所以我就直接上傳Word和範例了
當然是我自己做的,所以版權所有,請勿亂傳
主要是講如何製作Thread,並將它物件導向化
連結如下
內容:
https://drive.google.com/open?id=0B6u5oifJv3EKdGZiY0YyZlQwQkk
範例:
https://drive.google.com/open?id=0B6u5oifJv3EKejhScHBmM1d4bE0
2016年11月24日 星期四
寫程式的好習慣
總之就是多加註解了,其實上班以後,如果您有做案子的話,通常都一個案子好幾萬行,想想各個地方都是不同的想法,要是忙起來又接兩三個案子,來回不同的切換,就算您是功力很深厚的,怎麼可能都記的住,
也就是所謂的註解可能記不住,不註解更不可能記住
其實註解也是一門學問的,學問的意思不是說您要註解的很深奧或很文言,他其實傾向直接明白,您當時想什麼,有什麼特別構想或者是為什麼要那樣設計,就直白的寫上去,通常在註解時不要太多專業名詞,除非您是給做很久的人看的,他對專業名詞有基本認識,
想想如果您是初學者,我設計一個模組是用來搭架構的,例如底層建置好,您只要繼承我這個class的某個virtual function,他就會自動的在執行緒執行,
想想我這段話,要是看的人不知道執行緒是什麼,那是不是就卡住了?
就算您知道執行緒是什麼,我用一個專業名詞virtual function,沒學過AOOP的是不是又卡住了?
跟您說他會自動執行,我沒給範例,您怎麼知道真的他會在執行緒自動執行?
要是我再把這個class包成lib並把.cpp藏起來,您真的知道怎麼用嗎?
想想每碰到一個地方都是一個關卡,要是我註釋再改成英文,英文不好的不就又死了?
又或者是其實在公司上班,假設這是一個個人的東西,結果我懶或者是為了保密,根本沒加註釋,那是不是每個人都要來問我才會使用呢?
所以您看完這段會了解到,其實如果您想要快速的成長或者是有一群相同向前的同伴(要確保大家都很努力拉,當然也是要賺到錢),並且以最快速度上手並完成案子,
其實到最後很多東西是解密的,就是lib附.cpp,並提供看得懂的註釋,有時間要提供該模組的範例程式,並且有實際應用的案子可以給人參考,甚至,人家來問時,通常有時候我們會做一些拖拖拉拉的回應,為了拖人家時間或者是讓人家知難而退,故意不教人家,這也是不行的,要求效率要以最直白的方式,讓人家上手
這些就是所謂的好習慣
寫Code是一件很累的是,一個經典的function您要靠自己想出來,可能要一兩年一直修改,還是都有可能失敗做不完整,
想想一個大型案子(除非您做小的案子,但是往往小的案子不賺錢),通常要數10個經典算法或者是好的設計才做得出來,
您卡別人人家再卡您,案子是做不好的,但其實如果您是該環境的技術上游0.0有時候還是要保護自己,避免東西被人家挖走
總之,我們還是維持人性本善,通常東西只要用出來,您最好不要有再藏起來的想法,因為會發生我前面描述的那些,導致大家效率不好,團隊不賺錢,您怎麼拿到比較多的錢呢?
這是基本想法,當然一些技術領先還是要藏起來啦@@,不然就您的案子有用,其他案子都不要開發相關題目,這樣也是可以,但是往往不同案子會有相同的需求,其實藏不住的,
而且其實一般趕案子,一些模組不可能完整或者是沒有Bug,保密到最後只會讓大家陷入負向循環(除非您已經不想向前衝了,不然負向循環是一件很可怕的事)
例如您藏程式碼,人家用到來問您,結果您花額外時間回答很多人相同問題,結果您也有案子壓力,一急做不好,做不好東西有問題,人家又找您協助,你會發現一直窮忙,很糟糕的
所以第一件事,仔細評估要拿多少東西出來,可以讓環境有正向成長,通常講這樣就是全部拿出來拉,不想拿不如就不要使用,不要找其他人跟您一起偕同做事
這算是一個好習慣
再者我們寫東西時要把可以reuse的東西模組化,讓他可以重複使用,也就是您花一年的努力的成果,下一個人使用可能花5分鐘就可以達到相同效果,這樣團隊獲利才會比較快速
另外我們設計東西時,要規劃後面可能要做的事情…幹,有蟑螂,租到蟑螂屋…哭哭
總之就是設計的任何東西要有預先保留擴展的可能,例如您拉一個參數窗口,總不能拉的小小的,並且您的頁面剛剛好擺滿,要使用的參數,通常會建置一些分頁(例如PageControl),將參數分群在不同頁面,讓往後您需要新增參數時,可以有地方放,這也是要注意的
不只這個,例如您新增光源模組,您要考慮未來是否會有多組光源要控制,如果會有的話,記得模組化您的光源程式控制片段,並且使用一些可以調整組數的結構,例如使用vector,這樣往後要多幾組有可花比較小的力氣做新增,
您沒做上面這些準備當然沒關係,但是往往您下次要修改時,您可能要花很多倍的時間,寫這個功能,其實多做一點設計和準備是好事,儘管您目前交件時沒用到
註解,模組化,不要太摳,預留備載以利往後修改,總之最重要的就是,做事直接明白一點,不夠直白,喜歡拐彎抹角,往往您寫出來的東西,也會拐彎抹角,Code人家不好接手,您藏一個提示,對其他接手維護的人會增加困擾,少一個重要註解,人家要多花一段時間看您在寫什麼,想想要是您同伴也這麼做,陷入負向循環是遲早的事…不要不信邪喔
基本上多想兩分鐘,做一些比較完善的構思,再開始執行,會比您塗塗改改要容易多了,而且其實剛開始會看起來做事速度比較慢,您東西做大後您會發現人家會操死,而您有事前規劃會比較好做事(除非您只是要接小案子維生爾以,東西改完下個案子又是打掉重練)
也就是所謂的註解可能記不住,不註解更不可能記住
其實註解也是一門學問的,學問的意思不是說您要註解的很深奧或很文言,他其實傾向直接明白,您當時想什麼,有什麼特別構想或者是為什麼要那樣設計,就直白的寫上去,通常在註解時不要太多專業名詞,除非您是給做很久的人看的,他對專業名詞有基本認識,
想想如果您是初學者,我設計一個模組是用來搭架構的,例如底層建置好,您只要繼承我這個class的某個virtual function,他就會自動的在執行緒執行,
想想我這段話,要是看的人不知道執行緒是什麼,那是不是就卡住了?
就算您知道執行緒是什麼,我用一個專業名詞virtual function,沒學過AOOP的是不是又卡住了?
跟您說他會自動執行,我沒給範例,您怎麼知道真的他會在執行緒自動執行?
要是我再把這個class包成lib並把.cpp藏起來,您真的知道怎麼用嗎?
想想每碰到一個地方都是一個關卡,要是我註釋再改成英文,英文不好的不就又死了?
又或者是其實在公司上班,假設這是一個個人的東西,結果我懶或者是為了保密,根本沒加註釋,那是不是每個人都要來問我才會使用呢?
所以您看完這段會了解到,其實如果您想要快速的成長或者是有一群相同向前的同伴(要確保大家都很努力拉,當然也是要賺到錢),並且以最快速度上手並完成案子,
其實到最後很多東西是解密的,就是lib附.cpp,並提供看得懂的註釋,有時間要提供該模組的範例程式,並且有實際應用的案子可以給人參考,甚至,人家來問時,通常有時候我們會做一些拖拖拉拉的回應,為了拖人家時間或者是讓人家知難而退,故意不教人家,這也是不行的,要求效率要以最直白的方式,讓人家上手
這些就是所謂的好習慣
寫Code是一件很累的是,一個經典的function您要靠自己想出來,可能要一兩年一直修改,還是都有可能失敗做不完整,
想想一個大型案子(除非您做小的案子,但是往往小的案子不賺錢),通常要數10個經典算法或者是好的設計才做得出來,
您卡別人人家再卡您,案子是做不好的,但其實如果您是該環境的技術上游0.0有時候還是要保護自己,避免東西被人家挖走
總之,我們還是維持人性本善,通常東西只要用出來,您最好不要有再藏起來的想法,因為會發生我前面描述的那些,導致大家效率不好,團隊不賺錢,您怎麼拿到比較多的錢呢?
這是基本想法,當然一些技術領先還是要藏起來啦@@,不然就您的案子有用,其他案子都不要開發相關題目,這樣也是可以,但是往往不同案子會有相同的需求,其實藏不住的,
而且其實一般趕案子,一些模組不可能完整或者是沒有Bug,保密到最後只會讓大家陷入負向循環(除非您已經不想向前衝了,不然負向循環是一件很可怕的事)
例如您藏程式碼,人家用到來問您,結果您花額外時間回答很多人相同問題,結果您也有案子壓力,一急做不好,做不好東西有問題,人家又找您協助,你會發現一直窮忙,很糟糕的
所以第一件事,仔細評估要拿多少東西出來,可以讓環境有正向成長,通常講這樣就是全部拿出來拉,不想拿不如就不要使用,不要找其他人跟您一起偕同做事
這算是一個好習慣
再者我們寫東西時要把可以reuse的東西模組化,讓他可以重複使用,也就是您花一年的努力的成果,下一個人使用可能花5分鐘就可以達到相同效果,這樣團隊獲利才會比較快速
另外我們設計東西時,要規劃後面可能要做的事情…幹,有蟑螂,租到蟑螂屋…哭哭
總之就是設計的任何東西要有預先保留擴展的可能,例如您拉一個參數窗口,總不能拉的小小的,並且您的頁面剛剛好擺滿,要使用的參數,通常會建置一些分頁(例如PageControl),將參數分群在不同頁面,讓往後您需要新增參數時,可以有地方放,這也是要注意的
不只這個,例如您新增光源模組,您要考慮未來是否會有多組光源要控制,如果會有的話,記得模組化您的光源程式控制片段,並且使用一些可以調整組數的結構,例如使用vector,這樣往後要多幾組有可花比較小的力氣做新增,
您沒做上面這些準備當然沒關係,但是往往您下次要修改時,您可能要花很多倍的時間,寫這個功能,其實多做一點設計和準備是好事,儘管您目前交件時沒用到
註解,模組化,不要太摳,預留備載以利往後修改,總之最重要的就是,做事直接明白一點,不夠直白,喜歡拐彎抹角,往往您寫出來的東西,也會拐彎抹角,Code人家不好接手,您藏一個提示,對其他接手維護的人會增加困擾,少一個重要註解,人家要多花一段時間看您在寫什麼,想想要是您同伴也這麼做,陷入負向循環是遲早的事…不要不信邪喔
基本上多想兩分鐘,做一些比較完善的構思,再開始執行,會比您塗塗改改要容易多了,而且其實剛開始會看起來做事速度比較慢,您東西做大後您會發現人家會操死,而您有事前規劃會比較好做事(除非您只是要接小案子維生爾以,東西改完下個案子又是打掉重練)
四種型態轉換
http://windsplife.blogspot.tw/2010/09/cstaticcast-dynamiccast-reinterpretcast.html
http://ot-note.logdown.com/posts/173174/note-cpp-named-type-convertion
有四種static_cast,dynamic_cast,reinterpret_cast,const_cast
其實網頁上寫的應該都是很詳細了
所以這裡我只是就我認知寫一下,
http://ot-note.logdown.com/posts/173174/note-cpp-named-type-convertion
有四種static_cast,dynamic_cast,reinterpret_cast,const_cast
其實網頁上寫的應該都是很詳細了
所以這裡我只是就我認知寫一下,
Static_cast<T>exp是靜態轉換
它等同於(T)exp
直接舉例好了
int a = 5;
double b = (int)a; or
double b = static_cast<int>(a);
總之主要就是算術轉型
一般用這個大部分都是用來做算術轉型
雖然他也可以用來轉型指標,但是不保證安全,尤其在多重繼承的情況下,幾乎是很容易出錯,也就是失敗
而主要指標一般有需要用來轉型,一般是在一般的變數結構裡
例如一個一維陣列
char* rrr = new char[100 * 3];
就是一個一維陣列存RGB存100筆
一般我們可以宣告一個結構去接他
Struct aaa
{
Char r;
Char g;
Char b;
};
Aaa* temp = (aaa*)rrr;
這樣只要temp[xx].r,就可以很明瞭的作存取值的動作
一般做繼承的class的指標轉換會用dynamic_cast去轉,但是網頁上有說dynamic_cast轉class,class內必須有virtual function才會成功
總之要是有多層結構,記得用dynamic_cast去轉換,轉失敗他會回傳NULL,
雖然說dynamic_cast需要做一些檢查,但是其實在繼承的架構底下,指標轉來轉去,沒用這個基本上會莫名其妙的錯誤,所以有時候還是要乖乖地做轉換
剩餘兩個其實比較不常用
reinterpret_cast就是強制轉換,反正轉換完他就用新的類型的bit結構去處理
例如:
int* i;
char* str = "test";
i = reinterpret_cast<int*>(str);
您會發現*i讀出會是134514704
總之就是強制bit轉換,轉換後直接把原來的bit樣子用轉換後的類型去解讀
至於const_cast其實我也不常用,總之網頁上是將const類型轉換為一般類型,通常會用const都是為了做保護,把他轉換為可讀寫的,一般容易亂,建議少用
它等同於(T)exp
直接舉例好了
int a = 5;
double b = (int)a; or
double b = static_cast<int>(a);
總之主要就是算術轉型
一般用這個大部分都是用來做算術轉型
雖然他也可以用來轉型指標,但是不保證安全,尤其在多重繼承的情況下,幾乎是很容易出錯,也就是失敗
而主要指標一般有需要用來轉型,一般是在一般的變數結構裡
例如一個一維陣列
char* rrr = new char[100 * 3];
就是一個一維陣列存RGB存100筆
一般我們可以宣告一個結構去接他
Struct aaa
{
Char r;
Char g;
Char b;
};
Aaa* temp = (aaa*)rrr;
這樣只要temp[xx].r,就可以很明瞭的作存取值的動作
一般做繼承的class的指標轉換會用dynamic_cast去轉,但是網頁上有說dynamic_cast轉class,class內必須有virtual function才會成功
總之要是有多層結構,記得用dynamic_cast去轉換,轉失敗他會回傳NULL,
雖然說dynamic_cast需要做一些檢查,但是其實在繼承的架構底下,指標轉來轉去,沒用這個基本上會莫名其妙的錯誤,所以有時候還是要乖乖地做轉換
剩餘兩個其實比較不常用
reinterpret_cast就是強制轉換,反正轉換完他就用新的類型的bit結構去處理
例如:
int* i;
char* str = "test";
i = reinterpret_cast<int*>(str);
您會發現*i讀出會是134514704
總之就是強制bit轉換,轉換後直接把原來的bit樣子用轉換後的類型去解讀
至於const_cast其實我也不常用,總之網頁上是將const類型轉換為一般類型,通常會用const都是為了做保護,把他轉換為可讀寫的,一般容易亂,建議少用
virtual和override和final
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=547
如網頁上寫的,其實很清楚了
我就講一下virtual的注意地方,其實就是雖然virtual可以寫成虛函式,但是其實有時候型態轉換錯誤,或是不小心存取到虛函式時,還是會出錯,所以我為了避免跳出錯誤訊息,其實就算是用來被繼承而已的虛函式,其實我也會把他實例化(在cpp),也就是寫個他的實體函式,這樣就算錯誤時他也只會執行到空函式,提供給您們參考
總之virtual很好用的,
class CA
{
public:
virtual void func1(int a)
{
////
// 其他程式片段
////
}
virtual void func2(int a)
{
////
// 其他程式片段
////
}
};
class CB : public CA
{
public:
void func1(int a) {
CA::func1(a);
CA::func2(a);
////
// 其他程式片段
////
}
};
這裡這樣寫的是,如果您繼承後,執行CB的Func1,其實CA的Func1還是存在的如您有寫處理寫在CA的Func1,您可以使用CA::func1(a);順便執行父親class的函式,這是一個小技巧
其實在寫很多繼承架構時,會用到這個,當然其他父class函式也是可以存取的,總之就加CA::其他父class函式,只要您滿足繼承關係(就public,private,protected),要怎樣使用就怎樣使用
例外就簡單講override和final吧,其實連結裡面已經有寫很清楚了,
Override加在virtual函式後面,他會檢查是否有蓋到繼承的class的函式,沒蓋到編譯會出錯,
Fianl則是該函式或是class是最後端點,不可以做繼承用,如果您繼承了,他編譯會出錯
基本上在classic Borland compiler是沒有這個的,要用新的clang c++11 compiler可以編譯過,由於後來我在處理DLL溝通時,在classic Borland compiler(32bit)和clang c++11 compiler(64bit)切換實在麻煩,就是語法上有些差異,要額外處理,因此我都改成clang c++11 compiler(32bit/64bit)了
至於CodeGuard基本上已經棄用了,我在等C++ Builder支援AddressSanitizer再來做偵錯(不確定是否會支援),基本上只要少直接用new指標傳來傳去,基本上不太會會出現沒有delete到的狀況,而且說實在的,其實如果動態產生指標傳來傳去,其實CodeGuard好像也抓不到,所以基本上CodeGuard對我個人用處不是很大(重點CodeGuard好像沒維護了,其實案子一大,有時候跑一跑會程式會出錯,總之感覺用處不大)
如網頁上寫的,其實很清楚了
我就講一下virtual的注意地方,其實就是雖然virtual可以寫成虛函式,但是其實有時候型態轉換錯誤,或是不小心存取到虛函式時,還是會出錯,所以我為了避免跳出錯誤訊息,其實就算是用來被繼承而已的虛函式,其實我也會把他實例化(在cpp),也就是寫個他的實體函式,這樣就算錯誤時他也只會執行到空函式,提供給您們參考
總之virtual很好用的,
class CA
{
public:
virtual void func1(int a)
{
////
// 其他程式片段
////
}
virtual void func2(int a)
{
////
// 其他程式片段
////
}
};
class CB : public CA
{
public:
void func1(int a) {
CA::func1(a);
CA::func2(a);
////
// 其他程式片段
////
}
};
這裡這樣寫的是,如果您繼承後,執行CB的Func1,其實CA的Func1還是存在的如您有寫處理寫在CA的Func1,您可以使用CA::func1(a);順便執行父親class的函式,這是一個小技巧
其實在寫很多繼承架構時,會用到這個,當然其他父class函式也是可以存取的,總之就加CA::其他父class函式,只要您滿足繼承關係(就public,private,protected),要怎樣使用就怎樣使用
例外就簡單講override和final吧,其實連結裡面已經有寫很清楚了,
Override加在virtual函式後面,他會檢查是否有蓋到繼承的class的函式,沒蓋到編譯會出錯,
Fianl則是該函式或是class是最後端點,不可以做繼承用,如果您繼承了,他編譯會出錯
基本上在classic Borland compiler是沒有這個的,要用新的clang c++11 compiler可以編譯過,由於後來我在處理DLL溝通時,在classic Borland compiler(32bit)和clang c++11 compiler(64bit)切換實在麻煩,就是語法上有些差異,要額外處理,因此我都改成clang c++11 compiler(32bit/64bit)了
至於CodeGuard基本上已經棄用了,我在等C++ Builder支援AddressSanitizer再來做偵錯(不確定是否會支援),基本上只要少直接用new指標傳來傳去,基本上不太會會出現沒有delete到的狀況,而且說實在的,其實如果動態產生指標傳來傳去,其實CodeGuard好像也抓不到,所以基本上CodeGuard對我個人用處不是很大(重點CodeGuard好像沒維護了,其實案子一大,有時候跑一跑會程式會出錯,總之感覺用處不大)
而最近其實有測試了Intel Inspector,他在XE10.1 berlin的64bit環境是可以抓記憶體錯誤的(32bit不行),有空可以試試看
2016年8月10日 星期三
原來Blogger可以貼程式碼
好酷喔@@ 原本以為不行的說 哈哈哈
用FireFox和Chrome不會複製到行數
http://holeyshared.blogspot.tw/2016/05/blogger-code-highlighter.html http://o1o1o1o1o.blogspot.tw/2016/07/blogger.html
http://rj-memo.blogspot.tw/2015/05/blogger_23.html
https://pjchender.blogspot.tw/2015/03/blogger.html
測試
用FireFox和Chrome不會複製到行數
http://holeyshared.blogspot.tw/2016/05/blogger-code-highlighter.html http://o1o1o1o1o.blogspot.tw/2016/07/blogger.html
http://rj-memo.blogspot.tw/2015/05/blogger_23.html
https://pjchender.blogspot.tw/2015/03/blogger.html
測試
void ddd() { int rrr = 0; return ; }
void ddd() { int rrr = 0; return ; }
public class HelloWorld { public static void main (String[] args) { System.out.println("Hello, world!\n"); } }
void ddd() { int rrr = 0; return ; }
2016年7月29日 星期五
關於新版移植及Skin及自製按鈕效果
基本上Windows視窗程式也是可以玩一些花招的,一般有錢的會去買skin,替您的按鈕或元件換上比較好看的特效,在C++ Builder這邊有兩個比較知名的Skin
也就是有錢的話,您可以買上面的元件來使用,幫助您的畫面更好看,
我們再買一些額外的附件的時候,一般最好選擇大廠有人在更新維護的,不然當您的畫面做好了,過陣子您C++ Builder版本升級,結果該元件不支援新版,這時候您的程式會被Skin綁死,導致不能更新新版
這邊也順便提到為什麼要用新版,其實C++ Builder已經很完善了,有一個版本就可以用來工作賺錢了,其實這樣也沒錯,
但是其實新版都有一些新的東西,例如XE7有TThreadPool可以用,也就是有內建執行緒池,XE10突然間Compiler支援了多執行緒編譯執行檔,原來的64bit編譯時間快了很多,這些都是新版持續更新的,
那要是您被某種已經不更新的Skin綁死(就是您用那種skin或vcl元件做好了,但卻因此不能升級新版),想想不能升級到XE10,您編譯一個執行檔要好久,很糟糕的,工作效率因此降低
因此這邊提到一些插件和Skin要慎選,最好是有人在持續維護的,不然會影響換新版
當然我們也沒有閒錢一直買新軟件,做移植其實也很浪費時間的,我認為還是要一段時間更新一次版本,避免與時代脫節,其實當您有做過移植這段的工作時,您會發現其實XE7後面版本幾乎移植一次後再移植是很快的,痛只要一次爾已,大部分都是C++11,他比較嚴謹,所以要改很多地方,但是當您已經相容C++11,後面其實都是小改小改,還OK的
當然有些人很不喜歡平台改來改去,那您想想BCB5跟BCB6再過10年您保證他還是可以Work在新的OS下嗎,移植是必須的
當然選版本移植也很重要,總之要持續關注拉,像我剛剛提到XE10支援多執行緒編譯執行檔,那有人會問是不是就移植到這板後面就不用移植了?
您有在認真寫Code的話,您會發現XE10
CodeGuard還是只支援傳統的Borland C++編譯器,其實CodeGuard很好用,不能沒有她,因此就我目前而言,再等一版新版的可以用新的編譯器又有類似CodeGuard可以幫我們抓錯誤的版本,我會打算再移植一次
那未來呢?總之自己決定要怎樣處理,不是我在推銷新版(其實我也用迷版(在家自己玩,正版對於一般收入的人是買不起的,何況要持續升級)),如果您真的有認真在做程式的話,其實要多關注新版帶來的好處
就像是您有用過Word2016嗎,她右邊多了頁面索引(可能2013就有了),那您還要用2007版嗎,新版本其實有些版本對工作效率的提升有很大幫助的
那這樣說其實更新到XE10就夠了嗎,其實不是的,
這邊都是廢話,進入正題
上面是一些概念及Skin介紹,主要是要介紹Skin拉
有錢的人就用買的吧,那您想想我們比較窮的,不想花錢買Skin的要怎辦(其實Skin也有提供一些功能,例如可以在標題列加按鈕,我並沒有說他只是用來作UI漂亮用的),其實有一些自製效果可以經由模組化的方式,來讓您做出有一些效果的按鈕,有用過網頁您就會看到當您滑鼠移到一些點選的地方,該地方會變色,移開時會恢復,那按下時可能又有另一種顏色,這C++ Builder也可以做得到
作法大概講一下,例如移動到按鈕上會變色,移開會恢復,按下會變色,
這我們可以利用TTimer和TPanel來實作,大概意思是利用程式碼將OnMouseMove,OnMouseDown等事件,寫在模組裡面,用模組設計他的事件處理
例如滑鼠移進去,我們變更Panel顏色,按下時再變更Panel顏色,當離開Panel區域時,我們利用Timer來監控是否已經離開Panel範圍,假設離開了恢復按鈕顏色
這樣就設計成一個有效果的按鈕(當然您Onclick時可以做您要的動作)
只可以寫死控制顏色嗎?當然不是,您可以定義Move,Down,Leave實的顏色,用程式碼更改,他就可以設定各種顏色
那要是您要其他效果呢,例如Move時字體加底線,移開時恢復,是類似作法,這請自己想
我這邊提供三種模組
一個是Panel按鈕
一個是Panel Down按鈕
一個是Pic Panel按鈕
怎麼做的就不說了,請自行看我範例的代碼和我怎樣做設定的,這其實是我在前公司做出的模組,不過我怕有法律問題,有稍微改名字一下,請自行研究吧
其實很龜毛的是它就是Panel Button,那我取名就直觀取Panel_Button.cpp,這樣要自己用還要改名,真的很麻煩,丟上來網路我又沒錢賺,還要花功夫,很糟糕的
範例連結
自己研究吧,不難的
Windows程式畫面布局設計概念
這個布局部分有點多,所以可能的話會分幾次來講
基本上您會發現,相同應用的軟件,基本上畫面布局(Layout)都很像,佈局是指什麼,就是您在畫面上放置一些容器,讓框架內可以放置一些您的按鈕或者是輸入欄位,當然也可以是顯示圖片
大概長這樣
這是一個空白的Form
其中用Panel或者是其他容器(例如ScrollBox,Notebook),定出畫面的擺放,這叫做布局(Layout)
這裡就直接稱乎布局了
我們常常看到很多舊型的程式,都會有一些相似的布局
我們以C++ Builder為例(這是新版的)
最上方會有一個Menu,再來下面是一些快捷按鈕,左邊是屬性設計,右邊也是顯示一些資訊的地方,下方會有一個狀態列(其中他將狀態列換成自製的),
基本上C++Builder他的視窗可以到處搬動,這已經是屬於進階部份了,不過基本樣式是固定的
因此就我剛剛提到的那些基本元素,我大概拉一個基本樣式
最上方有一個Menu,下面是一些快捷按鈕,例如按完可以做計算還是幹嘛,總之就是一些按鈕,再來是最下方的狀態列,而中間兩個則是自己設計的框架,我的框架式左右兩個Panel,右邊是放參數的,左邊是主要顯示Client視窗,
基本上您會在很多古早的應用程式,大約Windows XP那個年代,大概都長這個樣子
這是最最最基本的,也就是您完成一個應用程式,假設小到不行,您可以參考這總方式做基本畫面布局,
總之就是很古老的做法就是了,基本上您看到現在的一些應用程式很花俏,充滿了無數的設計,所以這簡單的畫面布局基本上也不算什麼秘密了,要做到像一些大型軟件那樣,其實是很多設計的,絕對不是就這樣弄一個Form,然後全部東西都弄在這裡,就結束了
大型軟件是指什麼,例如您打開近代的Word,C++ Builder,Visual Studio,他們會有一些框架,不同框架放不同的功能,其實您數一數可能也10~20種,您要在一個FHD的螢幕上,規劃10~20種框架,是不可能釘一釘Panel就處理完的,
因此這是一門學問也是一門藝術,但是基本上像這種大型軟件,框架可以到處釘,基本上這是模組化設計了(老實說我也不會),這就不再我們討論範圍,這一般沒有10來個人同時寫一支程式不太可能完成,我這裡會介紹的比較偏向於一個人能獨自完成的應用程式
如上面您看到我弄的框架,基本上很死,框架都釘好了,基本上是無法做任何變化的,
我們這裡談到的設計,牽涉到UX(User experience design ),也就是使用者體驗,
說他簡單,也很簡單,其實一個重要意義就是您的畫面如何設計,可以讓使用者操作起來最舒服,最方便
但是說他難,也很難,我們一支程式通常是從無到有,一般您在公司裡接案子,客戶不會一次就將所有要做的功能都跟您說,因此您的介面會一直增加新的東西
您會發現做一做,需求一直進來,您就加入很多東西,最後都塞到同一個地方,例如剛剛的圖,只有6個欄位,那要您的欄位一直加一直加,加到了20多個,通常來說,欄位太多要設定,如果您沒做分類處理,或者做一些分業,使用者會用起來很不舒服
假設您一支程式有一個功能,有18個參數可以控制,您以一個程式設計師來說最簡單的就是將欄位照順序分在一起
這裡就不做命名了,總之就是不同參數的欄位,這一般有接過案子才能體會,我也不知如何表達,總之您就把他想成您有18個欄位可以控制就是了
基本上您沒做分類,要懂怎麼操作您的軟體看了就不想學了,
所以我們先做基本分類,好啦,就假設我這個程式可以用來設定動物身上的顏色,
假設相關的顏色欄位,狗有6個,貓有4個,鳥有8個,
我們做一個索引如圖
這樣做簡單歸類,操作員就知道假設他要設定狗相關顏色參數,就改納六個欄位就好了,依此類推,我們程式設計目的做一支好用的程式給使用者,而不是只是為了完成功能賺錢而添加新的功能,這在一些比較落後的公司都不注重這個,往往就要啥參數就加啥,然後放一大堆,基本上要是我是使用者,我看到就不想用了,更別說對您的軟體有興趣,
當然講這樣好像太淺了,很像我是白癡一樣,所以我就再衍伸出去
通常我們程式是可以縮放的,要是您把參數欄位放在Panel上面,您會發現縮小時,欄位被遮住了,如圖
雖然看起來很弱智,但是假設是初學者對元件不熟,一定做到後來就會發生這個錯誤,基本上我們就使用ScrollBox,他會有ScrollBar可以拖曳,就不會擋到您的欄位了
這樣其實還不夠,通常使用者再看欄位時,可能一次10個以上就會抱怨了,所以除了分類,我們還要做分頁,最簡單的Solution就是PageControl,當然有很多替代的,也可以自己設計,這裡就不講自己設計的部分(因為要寫Code),其實自己設計的話會比較漂亮,所以我們將PageControl做三頁,將這些欄位分別放入PageControl的TabSheet裡面
您只要切換頁籤就可以設定不同的動物顏色,但是您會發現問題又來了,畫面縮小時又會欄位了
基本上就是
PageControl本身不會有ScrollBar,因此我們需要在它上面分別放上ScrollBox,再在ScrollBox上面放元件,這樣當縮小時就又會出現ScrollBar了
基本上您會發現ScrollBox很好用,他會幫您自動產生ScrollBar但是必須是元件跑到ScrollBox外面才會出現,
原則上如果您沒做畫面設計的話您大多時間會做我上面在做的事情,就是畫面布局,及參數分類管理,原則上可用的元件還是要熟拉,假設您沒有要深入,會到這裡就可以了
偷偷給您看經過畫面設計會有啥不一樣,我大概弄給您看,大概就是將PageControl改成自己用程式碼設定呼叫頁面顯示,往後教程我會弄一個範例給您下載研究,您會發現其實軟體是有很多技巧的,而不是就只是拉拉元件,兜兜功能,寫寫核心演算法就沒了
這裡只是先秀給您看一張圖
自製的PageControl,其中滑鼠放上去按鈕(其實他是Panel做的)他會變色,
這技術其實可以常常在網頁上看到,是一個模組化技巧(由於關鍵,就晚點再秀了(0 .0明年看有沒有機會),只要您會模組化,這種東西可以千變萬化)
先到這了
訂閱:
文章 (Atom)