1

I was looking for an easy way to use RichtText in a default combobox, but found nothing. So I wrote this little Delphi(7) component, that is working so far.

How is works: I'm calling "init" to replace the "Edit"-window inside a default combobox with a runtime-created RichEdit. Size is taken from the Edit, and Edit is finally hidden. Some event-handlers are included for change-detection and so on.

Problem: If I click an item of the dropdown-list, the text is shown in the RichEdit. If some text is entered inside the RichEdit and the dropdown-button is pressed again, the dropdown-list is opened and closed in the next moment. After some clicks, the list remains open and is working as expected. Every time I click the list and change the RichEdit again, the same is happening.

Maybe I have to sent some messages to the combobox to get that fixed ?

I didn't find any solution on the web, so far. Maybe you have an idea.

Thanks for your help !

unit RichTextComboBox;

interface

uses  SysUtils, Classes, Controls, StdCtrls, Windows, Messages, forms, Graphics, ComCtrls;

type
    TRichTextComboBox = class(TComboBox)
    private
        FOnChange     :TNotifyEvent;
        EditHandle :Integer;
        procedure proc_FOnComboChange(Sender: TObject);
    protected
    public
        Rich :TRichEdit;             // accessable from outside
        constructor Create(AOwner: TComponent); override;
        destructor  Destroy; override;
        procedure   Init;            // replace Edit in combobox with RichEdit
    published
    end;

procedure Register;

implementation



constructor TRichTextComboBox.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
end;


// click in Combo-Drop-Down-List
procedure TRichTextComboBox.proc_FOnComboChange(Sender :TObject);
begin
    if Rich.Text <> Items.Strings[ItemIndex] then begin
        Rich.Text:=  Items.Strings[ItemIndex];
    end;
    if assigned (FOnChange) then FOnChange(sender);
end;


procedure Register;
begin
    RegisterComponents('TEST', [tRichTextComboBox]);
end;


destructor TRichTextComboBox.Destroy;
begin
    if Rich <> nil then begin
        RemoveControl(rich);
        Rich.destroy;
    end;
    inherited Destroy;
end;


// Replace "Edit" with "RichEdit" in ComboBox
//
procedure TRichTextComboBox.init;
var       h      :integer;
          rect   :trect;
          wndpos :TWindowPlacement;
begin
    h:= FindWindowEx(
        self.Handle,
        0,              // handle to a child window
        'Edit',         // class name
        nil
    );

    Rich:= TRichEdit.create(self);
    rich.Parent:= self;

    if h <> 0 then begin
        EditHandle:= h;
        GetWindowRect(h, rect);

        // configure RichEdit

        GetWindowPlacement(h, @wndpos);        // RichEdit with position and size of Edit
        rich.BorderStyle:= bsNone;
        rich.Text:= self.Text;
        rich.Font.Style:= [fsbold, fsItalic];
        rich.Top:=   wndpos.rcNormalPosition.top;
        rich.Left:=  wndpos.rcNormalPosition.Left;
        rich.Width:= rect.Right - rect.Left;
        rich.Height:= rect.Bottom-rect.Top;
        rich.WantReturns:= false;              // just one line
        rich.WordWrap:= false;                 // just one line
        rich.ParentColor:= true;               // just one line
        rich.Visible:= true;
        showwindow(h, sw_hide);                // hide Edit
    end;

    // if drop-down-combo-list is clicked
    // change the string of the RichEdit
    FOnChange:=     self.OnChange;             // save original OnChange of ComboBox
    rich.OnChange:= FOnChange;
    self.OnChange:= proc_FOnComboChange;
end;

end.
Pete Hoover
  • 11
  • 1
  • 2

1 Answers1

0

Finally I found the solution :-)

The RichEdit is holding the Focus, which causes the drop-down-list not to stay open after entering s.th. in the RichEdit. This procedure sets the Focus back to the Combobox before it is opening. So everything works as expected.


Code to be inserted:

after protected enter:

procedure DropDown; override;

the procedure looks like this:

procedure TRichTextComboBox.DropDown;
begin
  Self.SetFocus;
  inherited DropDown;
end;

I prefer this approach, because I don't want to mess around with the OwnerDraw-problems that we can read on many pages. (Some things are still missing: Upkey/Downkey...)

Chris
  • 3,113
  • 26
  • 33
Pete Hoover
  • 11
  • 1
  • 2