使用C++Builder访问TIWDBGrid列时触发“参数越界”错误的解决办法
问题描述
参考Delphi示例尝试用C++Builder访问TIWDBGrid的列时,触发「Argument out of range(参数越界)」错误,相关代码如下:
__fastcall TForm1::TForm1(TComponent* Owner) : TFrame(Owner) {// TRESTClient *REST1Client = new TRESTClient(this); TRESTRequest *REST1Request = new TRESTRequest(this); TRESTResponse *REST1Response = new TRESTResponse(this); TClientDataSet *ClientDataSet1 = new TClientDataSet(this); TRESTResponseDataSetAdapter *REST1ResponseDataSetAdapter = new TRESTResponseDataSetAdapter(this); TDataSource *DataSource1 = new TDataSource(this); DataSource1->DataSet = ClientDataSet1; IWDBGrid1->DataSource = DataSource1; ClientDataSet1->AfterOpen = &ClientDataSet1AfterOpen; REST1Client->BaseURL = "my.URL.php"; REST1Request->AddParameter("IdField", "IdValue"); REST1Request->Client = REST1Client; REST1Request->Response = REST1Response; REST1Response->ContentType = "application/json"; REST1ResponseDataSetAdapter->Dataset = ClientDataSet1; REST1ResponseDataSetAdapter->Response = REST1Response; REST1ResponseDataSetAdapter->Active = true; REST1Request->Execute(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ClientDataSet1AfterOpen(TDataSet *DataSet) {// static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Width = (IWDBGrid1->Width/20) * 02; // => Argument out of range static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[1])->Width = (IWDBGrid1->Width/20) * 02; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[2])->Width = (IWDBGrid1->Width/20) * 13; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[3])->Width = (IWDBGrid1->Width/20) * 03; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Title->Text = "AFirstTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[1])->Title->Text = "ASecondTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[2])->Title->Text = "AThirdTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[3])->Title->Text = "AFourthTitle"; } //--------------------------------------------------------------------------- void __fastcall TForm1::IWDBGrid1Render(TObject *Sender) {// // static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Width = (IWDBGrid1->Width/20) * 02; // => Argument out of range } //--------------------------------------------------------------------------- void __fastcall TForm1::IWFrameRegionRender(TObject *Sender) {// // static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Width = (IWDBGrid1->Width/20) * 02; // => Argument out of range } //---------------------------------------------------------------------------
解决方案
错误核心原因是TIWDBGrid的Columns集合在DataSet打开后并未自动创建对应列,直接通过索引访问会触发越界。以下是几种可行解决方式:
方法一:手动创建列并绑定字段
在DataSet打开前,手动为IWDBGrid创建对应数量的列,并绑定到ClientDataSet的字段:
__fastcall TForm1::TForm1(TComponent* Owner) : TFrame(Owner) { // ... 保留原有初始化代码 ... // 提前创建4列(根据实际返回字段数量调整) for (int i = 0; i < 4; i++) { TIWDBGridColumn* Col = new TIWDBGridColumn(IWDBGrid1); // 绑定到ClientDataSet对应字段 Col->FieldName = ClientDataSet1->Fields->Fields[i]->FieldName; IWDBGrid1->Columns->Add(Col); } ClientDataSet1->AfterOpen = &ClientDataSet1AfterOpen; // ... 保留后续REST请求代码 ... }
方法二:开启自动创建列属性
检查TIWDBGrid的AutoCreateColumns属性,默认可能为false,可在设计时或代码中开启:
IWDBGrid1->AutoCreateColumns = true;
开启后,DataSet打开时IWDBGrid会自动根据字段生成对应列,此时访问Columns索引不会越界。
方法三:在Grid渲染事件中处理列属性
若上述方法不生效,可在IWDBGrid1Render事件中处理列属性,此时Grid已完成列创建:
void __fastcall TForm1::IWDBGrid1Render(TObject *Sender) { // 先判断列数量是否足够,避免越界 if (IWDBGrid1->Columns->Count >= 4) { static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Width = (IWDBGrid1->Width/20)*2; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[1])->Width = (IWDBGrid1->Width/20)*2; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[2])->Width = (IWDBGrid1->Width/20)*13; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[3])->Width = (IWDBGrid1->Width/20)*3; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[0])->Title->Text = "AFirstTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[1])->Title->Text = "ASecondTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[2])->Title->Text = "AThirdTitle"; static_cast<TIWDBGridColumn*>(IWDBGrid1->Columns->Items[3])->Title->Text = "AFourthTitle"; } }
额外注意事项
- 确认ClientDataSet实际返回字段数量,可在
ClientDataSet1AfterOpen中打印ClientDataSet1->FieldCount验证,避免字段数量不足导致越界。 - 避免在构造函数中直接访问Grid列,此时Grid可能未完成初始化,优先使用
AfterOpen或Render事件。
内容的提问来源于stack exchange,提问作者ibouka
相关产品推荐
相关产品推荐

