DBGrid Delphi Right Click with Popup Menu

     

I have a DBGrid component with a popup menu attached.  dgRowSelect and dgMultiSelect options are true, and need to remain this way.  

Can someone tell me how to make right click actually the row in a DBGrid before the popup menu appears?

Right clicking on the grid doesn't actually highlight the item right clicked upon, it selects the item and I believe also sets the .recno property of the associated dataset, but the row is not selected in the same way a left click selects rows.  

Basically I just want right click to highlight the row, just like left click does.  

The end behavior would be the same as doing the following, left click on a row to select, and then right click on the same row to bring up the popup menu.


Thanks,

sse
SheratonGroupAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

aflarinCommented:
try this OnMouseDown handler for DBGrid1:

type
  THackDBGrid = class(TDBGrid);

procedure TForm1.DBGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  gc: TGridCoord;
begin
  if Button = mbRight then
  begin
    gc:= DBGrid1.MouseCoord(x, y);

    if (gc.X > 0) AND (gc.Y > 0) then
      DBGrid1.DataSource.DataSet.MoveBy(gc.Y - THackDBGrid(DBGrid1).Row);
  end;
end;

Open in new window

Pierre CorneliusCommented:
Nice work aflarin. Simply, easy effective. You beat me to it...
SheratonGroupAuthor Commented:
Hi,

Thank you for that, but a protected hack is not what I am looking for.  

I was hoping for a simple win api call, eg, a sendmessage call that selects the right clicked row.  Unfortunately, I don't know the proper message to send the dbgrid to accomplish this.  

sse
Introduction to Web Design

Develop a strong foundation and understanding of web design by learning HTML, CSS, and additional tools to help you develop your own website.

Pierre CorneliusCommented:
The protected hack is just to access the row number. I wonder what brain-child thought this should be a protected property in the first place???

As for you sendmessage suggestion, there is no such support built into the dbgrid. It is not a windows control that delphi simply wraps around, it is a control written in delphi. In my mind the row number should have been a public property in the first place.
Pierre CorneliusCommented:
Just to add to my last comments:

the current cell is internally managed by the component. The only way to access it is using the Hack as suggested by aflarin or creating a descendant component and surfacing the property.
SheratonGroupAuthor Commented:
Dbgrid definitely handles and responds to sendmessages (and postmessages too), even though it does not wrap window controls.  

I say this because I have hacked dbgrid myself in the past, and written custom events that use sendmessage.  

Unfortunately, I can't hack dbGrid for this job (as much as I would like to).

Thank you anyway.
Pierre CorneliusCommented:
>>>Dbgrid definitely handles and responds to sendmessages (and postmessages too), even though it does not wrap window controls.  


I never said it does not. To clarify: I was talking about a message that give you the cell clicked or selecting the row of that cell.
SheratonGroupAuthor Commented:
Does anyone know what message I can send the dbGrid to change the selected row?
Pierre CorneliusCommented:
I believe the question was answered.
aikimarkCommented:
@SheratonGroup

Have you abandoned this question?
SheratonGroupAuthor Commented:
I have not abandoned the question, in fact I would welcome an answer.  It has not yet been answered.  

Pierre CorneliusCommented:
just so we're on the same page:

1. do you have rowselect option set?
2. do you have multiselect option set?
Pierre CorneliusCommented:
It seems your problem is related to a grid with multiselect option set. You could try the following:

procedure TForm1.DBGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if (Button = mbRight) then
    if not (ssCtrl in Shift) then
    begin
      DBGrid1.SelectedRows.Clear;
      DBGrid1.SelectedRows.CurrentRowSelected:= true;
    end
    else begin
      DBGrid1.SelectedRows.CurrentRowSelected:= not DBGrid1.SelectedRows.CurrentRowSelected;
    end;
end;


Ideally the SelectedRows.clear should be called in mousedown (not mouseup) if <ctrl> is not pressed but for some reason my OnMouseDown event is never called (a bug?)



I may be better to intercept the right click in the wndproc i.e to override the grids wndproc as below. Note that the popup is not linked but rather called manually.



function CtrlDown : Boolean;
var State : TKeyboardState;
begin
   GetKeyboardState(State) ;
   Result := ((State[vk_Control] And 128) <> 0) ;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  OriginalGridWndProc:= DBGrid1.WindowProc; //just saving it in a private var of the form for later use
  DBGrid1.WindowProc:= NewGridWndProc;
end;

procedure TForm1.NewGridWndProc(var Message: TMessage);
begin
  OriginalGridWndProc(Message);
  if (Message.Msg = WM_RBUTTONDOWN) then
  begin
    if NOT CtrlDown then
    begin
      DBGrid1.SelectedRows.Clear;
      DBGrid1.SelectedRows.CurrentRowSelected:= true;
    end
    else DBGrid1.SelectedRows.CurrentRowSelected:= not DBGrid1.SelectedRows.CurrentRowSelected;
    PopupMenu1.Popup(mouse.CursorPos.X, mouse.CursorPos.Y);
  end;
end;


This results in the left and right mouse buttons acting the same except that the right mouse also shows the popup.


Hope this helps. My only concern I have is your earlier comment about the not being able to use the hack. If you can't do what I suggested either perhaps you need to elaborate on your situation.


If you are hell bent on using a message why not send a left mouse button message and just manually open the popup?

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.