Delphi check if Tabsheet has finished loading data before making a clipboard picture

530 views Asked by At

I am working in Delphi XE3. I have made a loop that goes through a Pagecontrol with 6 tabsheets, that has frames with a lot of edit boxes which load mdb data.

When looping through the pages I make a "screen cut" image of the active tab and place it on an image in fastreport.

Everything works great but when testing on some slower computers it makes all the frames but the data has not been loaded. How do I check that all data is loaded in frame edit components that is placed on the tab before going to next page?

The code looks like this:

  begin
   Screen.Cursor := crHourGlass;
    p := PageControlKalkyl.ActivePageIndex; // Get page index

  for i := 0 to 7 do begin
   MyPage := frxReport1.FindObject('Page' + IntToStr(i)) as TfrxPage;
   MyPage.Visible := True;
  end;

  try
   for i := 0 to PageControlKalkyl.PageCount - 1 do
   If PageControlKalkyl.Pages[i].TabVisible then
   Begin
   PageControlKalkyl.ActivePageIndex := i;
    PageControlKalkyl.ActivePage.Repaint;
    Bilder := 'Pic' + IntToStr(i);


    if FLaddardata = False then //Check if page changed   
    Try
      Bitmap := TBitmap.Create;
      Assert(HandleAllocated);
      DC := GetWindowDC(Handle);
      Win32Check(DC <> 0);
      Bitmap.SetSize(Width, Height);
      Win32Check(BitBlt(Bitmap.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SRCCOPY));

      //Load data in to Images in Fastreport 
      if PageControlKalkyl.ActivePageIndex > 0  then
      Begin
      Ver:= 'Version NR: ' + Trim(DataModuleTrakop.ADOTableKALKYL.FieldByName('VERSION').AsString);                      
       Raid:= 'Kalkyl ID: ' +   Trim(DataModuleTrakop.ADOTableKALKYL.FieldByName('DENH').AsString);
       RepImage := frxReport1.FindObject('Pic'+IntTostr(i)) as TfrxPictureView;
       RepImage.Picture.Assign(Bitmap);
       Rappid := frxReport1.FindObject('Rapdata' + IntToStr(i)) as TfrxMemoView;
       Rappid.Font.Style:= [fsBold];
       Rappid.Text := Ver +'  '+Raid;
     end;
    Finally
      ReleaseDC(Handle, DC);
      Bitmap.Free;
    End;
  end
  else
  begin
    MyPage := frxReport1.FindObject('Page' + IntToStr(i)) as TfrxPage;
    MyPage.Visible := False;
  end;


if Fskaparapport = True then
begin
  Fskaparapport := False;
  frxReport1.PrepareReport;
  if FEpost = False then
    frxReport1.ShowPreparedReport;
  Screen.Cursor := crDefault;
end;
PageControlKalkyl.ActivePageIndex := p;

 except
  on E: Exception do
  ShowMessage(E.Message);
 end;

 end;
1

There are 1 answers

0
Disillusioned On BEST ANSWER

Since you're using TADOTable, I suspect your table is configured to operate asynchronously.

This can be done via property ExecuteOptions: TExecuteOptions;

Of course, if you set ExecuteOptions := [];, your data should load synchronously, but with the unpleasant side-effect of blocking your UI.

The 'friendlier' option would be to hook the OnFetchComplete event which is decalred as follows: procedure (DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus) of object;

The exact specifics requires more information on what exactly you're trying to achieve. You could:

  • Call your report method directly from the OnFetchComplete handler.
  • Use your handler to enable a menu option / button / action that is disabled while the data is loading.
  • Use a synchronisation object (such as TSimpleEvent) and signal the event inside the OnFetchComplete handler. Then other code can simply call the WaitFor method blocking code until the event has been signalled.