views:

539

answers:

4

I have a DBGrid, I need to run some code, each time the horizontal scrollbar is used. I couldn't find such event in DBGrid. Can you advise something?

A: 

I can't check this at the moment, but if I recall correctly the event's there, but not published. Try creating a control that descends from TDBGrid and publishes the scroll bar event.

Mason Wheeler
I checked this, and still couldn't find such event. There is an element called ScrollBars, but no event related to it.
Tofig Hasanov
+4  A: 

Maybe this will help. It shows an example for trapping the scrolling events of a regular TStringGrid. Synchronize the Scrolling of two TStringgrids?

yozey
This works, but I have a lack of knowledge in one point here, could you assist? I created a new component TScrDBGrid, but I have a DBGrid already placed on a form with lots of properties and events already declared, so I'd hate to delete and create a new one. Is there a way I can "migrate" this DBGrid to the new class?
Tofig Hasanov
You can install your new component into a package, and install that package into the IDE so the compiler is aware of it. Close the unit with the DBGrid you want to replace, so it's not open in the IDE. *MAKE A COPY OF THE .DFM AND PAS FILES FIRST!* Open the text .DFM in Notepad and replace the TDBGrid with your new grid's classname. Do the same with the matching .PAS file's interface section, and make sure you add your new unit's name to the *interface* uses clause. Save the file, and then reopen it in the IDE. If you did things right, all should be fine. If not, restore the backup copies.
Ken White
One last question. While this event works now, the scrollbar stopped working, it seems that while catching this event, it stops it from proceding further to windows for actual scrolling operation. How should I solve this?
Tofig Hasanov
@Tofig: did call inherited in your WMHScroll procedure? If not you would have to provide the expected behavior yourself
François
Are you calling the OldGridProc?
yozey
Yes, after I added inherited all became OK. Thanks everyone! :)
Tofig Hasanov
@Tofig: There is a hack you can use for not redeclaring all your components. If you create a descendent component with the exact name that you are descending from but references the parent component including the unit name, you should with just adding that unit be able to continue without changing components. So you would declare a TDBGrid = class(DBGrids.TDBGrid) with your added functionality in a new unit like 'MyGrid.pas', by adding that to those areas where you DBGrid is used, you should be ok. I am trying to find the article where I picked this up from.
yozey
A: 

EDIT: Wrong answer, obviously. It catches the vertical scrollbar, but not the horizontal one.

You don't catch it at the DBGrid level. You catch it at the BeforeScroll or AfterScroll of the attached TDataSet. It fires with either the scrollbar, up and down arrow keys, page up and page down keys, etc. that occurs within the DBGrid.

Ken White
It works for vertical scrolling, but not horizontal. How do you make it fire for horizontal scrolling?
Tofig Hasanov
I don't think it would do much good to the OP. He wants to trap the Horizontal scrolling, i.e when the visible colummns change.
François
Ah, of course you're right. I missed the "horizontal". Thanks for the correction. @Tofig: I don't think you can catch the horizontal scroll; at least a quick test app I wrote couldn't. Left and right arrow keys work in the OnColEnter and OnColExit events, but aren't triggered via the scrollbar as the selected column isn't changed.
Ken White
yozey's answer can actually help, but I have a problem with that (see comment to his answer), maybe you could help?
Tofig Hasanov
@Tofig: See my comment to yozey's answer.
Ken White
+1  A: 

There is a WMHScroll procedure in TCustomGrid, but it is private. You can't use it in a DBGrid.
You would have to create your own TDBGrid descendant and do your own

procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;

or do some seriously bad hacking...

Update: trick/hack to sneak your code in...

[...]
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, ADODB, Grids, DBGrids;

    type
      // Hack to redeclare your TDBGrid here whitout the the form designer going mad
      TDBGrid = class(DBGrids.TDBGrid)
        procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
      end;

      TForm8 = class(TForm)
        DBGrid1: TDBGrid;
        DataSource1: TDataSource;
        ADODataSet1: TADODataSet;
        ADOConnection1: TADOConnection;
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form8: TForm8;

    implementation

    {$R *.dfm}

    { TDBGrid }

    procedure TDBGrid.WMHScroll(var Msg: TWMHScroll);
    begin
      case Msg.ScrollCode of
        SB_ENDSCROLL: OutputDebugString('SB_ENDSCROLL') ;
        SB_LEFT:OutputDebugString('SB_LEFT');
        SB_RIGHT:OutputDebugString('SB_RIGHT');
        SB_LINELEFT:OutputDebugString('SB_LINELEFT');
        SB_LINERIGHT:OutputDebugString('SB_LINERIGHT');
        SB_PAGELEFT:OutputDebugString('SB_PAGELEFT');
        SB_PAGERIGHT:OutputDebugString('SB_PAGERIGHT');
        SB_THUMBPOSITION:OutputDebugString('SB_THUMBPOSITION');
      end;
      inherited; // to keep the expected behavior
    end;
[...]

Update2: Note that you can move your special TDBGrid code to a separate unit (recommended), just be sure to put this unit name AFTER DBGrids in your Form's uses clause.

François
Yep, that is what yozey's article actually suggests. I have already created such component. Now the problem is - how to migrate from old one to the new one, without deleting and creating again?
Tofig Hasanov
Thanks, I didn't know that such hacking was possible :)
Tofig Hasanov
Tofig, See my Update2. You can avoid changing your existing code.
François