Link to home
Start Free TrialLog in
Avatar of kpaschalis
kpaschalis

asked on

Please answer immediately

Guys I have this project in my university and I am totally stack: The program loads the (rectangular) grid of characters to be searched from a text file and places one character per cell within a string grid.  There is no requirement for the search area to be square (the number of columns may differ from the number of rows) but each row must contain the same number of characters (columns).  The actual number of columns is set by the first line of the file; if a line with a different number of columns is subsequently encountered as the file is loaded, an error message is displayed and the string grid is cleared.  As the file is loaded, each character is converted to its lower-case equivalent.
· User entry of the search string is via an edit box; searching is initiated either by pressing the return key within this edit box or by clicking the 'Search' button.  Prior to searching, the search string is converted to lower-case.
· The location of the search string within the grid is indicated by:
changing it to upper-case;
highlighting;
positioning.
· If the search string is not found within the grid, an appropriate error message is displayed.
· The search string within the edit box is selected after each search, enabling the user to make rapid entries with the minimum of keystrokes.
Avatar of AndersWP
AndersWP

kpaschalis, what is your question? What part of your program is giving you trouble? Please be more specific.

AndersWP
Avatar of kpaschalis

ASKER

I think it is better for me to type what I have done so far:

type
  TfrmMain = class(TForm)
    SDIAppMenu: TMainMenu;
    FileMenu: TMenuItem;
    OpenItem: TMenuItem;
    ExitItem: TMenuItem;
    N1: TMenuItem;
    OpenDialog: TOpenDialog;
    Help1: TMenuItem;
    About1: TMenuItem;
    SpeedPanel: TPanel;
    OpenBtn: TSpeedButton;
    ExitBtn: TSpeedButton;
    StatusBar: TStatusBar;
    pnlBackground: TPanel;
    pnlDisplay: TPanel;
    sgrDisplay: TStringGrid;
    pnlControls: TPanel;
    lblSearchString: TLabel;
    edtSearchString: TEdit;
    btnSearch: TButton;
    procedure ShowHint(Sender: TObject);
    procedure ExitItemClick(Sender: TObject);
    procedure OpenItemClick(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure edtSearchStringKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnSearchClick(Sender: TObject);
  private
  public
end;

var
  frmMain: TfrmMain;

implementation

uses SGLoader, SysUtils, About;

{$R *.DFM}

function Maximum(X,Y: Integer): Integer;
begin
  if X > Y then
    Result := X
  else
    Result := Y
end;

procedure TfrmMain.ShowHint(Sender: TObject);
begin
  StatusBar.SimpleText := Application.Hint;
end;

procedure TfrmMain.ExitItemClick(Sender: TObject);
begin
  Close;
end;

procedure TfrmMain.OpenItemClick(Sender: TObject);
begin
  if OpenDialog.Execute then
    if StringGridLoaded(OpenDialog.FileName,sgrDisplay) then begin
      edtSearchString.MaxLength :=
        Maximum(sgrDisplay.ColCount,sgrDisplay.RowCount);
      edtSearchString.Enabled := True
    end
end;

procedure TfrmMain.About1Click(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Application.OnHint := ShowHint;
end;

procedure TfrmMain.edtSearchStringKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
  CR = 13;
begin
  if Key = CR then
    btnSearch.Click
end;

procedure TfrmMain.btnSearchClick(Sender: TObject);
var
  Index : Integer;
  Line: String;
begin
  Line := '';
  for Index := 0 to SgrDisplay.Colcount-1 do
    Line := Line + sgrDisplay.Cells[Index,0]
  end;
  if pos(edtSearchString.Text,Line) > 0 then
  sgrDisplay.Cell[
end;

end.

What this programm is about is that it finds a word in the grid and it highlights it. What should happen is to find the word by making a row into string and using pos to make it look for a sub-string. What happens next?
It is still not clear to me what your question is. If you want the participants in Experts Exchange to actually write your program for you, I think you are expecting a bit much.

In the absence of specific questions I can give you a couple of hints:

Using a StringGrid for your problem is not a very good idea. As you have discovered, it is a bit cumbersome to find the text you are looking for by piecing together characters for the grid cells. In stead you might want to try a read-only multiline edit control. If you select a monospaced font (such as FixedSys), you will get proper alignment of your character rectangle. In an edit control you have your text stored as a string which makes searching easier (you can use the Pos function directly), and it supports text highlighting via the SelStart and SelLength properties.

I hope this will help you.
Thank you for answering. I am sorry if I was misunderstood. You see I only want some advise and I am not very experienced in Delphi and I need help. I am afraid that I can't understand what you are saying and I would like you to answer once again if you could.
OK, I will try to be a bit more specific. I can see that I even misled you a bit: The control that would be relevant for you is the TMemo rather than TEdit (which does not support multiple lines after all).

Now, to solve your problem using a TMemo, you do the following:

1. Select a Memo component from the Standard palette sheet and place it on you form.
2. Set the ReadOnly property of the Memo control to True if you do not want the user to change the text.
3. The memo control has a Lines property which holds the actual text. To load you text into the memo control, you do a Memo.Lines.Add(<YourText>) for each line of text.
4. To seach through the text you use the Pos function on each line like you already did. You will have to think about what to do if there are multiple occurrences of the search text in your text rectangle. Also, how about a search hit that spans more than one line of text?
5. To highlight a search hit, set the StartSel property of the memo control to the starting position of the search hit, and set the SelLength property to the length of the search text. Remember that the Pos function will give you the position within the search string you have provided. If this is not the first line of text in the memo control, you will have to add the length of the preceeding text lines to get the correct value for StartSel.

I hope this will help you,

AndersWP


Thanks. This really helped but I still have some difficulties. l'd like to know how do I make a file that has text on it to load through the memo component? What I mean is that I have the text inside a plain doc file and I want to load it. In the programme that I was writting above there is an OpenFile dialog box. I would like to know if there is a way I can still use this OpenFile dialog box to load the file and then pass it to the Memo. Would you also know how can I make it seach diagonal, from left to right, from bottom to top etc? I hope I wasn't tiring and I would like to thank you once again for your invaluable help.
Loading the text from a file is not difficult. The Lines property of a Memo component has a LoadFromFile method, so you just write

Memo.Lines.LoadFromFile(<Your file name>).

Note that this loads *all* the text from the file into the memo component. If your text file has a first line with a number describing the width of the text, this number will appear as the first line of text in your memo. If this is the case, you can delete it with Lines.Delete(0).

Searching in other directions than left-to-right is relatively straight forward. You just have to do it manually rather than using the Pos function. If you need to search in all 8 directions, I suggest you do something like the following:

1. Search through your text and look for the first character in your search string. If you find it, the position of the character (LineNo, index in line) becomes your base position. If not, you are done, and there is no match.
2. To search upwards, look in position (LineNo-1,index) for the second character in your search string. If there is a match, continue with the third and so on until you have found all characters in the search string. If one of the matches fail, you have not search hit from this base position. You can generalize this for the other search directions.

Now, if you have to highlight the search results for other than horizontal searches, you are in trouble, as the Memo component can only highlight a simple sequence of characters. Then I guess you will have to go back to something like your Stringgrid and do a customdraw of each cell to indicate whether the character in the cell is highlighted.

Good luck,

AndersWP

You have been very helphfull, but I am afraid I have one more question to ask. In case I wish to do that with the StringGrid using the pos function how can I make it highlight the word I am looking for and make it change to upper-case. Thanks
You can not easily use the Pos function for searching in non-trivial directions. To do so would require build strings to search by walking through your stringgrid in the requiered direction. There are some unpleasent special cases for this, particularly when searching in a diagonal direction. So I would suggest that you search as described in my previous comment.

To highlight a number of cells in a stringgrid you will have to draw the cell background yourself. To do this, you select your stringgrid component and click on the Events tab in the object browser window. The event you want to customize is OnDrawCell. By double-clicking this, you get a procedure in you form unit somewhat like this:

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
   If Cell_is_Highlighted Then
   With StringGrid1.Canvas Do
   Begin
     Brush.Color:=clAqua;
     FillRect(Rect);
   End;
end;

I have filled out the procedure with some skeleton code. The procedure will be called for each cell in the stringgrid. You will need to determine for each cell if it should be highlighted. If so, you draw the cell background as I have indicated in the code snippet. I have set the highlighted background code to clAqua, which is a light blue. You can select a different color, but remember that the text is shown in black (unless you change its color, but the color applies to the entire grid), which means that you do not want a background color that is too dart.

I hope this helps.

Regards,
AndersWP

Unfortunately I asked my tutor about the TMemo method and he told me that it won't be accepted. I have to work on the first way. Before asking please let me know if it is ok with you! I don't want to be a lot of trouble.
Thanks,
Kostas
I have no problem with whatever method you choose, that is entirely up to you.

Regards,
AndersWP
ASKER CERTIFIED SOLUTION
Avatar of AndersWP
AndersWP

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial