My program is in a post release state so please bear with me.
Scenario
My program is based on multiple layouts for different pages of different function for an office data management system (vehicle maintenance oriented). A major category of those functions is obviously data entry. I have used different styles to suite different audiences.
Getting to the point, one of the interfaces has excel styled grids and 3 buttons for Print/Save/Reset functions. I use FastReports for the form prints.
I am developing a custom class for the grid columns to make them accommodate a predefined list of controls instead of their cells on the fly but for now i just made the required controls children of the cells in code.
The page has 3 sections (layouts);
The top one is a kind of a purpose (Add/Modify/Add Partial) selector specific to all pages and may not be visible where not required.
The Middle one is a control for receiving receipt nos of the forms to be modified, their information embedded in others etc. Its mostly on every page but not all.
The Last one has the page's content which is the grid and the 3 buttons as mentioned earlier.
Code
This is a snippet of code for displaying one of the problematic pages. It is executed when all data processing has been done with and the server OKs the transition.
Legend
AState : State Machine State Variable; Signifies the current state of the page displayed.
AMode : State Machine State Enumerator; Signifies the mode of the application as a whole, e.g. Booking (Data entry) etc. I have skipped the code involving this as it gets skipped during the transition of AState for this problem to occur.
fMode : Same as above but its the main field of the form for the purpose.
UI_CA_Controls1 : The layout which contains the booking mode's purpose selector (Combo List Box).
EV_Mode : A variable for convenience; It stores the Item Index of the purpose selector.
UI_CA_Grid : The Layout contained in UI_CA_Content and itself contains UI_CA_FieldGrid (TGrid).
fEditColumn : The second column of the grid having TEdits.
fGridDataset : The grid associated 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;
The Problem
The problem is that whenever the receipt section is displayed the content section doesn't get displayed on the spot. The behavior is such that when i hover the mouse where those children controls and the 3 buttons should be they get displayed but the grid gets displayed when I click on it only.
The problem has arose by itself with no change in UI code which has baffled me for 3 days now. I have only made optimizations to protocol and data handling on the network side (Separate Data Module).
Sequence
The user wants to modify already booked vehicle's data.
The user enters the booking receipt no. ( AState = 0, AMode = UIM_Booking )
The client query's the server and the server replies with the complete dataset if exists.
The client takes the data and copies it in the strings of the Grid associated TStringlist and the children fields.
The client doesn't display the grid with the data and the 3 buttons. ( AState = 1, AMode = UIM_Booking )
What have I tried till now
Used BeginUpdate/EndUpdate which made it worse with alignment artifacts.
Used SetFocus on the grid and the buttons which resulted in random display of some of them and sometimes complete display but not every time.
Used Application.ProcessMessages with no change rather the UI thread sometimes just got stuck in it never to return. Used it in a separate thread, calling it every second with no change.
Used a separate thread for the method with even more issues.
Back tracked and restored old working code with no change (made me really angry).
Update 1: I have tried to make the grid invisible and then visible at the end of the code. Now some cells of the grid get shown randomly.
Workaround 1
- The grid and buttons can be shown when the SetFocus method is called for each of them.
- The order of the calls is erratic for the buttons. Like I had to call reset first and then print and save's SetFocus method otherwise only one of them got displayed.
- There is a split second realignment glitch which shows the controls resizing but i think that's ignorable.
Workaround 2
- Do queued repainting rather than immediate. It doesn't have any caveats but the catch is after all that there is a delay in between every repaint. Link: https://stackoverflow.com/a/8424750/1388291
So if you people have any suggestions, I'll be really grateful.