我的程序处于发布后状态,所以请多多包涵。
设想
我的程序基于办公数据管理系统(面向车辆维护)的不同功能的不同页面的多种布局。这些功能的一个主要类别显然是数据输入。我使用不同的风格来适应不同的受众。
言归正传,其中一个界面具有 excel 样式的网格和 3 个用于打印/保存/重置功能的按钮。我使用 FastReports 打印表单。
我正在为网格列开发一个自定义类,以使它们适应预定义的控件列表而不是动态的单元格,但现在我只是在代码中创建了所需的单元格子控件。
该页面有 3 个部分(布局);
- 顶部是一种特定于所有页面的目的(添加/修改/添加部分)选择器,在不需要的地方可能不可见。 
- 中间一个是一个控件,用于接收要修改的表单的收据编号,它们的信息嵌入到其他表单中等。它主要在每一页上,但不是全部。 
- 最后一个具有页面内容,即前面提到的网格和 3 个按钮。 
代码
这是用于显示其中一个有问题的页面的代码片段。它在所有数据处理完成并且服务器 OK 转换时执行。
传奇
- AState : 状态机状态变量;表示显示页面的当前状态。 
- AMode : 状态机状态枚举器;表示整个应用程序的模式,例如预订(数据输入)等。我跳过了涉及此的代码,因为它在 AState 转换期间被跳过以发生此问题。 
- fMode:与上面相同,但它是表单的主要字段。 
- UI_CA_Controls1:包含预订模式的目的选择器(组合列表框)的布局。 
- EV_Mode:为方便起见的变量;它存储目的选择器的项目索引。 
- UI_CA_Grid:包含在 UI_CA_Content 中的布局本身包含 UI_CA_FieldGrid (TGrid)。 
- fEditColumn:具有 TEdits 的网格的第二列。 
- fGridDataset:网格关联的 TStringList。 
//
procedure TUI.SetFormState ( AState : Byte; AMode : TMode = UIM_Unselected );
var
  EV_Mode, I : Byte;
begin
  
  // ---------------------------------------------------------------------------
  fFormState          := AState;
  // The children of the grid cells
  
  fCalEdit1.Parent    := nil; // Calender Edits
  fCalEdit2.Parent    := nil;
  fVehicleClass.Parent := nil; // Combo List Boxes
  fEmployee1.Parent   := nil;
  fEmployee2.Parent   := nil;
  fEmployee3.Parent   := nil;
  fEmployee4.Parent   := nil;
  // ---------------------------------------------------------------------------
  if AState = 0 then
  begin
  
    for I := 0 to 20 do
      DPCM.fGridDataset.Strings [I] := ''; // The Grid Associated TStringList
    UI_CA_ReceiptNo.ReadOnly  := False;
    UI_CA_ReceiptNo.Text      := '';
  end;
  // ---------------------------------------------------------------------------
  UI_CA_Content.BeginUpdate;
  case fMode of
    // Skipped unrelated modes
    UIM_Booking :
    begin
      UI_CA_Controls1.Visible := True;
      EV_Mode := UI_CA_EV_ModeSelect.ItemIndex;
      // -----------------------------------------------------------------------
      if fFormState = 0 then
      begin
        // Skipped handling of other EV_Mode values
        if EV_Mode < 7 then
        begin
          UI_CA_ReceiptControl.Visible  := True;
          UI_CA_Content.Visible         := False;
        end;
      end
      // -----------------------------------------------------------------------
      else if fFormState = 1 then // The problematic area
      begin
        if ( EV_Mode = 3 ) or ( EV_Mode = 4 ) then
        begin
          UI_CA_FieldGrid.RowCount := 6;
          UI_CA_Grid.Height        := 160;
          fCalEdit1.Parent        := fEditColumn.CellControlByRow ( 0 );
          fCalEdit1.Date          := Date;
          fCalEdit2.Parent        := nil;
          fVehicleClass.Parent    := fEditColumn.CellControlByRow ( 2 );
          fVehicleClass.ItemIndex := 0;
        end;
    
        UI_CA_Content.Visible := True;
      end;
    end;
    // -------------------------------------------------------------------------
  end;
  // ---------------------------------------------------------------------------
  // Workaround 1
  
  if UI_CA_Content.Visible then
  begin
    UI_CA_FieldGrid.UpdateColumns;
    UI_CA_Content.EndUpdate;
    UI_CA_FieldGrid.SetFocus;
    UI_CA_C2_Reset.SetFocus;
    UI_CA_C2_Print.SetFocus;
    UI_CA_C2_Save.SetFocus; 
    UI_CA_FieldGrid.SetFocus;
  end
  else UI_CA_Content.EndUpdate; 
end;
问题
问题是,无论何时显示收据部分,内容部分都不会在现场显示。行为是这样的,当我将鼠标悬停在应该显示这些子控件和 3 个按钮的位置时,当我单击它时才显示网格。
这个问题本身就出现了,UI 代码没有变化,这让我困惑了 3 天。我只对网络端的协议和数据处理(独立数据模块)进行了优化。
序列
- 用户想要修改已经预订的车辆数据。 
- 用户输入预订收据编号。(AState = 0,AMode = UIM_Booking) 
- 客户端查询的服务器和服务器回复完整的数据集(如果存在)。 
- 客户端获取数据并将其复制到 Grid 关联的 TStringlist 和子字段的字符串中。 
- 客户端不显示带有数据和 3 个按钮的网格。(AState = 1,AMode = UIM_Booking) 
到目前为止我尝试了什么
- 使用了 BeginUpdate/EndUpdate,这使得对齐工件变得更糟。 
- 在网格和按钮上使用 SetFocus 会导致其中一些随机显示,有时会完整显示,但并非每次都显示。 
- 使用 Application.ProcessMessages 没有任何变化,而不是 UI 线程有时只是卡在其中永远不会返回。在单独的线程中使用它,每秒调用一次,没有任何变化。 
- 为该方法使用了单独的线程,但问题更多。 
- 回溯和恢复旧的工作代码,没有任何变化(让我很生气)。 
- 更新 1:我试图使网格不可见,然后在代码末尾可见。现在网格的一些单元格随机显示。 
解决方法 1
- 当为它们中的每一个调用 SetFocus 方法时,可以显示网格和按钮。
- 按钮的调用顺序是不稳定的。就像我必须先调用重置然后打印并保存 SetFocus 方法,否则只有其中一个被显示。
- 有一个瞬间的重新对齐故障,显示控件正在调整大小,但我认为这是可以忽略的。
解决方法 2
- 进行排队重绘而不是立即重绘。它没有任何警告,但问题在于每次重绘之间都有延迟。链接:https ://stackoverflow.com/a/8424750/1388291
因此,如果你们有任何建议,我将不胜感激。