手持裝置開發心得分享(C#) |
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
用同樣的 C# 開發 , 但有些屬性事件甚至類別在 WIN FORM (WIN32) 上能用 ,
不見得在手持裝置(PDA ; WIN CE)上能用 , 所以整理出了一些類別分享之 C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/ using System; using System.IO; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Collections; //ArrayList //------------------------------------------------- //MyFunction //------------------------------------------------- class My { public void ShowMessage(string bufstr) { MessageBox.Show(bufstr); } //取系統資訊相關 -------------------------------------------------- public string ApplicationPath() { //string tmp = System.Windows.Forms.Application.StartupPath; //for win ce string tmp = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); if (Right(tmp,1)!="\\") tmp=tmp "\\"; return tmp; } public string ApplicationName() { //return System.Windows.Forms.Application.ExecutablePath; //for win ce return System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase; } public string ApplicationIniName() { /* string tmp; tmp=System.Windows.Forms.Application.ExecutablePath; tmp=tmp.Substring(0,tmp.Length-4) ".ini"; return tmp; */ //for win ce string tmp=ApplicationName(); tmp=tmp.Substring(0,tmp.Length-4) ".ini"; return tmp; } public string ApplicationLogName() { /* string tmp; tmp=System.Windows.Forms.Application.ExecutablePath; tmp=tmp.Substring(0,tmp.Length-4) ".log"; return tmp; */ //for win ce string tmp=ApplicationName(); tmp=tmp.Substring(0,tmp.Length-4) ".log"; return tmp; } public bool DirectoryExists(string bufstr) { return System.IO.Directory.Exists(bufstr); } public void CreateDirectory(string bufstr) { if (!(System.IO.Directory.Exists(bufstr))) { System.IO.Directory.CreateDirectory(bufstr); } } //ListBox 相關 -------------------------------------------------- //<例> My.ListBoxSaveToFile(listBox1, "test2.txt"); public void ListBoxSaveToFile(ListBox tmp_listbox, string fn) { //StreamWriter sw = File.CreateText(fn); //這樣才能寫出中文字元 StreamWriter sw = new StreamWriter(fn, false, System.Text.Encoding.GetEncoding(950)); for(int i = 0; i != tmp_listbox.Items.Count; i ) { sw.WriteLine(tmp_listbox.Items[i]); } sw.Close(); } //<例> My.ListBoxLoadFromFile(ref listBox1, "test.txt"); public void ListBoxLoadFromFile(ref ListBox tmp_listbox, string fn) { tmp_listbox.Items.Clear(); //StreamReader sr = new StreamReader(File.OpenRead(fn)); //這樣才能讀入中文字元 StreamReader sr = new StreamReader(fn, System.Text.Encoding.GetEncoding(950)); //或 System.Text.Encoding.Default while (sr.Peek() >= 0) { tmp_listbox.Items.Add(sr.ReadLine()); } sr.Close(); } //型態轉換相關 -------------------------------------------------- public string IntToStr(int v) { return v.ToString(); } public int StrToInt(string bufstr) { int r = 0; try { r = Convert.ToInt32(bufstr); //或 r = int32.Parse(bufstr); } catch (Exception ex) { MessageBox.Show(ex.Message); } return r; } public string NowStr() { //加了 System.Globalization.DateTimeFormatInfo.InvariantInfo 才不會用民國 return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo); } //字串處理相關 -------------------------------------------------- public string Trim(string bufstr) { return bufstr.Trim(); } public int Length(string bufstr) { return bufstr.Length; } public string Copy(string bufstr, int stridx, int len) { return bufstr.Substring(stridx-1,len); } public string Left(string bufstr, int len) { return bufstr.Substring(0,len); } public string Right(string bufstr, int len) { if (bufstr.Length return bufstr; } else { return bufstr.Substring(bufstr.Length-len,len); } } public string CutLeft(string bufstr, int len) //2007/06/17 { string r = ""; if (bufstr.Length return r; } else { return bufstr.Substring(len,bufstr.Length-len); } } public string CutRight(string bufstr, int len) //2007/06/17 { string r = ""; if (bufstr.Length return r; } else { return bufstr.Substring(0,bufstr.Length-len); } } public string UpperCase(string bufstr) //2007/06/17 { return bufstr.ToUpper(); } public string LowerCase(string bufstr) //2007/06/17 { return bufstr.ToLower(); } public string StrSeg(string bufstr, char bufkey, int idx) //2007/06/17 { string[] tmp = bufstr.Split(bufkey); return tmp[idx]; } public string RepeatStr(string bufstr, int num) //2007/06/17 { string r = ""; for (int i=1; i<=num; i ) { r = r bufstr; } return r; } //Log 處理相關 -------------------------------------------------- public void DebugLog(string bufstr) { if (g.debug_sw==1) SaveLog(" } public void SaveLog(string bufstr) { //這樣才能寫出中文字元 StreamWriter sw = new StreamWriter(My.ApplicationLogName(), true, System.Text.Encoding.GetEncoding(950)); sw.WriteLine(My.NowStr() " " bufstr); sw.Close(); } } |
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
不用 DllImport("kernel32") 就可跨平台讀寫 INI 檔 --- by C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/
//------------------------------------------------- //自己寫的 TIniFile (可用於手持裝置) //2007/06/21-22 // //TIniFile TmpIni = new TIniFile(My.ApplicationIniName()); //TmpIni.WriteString("sec","key1","test"); //..... //..... //TmpIni.Close(); //此時才會將 INI 寫入檔案 //------------------------------------------------- public class TIniFile { private string m_Path; private TStringList TmpList; //TStringList 也是我造的一個類別 , 請看後續發表 // IniFile Constructor. public TIniFile(string strIniPath) { m_Path = strIniPath; TmpList = new TStringList(); TmpList.Clear(); if (File.Exists(m_Path)) TmpList.LoadFromFile(m_Path); } //~TIniFile() public void Close() { TmpList.SaveToFile(m_Path); } public void DeleteKey(string str_sec, string str_key) { int dest_idx; dest_idx=FindSec(str_sec); if (dest_idx>=0) { dest_idx=FindKey(str_key,dest_idx); if (dest_idx>=0) //有 section 有 key { TmpList.RemoveAt(dest_idx); } } } public void EraseSection(string str_sec) { int from_idx; int dest_idx; from_idx=FindSec(str_sec); dest_idx=FindSecLastIdx(str_sec); for (int i=from_idx; i<=dest_idx; i ) { TmpList.RemoveAt(from_idx); } } public void WriteInteger(string str_sec, string str_key, int int_value) { WriteString(str_sec, str_key, int_value.ToString()); } public int ReadInteger(string str_sec, string str_key, int int_default) { string rr=ReadString(str_sec, str_key, int_default.ToString()); int r=Convert.ToInt32(rr); //或 r = int32.Parse(rr); return r; } public void WriteBool(string str_sec, string str_key, bool bool_value) { if (bool_value) { WriteString(str_sec, str_key, "1"); } else { WriteString(str_sec, str_key, "0"); } } public bool ReadBool(string str_sec, string str_key, bool bool_default) { string rr; bool r=false; if (bool_default) rr=ReadString(str_sec, str_key, "1"); else rr=ReadString(str_sec, str_key, "0"); if (rr.Trim()=="1") r=true; return r; } public void WriteString(string str_sec, string str_key, string str_value) { int dest_idx; int tmp_idx; dest_idx=FindSec(str_sec); if (dest_idx>=0) { dest_idx=FindKey(str_key,dest_idx); if (dest_idx>=0) //有 section 有 key { TmpList[dest_idx] = str_key "=" str_value; } else //有 section 沒 key { tmp_idx=FindSecLastIdx(str_sec); //TmpList.Insert(tmp_idx,str_key "=" str_value); if (tmp_idx!=TmpList.Count-1) { TmpList.Insert(tmp_idx 1,str_key "=" str_value); } else { TmpList.Add(str_key "=" str_value); } } } else //沒 section 沒 key { TmpList.Add("[" str_sec "]"); TmpList.Add(str_key "=" str_value); } } public string ReadString(string str_sec, string str_key, string str_default) { string r=str_default; int dest_idx; dest_idx=FindSec(str_sec); if (dest_idx>=0) { dest_idx=FindKey(str_key,dest_idx); if (dest_idx>=0) //有 section 有 key { string[] tmp = TmpList[dest_idx].Split('='); r=tmp[1]; } } return r; } private int FindSec(string str_sec) { int r=-1; string str_sec_label="[" str_sec.ToUpper() "]"; for (int i=0; i<=TmpList.Count-1; i ) { if (TmpList[i].ToUpper()==str_sec_label) { r=i; break; } } return r; } private int FindKey(string str_key, int from_idx) { int r=-1; for (int i=from_idx 1; i<=TmpList.Count-1; i ) { if (TmpList[i].Substring(0,1)=="[") //遇到下一個節區 { break; } string[] tmp = TmpList[i].Split('='); if (tmp[0].ToUpper()==str_key.ToUpper()) { r=i; break; } } return r; } private int FindSecLastIdx(string str_sec) //找到某一 section 區最後位置 { int r=-1; int dest_idx=FindSec(str_sec); if (dest_idx>=0) { for (int i=dest_idx 1; i<=TmpList.Count-1; i ) { if (TmpList[i].Substring(0,1)=="[") //遇到下一個節區 { r=i-1; break; } } if (r==-1) //沒遇到下一個節區 { r=TmpList.Count-1; } } else { r=TmpList.Count-1; } return r; } }
編輯記錄
bruce0211 重新編輯於 2007-07-05 23:53:00, 註解 無‧
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
包裝 ArrayList 成為 TStringList --- by C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/
using System.Collections; //ArrayList //------------------------------------------------- //TStringList //------------------------------------------------- //使用例 //TStringList TmpList = new TStringList(); //TmpList.Add("123"); //TmpList.Add("456"); //TmpList.SaveToFile("test.txt"); // //TmpList.LoadFromFile("test.txt"); //for (int i=0; i<=TmpList.Count-1; i ) //{ // MessageBox.Show(TmpList[i]); //} //------------------------------------------------- public class TStringList : ArrayList { public void SaveToFile(string fn) { //StreamWriter sw = File.CreateText(fn); StreamWriter sw = new StreamWriter(fn, false, System.Text.Encoding.GetEncoding(950)); //這樣才能寫出中文字元 for(int i = 0; i != this.Count; i ) { sw.WriteLine(this[i]); } sw.Close(); } public void LoadFromFile(string fn) { this.Clear(); //這樣才能讀入中文字元 StreamReader sr = new StreamReader(fn, System.Text.Encoding.GetEncoding(950)); //或 System.Text.Encoding.Default while (sr.Peek() >= 0) { this.Add(sr.ReadLine()); } sr.Close(); } } |
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
WINCE 平台之 tabControl 頁籤索引亂跳 BUG 解決方案 --- by C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/
tabControl 是一個多頁容器元件 , 像是 VCL 的 Notebook 元件 , 元件功用我不必多說了 , 但我發現在 VS2003 C# WINCE 4.2 平台下 , 跳頁會有 BUG , 例如我要從其他頁切換到第 3 頁交易新增頁面 應該是用 tabControl1.SelectedIndex = 2 ; 看了物件屬性 , 明明第 3 頁就是交易新增頁面 為何用 tabControl1.SelectedIndex = 2 跳出的卻是其它頁面 後來發現它的確有這 BUG (第一次試不出來的 , 多試幾次就會發現 BUG 跑出來) 後來改成下面的方法就 OK 了 , 但要設定 tabControl 容器內 每個子元件 TabPages.Text 屬性跟 TabPages.Name 一樣 private void SetPage(int pgid) { //tabControl1.SelectedIndex = pgid-1; //我習慣把第一頁當作索引 1 而不是索引 0 //SelectedIndex 有 bug 會亂跳,使用下列方式取代, 但要設定 TabPages.Text 屬性 int idx=-1; for (int i=0; i<=tabControl1.TabPages.Count-1; i ) { if (tabControl1.TabPages[i].Text=="tabPage" pgid.ToString()) { idx=i; break; } } tabControl1.SelectedIndex = idx; } |
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
WINCE 主 Form 沒有 KeyPreView 的解決方案 --- by C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/
原理很簡單 , 將所有編輯元件(TextBox)的 GotFocus 事件導向到自建的 OnGotFocus() , 統一由主 Form 取得焦點 , 取得焦點就能掌控所有 KeyDown 事件 (一般 PDA 都沒有硬體鍵盤 , 所以這個解決方案在一般 PDA POS 上就不顯得那麼重要) //--------------------------------------------------------------------------- private void Form1_Load(object sender, System.EventArgs e) { control_list(this); //這樣才能連 COLLECTION 中的物件全部找出來 } //--------------------------------------------------------------------------- private void control_list(Control c) { for (int i = 0; i < c.Controls.Count; i ) { if (c.Controls[i] is TextBox) { c.Controls[i].GotFocus = new EventHandler(OnGotFocus); } control_list(c.Controls[i]); //遞迴 } } //--------------------------------------------------------------------------- private void OnGotFocus(object sender, System.EventArgs e) { //MessageBox.Show("this.Focus()"); this.Focus(); }
編輯記錄
bruce0211 重新編輯於 2007-07-05 23:51:31, 註解 無‧
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
UNICODE 下取部份字串跟長度 --- by C# 源碼任務 http://tw.myblog.yahoo.com/bruce0211/
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
新增兩篇心得分享 , 圖太多 , 就不貼在這兒了
輸入對話盒(InputBox)按鍵的設計參考 tw.myblog.yahoo.com/bruce0211/article WINCE 版 POS (手持式收銀機) 開發進度現場直播 (UI) tw.myblog.yahoo.com/bruce0211/article 手持式收銀機並不"只"是點菜機或賣當勞那種點餐機 (一般市售程式開發書籍都把 PDA POS 當點菜機方面應用) , 它是完整的 POS , 有自己的資料庫 , 可刷條碼 , 可單機離線作業 , 可用藍芽印表機列印發票 .... 當然它也可以當點餐機 , 透過無線網路或瀏覽器 , 當作後台主機畫面的延申 , 收集資料後把所有資料丟往後台處理 , 不過在這裏還是朝完整 POS 手持化(或說小型化)的方向來做開發研究 .... |
skcc
中階會員 發表:36 回覆:96 積分:88 註冊:2002-08-28 發送簡訊給我 |
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
sorry , 不清楚喔
目前都在 VS2003 C# 及 WIN CE 4.2 中打轉 .... ===================引 用 skcc 文 章=================== 這是非常實用的心得… 支持心得分享… 另外,請問 bruce0211 兄有沒有 WM5 裡有關 database 及如何在 VC# 上使用的資料呢?我在 M$ 網站找過,好像有個產品叫 SQL Server 2005 Compact Edition,但不知道怎樣使用… Anthony Lee |
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
另外給大家看一下 Delphi for .NET 開發手持行動程式的Delphi 程式碼
unit WinForm1; interface {$define CF} uses System.Drawing, System.Collections, System.ComponentModel, {$ifdef CF} //===== Fix Libraries for MS Compact Framework (Above Windows Mobile 2003 V2)===== System.Drawing.Font,System.Drawing.GraphicsUnit,System.ComponentModel.WindowsCE, {$endif} System.Windows.Forms, System.Data, Borland.Vcl.Classes; type TWinForm1 = class(System.Windows.Forms.Form) {$REGION 'Designer Managed Code'} strict private /// /// Required designer variable. /// Components: System.ComponentModel.Container; Button1: System.Windows.Forms.Button; /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// procedure InitializeComponent; procedure Button1_Click(sender: System.Object; e: System.EventArgs); {$ENDREGION} strict protected /// /// Clean up any resources being used. /// procedure Dispose(Disposing: Boolean); override; private { Private Declarations } public constructor Create; end; [assembly: RuntimeRequiredAttribute(TypeOf(TWinForm1))] implementation {$AUTOBOX ON} {$REGION 'Windows Form Designer generated code'} /// /// Required method for Designer support -- do not modify /// the contents of this method with the code editor. /// procedure TWinForm1.InitializeComponent; begin Self.Button1 := System.Windows.Forms.Button.Create; Self.SuspendLayout; // // Button1 // Self.Button1.Location := System.Drawing.Point.Create(36, 33); Self.Button1.Name := 'Button1'; Self.Button1.TabIndex := 0; Self.Button1.Text := 'Button1'; Include(Self.Button1.Click, Self.Button1_Click); // // TWinForm1 // Self.AutoScaleBaseSize := System.Drawing.Size.Create(6, 16); Self.ClientSize := System.Drawing.Size.Create(244, 302); Self.Controls.Add(Self.Button1); Self.Font := System.Drawing.Font.Create('新細明體', 9.75, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(136))); Self.Name := 'TWinForm1'; Self.Text := 'WinForm1'; Self.ResumeLayout(False); end; {$ENDREGION} procedure TWinForm1.Dispose(Disposing: Boolean); begin if Disposing then begin if Components <> nil then Components.Dispose(); end; inherited Dispose(Disposing); end; constructor TWinForm1.Create; begin inherited Create; // // Required for Windows Form Designer support // InitializeComponent; // // TODO: Add any constructor code after InitializeComponent call // end; procedure TWinForm1.Button1_Click(sender: System.Object; e: System.EventArgs); var SS:TStringList; begin SS := TStringList.Create; ss.Add('測試!! 我的VCL Class for CF!!'); ss.SaveToFile('\My Documents\AAA.txt'); ss.Clear; ss.Free; end; end. |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
你這部份會錯誤,是理所當然的
byte[] bytData = Encoding.Unicode.GetBytes(bufstr); 這一行,把 bufstr 內容的「Unicode 內碼」,存進了 bytData string r = Encoding.GetEncoding(950).GetString(bytData); 而這一行,把 bytData 的內容,用「CP950」來解釋,轉成字串,存進了 r 這個字串變數 錯誤就在於,把「Unicode 內碼」用「CP950」來解釋,這樣出來的 r 字串,怎可能不是亂碼? 所以很簡單,只要改成 byte[] bytData = Encoding.GetEncoding(950).GetBytes(bufstr); 這樣 bytData 的內容就是 CP950 內碼 接下來,只要 string r = Encoding.GetEncoding(950).GetString(bufstr, 0, 你要的長度); 就行了 ===================引 用 bruce0211 文 章=================== /* byte[] bytData = Encoding.Unicode.GetBytes(bufstr); string r = Encoding.GetEncoding(950).GetString(bytData); return r.Length; //用於 Ansi 字串(如 r)有問題 , 如取"大家好1" -> 7 , 如取"大家壞1" -> 6 */
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
===================引 用 G01 文 章=================== To Bruce0211: ??????????????????????????? 如果使用Delphi for .NET 開發CF , 真的可以省很多事..... ??????????????????????????? TStringList類別也可以直接使用 小弟從 delphi/bcb 一路走來 您說的小弟又何嘗不知 只是因公司專案需要,還有新版 delphi/bcb 實在越來越少資源 所以不得已轉換跑道 |
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
===================引 用 sryang 文 章=================== 你這部份會錯誤,是理所當然的 byte[] bytData = Encoding.Unicode.GetBytes(bufstr); 這一行,把 bufstr 內容的「Unicode 內碼」,存進了 bytData string r = Encoding.GetEncoding(950).GetString(bytData); 而這一行,把 bytData 的內容,用「CP950」來解釋,轉成字串,存進了 r 這個字串變數 錯誤就在於,把「Unicode 內碼」用「CP950」來解釋,這樣出來的 r 字串,怎可能不是亂碼? 所以很簡單,只要改成 byte[] bytData = Encoding.GetEncoding(950).GetBytes(bufstr); 這樣 bytData 的內容就是 CP950 內碼 接下來,只要 string r = Encoding.GetEncoding(950).GetString(bufstr, 0, 你要的長度); 就行了 ===================引 用 bruce0211 文 章=================== /* byte[] bytData = Encoding.Unicode.GetBytes(bufstr); string r = Encoding.GetEncoding(950).GetString(bytData); return r.Length; //用於 Ansi 字串(如 r)有問題 , 如取"大家好1" -> 7 , 如取"大家壞1" -> 6 */ 感謝長官蒞臨指導 , 小弟都快忘了有發表過此篇文章 , 真是越來越懶了 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |