Recent

Author Topic: [SOLVED] How to refresh the screen while app is running?  (Read 3652 times)

dodgebros

  • Full Member
  • ***
  • Posts: 161
[SOLVED] How to refresh the screen while app is running?
« on: July 31, 2015, 09:18:41 pm »
For some background on my app see this thread
http://forum.lazarus.freepascal.org/index.php?topic=29214.msg184057#msg184057

Once you click the PROCESS button, which starts the process to scrape data from particular websites, if you click on another application you might have open on the same pc, then click back on the window where this app is running, the screen does not re-appear until the app finishes processing all of the websites.

I need a way to resolve this as I plan on adding a PAUSE button to the app but that's useless if the screen will not re-appear once you move off it.

Hope you guys have some simple way to address this problem.  BTW, the code for this app is below.
TD

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  StdCtrls, Grids, Buttons, fpspreadsheetgrid, fpspreadsheet, fpsallformats,
  fpspreadsheetctrls, fpstypes, StrUtils, httpsend;

type

  { TForm1 }

  TForm1 = class(TForm)
    btnLoadFile: TButton;
    btnProcessFile: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    OpenDialog1: TOpenDialog;
    PageControl1: TPageControl;
    ProgressBar1: TProgressBar;
    sWorkbookSource_Enco: TsWorkbookSource;
    sWorkbookTabControl_Enco: TsWorkbookTabControl;
    sWorksheetGrid_Enco: TsWorksheetGrid;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    procedure btnLoadFileClick(Sender: TObject);
    procedure btnProcessFileClick(Sender: TObject);
  private
    { private declarations }
    function fDownloadHTTP(URL: string; Response: TStringList): boolean;
    function fIsEncoFile(): boolean;
    function fGetText(strInput: string):string;
    function fGetTextBold(strInput: string):string;
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }


function TForm1.fDownloadHTTP(URL: string; Response: TStringList): boolean;
var
  HTTPGetResult: boolean;
  HTTPSender: THTTPSend;
begin
  Response.Clear;
  Result := False;
  HTTPSender := THTTPSend.Create;
  try
    HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
    if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode <= 299) then
    begin
      Response.LoadFromStream(HTTPSender.Document); // <-- this will write the result to your tstringlist
      Result := True;
    end;
  finally
    HTTPSender.Free;
  end;
end;

function TForm1.fIsEncoFile(): boolean;
var
  strContent: ansistring;
  strSearchFor: ansistring;
  cell: PCell;
begin
  Result:= false;
  strSearchFor:= 'Enco'; //need to add to xml setup file later
    sWorkbookTabControl_Enco.Workbook.GetFirstWorksheet;
    for cell in sWorksheetGrid_Enco.Worksheet.Cells do
      begin
        strContent:= sWorksheetGrid_Enco.Worksheet.ReadAsUTF8Text(cell);
          if AnsiContainsText(strContent,strSearchFor) then
            begin
              fIsEncoFile:= true;
            end;
     end;
end;

function TForm1.fGetText(strInput: string):string;
var
  intBegin: integer;
  intEnd: integer;
begin
     intBegin:= (AnsiPOS('>',strInput) + 1);
     intEnd:= AnsiPOS('</',strInput);
     fGetText:= AnsiMidStr(strInput,intBegin,(intEnd - intBegin));
end;

function TForm1.fGetTextBold(strInput: string):string;
var
  intBegin: integer;
  intEnd: integer;
begin
     intBegin:= (AnsiPOS('<b>',strInput) + 3);
     intEnd:= AnsiPOS('</b>',strInput);
     fGetTextBold:= AnsiMidStr(strInput,intBegin,(intEnd - intBegin));
end;

procedure TForm1.btnLoadFileClick(Sender: TObject);
  var
  strFile: string;
begin
  //locate excel file to process
  OpenDialog1.Execute;
  strFile:= OpenDialog1.FileName;

  //load file name into edit box
  Edit1.Text:= strFile;

  //load spreadsheet into grid
  sWorkbookSource_Enco.FileName:= strFile;
end;

procedure TForm1.btnProcessFileClick(Sender: TObject);
var
   baseSheet: TsWorksheet;
   strSpaces: string;
   strFile: string;
   strCell: string;
   strMsg: string;
   strTab: string;
   strURL: string;
   strText: ansistring;
   row, rowNum: Cardinal;
   cell: PCell;
   SL: TStringList;
   i, c, SLCount, numOfRows: Integer;

begin
  try
    //setup screen
    Screen.Cursor := crHourglass;

    //initialize stringlist
    SL := TStringList.Create;

    //check if Enco file, if not exit
    if Not fIsEncoFile() then
      begin
        strSpaces:= StringOfChar(AnsiChar(32),20);
        strMsg:= strSpaces + 'THIS IS NOT A Enco FILE' + strSpaces;
        showmessage(strMsg);
        Exit;
      end;

    //get number of rows in spreadsheet
    numOfRows:= sWorksheetGrid_Enco.Worksheet.GetLastRowIndex;

    //setup progress bar
    ProgressBar1.Min := 0;
    ProgressBar1.Max := numOfRows;
    ProgressBar1.Position := 0;
    ProgressBar1.Visible := true;

    //begin processing webpages
    baseSheet:= sWorkbookTabControl_Enco.Workbook.GetFirstWorksheet;

    for row:=1 to numOfRows do
      begin
        //get new tab name
        cell:= baseSheet.FindCell(row,2);
        strTab:= baseSheet.ReadAsUTF8Text(cell);

        //get webpage URL
        cell:= baseSheet.FindCell(row,3);
        strURL:= baseSheet.ReadAsUTF8Text(cell);

        //create new tab
        sWorkbookSource_Enco.Workbook.AddWorksheet(strTab);

        //retrieve webpage html
        if fDownloadHTTP(strURL,SL) then
          begin
            //begin adding webpage data to spreadsheet tab
            SLCount:=SL.Count;

            //webpage header
            strText:= '';
            rowNum:=0;
            i:=0;
            for i:=2 to 7 do
              begin
                strText:= strText + fGetText(SL[i]);
                if i in [3,5] then
                  begin
                    strText:= strText + StringOfChar(AnsiChar(32),5);
                  end;
              end;
              sWorksheetGrid_Enco.Worksheet.MergeCells(0,0,0,7);
              sWorksheetGrid_Enco.Worksheet.WriteHorAlignment(rowNum,0,haCenter);
              sWorksheetGrid_Enco.Worksheet.WriteVertAlignment(rowNum,0,vaCenter);
              sWorksheetGrid_Enco.Worksheet.WriteFontStyle(rowNum,0,[fssBold]);
              sWorksheetGrid_Enco.Worksheet.WriteRowHeight(rowNum,1.75);
              sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,0,strText);

            //webpage column names
            strText:= '';
            rowNum:=1;
            i:=0;
            for i:=12 to 19 do
              begin
                strText:= fGetText(SL[i]);
                c:=i-12;
                sWorksheetGrid_Enco.Worksheet.WriteHorAlignment(rowNum,c,haCenter);
                sWorksheetGrid_Enco.Worksheet.WriteVertAlignment(rowNum,c,vaCenter);
                sWorksheetGrid_Enco.Worksheet.WriteFontStyle(rowNum,c,[fssBold]);
                sWorksheetGrid_Enco.Worksheet.WriteRowHeight(rowNum,1.75);
                sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,c,strText);
              end;

            //webpage data
            strText:= '';
            rowNum:=2;
            SLCount:=(SLCount - 8);
            i:=0;
            c:=22;
            //write standard rows
            While c < SLCount do
              begin
                For i:=0 to 7 do
                  begin
                    strText:= fGetText(SL[c]);
                    sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,i,strText);
                    c:=c+1;
                  end;
              c:=c+2;
              rowNum:=rowNum+1;
              end;

            //manually expand worksheet to eliminate "ont of bounds" error
            sWorksheetGrid_Enco.RowCount := rowNum + 3;

            //write TOTALS row
            SLCount:=(SLCount + 5);
            //first cell
            sWorksheetGrid_Enco.Worksheet.MergeCells(rowNum,0,rowNum,4);
            sWorksheetGrid_Enco.Worksheet.WriteVertAlignment(rowNum,0,vaCenter);
            sWorksheetGrid_Enco.Worksheet.WriteFontStyle(rowNum,0,[fssBold]);
            strText:= fGetTextBold(SL[c]);
            sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,0,strText);
            //second cell
            sWorksheetGrid_Enco.Worksheet.WriteHorAlignment(rowNum,6,haCenter);
            sWorksheetGrid_Enco.Worksheet.WriteVertAlignment(rowNum,6,vaCenter);
            sWorksheetGrid_Enco.Worksheet.WriteFontStyle(rowNum,6,[fssBold]);
            strText:= fGetTextBold(SL[c+1]);
            sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,6,strText);
            //third cell
            sWorksheetGrid_Enco.Worksheet.WriteHorAlignment(rowNum,7,haCenter);
            sWorksheetGrid_Enco.Worksheet.WriteVertAlignment(rowNum,7,vaCenter);
            sWorksheetGrid_Enco.Worksheet.WriteFontStyle(rowNum,7,[fssBold]);
            strText:= fGetTextBold(SL[c+2]);
            sWorksheetGrid_Enco.Worksheet.WriteUTF8Text(rowNum,7,strText);

            SL.Clear;
            ProgressBar1.Position := row;
            Sleep(1000);   //needs to be stored in external xml file
          end
        else
          begin
            showmessage('UNABLE TO DOWNLOAD WEBPAGE');
          end;
        sWorkbookSource_Enco.SelectWorksheet(baseSheet);
     end;

    //remove Enco from apreadsheet
    //for cell in sWorksheetGrid_Enco.Worksheet.Cells do
    //  begin
    //    strText:= sWorksheetGrid_Enco.Worksheet.ReadAsUTF8Text(cell);
    //    strText:= UpperCase(strText);
    //    strText:= StringReplace(strText,'Enco','',[rfReplaceAll, rfIgnoreCase]);
    //    sWorksheetGrid_Enco.Worksheet.WriteCellValueAsString(cell,strText);
    //  end;

    //save changes to existing excel file
    SL.Free;
    strFile:= Edit1.Text;
    sWorkbookSource_Enco.SaveToSpreadsheetFile(strFile,true);

  finally
    Screen.Cursor := crDefault;
  end;
end;

end.

« Last Edit: August 01, 2015, 05:11:09 am by dodgebros »

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: How to interrupt app while it downloads webpage data?
« Reply #1 on: July 31, 2015, 09:30:29 pm »
Your title is somewhat poorly chosen.
"How to interrupt app while it downloads webpage data"

Once you click the PROCESS button, which starts the process to scrape data from particular websites, if you click on another application you might have open on the same pc, then click back on the window where this app is running, the screen does not re-appear until the app finishes processing all of the websites.

I need a way to resolve this as I plan on adding a PAUSE button to the app but that's useless if the screen will not re-appear once you move off it.
So your question is how you can redraw the screen when your application gains focus.

The problem is that your application is busy in your own procedure and does not have the opportunity to redraw itself.

You can easilly fix this by adding the line Application.ProcessMessages; in (a) strategic place(s). (So inside the loop)

The Processmessages gives your application the opportunity to handle some messages of which "redraw myself" is one.

dodgebros

  • Full Member
  • ***
  • Posts: 161
Re: How to interrupt app while it downloads webpage data?
« Reply #2 on: July 31, 2015, 09:57:23 pm »
Awesome, worked great!

Thanks,
TD

 

TinyPortal © 2005-2018