BCB 使用Thread 後產生的錯誤 Canvas does not allow drawing
下圖是我在BCB使用中Thread後,原本相安無事的程式碼,突然出現的例外錯誤"Canvas does not allow drawing"。求救估狗大神後,說是在子執行緒中使用ShowMessage方法,會讓部分底層元件出現問題。
解決的方法就是呼叫Win32API,或是進行同步化,下面簡略的介紹以Win32API作轉換。
其實在子執行緒中使用ShowMessage,也不見得會有Exception產生,有時可能沒事情(機率很小),有時可能只跳出一個放大的Dialog且沒有按鈕可以結束它。
解決方案-Win32API
本解決方案就是將你的視窗類別中多加一個ShowMessage方法。若你的主式窗名稱是TForm1,則將要加入的函式寫成下面這樣。
然後記得在主視窗類別的.h檔也要加入對應的宣告。
放在類別的private、protected或public區域都行,視你的應用而定。
解決的方法就是呼叫Win32API,或是進行同步化,下面簡略的介紹以Win32API作轉換。
其實在子執行緒中使用ShowMessage,也不見得會有Exception產生,有時可能沒事情(機率很小),有時可能只跳出一個放大的Dialog且沒有按鈕可以結束它。
解決方案-Win32API
這個解決方案只能使用於小型的程式,大型程式可能會顯得礙手礙腳。
若你在個人的程式庫,十分愛用ShowMessage作為對使用者顯示訊息的手段,建議現在就著手修改為其他方式(有學過Java的朋友,可以考慮改為丟出Exception),因為本方案並不能解決你的問題。
本解決方案就是將你的視窗類別中多加一個ShowMessage方法。若你的主式窗名稱是TForm1,則將要加入的函式寫成下面這樣。
void TForm1::ShowMessage(const AnsiString &str)
{
// 一定要有雙冒號(::)代表存取Scope最外面部的MessageBox函式
::MessageBox(NULL, str.c_str(), "Dialog Title", MB_OK);
}
Win32API的MessageBox參數簡易解說- NULL 是方便行事,其是也可以改成的你視窗的handle屬性。
- str.c_str() 是將因為MessageBox支援的型態不是AnsiString,而是char*。
- "Dialot Title" 是你可以改的顯示視窗標題(Title)。
- MB_OK 顯示的按鈕種類,請查閱BCB的Help取得更多的種類說明。
然後記得在主視窗類別的.h檔也要加入對應的宣告。
void ShowMessage(const AnsiString&);
放在類別的private、protected或public區域都行,視你的應用而定。
留言