2008年9月30日 星期二

MySQL中使用DataTable.Load() 讀取BIGINT型態的欄位時發生( "數值對 Int32 而言太大或太小" )的錯誤!

原始碼如下:
string strConnection = "dataSource=localhost;database=test;user=root;password=1234";
MySqlConnection myConnection = new MySqlConnection(strConnection);
string strCommand = "SELECT AdID FROM Advertisement";
MySqlCommand myCommand = new MySqlCommand(strCommand, myConnection);
DataTable table = new DataTable();
try
{
 myConnection.Open();
 table.Load(myCommand.ExecuteReader()); //此行發生錯誤
}
catch { MessageBox.Show("讀取失敗"); }
finally { myConnection.Close(); }

真是奇怪?
我記得TableLoad的時候會自動判斷資料庫中Column的型態,然後自動對Table新增相對應型態的Column啊,明明Table一開始也沒有指定任何型態,怎麼會發生這樣的事情?

找了很久終於找到原因了。
原來AdID這個Column在資料庫中是"自動遞增(Auto Increment)",結果將此ColumnAuto INC取消,然後將Default Value設為0 錯誤就消失了^^'''

到現在我還是不知道到底是為什麼,兩者看起來似乎沒有什麼關係啊! 有人知道嗎?

2008年9月28日 星期日

正則表達式

下面是自己嘗試寫出來的不保證一定正確
for C#

using
System.Text.RegularExpressions;

Regex 類別

[資料夾路徑驗證 ]
適用格式如下:
c: , c:\ , c:\abc
, c:\abc\

正則表達式如下:
"^[a-zA-Z]:(\\\\|(\\\\[^\\\\/:*?\"<>|]+)*|\\\\([^\\\\/:*?\"<>|]+\\\\)*)$"

[取得副檔名 ]
適用格式如下:
.a , .ab , .
abc , .abcd

正則表達式如下:
@"\.[a-zA-Z0-9]{1,4}$"

Match match = Regex.Match("要驗證的文字","正則表達式") ;
if (match.Success)
 string extName = match.Groups[0].Value;
else
 MessageBox.Show("無任何匹配");

[IPv4驗證 ]
適用格式如下:
0-255.0-255.0-255.0-255
ps. 開頭不得為0 ( ex. 192.168.00.001 )

正則表達式如下:
@"^(\d|[1-9]\d|1\d{1,2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{1,2}|2[0-4]\d|25[0-5])){3}$"

2008年9月23日 星期二

兩程式之間的訊息傳遞(使用SendMessage)

想要從一個程式傳送消息到另一個程式可以使用下面兩個Win32 API
1. SendMessage( ):用來傳遞消息代號
2. FindWindows( ):用來找出目標視窗的Handler

下面例子為由Client端發送訊息至Server端

Client端程式

using System.Runtime.InteropServices;

public class Client
{
 [DllImport("User32.dll", EntryPoint = "FindWindow")]
 private static extern int FindWindows(string lpClassName, string lpWindowName);

 [DllImport("User32.dll", EntryPoint = "SendMessage")]

 private static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
 
 
public Cliect()
 {
  //傳送代號為1982,且帶兩個參數為8與1的訊息到另一支程式
  SendMsgToServer(1982, 8, 1);    
 }

 //傳送訊息至Server端  
 public void SendMsgToServer(int msgCode, int wp, int lp)
 {
  //先取得另一支程式的視窗Handler,
  //這裡使用視窗標題名稱 "Form1" 來尋找
  int windowHandler = FindWindows(null, @"Form1");
  if (windowHandler > 0) 
  {
   //傳送訊息     
   int hr = SendMessage(windowHandler, msgCode, wp, lp);
  }
 }
}

Server端程式 (主要為覆寫 DefWndProc 事件處理函式)

publc class Server
{
 protected override void DefWndProc(ref Message m)
 {
  if (m.Msg == 1982)
  {
   MessageBox.Show(string.Format( "My birthday is {0}-{1}-{2}", m.Msg, m.WParam, m.LParam));
  }
  else
   base.DefWndProc(ref m);
 }
}

PS1. 如果電腦中同時有數個相同標題名稱的視窗,只有最上層的視窗收的到訊號,也就是說FindWindows( )只會回傳最上層視窗的Handler。

PS2.無法發送訊號時,請檢查msgCode是否太小。

2008年9月22日 星期一

Serialize(序列化) 與 Deserialize(還原序列化)

程式是在記憶體中執行的,一旦結束程式資料也就消失了
有時候我們希望將某個物件的內容(資料)保存起來
所以必須將資料寫進檔案中,要使用的時候再重新讀進來
至於寫入的格式該怎麼訂,讀出的時候該怎麼分析這就依照個人喜好了
有時候這些步驟是很麻煩的

現在有一個叫 IFormatter 的東西可以簡單的完成這項任務
下面的例子僅將物件讀進資料流,再由資料流寫回物件

假設我們有一個自定類別,定義如下:
[Serializable]
public class MyObject
{
  public int age = 0;
  public string name = string.empty;
}
//這裡需注意的是,要使該類別的物件能被序列化,該類別必須加入[Serializable]屬性

using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;

public class Main
{
 public Main()
 {
 
 //處理序列化的物件
 
 IFormatter formatter = new BinaryFormatter();

 
 //要被序列化的物件
 
 MyObject obj = new MyObject();

 
 MemoryStream ms = new MemoryStream();
 
 //將物件序列化
  formatter .Serialize(ms, obj);

 
 //還原序列化資料
 
 ms.Position = 0;
 
 MyObject obj2 = (MyObject)formatter.Deserialize(ms);
 }
}

2008年9月5日 星期五

'CoInitializeEx' : undeclared identifier 錯誤

從MSDN中知道了要include objbase.h標頭檔

 #include <objbase.h>
 void main()
 {
  int hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
 }

奇怪怎麼發生錯誤? Google了一下原來在 ColnitializeEx在objbase.h中的定義如下:

 #if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
 WINOLEAPI  CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit);
 #endif // DCOM

這表示使用前必須先加入:#define   _WIN32_DCOM
重點是此行必須加在 #include <objbase.h> 之前,改成如下即可執行。

 #define   _WIN32_DCOM
 #include <objbase.h>
 void main()
 {
  int hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
 }


2008年9月4日 星期四

wchar_t 輸出中文


原本執行下列程式碼
wchar_t str[] = L"Hello";
wcout  << str << endl;
可順利輸出Hello

但是當字串改成中文後

wchar_t str[] = L"哈囉";
wcout  << str << endl;
卻沒有輸出任何字元

google 後的結果是因為輸出語系的關係

將程式碼更正後如下:

wchar_t str[] = L"哈囉";
wcout.imbue(locale("cht")); //更改輸出語系
wcout  << str << endl;
即可順利輸出 哈囉

IDL的型態 和C++、Visual Basic及JAVA 型態之間的轉換




IDL Type

C++

Visual Basic

Java

signed char

signed char


byte

unsigned char

unsigned char

Byte


wchar_t

wchar_t

Integer

char

signed short

short

Integer

short

unsigned short

unsigned short



signed int

int

Long

int

unsigned int

unsigned int



signed hyper

__int64


long

float

float

Single

float

double

double

Double

double

BSTR

BSTR

String

java.lang.String

boolean

bool

Boolean

boolean

VARIANT

VARIANT

Variant

com.ms.com.Variant

DATE

DATE

Date

double

CY

CY

Currency

long

SAFEARRAY

SAFEARRAY

[] (a standard Visual Basic array)

com.ms.com.SafeArray

IUnknown*

IUnknown*

IUnknown

com.ms.com.IUnknown

IDispatch*

IDispatch*

Object

java.lang.Objec

2008年9月3日 星期三

位址空間

在程式中出現的指標 ( ex. char *p),指向的並不是實體記憶體中的位址,而是應用程式載入記憶體時CPU指定給程式的邏輯位址。因為如果CPU指定的是實體位址的話,那麼當程式在記憶體中SWAP時就需要不停的修改程式。因此,一個指標指向的邏輯位址,對於另一個應用程式來說沒有任何意義,在應用程式之間傳遞資料時,應該直接傳遞資料,而不是傳遞指標

建立一個COM物件時,需要2個ID

1. 類別ID ( CLSID ):用來表示COM元件 ( DDL 或 EXE 檔案 ) 的ID

2. 介面ID ( IID ):用來表示要建立的物件的類別ID