現有 Delphi 程式轉移到 D2009 中的注意事項與方法 |
|
careychen
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:41 回覆:580 積分:959 註冊:2004-03-03 發送簡訊給我 |
這邊有個網站,他介紹了從現在的 delphi 昇級至 Delphi 2009 的一些方法
現有 Delphi 項目遷移到 Tiburon 中的注意事項 有在玩 Delphi 2009 的先進們可以參考看看
------
價值的展現,來自於你用哪一個角度來看待它!! | ||||||||||
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
|||||||||||
qupyliang
一般會員 ![]() ![]() 發表:21 回覆:22 積分:23 註冊:2007-04-26 發送簡訊給我 |
10/3~9之間,興德資訊針對
.如何將原來的 Big 5 資訊系統轉換成 Unicode 系統 .如何將舊有資料庫應用系統升級到 Delphi 2009環境 這兩個題目舉辦技術研討會,有興趣想了解過去版本的專案 如何移植到Delphi 2009的先進們,不妨前往了解。 http://www.sinter.com.tw/borland/seminars/Delphi2009_0810.html |
||||||||||
danny
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:100 回覆:522 積分:595 註冊:2002-03-11 發送簡訊給我 |
會出現
A fatal MySQL error occured: Table './cnpack/cns_log' is marked as crashed and should be repaired SELECT max(hid), max(uid) FROM cns_log; ===================引 用 careychen 文 章=================== 這邊有個網站,他介紹了從現在的 delphi 昇級至 Delphi 2009 的一些方法 現有 Delphi 項目遷移到 Tiburon 中的注意事項 有在玩 Delphi 2009 的先進們可以參考看看
------
將問題盡快結案也是一種禮貌! |
||||||||||
careychen
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:41 回覆:580 積分:959 註冊:2004-03-03 發送簡訊給我 |
哦~~, Sorry 我試了一下似乎是他的網站掛了,他回復時,小弟會再回文一次,謝謝版主
===================引 用 danny 文 章=================== 會出現 A fatal MySQL error occured: Table './cnpack/cns_log' is marked as crashed and should be repaired SELECT max(hid), max(uid) FROM cns_log; ===================引 用 careychen 文 章=================== 這邊有個網站,他介紹了從現在的 delphi 昇級至 Delphi 2009 的一些方法 現有 Delphi 項目遷移到 Tiburon 中的注意事項 有在玩 Delphi 2009 的先進們可以參考看看
------
價值的展現,來自於你用哪一個角度來看待它!! |
||||||||||
pedro
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
以下貼自google的該頁庫存
http://www.google.com.tw/search?hl=zh-TW&q=現有 Delphi 項目遷移到 Tiburon 中的注意事項&btnG=Google 搜尋&meta=&aq=f&oq= 現有 Delphi 專案遷移到 Tiburon 中的注意事項 翻譯:峪飛鷹 2008-08-30 隨著 Embarcadero 8 月 25 號發佈 RAD Studio 2009 (Tiburon) 以來(Tiburon 的 RTM 日期可能要延後到 9 - 10 月),隨著 Tiburon 全面支持 Unicode,現有的 Delphi / C Builder 專案要遷移到 Unicode 下應該注意些什麼也成為大家最為關心的問題。Tiburon 對 Unicode 的支援不僅僅是將原來 類型映射為 AnsiString 的 String 類型直接改成 WideString,而是對 AnsiString 結構作出修改,同時增加了 UnicodeString 類型來完美支持 Unicode。這意味著,要想平穩遷移到 Unicode 下,程式師不得不對現有代碼作出一定的修改。 在 Tiburon 以前的版本中,AnsiString 和 WideString 除了 data size 不同外,在功能上是相同的。早先版本的 AnsiString 的結構如下: Format of AnsiString Data Type
而這個結構在 Tiburon 中已經發生變化,AnsiString 增加了兩個新的 fields, 一個是 CodePage,一個是 ElemSize,這樣做可以讓新版的 AnsiString 和 UnicodeString 在結構上保持一致。 而 WideString 類型在早先的版本中用來保存雙位元組資料。其本質和 Windows BSTR 是一樣的。在 Tiburon 中 WideString 仍然是為 COM 保持相容的,也就是說它依然沒有引用計數,相比較而言,UnicodeString 在性能和效率上將會是 COM 以外的程式首選的字元類型。 閃亮登場的 UnicodeString 類型 Tiburon 中,新的、默認的 string 就是 UnicodeString。這個類型既可以包含 ANSI 字元,也可以包含 Unicode 字元。下面是 UnicodeString 類型的結構: Format of UnicodeString Data Type
UnicodeString 和 AnsiString 都是如上的結構,儘管 UnicodeString 包含是雙位元組資料,AnsiString 包含的是單字節的。 用 Object Pascal 語言來描述 UnicodeString 的結構,應該是這樣: type StrRec = record CodePage: Word; ElemSize: Word; refCount: Integer; Len: Integer; case Integer of 1: array[0..0] of AnsiChar; 2: array[0..0] of WideChar; end; UnicodeString 增加了 code page 欄位和 element size 來描述字串內容,這使得 UnicodeString 和其他類型的字串可以很好的相相容,所以 AnsiString 和 UnicodeString 可以很方便的互相轉換,唯一要注意的是,當把 UnicodeString 向下轉型到 AnsiString 的時候,可能會丟失資料,因此強烈建議你不要這麼做。UnicodeString 保存的是 UTF-16 字元。 在舊的環境下,可以使用編譯標誌 Unicode 來判斷編譯環境是否支援 UnicodeString,以便您可以在同一套代碼中維護不同版本的字元支援環境。編譯指令如下: Delphi 使用: {$IFDEF Unicode} C Builder 使用: #ifdef _DELPHI_STRING_UNICODE 變化概要: String 類型映射為 UnicodeString 而不是 AnsiString Char 類型映射為 WideChar(2 bytes not 1 byte), 並且是 UTF-16 字元 PChar 類型映射為 PWideChar C 中,System::String 映射到 UnicodeString 類 Delphi 中,AnsiString 映射為早先版本中默認的 string 未變化概要: AnsiString WideString AnsiChar PAnsiChar 隱式轉換仍然可用 用戶的活動頁代碼(The user's active code page)控制著模式(ANSI vs. Unicode),所以 AnsiString 仍然可以支援 由於這些變化,代碼編寫上也出現了一些值得注意的情況,特別是在你打算將舊有的項目遷移到 Tiburon 下時更是如此。下面就列出一些發生的變化情況以及編寫代碼時應該注意的注意事項。 下麵的操作將不再依賴字元 Size: 合併字串 Concat( , ) 標準字串函數 Length()返回字元元素的長度,此值可能和字元在位元組長度上並不匹配。SizeOf 函數則返回資料的位元組長度,這意味著 SizeOf 和 Length 的返回值可能是不同的 Copy(, , )返回的 SubString 基於字元元素 Pos(,)返回第一個字元元素的序號 操作 CompareStr() CompareText() ... FillChar() FillChar(Rect, SizeOf(Rect), #0) FillChar(WndClassEx, SizeOf(TWndClassEx), #0). 使用的時候注意 WndClassEx.cbSize := SizeOf(TWndClassEx) Windows API API 默認使用 WideString (*W)形態的版本 PChar()具有相同的語義 範例: GetModuleFileName: function ModuleFileName(Handle: HMODULE): string; var Buffer: array[0..MAX_PATH] of Char; begin SetString(Result, Buffer, GetModuleFileName(Handle, Buffer, Length(Buffer))); end; GetWindowText: function WindowCaption(Handle: HWND): string; begin SetLength(Result, 1024); SetLength(Result, GetWindowText(Handle, PChar(Result), Length(Result))); end; 字串索引: function StripHotKeys(const S: string): string; var I, J: Integer; LastChar: Char; begin SetLength(Result, Length(S)); J := 0; LastChar := #0; for I := 1 to Length(S) do begin if (S[I] <> '&') or (LastChar = '&') then begin Inc(J); Result[J] := S[I]; end; LastChar := S[I]; end; SetLength(Result, J); end; 接上文 依賴字元 Size 的代碼結構: 在 Tiburon 中,下列列表中列出的這些函數和特性依賴字元 Size,並且已經包含了一個“輕便”的版本,遷移代碼的時候只需要將列出的代碼遷移到後面提供的輕便版本即可。 SizeOf() 替換為 Length() 範例: var Count: Integer; Buffer: array[0..MAX_PATH - 1] of Char; begin // 現有代碼 - 當 string = UnicodeString 的時候這段代碼是錯的 Count := SizeOf(Buffer); GetWindowText(Handle, Buffer, Count); // 正確的應該是下面這樣 Count := Length(Buffer); // <<-- Count 應該是 Chars 而不是 Bytes GetWindowText(Handle, Buffer, Count); end; SizeOf 返回的是陣列的位元組數,而 GetWindowText 的 Counts 參數需要的是字元數,所以這裏需要把 SizeOf 換成 Length。 Move(... CharCount) 替換為 Move( ,,, CharCount * SizeOf(Char)) var Count: Integer; Buf1, Buf2: array[0..255] of Char; begin // 現有代碼 - 當 string = UnicodeString (char = 2 bytes) 時,下面的代碼是錯誤的 Count := Length(Buf1); Move(Buf1, Buf2, Count); // 正確的寫法應該是 Count := SizeOf(Buf1); // <<-- Specify buffer size in bytes Count := Length(Buf1) * SizeOf(Char); // <<-- Specify buffer size in bytes Move(Buf1, Buf2, Count); end; 由於 Length 返回的是字元數,而 Move 的 Count 參數需要的是位元組數,所以應該用 SizeOf 或者 Length(Buf1) * SizeOf(Char) 替換 Length(Buf1)。 Stream 的 Read/Write 替換為 AnsiString, SizeOf(Char),或者使用 TEncoding 類 調用 Read/ReadBuffer 方法的範例: var S: string; L: Integer; Stream: TStream; Temp: AnsiString; begin // 現有代碼- 當 string = UnicodeString 時它是不正確的 Stream.Read(L, SizeOf(Integer)); SetLength(S, L); Stream.Read(Pointer(S)^, L); // 正確的 Unicode 寫法如下 Stream.Read(L, SizeOf(Integer)); SetLength(S, L); Stream.Read(Pointer(S)^, L * SizeOf(Char)); // <<-- Specify buffer size in bytes //正確的 Ansi 寫法如下 Stream.Read(L, SizeOf(Integer)); SetLength(Temp, L); // <<-- 使用臨時的變數 AnsiString Stream.Read(Pointer(Temp)^, L * SizeOf(AnsiChar)); // <<-- Specify buffer size in bytes S := Temp; // <<-- 放寬 string 到 Unicode end; 上面的解決方案依賴於您存儲在 Stream 中的字串的編碼格式,更好的讀取和轉換他們建議使用 TEncoding 類。 調用 Write/WriteBuffer 的範例: var S: string; Stream: TStream; Temp: AnsiString; begin // 現有代碼 - 當 string = UnicodeString 時它是錯的 Stream.Write(Pointer(S)^, Length(S)); // 正確的讀取 Unicode 的代碼 Stream.Write(Pointer(S)^, Length(S) * SizeOf(Char)); // <<-- Specify buffer size in bytes // 正確的讀取 Ansi 的代碼 Temp := S; // <<-- Use temporary AnsiString Stream.Write(Pointer(Temp)^, Length(Temp) * SizeOf(AnsiChar));// <<-- Specify buffer size in bytes end; 上面的解決方案依賴於您要存儲進 Stream 中的字串的編碼格式,建議使用 TEncoding 類來更好的對格式進行處理。 FillChar(, , ) 如果採用 #0 填充, 替換為 * SizeOf(Char);如果填充其他字元,替換為 StringOfChar 函數 範例: var Count: Integer; Buffer: array[0..255] of Char; begin // 現有代碼 - 當 string = UnicodeString ( char = 2 位元組) 時,這段代碼是錯的 Count := Length(Buffer); FillChar(Buffer, Count, 0); // 正確的代碼應該寫作下面這樣 Count := SizeOf(Buffer); // <<-- Specify buffer size in bytes Count := Length(Buffer) * SizeOf(Char); // <<-- Specify buffer size in bytes FillChar(Buffer, Count, 0); end; Length 返回的是字元數,而 FillChar 的 Count 參數需要的是位元組數,所以必須用 SizeOf 替換 Length,或者使用 Length * SizeOf(Char)。 另外,需要注意的是,Tiburon 中 Char 等於 2 個位元組,FillChar 填充的時候確是按照 Bytes 來計算的,所以,下面的代碼 var Buf: array[0..32] of Char; begin FillChar(Buf, Length(Buf), #9); end; 並不是向目標中填充 $09,而是 $0909,要得到正確的數值,應該改寫成下面這樣: var Buf: array[0..32] of Char; begin StrPCopy(Buf, StringOfChar(#9, Length(Buf))); ... end; GetProcAddress(, ) 由於 GetProcAddres 沒有對應的 *W (Unicode) 版本的 API,所以只能使用下面的代碼來正確調用它: procedure CallLibraryProc(const LibraryName, ProcName: string); var Handle: THandle; RegisterProc: function: HResult stdcall; begin Handle := LoadOleControlLibrary(LibraryName, True); @RegisterProc := GetProcAddress(Handle, PAnsiChar(AnsiString(ProcName))); end; RegQueryValueEx 函數 由於 RegQueryValueEx 函數的 Len 指定的是位元組數,而不是字元數,所以 Unicode 版本中它的大小是實際需要大小的 2 倍,所以這樣的代碼: Len := MAX_PATH; if RegQueryValueEx(reg, PChar(Name), nil, nil, PByte(@Data[0]), @Len) = ERROR_SUCCESS then SetString(Result, Data, Len - 1) // Len includes #0 else RaiseLastOSError; 應該換成下面這樣: Len := MAX_PATH * SizeOf(Char); if RegQueryValueEx(reg, PChar(Name), nil, nil, PByte(@Data[0]), @Len) = ERROR_SUCCES then SetString(Result, Data, Len div SizeOf(Char) - 1) // Len includes #0, Len contains the number of bytes else RaiseLastOSError; CreateProcessW 函數 在 Unicode 版本的 CreateProcess 函數中,其行為和 ANSI 的版本略有不同。Unicode 的 CreateProcessW 會改變參數 lpCommandLine 傳入的資料,因此調用 CreateProcess / CreateProcessW 的時候,不可以給 lpCommandLine 賦值常量,或者是一個變數指向的常量,否則函數會拋出 access violations 的異常。下面是錯誤的代碼: // 傳入了一個 string 常量 CreateProcess(nil, 'foo.exe', nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); // 傳入了一個常量運算式 const cMyExe = 'foo.exe' CreateProcess(nil, cMyExe, nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); // 傳入了一個引用計數為 -1 的字串: const cMyExe = 'foo.exe' var sMyExe: string; sMyExe := cMyExe; CreateProcess(nil, PChar(sMyExe), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); LeadBytes 常量 早先的版本中 LeadBytes 常量包含了本地系統中所有可以作為雙位元組字元 LeadByte 的列表,常常有這樣的代碼: if Str[I] in LeadBytes then 現在你需要將它改成調用 IsLeaderChar 函數 if IsLeadChar(Str[I]) then 使用 TMemoryStream 類 當您需要用 TMemoryStream 寫入一個文字檔案的時候,最好在寫入任何字元資料進去之前先寫入一個 Byte Order Mark (BOM): var Bom: TBytes; begin ... Bom := TEncoding.UTF8.GetPreamble; Write(Bom[0], Length(Bom)); 而任何寫入的字元需要被轉換成 UTF-8 編碼: var Temp: Utf8String; begin ... Temp := Utf8Encode(Str); // Str 是要寫入檔的字元 Write(Pointer(Temp)^, Length(Temp)); //Write(Pointer(Str)^, Length(Str)); 原來寫入字串的代碼 接上文 MultiByteToWideChar 函數 調用 Windows API MultiByteToWideChar 函數可以簡單的用一個任務替代,下面是一個是用 MultiByteToWideChar 的例子: procedure TWideCharStrList.AddString(const S: string); var Size, D: Integer; begin Size := SizeOf(S); D := (Size 1) * SizeOf(WideChar); FList[FUsed] := AllocMem(D); MultiByteToWideChar(0, 0, PChar(S), Size, FList[FUsed], D); Inc(FUsed); end; 轉換到 Unicode 下可以寫作這樣(同時支援 Unicode 和 ANSI 字元): procedure TWideCharStrList.AddString(const S: string); {$IFNDEF UNICODE} var L, D: Integer; {$ENDIF} begin {$IFDEF UNICODE} FList[FUsed] := StrNew(PWideChar(S)); {$ELSE} L := Length(S); D := (L 1) * SizeOf(WideChar); FList[FUsed] := AllocMem(D); MultiByteToWideChar(0, 0, PAnsiChar(S), L, FList[FUsed], D); {$ENDIF} Inc(FUsed); end; SysUtils.AppendStr 函數 AppendStr 函數已經廢棄了,因為它與 AnsiString 硬編碼在一起,而且沒有 Unicode 的版本可以替換,所以下面的代碼 AppendStr(String1, String2); 應該換成: String1 := String1 String2; 您也可以使用新的 TStringBuilder 類來替換。 使用 Named Threads 現有 Delphi 代碼中使用了 Named Threads 的代碼必須修改了。在早先的版本中,當你需要在分類(gallery)中用一個新的 Thread Object 去創建一個 Thread 的時候,需要在新的 Thread 單元中建立下面的類型: type TThreadNameInfo = record FType: LongWord; // must be 0x1000 FName: PChar; // pointer to name (in user address space) FThreadID: LongWord; // thread ID (-1 indicates caller thread) FFlags: LongWord; // reserved for future use, must be zero end; 在調試器中,Named Thread 的處理器期待 FName 成員是 ANSI 字元,不是 Unicode,所以上面的聲明必須改成下面這樣: type TThreadNameInfo = record FType: LongWord; // must be 0x1000 FName: PAnsiChar; // pointer to name (in user address space) FThreadID: LongWord; // thread ID (-1 indicates caller thread) FFlags: LongWord; // reserved for future use, must be zero end; 在新版本中上述聲明已經修改,提示這段代碼是需要您注意早先版本中您手工創建並聲明的代碼需要您自己修改。 如果您需要在 Named Thread 中使用 Unicode 字元,您必須將字串格式化成 UTF-8 編碼,調試器可以完全支援改編碼。例如: ThreadNameInfo.FName := UTF8String('UnicodeThread_фис'); 注意:C Builder 裏面一直使用的是正確的代碼,所以上述問題在 C Builder 中並不存在。 使用 PChar 轉換的指針運算 在 Tiburon 更早的版本中,並不是所有的指針類型都支持指針運算。因為這樣,為了讓無類型指標也支持指標運算,許多代碼都將其轉化成 PChar 操作。現在,可以使用 Tiburon 中的新編譯條件 {$POINTERMATH} 來指示編譯器允許指標運算,特別是允許 PByte 的指針運算。{$POINTERMATH ON/OFF} 可以打開/禁止對任意指標變數的運算,增減指標實際操作的是指標元素的大小。 下面的例子是一個將某類型指標轉換成 PChar 後的指標運算: function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer; begin if (Node = FRoot) or (Node = nil) then Result := nil else Result := PChar(Node) FInternalDataOffset; end; 您應該將其修改成 PByte 而不是 PChar: function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer; begin if (Node = FRoot) or (Node = nil) then Result := nil else Result := PByte(Node) FInternalDataOffset; end; 在上面的例子中,Node 真實的資料不是 PChar 的資料。將其強制轉換成 PChar 的操作在早先的版本中是正常的,因為早先版本中 SizeOf(Char) == Sizeof(Byte)。但是現在不同了,所以這樣的代碼必須從 PChar 改換成 PByte。如果不做這樣的更改,返回的 Pointer 將指向錯誤的資料。 變體開放陣列(Variant Open Array)參數 如果你的代碼中有使用 TVarRec 類型去處理開放陣列的話,你可能需要為其添加對 vtUnicodeString 的支持。參看下列示例: procedure RegisterPropertiesInCategory(const CategoryName: string; const Filters: array of const); overload; var I: Integer; begin if Assigned(RegisterPropertyInCategoryProc) then for I := Low(Filters) to High(Filters) do with Filters[I] do case vType of vtPointer: RegisterPropertyInCategoryProc(CategoryName, nil, PTypeInfo(vPointer), ); vtClass: RegisterPropertyInCategoryProc(CategoryName, vClass, nil, ); vtAnsiString: RegisterPropertyInCategoryProc(CategoryName, nil, nil, string(vAnsiString)); vtUnicodeString: RegisterPropertyInCategoryProc(CategoryName, nil, nil, string(vUnicodeString)); else raise Exception.CreateResFmt(@sInvalidFilter, [I, vType]); end; end; 其他需要注意的代碼: AllocMem( AnsiChar of AnsiChar AnsiString of Char Copy( GetMem( Length( PAnsiChar( Pointer( Seek( ShortString string[ 代碼中包含上述寫法的地方可能需要修改以適應 UnicodeString 的變化。 帶字元的集合類型 您可能需要修改下列類型: in AnsiChar> 這樣的代碼生成的程式是正確的(>#255 的字元不會包含在集合內)。編譯器會提出 "WideChar reduced in set operations" 的警告,基於您代碼的需要,您可以關閉這個警告,或者使用 CharInSet 函數替代。 in LeadBytes 全局的 LeadBytes 變數包含的是本地 MBCS Ansi 字元的集合。UTF-16 格式也有 LeadChar 的概念((#$D800 - #$DBFF 是高 surrogate, #$DC00 - #$DFFF 是低 surrogate)。因此建議使用 overload 函數 IsLeadChar 來判斷,該函數的 ANSI 版本檢測 LeadBytes,WideChar 版本檢測 high/low surrogate。 字元分類 使用靜態類 TCharacter。Character 單元中提供了一些函數對字元分類:IsDigit, IsLetter, IsLetterOrDigit, IsSymbol, IsWhiteSpace, IsSurrogatePair,等等。 應當心這些結構 您需要檢查下列可能引起錯誤的結構: 模糊的類型轉換 AnsiString(Pointer(foo)) 檢查正確性:代碼是什麼意圖? 可疑的類型轉換引發的警告 PChar() PAnsiChar() 直接建立、操作、訪問 string 的內部結構。例如 AnsiString 的內部結構已經發生變化,所以這樣的操作是危險的。您應該使用 StringRefCount, StringCodePage, StringElementSize 等方法來獲得額外資訊。 控制項和類 TStrings: 內部存儲的是 UnicodeStrings。 TWideString:(可能被廢棄)沒有更改,內部使用 WideString (BSTR) TStringStream 被重寫成內部存儲 ANSI 字元 字元編碼可以被重載 考慮使用 TStringBuilder 替代 TStringStream 來逐步構建字串 TEncoding Default 屬性是用戶活動頁碼(users’ active code page) 支持 UTF-8 支持 UTF-16, big 和 little endian 支持 Byte Order Mark (BOM) 您可以繼承子類實現特殊的編碼 Byte Order Mark BOM 必須添加到檔中以便判斷檔的編碼方式。 UTF-8 使用 EF BB EF UTF-16 Little Endian 使用 FF FE UTF-16 Big Endian 使用 FE FF 做好這些注意事項,將幫助您順利地把舊有專案遷移到 Tiburon 的 Unicode 下。當然,如果您開發的是多版本控制項,或者是希望專案能在多個版本中編譯,您最好根據這些特性定義適當的編譯條件,以便讓代碼更好的被更低的版本的編譯器支持和編譯。
本文基於 Tiburon 幫助編寫,如有翻譯錯誤或描述不準確的地方歡迎大家指正!相信這次 Delphi / C Builder 2009 將是廣大愛好者最喜歡的版本之一。 全文完。 |
||||||||||
careychen
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:41 回覆:580 積分:959 註冊:2004-03-03 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |