03 10月 2007

Skype API example in BCB

因為我未來的開發環境是在BCB上,因此在這邊寫了個簡單的BCB的小程式,可以與Skype連線,並送出最簡單的"PING" button。不過從最簡單的Win32 API轉至BCB時,遇到了不少難題,不過也一一克服了,在下面會詳細地說明。

在這邊的步驟可以對照Win32 API simple example這篇文章,流程是差不多的,只是實作的方法不一樣而已。

我的code在這邊…http://falldog7.googlepages.com/Skype_BCB.rar

首先遇到的問題就是...指定處理Message的Function,不能由BCB定義的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP來處理。因為BCB背後所處理的方式是#define ...,所以這些Message的Message ID必須是compile前就定義好的"常數"(Ex: WM_USR+n),而我們要處理的Skype Message是在程式開始執行後,透過RegisterWindowMessage()所獲得的動態Messag ID,所以當你用BEGIN_MESSAGE_MAP來定義處理uiGlobal_MsgID_SkypeControlAPIAttach,會出現這種錯誤:
E2313 Constant expression required
因此,要定義這種由RegisterWindowMessage()取得的MessageID的處理function,可以做WndProc()的Override(覆寫)
在class TForm1中定義:

virtual void __fastcall WndProc(TMessage&);


WndProc()的Defination...
//WndProc() Overloading
void __fastcall TForm1::WndProc(TMessage & msg){
TForm::WndProc(msg);//用基本的WndProc函数讓Windows其他程式去處理~
//....
}

不過這種作法要小心,因為你可能把其他的Message都給吃下來,記得要呼叫base WndProc()去處理其他的Message

第二個比較需要注意的問題就是當接收到WM_COPYDATA的時候,要return 1; 而WndProc()一定要定義成void,所以一開始讓我很困擾,讓我不知所措,想說把void改成UINT,結果連compile都不會過了... 後來才知道,原來void WndProc(TMessage & msg);其中的參數TMessage可以設定return的值。所以只要當我們接收到WM_COPYDATA時,將msg的return值設為1即可,這樣Skype就不會Disconnect了!

if(msg.Msg==WM_COPYDATA){
// ...
msg.Result = 1;
}

2 則留言:

匿名 提到...

這個範例改寫後,若使用中文會發生問題

例如 SET SMS 145 BODY 測試

Falldog 提到...

是的 沒錯
官網有提到Skype在傳輸訊息時,一定要用UTF-8的編碼(Overview of the Skype API)
而我這個範例檔並沒有去做Big5->UTF-8的處理

所以必須將訊息由Big-5轉碼為UTF-8後,再傳出去,才會得到正確的結果。
在Windows上,你可以參考一下WideCharToMultiByte這個Win32 API function。
:)