アプリが COMCTL32.dll から TListBox::OnDrawItem へのアクセス違反を生成する原因を絞り込みました。TListBox.Style は lbOwnerDrawFixed です。
アプリは C++ Builder XE4 で構築され、Win7-64 および Win8-64 で実行されます。私はWin7でそれを実現できますが、IDE内からのみ、散発的にしか実現できません。Win7 のリリース ビルドではエラーは発生しませんが、Win8 では毎回発生します。
これは、フォームが最初に作成されたときにのみ発生します。フォームには、次/前のレコードに移動するためのボタンが含まれています。これは、コントロールを設定するすべてのコードを呼び出しますが、これらの呼び出しに問題はありません。フォーム構築後の初回のみ。
フォーム コンストラクターは、TTimer を 100 ミリ秒一時停止するように設定します。TTimer::OnTimer は、データをコントロールにロードする関数を呼び出します。TListBox が読み込まれた後、OnDrawItem イベントが呼び出されます。
TListBox.Style を lbStandard に設定し、カスタム OnDrawItem を削除しても問題ありません。
OnDrawItem ハンドラーのサンプルを次に示します。
void __fastcall TFieldForm::EditsListDrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
TListBox* t_box = (TListBox*)Control;
TCanvas* t_canvas = t_box->Canvas;
int t_offset = 2; // default text offset width
t_canvas->Brush->Color = (State.Contains(odSelected) ?
clHighlight : Panel->Color);
t_canvas->Font->Color = (State.Contains(odSelected) ?
clHighlightText : clWindowText);
t_canvas->Font->Style = TFontStyles();
t_box->ItemHeight = t_canvas->TextHeight(FieldNameLabel->Caption);
t_canvas->FillRect(Rect); // clear the rectangle
t_canvas->TextOut(Rect.Left + t_offset, Rect.Top,
t_box->Items->Strings[Index]);
}
TListBox.Canvas が NULL でないことを確認するためにテストしましたが、違いはありませんでした。どうやらそれは常にNULLではありません。
ここから先に進む方法がわかりません。提案を歓迎します。
ありがとう、キャスリーン