Hi.

If I define a lookup field, there will be a corresponding pick-list in the dbgrid. Is there a way to open this pick-list with the keyboard, instead of clicking on it? Otherwise I may have to use a TDBlookupcombobox in every column with a pick-list, because the user may not have a mouse.

TIA,

Eduardo

Dani AI

Generated

— good question. ’s keyboard-simulation trick (Alt+Down via keybd_event) does work, but it’s brittle (sends global keyboard events and can be intercepted by other windows). A cleaner, more direct approach is to call the DBGrid’s in-place editor and open its pick list programmatically.

Call the in-place editor’s DropDown method (that is the same method invoked when the user clicks the column button). The grid creates its InplaceEditor the first time it goes into edit mode, and the editor class for DBGrid supports a DropDown operation. (docwiki.embarcadero.com)

Example (use an interposer/class-hack so you can access protected members safely):

type
  TDBGridHack = class(TDBGrid);
  TInplaceEditListHack = class(TInplaceEditList);

procedure TForm1.DBGrid1ColEnter(Sender: TObject);
var
  LEdit: TInplaceEditList;
begin
  TDBGridHack(DBGrid1).EditorMode := True; // ensure editor exists
  if TDBGridHack(DBGrid1).InplaceEditor <> nil then
  begin
    LEdit := TInplaceEditList(TDBGridHack(DBGrid1).InplaceEditor);
    if DBGrid1.Columns[DBGrid1.SelectedIndex].PickList.Count > 0 then
      TInplaceEditListHack(LEdit).DropDown;
  end;
end;

That pattern (cast the grid to a small “hack” type, get InplaceEditor, cast to TInplaceEditList and call DropDown) is used in practice; it avoids synthesizing keystrokes. See examples and notes about exposing the inplace editor and calling DropDown directly. (mrxray.on.coocan.jp)

A few practical checks and caveats:

  • Only attempt DropDown if the column actually has a pick list / appropriate ButtonStyle (PickList exists or ButtonStyle = cbsAuto). (docwiki.embarcadero.com)
  • InplaceEditor is nil until the editor is created; make sure EditorMode (or ShowEditor) runs before you call DropDown. (docwiki.embarcadero.com)
  • If access/visibility gives compile errors, expose the members via a tiny descendant or helper type in your unit (the code above shows the usual approach).

This method is more robust than sending keyboard events and keeps logic local to the grid/editor itself.

Recommended Answers

All 2 Replies

I know Alt-DownArrow opens the pick-list, but only after the user at least presses another key. I'd like to show the drop down button as soon as the cell is entered.

Hi.

If I define a lookup field, there will be a corresponding pick-list in the dbgrid. Is there a way to open this pick-list with the keyboard, instead of clicking on it? Otherwise I may have to use a TDBlookupcombobox in every column with a pick-list, because the user may not have a mouse.

TIA,

Eduardo

Member Avatar for Member #82008

I know Alt-DownArrow opens the pick-list, but only after the user at least presses another key. I'd like to show the drop down button as soon as the cell is entered.

Hi ecostas, try this my function that simules keyboard pressed:

procedure ForcedDropDownList(OpenList :Boolean);
begin
  if OpenList then
  begin
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
    keybd_event(VK_DOWN, MapVirtualKey(VK_DOWN, 0), 0, 0);
    keybd_event(VK_DOWN, MapVirtualKey(VK_DOWN, 0), KEYEVENTF_KEYUP, 0);
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
  end else
  begin
    keybd_event(VK_ESCAPE, MapVirtualKey(VK_ESCAPE, 0), 0, 0);
    keybd_event(VK_ESCAPE, MapVirtualKey(VK_ESCAPE, 0), KEYEVENTF_KEYUP, 0);
  end;
end;

You can put than in an useful unit in order to be used in others projects.

In order to use, You need to intercept TDBGrid OnColEvent event. We'll need check if dataset is in edit or insert mode before try to dropping-down the pick-list.

Moving from a column to other, the cell is focused but we'll need put it in edit mode in order to gerenerate keyboard events and this is made by setting TDBGrid EditorMode property to True.

So, this is an exemple to use:

procedure TForm1.DBGrid1ColEnter(Sender: TObject);
begin
  if (DBGrid1.DataSource.State in [dsInsert, dsEdit]) and // check edit/insert mode
     (DBGrid1.SelectedIndex = 1) then // column to applay dropping-down
  begin
    DBGrid1.EditorMode := True;
    ForcedDropDownList(True);
  end;
end;

The dropped pick-list will close only after a choice has been selected or ESCape key pressed - like is normally it occurs.

I hope to help You.

Bye

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.