4
votes

I was just about to replace a TEdit + TButton combination with one TButtonedEdit control but when I tried to test it, I found no way to "press" the (right) button using the keyboard.

I tried Alt+Enter, Alt+Down, Alt+Right, the same keys with Ctrl and a few more key combinations but none of them worked. The VCL sources did not shed any light on this issue either (but hey "professional programmers don't look at the VCL sources" anyway)

Am I missing something?

This is with Delphi 2010 on a Windows XP box, the TButtonedEdit component was introduced in Delphi 2009 IIRC.

Note: I have accepted Andreas Rejbrand's answer because it answers the question. But I have also added my own answer for the benefit of those who might be interested in what I actually implemented.

3
Professional programmers study the RTL/VCL source code extensively.Andreas Rejbrand
@Andreas: Yes, I know, I certainly do. This was just referring to Embarcadero's comment on not including the RTL/VCL sources with the new entry level Delphi version.dummzeuch

3 Answers

3
votes

No, there is no such keyboard shortcut, partly (maybe) because of the ambiguity in which button (the left or right button) the keyboard shortcut should execute.

I always do it like this:

procedure TForm1.ButtonedEdit1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_RETURN) and (ssCtrl in Shift) then
    ButtonedEdit1RightButtonClick(Sender);
end;

The Ctrl+Enter shortcut is very natural if the button displays a modal dialog (which helps the user fill the edit box), or something similar. If it instead executes a procedure taking the edit text as argument (e.g., an address bar or a search box), Enter alone is more suitable. If the button is a clear button (that clears the edit box), then Escape might be the best shortcut, or possibly no shortcut at all (and then it is a good thing that there is no default shortcut).

The fact that the suitable shortcut depends on the situation also suggests that there should be no default shortcut, I think.

By the way, don't forget to make the TButtonedEdit DoubleBuffered, for otherwise it will flicker way too much.

2
votes

I have now created an interposer class that looks like this:

interface
{...}
type
  TdzButtonedEdit = class(TButtonedEdit)
  protected
    procedure KeyDown(var _Key: Word; _Shift: TShiftState); override;
  public
    procedure Loaded; override;
  end;

{...}

implementation

{...}

{ TdzButtonedEdit }

procedure TdzButtonedEdit.KeyDown(var _Key: Word; _Shift: TShiftState);
begin
  inherited;
  if (_Key = VK_RETURN) and (ssCtrl in _Shift) then
    if Assigned(OnRightButtonClick) then
      OnRightButtonClick(Self);
end;

procedure TdzButtonedEdit.Loaded;
begin
  inherited;
  if RightButton.Visible and (RightButton.Hint = '') then begin
    RightButton.Hint := _('Ctrl+Return to ''click'' right button.');
    ShowHint := true;
  end;
end;

which I use in the form by declaring:

TButtonedEdit = class(TdzButtonedEdit)
end;

before the form's class declaration.

If I can ever be bothered I'll make it a full blown custom component.

btw: Why did Embarcadero make TEditButton.TGlyph strict private? That's very inconvenient because normally I would have called RightButton.Glyph.Click rather than OnRightButtonClick.

0
votes

Given that there is no way to pass the input focus to these embedded buttons, and given that they display glyphs, how could there be keyboard access? How would the user discover it?

On a modal dialog you can press enter and so long as the focus control is not a button, then the default button is pressed and the form closes. That is part of the platform UI standard. Similarly for escape and cancel. Many other controls have standard keyboard access (lists, drop downs, edits etc.)

This is not a standard control and so it would be wrong to impose some default keyboard access beyond what is expected in an edit control. It's fine for the designer to add access because they know what is reasonable on their form, but the VCL designers got it right by not including a default behaviour that would apply to every instance of this control..