Solved

Find and Replace in DHTMLEdit

Posted on 2004-04-14
17
516 Views
Last Modified: 2010-04-05
How can I find and select text in DHTMLEdit without showing the Find window, I tried OLECMDEXECOPT_DONTPROMPTUSER but it returns a "Catastrophic faliure". I want to find text without the dialog , then I know how to replace it.

Thanks in advance!
0
Comment
Question by:Bindza
  • 6
  • 4
  • 4
  • +1
17 Comments
 
LVL 2

Expert Comment

by:insomniac92
ID: 10829792
Hi, put a DHTMLEdit, a Button, and an Editbox on your form.
Add MSHTML_TLB to your uses clause.

Put this code on the button click event

procedure TForm1.Button1Click(Sender: TObject);
var
  FRange : IHTMLTxtRange;
  bFound:   boolean;
  iFlag, FiLen:    integer;
begin
 FRange := (DHTMLEdit1.DOM.Body as IHTMLBodyElement).CreateTextRange;
 FiLen := length(FRange.text);
 iFlag := 2; //find the whole word...
 FRange.collapse(True);
 bFound := FRange.findText(Edit1.Text, FiLen, iFlag);
 if (bFound) then //If we found it, select it and make sure it's visible
  begin
   FRange.select;
   FRange.scrollIntoView(True);
  end
 else
  begin
    MessageDlg('Search string ''' + Edit1.Text + ''' was not found', mtInformation, [mbOK], 0);
  end;
end;

Type some text into the DHTMLEdit and put a word to highligh in the Editbox. Hit the button and the code will  look for the word and highlight it. I have grabbed this code from a search and replace routine. This code will only find the first occurance.
Cheers
0
 
LVL 33

Expert Comment

by:Slick812
ID: 10829954
0
 

Author Comment

by:Bindza
ID: 10831839
Thanks for the code, but do you know how to find all occurences of the string. I need the code because I'm want to search and replace text, and for that I need to get all of the text.

PS: I see you know your way around DHTMLEdit and/or MSHTML, perhaps you can help me with another problem I've been having. It's on this site, it's about getting current line's paragraph code.
0
 
LVL 2

Expert Comment

by:insomniac92
ID: 10839032
I am at work at the moment but I have some code for a search and replace function at home. I'll have a look for it tonight. I am in Sydney Australia, so I'm not sure what time that'll be where you are (it's currently 1:30pm). I'll also have a look at your other question later.
Cheers
0
 
LVL 2

Expert Comment

by:insomniac92
ID: 10841430
Ok, here goes. I have a search and replace form that the user can enter text to find and text to replace. Here is the code for the replace All button. It's been a while but I think I've grabbed the bits you need.
I got parts of this code from a Yahoo group dedicated to DHTMLEdit and MSHtml. I suggest you look through the posts in this group. it is really helpful.
Ignore the "EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex]" this just gets me back to the actual DHTMLEdit window that needs the find/replace.
If you want I can send you the entire find/replace unit. Just post your email and I'll send it to you.
Break up your address   e.g.. me At this dot com. before posting it here.

You will need to declare some or all of the following:

  FRange:     IHTMLTxtRange;      //MSHTML HTML Text range interface
  FRangeToo:  IHTMLTxtRange;      //MSHTML HTML Text range interface
  FSelect:    IHTMLSelectionObject;
  FbHaveSelect : boolean;
  bFirst     : boolean;
  bWholeWord : boolean;       //Find whole word only
  bMatchCase : boolean;       //Case sensitive
  bForward   : boolean;       //Search from top to bottom
  FRangeSave : IHTMLTxtRange; //Save original range info
  FRangeTemp : IHTMLTxtRange; //Temporary range
  FiLen      : integer;       //Length to search or selection length


//Find and replace all... report finds
procedure TReplaceForm.cmdReplaceAllClick(Sender: TObject);
var
  bFound,
  bDone:    boolean;
  iFlag,
  iDid:     integer;
begin
  iFlag := 0;
  iDid  := 0;
  if bWholeWord then
    iFlag := iFlag + 2;
  if bMatchCase then
    iFlag := iFlag + 4;
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    bDone := False;
    FRange.Set_text(edtReplace.Text);
    inc(iDid);
    if bFirst then
      bFirst := False;
    while (not bDone) do
    begin
      //Make sure we stay in a selection (if we have one)
      FRange.collapse(bFirst);
      bFound := FRange.findText(edtFind.Text, FiLen, iFlag);
      FRangeTemp := Frange.Duplicate;
      if bFound then
        if (FRangeSave.inRange(FRangeTemp)) then
          bFound := True
        else
          bFound := False; //End of selection

      if (bFound) then //If we found it, select it and make sure it's visible
      begin
        FRange.select;
        FRange.scrollIntoView(True);
        FRange.Set_text(edtReplace.Text);
        inc(iDid);
      end
      else
      begin
        //Otherwise just dump out an error and bail out of the loop
        if iDid < 1 then
          MessageDlg('Search string ''' + edtFind.Text + ''' was not found', mtInformation, [mbOK], 0)
        else if idid = 1 then
           MessageDlg('''' + edtFind.Text + ''' was replaced with' + CRLF +
                      '''' + edtReplace.Text + '''.' + CRLF + CRLF +
                      'Replaced ' + IntToStr(iDid) + ' occurance.' , mtInformation, [mbOK], 0)
        else
           MessageDlg('''' + edtFind.Text + ''' was replaced with' + CRLF +
                      '''' + edtReplace.Text + '''.' + CRLF + CRLF +
                      'Replaced ' + IntToStr(iDid) + ' occurances.' , mtInformation, [mbOK], 0);
        bDone := True;
      end;
    end;
  end;
  cmdNext.Enabled       := False;
  cmdReplace.Enabled    := False;
  cmdReplaceAll.Enabled := False;
  edtFind.SetFocus;
end;

The yahoo group is called... delphi-dhtmledit.
Hope this helps.
Cheers.

0
 

Author Comment

by:Bindza
ID: 10842289
Thanks alot, I'll test this code right away. If it works - just tell me how and - I'll give you another 100 points, cause you've been of great help.

PS: Just so you know, I'm from Serbia, and the time difference is 5 hours. Anyway, Sydney is one of my two favourite cities, the other one is LA. Cheers (mate) :) !
0
 

Author Comment

by:Bindza
ID: 10842413
Hi,sorry if I'm being boring, but I can't make heads or tails with this code, I get an Access violation. Please send
me the whole form and I'll check it out. I'm a member of the Yahoo group you spoke about, but they have such a lousy
message search engine that I couldn't find anything asociated to find/replace.

My e-mail is "maxsoft at ptt dot yu" and "marko_binic at yahoo dot com".

Thanks!
0
 
LVL 2

Accepted Solution

by:
insomniac92 earned 350 total points
ID: 10851468
No problems.
Email on its way...
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:Bindza
ID: 10852718
Thanks alot Garry, you've been very helpful! You deserve to be called an expert!

Marko
0
 
LVL 30

Expert Comment

by:Wayne Barron
ID: 14668944
Hello insomniac92;

  I would be very interested in the Find/Replace sample that you have, if you would
Not mind sending it over to me?
Also I have a question that is in Dyring need of a solution, and I cannot seem
To get any information about it.

I am going to post a question about it now, and paste the link in here
That deals with the MSHTML issue, of the Generated HTML Code that it produces.

Here is the link, if you can assist me with it.
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21526399.html

Thanks
Carrzkiss
e-mail address to send code too, just let me know when it has been sent

dreaminkisscarr @ yahoo.com
0
 
LVL 2

Expert Comment

by:insomniac92
ID: 14713437
Email on its way...
Cheers
0
 
LVL 30

Expert Comment

by:Wayne Barron
ID: 14713660
Thank you, I have received the e-mail with attachment.
I will have a look at it later on when I have the time.

About the link that I have posted above.
I figured out a way to do it on my own, so I deleted out the question.

Take Care
0
 
LVL 33

Expert Comment

by:Slick812
ID: 14714366
here at EE you are NOT suppose to Email anything for the responce to a EE question
WHY?
because the others (like me) can NOT see the code and solution to problems. . .
It is in the User's agreement here at EE. . .
you should at least post the code that you used for the solution, so others can see what they might need to solve problems

If I did a seach for a soution an got this EE question, hoe could I use -

 No problems.
Email on its way...


which is your Accepted answer?
0
 
LVL 30

Expert Comment

by:Wayne Barron
ID: 14714434
Hey Slick,

Do not want anyone to get into any trouble for sending something to me
When I asked for them to do so.

I will post this, it will stay good until "Hopefully" forever.

http://www.carrz-fox-fire.com/1/Find-Replace.zip

I hope that this will make things better, And do not be
Mad at [insomniac92];
Most of the people do not have access to a download server.
So they e-mail the information out.

Take Care
Carrzkiss
0
 
LVL 2

Expert Comment

by:insomniac92
ID: 14714442
No problems... I didn't want to post a whole lot of code here.. but here goes.

this procedure sits on the form with the DHTML Edit control and is called from a menu otem - Edit - Replace.

procedure TEditorForm.eReplace;
Var
  FRange:     IHTMLTxtRange
  FSelect:    IHTMLSelectionObject;
begin
  FSelect :=  DHTMLEdit1.DOM.selection;
  if SameText(FSelect.type_, 'Text') then
   begin
    FRange := FSelect.createRange as IHTMLTxtRange;
    FbHaveSelect := True;
   end
  else
   begin
    FRange := (DHTMLEdit1.DOM.Body as IHTMLBodyElement).CreateTextRange;
    FbHaveSelect := False;
   end;
  ReplaceForm.ShowModal;
  FSelect := nil;
end;

Here is the code for the ReplaceForm.....(dfm)

object ReplaceForm: TReplaceForm
  Left = 527
  Top = 405
  BorderStyle = bsDialog
  Caption = 'Replace text'
  ClientHeight = 136
  ClientWidth = 346
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  KeyPreview = True
  OldCreateOrder = False
  Position = poMainFormCenter
  OnClose = FormClose
  OnKeyDown = FormKeyDown
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object labFind: TLabel
    Left = 4
    Top = 11
    Width = 49
    Height = 13
    Caption = 'Find what:'
  end
  object labReplace: TLabel
    Left = 4
    Top = 43
    Width = 65
    Height = 13
    Caption = 'Replace with:'
  end
  object edtFind: TEdit
    Left = 73
    Top = 8
    Width = 182
    Height = 21
    TabOrder = 0
    OnKeyPress = edtFindKeyPress
  end
  object grpOption: TGroupBox
    Left = 8
    Top = 63
    Width = 247
    Height = 39
    Caption = 'Options'
    TabOrder = 2
    object chkWholeWord: TCheckBox
      Left = 8
      Top = 17
      Width = 81
      Height = 17
      Caption = '&Whole word'
      TabOrder = 0
      OnClick = chkWholeWordClick
    end
    object chkMatchCase: TCheckBox
      Left = 116
      Top = 17
      Width = 81
      Height = 17
      Caption = '&Match case'
      TabOrder = 1
      OnClick = chkMatchCaseClick
    end
  end
  object cmdNext: TButton
    Left = 261
    Top = 8
    Width = 79
    Height = 25
    Caption = '&Find next'
    Enabled = False
    TabOrder = 3
    OnClick = cmdNextClick
  end
  object cmdCancel: TButton
    Left = 261
    Top = 104
    Width = 79
    Height = 25
    Caption = '&Done'
    TabOrder = 6
    OnClick = cmdCancelClick
  end
  object cmdReplace: TButton
    Left = 261
    Top = 40
    Width = 79
    Height = 25
    Caption = '&Replace'
    Enabled = False
    TabOrder = 4
    OnClick = cmdReplaceClick
  end
  object cmdReplaceAll: TButton
    Left = 261
    Top = 72
    Width = 79
    Height = 25
    Caption = 'Replace &all'
    Enabled = False
    TabOrder = 5
    OnClick = cmdReplaceAllClick
  end
  object edtReplace: TEdit
    Left = 73
    Top = 39
    Width = 182
    Height = 21
    TabOrder = 1
    OnKeyPress = edtReplaceKeyPress
  end
end

Here is the code for the replace unit.. (PAS file)....

unit ReplaceUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, MSHTML_TLB;

type
  TReplaceForm = class(TForm)
    labFind: TLabel;
    edtFind: TEdit;
    grpOption: TGroupBox;
    chkWholeWord: TCheckBox;
    chkMatchCase: TCheckBox;
    cmdNext: TButton;
    cmdCancel: TButton;
    cmdReplace: TButton;
    cmdReplaceAll: TButton;
    edtReplace: TEdit;
    labReplace: TLabel;
    procedure FormShow(Sender: TObject);
    procedure edtFindKeyPress(Sender: TObject; var Key: Char);
    procedure edtReplaceKeyPress(Sender: TObject; var Key: Char);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure cmdNextClick(Sender: TObject);
    procedure chkWholeWordClick(Sender: TObject);
    procedure chkMatchCaseClick(Sender: TObject);
    procedure cmdCancelClick(Sender: TObject);
    procedure cmdReplaceClick(Sender: TObject);
    procedure cmdReplaceAllClick(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  CRLF = #13 + #10;

var
  ReplaceForm: TReplaceForm;
  bFirst     : boolean;
  bWholeWord : boolean;       //Find whole word only
  bMatchCase : boolean;       //Case sensitive
  bForward   : boolean;       //Search from top to bottom
  FRangeSave : IHTMLTxtRange; //Save original range info
  FRangeTemp : IHTMLTxtRange; //Temporary range
  FiLen      : integer;       //Length to search or selection length


implementation

uses EditorUnit, MainProcUnit, MainUnit;

{$R *.DFM}

procedure TReplaceForm.FormShow(Sender: TObject);
begin
  edtFind.Text            := '';
  cmdNext.Enabled         := False;
  cmdReplace.Enabled      := False;
  cmdReplaceAll.Enabled   := False;
  chkWholeWord.Checked    := False;
  chkMatchCase.Checked    := False;
  bWholeWord := chkWholeWord.Checked;
  bMatchCase := chkMatchCase.Checked;
  bFirst := True;
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    FRangeSave := FRange.duplicate;
    FRangeTemp := Frange.duplicate;
    if FbHaveSelect then
      FiLen := length(FRangeSave.text)
    else
      FiLen := length(FsHTMLImage);
  end;
  edtFind.SetFocus;
end;

procedure TReplaceForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  edtFind.Text            := '';
  edtReplace.Text         := '';
  cmdNext.Enabled         := False;
  cmdReplace.Enabled      := False;
  cmdReplaceAll.Enabled   := False;
  chkWholeWord.Checked    := True;
  chkMatchCase.Checked    := False;
  bWholeWord := chkWholeWord.Checked;
  bMatchCase := chkMatchCase.Checked;
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    FRange := FRangeSave.duplicate; //Restore the original range
    FRangeSave := nil;
    FRangeTemp := nil;
    if FbHaveSelect then //Restore the selection if needed
     begin
      FRange.select;
      FRange.scrollIntoView(True);
      FbHaveSelect := False;
     end;
  end;
end;


//Turn on the find button once we have something to look for and replace with
procedure TReplaceForm.edtFindKeyPress(Sender: TObject; var Key: Char);
begin
  if ((length(edtFind.Text) > 0) and
      (length(edtReplace.Text) >0)) then
  begin
    cmdNext.Enabled := True;
    with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
    begin
      if not FbHaveSelect then
        FRange.moveStart('textedit', -1);
      FRange.collapse(True);
    end;
  end
  else
    cmdNext.Enabled := False;
  if Key = #13 then
  begin
    Key := #0;
    if (cmdNext.Enabled) then
    begin
      with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
      begin
        FRangeSave := FRange.duplicate;
        FRangeTemp := Frange.duplicate;
        if FbHaveSelect then
          FiLen := length(FRangeSave.text)
        else
          FiLen := length(FsHTMLImage);
      end;
      cmdNextClick(self);
    end;
  end;
end;


//Turn on the find button once we have something to look for and replace with
procedure TReplaceForm.edtReplaceKeyPress(Sender: TObject; var Key: Char);
begin
  if ((length(edtFind.Text) > 0) and
      (length(edtReplace.Text) >0)) then
  begin
    cmdNext.Enabled := True;
    with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
    begin
      if not FbHaveSelect then
        FRange.moveStart('textedit', -1);
      FRange.collapse(True);
    end;
  end
  else
    cmdNext.Enabled := False;
  if Key = #13 then
  begin
    Key := #0;
    if (cmdNext.Enabled) then
    begin
      with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
      begin
        FRangeSave := FRange.duplicate;
        FRangeTemp := Frange.duplicate;
        if FbHaveSelect then
          FiLen := length(FRangeSave.text)
        else
          FiLen := length(FsHTMLImage);
      end;
      cmdNextClick(self);
    end;
  end;
end;

procedure TReplaceForm.cmdNextClick(Sender: TObject);
var
  bFound:   boolean;
  iFlag:    integer;
begin
  iFlag := 0;
  if bWholeWord then
    iFlag := iFlag + 2;
  if bMatchCase then
    iFlag := iFlag + 4;
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    //Make sure we stay in a selection (if we have one)
    FRange.collapse(bFirst);
    bFound := FRange.findText(edtFind.Text, FiLen, iFlag);
    FRangeTemp := Frange.Duplicate;
    if bFound then
      if (FRangeSave.inRange(FRangeTemp)) then
        bFound := True
      else
        bFound := False; //End of selection

    if (bFound) then //If we found it, select it and make sure it's visible
     begin
      FRange.select;
      FRange.scrollIntoView(True);
      cmdReplace.Enabled    := True;
      cmdReplaceAll.Enabled := True;
    end
    else
    begin
      //Otherwise just dump out an error
      MessageDlg('Search string ''' + edtFind.Text + ''' was not found', mtInformation, [mbOK], 0);
      cmdNext.Enabled       := False;
      cmdReplace.Enabled    := False;
      cmdReplaceAll.Enabled := False;
      edtFind.SetFocus;
    end;
  end;
  if bFirst then
    bFirst := False;
end;

//Replace the current selection, find the next one...
procedure TReplaceForm.cmdReplaceClick(Sender: TObject);
begin
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    FRange.Set_text(edtReplace.Text);
  end;
  cmdNextClick(self);
end;

//Find and replace all... report finds
procedure TReplaceForm.cmdReplaceAllClick(Sender: TObject);
var
  bFound,
  bDone:    boolean;
  iFlag,
  iDid:     integer;
begin
  iFlag := 0;
  iDid  := 0;
  if bWholeWord then
    iFlag := iFlag + 2;
  if bMatchCase then
    iFlag := iFlag + 4;
  with EditWindowArray[MainForm.MainNoteBook.ActivePage.PageIndex] do
  begin
    bDone := False;
    FRange.Set_text(edtReplace.Text);
    inc(iDid);
    if bFirst then
      bFirst := False;
    while (not bDone) do
    begin
      //Make sure we stay in a selection (if we have one)
      FRange.collapse(bFirst);
      bFound := FRange.findText(edtFind.Text, FiLen, iFlag);
      FRangeTemp := Frange.Duplicate;
      if bFound then
        if (FRangeSave.inRange(FRangeTemp)) then
          bFound := True
        else
          bFound := False; //End of selection

      if (bFound) then //If we found it, select it and make sure it's visible
      begin
        FRange.select;
        FRange.scrollIntoView(True);
        FRange.Set_text(edtReplace.Text);
        inc(iDid);
      end
      else
      begin
        //Otherwise just dump out an error and bail out of the loop
        if iDid < 1 then
          MessageDlg('Search string ''' + edtFind.Text + ''' was not found', mtInformation, [mbOK], 0)
        else if idid = 1 then
           MessageDlg('''' + edtFind.Text + ''' was replaced with' + CRLF +
                      '''' + edtReplace.Text + '''.' + CRLF + CRLF +
                      'Replaced ' + IntToStr(iDid) + ' occurance.' , mtInformation, [mbOK], 0)
        else
           MessageDlg('''' + edtFind.Text + ''' was replaced with' + CRLF +
                      '''' + edtReplace.Text + '''.' + CRLF + CRLF +
                      'Replaced ' + IntToStr(iDid) + ' occurances.' , mtInformation, [mbOK], 0);
        bDone := True;
      end;
    end;
  end;
  cmdNext.Enabled       := False;
  cmdReplace.Enabled    := False;
  cmdReplaceAll.Enabled := False;
  edtFind.SetFocus;
end;


//Full or partial word search
procedure TReplaceForm.chkWholeWordClick(Sender: TObject);
begin
 bWholeWord := chkWholeWord.Checked;
end;


//Case sensitivity
procedure TReplaceForm.chkMatchCaseClick(Sender: TObject);
begin
 bMatchCase := chkMatchCase.Checked;
end;

procedure TReplaceForm.cmdCancelClick(Sender: TObject);
begin
  ModalResult := mrCancel;
end;

procedure TReplaceForm.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if Key = 27 then ModalResult := mrCancel;
end;

end.


Cheers



0
 
LVL 30

Expert Comment

by:Wayne Barron
ID: 14714447
Now they have the code here, and they have my download link
So that should give everyone the opertunity to grab it.
0
 
LVL 33

Expert Comment

by:Slick812
ID: 14716053
thanks for the new information ! !. . .

if you NEED a way to fix something, andr do a search here at EE and get an EE question that only has an Email addy for the solution, you will not be happy. .
I have done that many times, and is Why I made the comment. . . appreciate your efforts

Good luck
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now