I think this should be quite easy, but still can't make it work...
What I want is to be able to scroll records in DBGrid with a mouse wheel. However, i can't even get it reacting on mouse wheel, as there is no such event defined for DBGrid. I only found it in the Form event list, but it doesn't work.
Your help would be highly appreciated.
Comments
:
: What I want is to be able to scroll records in DBGrid with a mouse wheel. However, i can't even get it reacting on mouse wheel, as there is no such event defined for DBGrid. I only found it in the Form event list, but it doesn't work.
:
: Your help would be highly appreciated.
:
I don't know if the following works, but you could give it a shot. In the form's OnMouseWheel() check if the mouse is in the grid (see the Mouse variable and TControl object in the help files for more info). If it is, then call the Grid's DataSource.DataSet.Next() (or Prior()) to perform the actual scrolling.
Hi!
zibadian's offer works (I tried it before) but there is more better solution:
add TApplicationEvent (Delphi 7) (maybe TApplication in prev. versions- I'm not sure.)
Add this code to onMessage event:
procedure TFrm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
i: SmallInt;
begin
if Msg.message = WM_MOUSEWHEEL then
begin
Msg.message := WM_KEYDOWN;
Msg.lParam := 0;
i := HiWord(Msg.wParam) ;
if i > 0 then
Msg.wParam := VK_UP
else
Msg.wParam := VK_DOWN;
Handled := False;
end;
end;
: [b][red]This message was edited by ieri at 2004-9-9 11:27:1[/red][/b][hr]
: Hi!
: zibadian's offer works (I tried it before) but there is more better solution:
: add TApplicationEvent (Delphi 7) (maybe TApplication in prev. versions- I'm not sure.)
: Add this code to onMessage event:
:
: procedure TFrm1.ApplicationEvents1Message(var Msg: tagMSG;
: var Handled: Boolean);
: var
: i: SmallInt;
: begin
: if Msg.message = WM_MOUSEWHEEL then
: begin
: Msg.message := WM_KEYDOWN;
: Msg.lParam := 0;
: i := HiWord(Msg.wParam) ;
: if i > 0 then
: Msg.wParam := VK_UP
: else
: Msg.wParam := VK_DOWN;
: Handled := False;
: end;
: end;
:
:
:
:
The TApplicationEvents is also known in Delphi 5. This solution might cause problems, if you want to use the mousewheel for other things, when the grid doesn't have the focus. For example: when a memo is focused and you want the mousewheel to move the scrollbar instead of the text-cursor. It is better to include a check if the message is intended for the grid.
Another disadvantage of this code is that, when used for too many different special-handling, it might slow down the program. This is because each message must be preprocessed by the OnMessage(), then processed by the stub into an event. And finally that event is processed by the control itself.
I check if the dbgrid is focused at the beginning of the event handler. it works.
2. "it might slow down the program." What can cause slowing down? I really dont have any idea.
3. I tried prior and next methods before. But it didnt scroll one by one. I think it was because of the mouse configuration (Set in Control Panel).
: I check if the dbgrid is focused at the beginning of the event handler. it works.
:
: 2. "it might slow down the program." What can cause slowing down? I really dont have any idea.
:
: 3. I tried prior and next methods before. But it didnt scroll one by one. I think it was because of the mouse configuration (Set in Control Panel).
:
:
:
1. I included this as a note, because the posted code didn't check it.
2. The OnMessage() is called for every message the entire application gets, which are 100's per second (if not more). A single if-then is at least a single operation and always has some memory latency (http://encyclopedia.thefreedictionary.com/Latency) accompanied with it. This is in this case not noticable, but if you put several if-then's in the OnMessage(), then it might become noticable.
3. The mouse settings have probable nothing to do with it, because the OnMouseWheel() is called only once per click. This means that the Prior or Next is called only once per click, which should scroll the grid one by one for each click. But perhaps the database handling components work different than I thought (I never use them myself).
: : I check if the dbgrid is focused at the beginning of the event handler. it works.
: :
: : 2. "it might slow down the program." What can cause slowing down? I really dont have any idea.
: :
: : 3. I tried prior and next methods before. But it didnt scroll one by one. I think it was because of the mouse configuration (Set in Control Panel).
: :
: :
: :
: 1. I included this as a note, because the posted code didn't check it.
: 2. The OnMessage() is called for every message the entire application gets, which are 100's per second (if not more). A single if-then is at least a single operation and always has some memory latency (http://encyclopedia.thefreedictionary.com/Latency) accompanied with it. This is in this case not noticable, but if you put several if-then's in the OnMessage(), then it might become noticable.
: 3. The mouse settings have probable nothing to do with it, because the OnMouseWheel() is called only once per click. This means that the Prior or Next is called only once per click, which should scroll the grid one by one for each click. But perhaps the database handling components work different than I thought (I never use them myself).
:
My Ideal would be, that why dont we extend the capability of the DBGrid, with deriving a new component from TDBGrid, override the windwos wndProc, process the message, and do the proper actions.
I wrote a component like this before. This component manages the scrolling and adds a new event 'OnMouseWheel' for futher processing if its nesessary.
Here I post the code:
[code]
unit WheelGrid;
interface
uses
SysUtils, Classes, Controls, Grids, DBGrids, Messages, dialogs, Windows;
type TmwState = (mwUp,mwDown); // mousewheel direction status
type TMouseWheel = procedure(Sender : TObject;WheelDirection:TMwState) of object; // new event
type
TWheelGrid = class(TDBGrid)
private
FOnMouseWheel: TMouseWheel;
procedure SetOnMouseWheel(const Value: TMouseWheel);
{ Private declarations }
protected
{ Protected declarations }
public
procedure WndProc(var Message: TMessage);override; //overriding the wndproc of the grid
{ Public declarations }
published
property OnMouseWheel : TMouseWheel read FOnMouseWheel write SetOnMouseWheel; // add the new property
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('OSoft', [TWheelGrid]);
end;
{ TWheelGrid }
procedure TWheelGrid.SetOnMouseWheel(const Value: TMouseWheel);
begin
FOnMouseWheel := Value;
end;
procedure TWheelGrid.WndProc(var Message: TMessage);
var
WData : SmallInt; //wheel data
begin
if Message.Msg = WM_MOUSEWHEEL then //it the windows message is mousewheen (NT ONLY!)
begin
WData := HiWord(Message.WParam); //The HI part of the data gives the wheel movement multipled by mouse delta (120 usually)
// it lower then 0 then wheel up, else wheel down
Message.Msg := WM_KEYDOWN; //change the message to WM_KEYDOWN
Message.LParam := 0; //reset lparam
if WDAta>0 then // if wheel up
begin
if Assigned(FOnMouseWheel) then FOnMouseWheel(self,mwUp); //call the event handler
Message.WParam := VK_UP; // new windows message parameter is VK_UP
end
else
begin
if Assigned(FOnMouseWheel) then FOnMouseWheel(self,mwDown); //call the event handler
Message.WParam := VK_DOWN; // new windows message parameter is VK_DOWN
end;
end;
inherited WndProc(Message); // inherit whith the original, or cahnged windows message
end;
end.
[/code]
I prefer writing components in this case, cos' this way it is reusable.
In the components OnMouseWheel event you can check the direction like:
[code]
procedure TForm1.WheelGrid1MouseWheel(Sender: TObject;
WheelDirection: TmwState);
begin
if WheelDirection = mwUP then
ShowMessage('UP')
else
ShowMessage('DOWN');
end;
[/code]
This way, the question of time latencies, wont matter, cos' the component windproc invoked only, if a message is sent to.
Will not effect the speed of your entire application.
SoftMan
: : : 1. "This solution might cause problems, if you want to use the mousewheel for other things, when the grid doesn't have the focus. "
: : : I check if the dbgrid is focused at the beginning of the event handler. it works.
: : :
: : : 2. "it might slow down the program." What can cause slowing down? I really dont have any idea.
: : :
: : : 3. I tried prior and next methods before. But it didnt scroll one by one. I think it was because of the mouse configuration (Set in Control Panel).
: : :
: : :
: : :
: : 1. I included this as a note, because the posted code didn't check it.
: : 2. The OnMessage() is called for every message the entire application gets, which are 100's per second (if not more). A single if-then is at least a single operation and always has some memory latency (http://encyclopedia.thefreedictionary.com/Latency) accompanied with it. This is in this case not noticable, but if you put several if-then's in the OnMessage(), then it might become noticable.
: : 3. The mouse settings have probable nothing to do with it, because the OnMouseWheel() is called only once per click. This means that the Prior or Next is called only once per click, which should scroll the grid one by one for each click. But perhaps the database handling components work different than I thought (I never use them myself).
: :
:
: My Ideal would be, that why dont we extend the capability of the DBGrid, with deriving a new component from TDBGrid, override the windwos wndProc, process the message, and do the proper actions.
: I wrote a component like this before. This component manages the scrolling and adds a new event 'OnMouseWheel' for futher processing if its nesessary.
:
: Here I post the code:
:
: [code]
: unit WheelGrid;
:
: interface
:
: uses
: SysUtils, Classes, Controls, Grids, DBGrids, Messages, dialogs, Windows;
: type TmwState = (mwUp,mwDown); // mousewheel direction status
: type TMouseWheel = procedure(Sender : TObject;WheelDirection:TMwState) of object; // new event
: type
: TWheelGrid = class(TDBGrid)
: private
: FOnMouseWheel: TMouseWheel;
: procedure SetOnMouseWheel(const Value: TMouseWheel);
: { Private declarations }
: protected
: { Protected declarations }
: public
: procedure WndProc(var Message: TMessage);override; //overriding the wndproc of the grid
: { Public declarations }
: published
: property OnMouseWheel : TMouseWheel read FOnMouseWheel write SetOnMouseWheel; // add the new property
: { Published declarations }
: end;
:
: procedure Register;
:
: implementation
:
: procedure Register;
: begin
: RegisterComponents('OSoft', [TWheelGrid]);
: end;
:
: { TWheelGrid }
:
: procedure TWheelGrid.SetOnMouseWheel(const Value: TMouseWheel);
: begin
: FOnMouseWheel := Value;
: end;
:
: procedure TWheelGrid.WndProc(var Message: TMessage);
: var
: WData : SmallInt; //wheel data
: begin
:
: if Message.Msg = WM_MOUSEWHEEL then //it the windows message is mousewheen (NT ONLY!)
: begin
: WData := HiWord(Message.WParam); //The HI part of the data gives the wheel movement multipled by mouse delta (120 usually)
: // it lower then 0 then wheel up, else wheel down
: Message.Msg := WM_KEYDOWN; //change the message to WM_KEYDOWN
: Message.LParam := 0; //reset lparam
: if WDAta>0 then // if wheel up
: begin
: if Assigned(FOnMouseWheel) then FOnMouseWheel(self,mwUp); //call the event handler
: Message.WParam := VK_UP; // new windows message parameter is VK_UP
: end
: else
: begin
: if Assigned(FOnMouseWheel) then FOnMouseWheel(self,mwDown); //call the event handler
: Message.WParam := VK_DOWN; // new windows message parameter is VK_DOWN
: end;
: end;
: inherited WndProc(Message); // inherit whith the original, or cahnged windows message
: end;
:
: end.
: [/code]
:
: I prefer writing components in this case, cos' this way it is reusable.
: In the components OnMouseWheel event you can check the direction like:
: [code]
: procedure TForm1.WheelGrid1MouseWheel(Sender: TObject;
: WheelDirection: TmwState);
: begin
: if WheelDirection = mwUP then
: ShowMessage('UP')
: else
: ShowMessage('DOWN');
: end;
: [/code]
:
: This way, the question of time latencies, wont matter, cos' the component windproc invoked only, if a message is sent to.
: Will not effect the speed of your entire application.
: SoftMan
:
:
I dislike creating new components, because the source code is not very portable to other computers. For my work I never know if I'm working on the same machine again, and thus never know if my components are already installed. As for the speed, that's correct.
Secondly, I want to contribute a little to the discussion and state that on the net I also found the following code for scrolling DBGrid:
[code]
procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
begin
if (Msg = META_SETTEXTJUSTIFICATION)
and (Msg.Handle = DBGrid1.Handle)
and assigned(DBGrid1.Datasource)
and assigned(DBGrid1.Datasource.Dataset) then
begin
if Msg.wParam > 0 then
DBGrid1.Datasource.Dataset.Next
else
DBGrid1.Datasource.Dataset.Previous;
end;
end;
[/code]
It didn't work, however, until I changed META_SETTEXTJUSTIFICATION to 522 and Msg.Handle to Msg.hwnd. I have no idea how it works, but it works perfectly for my DBGrid where I draw all the cells manually. In the case of default drawing, however, it works really stange, sometimes scrolling by two records, etc. And also, I believe, it is subject to the same issue of slowing down performance.
:
: Secondly, I want to contribute a little to the discussion and state that on the net I also found the following code for scrolling DBGrid:
:
: [code]
: procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
: begin
: if (Msg = META_SETTEXTJUSTIFICATION)
: and (Msg.Handle = DBGrid1.Handle)
: and assigned(DBGrid1.Datasource)
: and assigned(DBGrid1.Datasource.Dataset) then
: begin
: if Msg.wParam > 0 then
: DBGrid1.Datasource.Dataset.Next
: else
: DBGrid1.Datasource.Dataset.Previous;
: end;
: end;
: [/code]
:
: It didn't work, however, until I changed META_SETTEXTJUSTIFICATION to 522 and Msg.Handle to Msg.hwnd. I have no idea how it works, but it works perfectly for my DBGrid where I draw all the cells manually. In the case of default drawing, however, it works really stange, sometimes scrolling by two records, etc. And also, I believe, it is subject to the same issue of slowing down performance.
:
Hi
You can try this, works for all grids on the form
[code]
procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
begin
if (Msg.message = META_SETTEXTJUSTIFICATION) then
if ActiveControl is TDBGrid then
begin
if msg.wParam >0 then
SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_UP,0)
else
SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_DOWN,0);
handled := true;
end
end;
[/code]
SoftMan
: You can try this, works for all grids on the form
:
: [code]
: procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
: begin
: if (Msg.message = META_SETTEXTJUSTIFICATION) then
: if ActiveControl is TDBGrid then
: begin
: if msg.wParam >0 then
: SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_UP,0)
: else
: SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_DOWN,0);
: handled := true;
: end
: end;
: [/code]
: SoftMan
:
:
Well, somehow it says "Undeclared identifier 'handled'". Did I miss something?
: : Hi
: : You can try this, works for all grids on the form
: :
: : [code]
: : procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
: : begin
: : if (Msg.message = META_SETTEXTJUSTIFICATION) then
: : if ActiveControl is TDBGrid then
: : begin
: : if msg.wParam >0 then
: : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_UP,0)
: : else
: : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_DOWN,0);
: : handled := true;
: : end
: : end;
: : [/code]
: : SoftMan
: :
: :
:
: Well, somehow it says "Undeclared identifier 'handled'". Did I miss something?
:
Well, for me it works, check if you added,
Application.OnMessage := MyMessageHandler; at main form's FormCreate?
'Handled' is the var parameter of the procedure, should work. Didn't you confused Handled, and Handle?
: : : Hi
: : : You can try this, works for all grids on the form
: : :
: : : [code]
: : : procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
: : : begin
: : : if (Msg.message = META_SETTEXTJUSTIFICATION) then
: : : if ActiveControl is TDBGrid then
: : : begin
: : : if msg.wParam >0 then
: : : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_UP,0)
: : : else
: : : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_DOWN,0);
: : : handled := true;
: : : end
: : : end;
: : : [/code]
: : : SoftMan
: : :
: : :
: :
: : Well, somehow it says "Undeclared identifier 'handled'". Did I miss something?
: :
:
: Well, for me it works, check if you added,
: Application.OnMessage := MyMessageHandler; at main form's FormCreate?
:
: 'Handled' is the var parameter of the procedure, should work. Didn't you confused Handled, and Handle?
:
:
OK, I understood where the problem was. In my Application.OnMessage procedure boolean var parameter is Handler not Handled.
And thanks for the code, it works perfectly.
: : : : Hi
: : : : You can try this, works for all grids on the form
: : : :
: : : : [code]
: : : : procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
: : : : begin
: : : : if (Msg.message = META_SETTEXTJUSTIFICATION) then
: : : : if ActiveControl is TDBGrid then
: : : : begin
: : : : if msg.wParam >0 then
: : : : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_UP,0)
: : : : else
: : : : SendMessage(ActiveControl.Handle,WM_KEYDOWN,VK_DOWN,0);
: : : : handled := true;
: : : : end
: : : : end;
: : : : [/code]
: : : : SoftMan
: : : :
: : : :
: : :
: : : Well, somehow it says "Undeclared identifier 'handled'". Did I miss something?
: : :
: :
: : Well, for me it works, check if you added,
: : Application.OnMessage := MyMessageHandler; at main form's FormCreate?
: :
: : 'Handled' is the var parameter of the procedure, should work. Didn't you confused Handled, and Handle?
: :
: :
:
: OK, I understood where the problem was. In my Application.OnMessage procedure boolean var parameter is Handler not Handled.
:
: And thanks for the code, it works perfectly.
:
Which Delphi version do you use, SaMo?
: : OK, I understood where the problem was. In my Application.OnMessage procedure boolean var parameter is Handler not Handled.
: :
: : And thanks for the code, it works perfectly.
: :
: Which Delphi version do you use, SaMo?
:
Delphi 6 Enterprise. But nevermind. I recall now that I might have manually changed it to Handler a while ago for some other purposes and forgot to change back.