[DevExpress Support Team: CLONED FROM Q538627: How to redirect mouse wheel message to a cxGrid]
I'm working on upgrading fra v12 to newest v14,
The example does not work in v14. And I cannot get it to work. (I suspect a problem in v14)
It is only after selecting one of the controls it works a bit and the Richedit does not work at all.
Also you have these minor problems in the example:
This code:
Result := (Assigned(Control) AND (not Control.Focused));
if(Control is TcxControl) or (Control.Parent is TcxControl) then
- Access viol. if Result = nil.
- FindVCLWindow is STILL broken in XE6 as it has been since 2010 at least.
You have to make your own if your layout is more complex.
(this is just a note to other developers) - you also need ScreenToClient(MousePos);
Can you make your sample function with v14 please?
I have a lot of trouble getting wheel to function in my app. as it did before. But I guess if your sample works I can also find how to make my app do it.
Hello Poul,
Does John Friel's solution in the Q538627 thread meet your requirements?
hello Mikhail,
Using TApplicationEvent in this situation would be introduction of spagetti code in this large application (it is complex enough already).
I have a TApplicationEvent in the app. but in relation to the issue at hand, the code runs in a popup form, which should not be connected to the 'global' TApplicationEvent both ways (the spagetti). So I must use Form.OnMouseWheel to handle it in the popup.
Then I cant just 'send' the message to other controls like when using TApplicationEvent.
I found for grid I can use
this works well now for grid.
However when the control is e.g. TcxCustomInnerMemo
And I call
It goes into your code:
function TcxControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; begin Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos); if not Result and IsMouseWheelHandleNeeded(Shift, WheelDelta, MousePos) then
but does nothing because IsMouseWheelHandleNeeded evaluated to false. (True when it's a grid)
it is overridden for memo:
function TcxCustomTextEdit.IsMouseWheelHandleNeeded(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; begin Result := DoIsMouseWheelHandleNeeded(Shift, MousePos); end; function TcxCustomTextEdit.DoIsMouseWheelHandleNeeded(Shift: TShiftState; MousePos: TPoint): Boolean; begin Result := GetScrollLookupDataList(escMouseWheel) and not HasPopupWindow and ActiveProperties.UseLookupData and not ILookupData.IsEmpty and HandleMouseWheel(Shift); end; function TcxCustomTextEdit.GetScrollLookupDataList(AScrollCause: TcxEditScrollCause): Boolean; begin Result := False; end;
Any ideas?
Hello Poul,
We will examine this behavior and get back to you once we have any results or need additional information. But this can take us some time. We appreciate your understanding.
Poul, you can apply the fix that I believe will help you:
unit cxTextEdit; function TcxCustomTextEdit.IsMouseWheelHandleNeeded(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; begin Result := inherited InternalMouseWheel(Shift, WheelDelta, MousePos) or DoIsMouseWheelHandleNeeded(Shift, MousePos); end;
Ok, I found a solution, I just want to show the code for others to use. Also I like to say it would be nice if it could be possible to use TControlAccess(FCurrentWheelControl).DoMouseWheel([], WheelDelta, MousePos);
for all controls, also cxMemo and rich edit.
Here is my code (note it has an outer scrollbox which I want to be scrolled if the mouse wheeling is not started on top of a single control like cxMemo (which should then be scrolled insead of the outer scrollbox, hence the event handling to clear the 'grabbed' control):
function TEditRecordForm.HandleMouseWheel(Sender: TObject; WheelDelta: Integer; MousePos: TPoint): boolean; var i: Integer; LPosInForm: TPoint; LControl: TControl; LRealControl: TWinControl; LOkToScroll: Boolean; begin if not Assigned(FCurrentWheelControl) then begin LPosInForm := ScreenToClient(MousePos); LControl := TSMUtils.CustomControlAtPos( Self, LPosInForm, True, True, True); LOkToScroll := Assigned(LControl) and (LControl is TWinControl) and (not (LControl as TWinControl).Focused); if LOkToScroll then FCurrentWheelControl := LControl as TWinControl; end; Result := Assigned(FCurrentWheelControl); if Result then begin if (FCurrentWheelControl is TcxGridSite) then begin TControlAccess(FCurrentWheelControl).DoMouseWheel([], WheelDelta, MousePos); end else if (FCurrentWheelControl is TcxCustomInnerMemo) then begin LRealControl := (FCurrentWheelControl as TcxCustomInnerMemo).Parent; if WheelDelta > 0 then (LRealControl as TcxControl).ScrollContent(dirUp) else (LRealControl as TcxControl).ScrollContent(dirDown); end else begin // All other must always go to bottom scrollbox. // TControlAccess(MyRecordView).DoMouseWheel([], WheelDelta, MousePos); if WheelDelta > 0 then (MyRecordView as TcxControl).ScrollContent(dirUp) else (MyRecordViewas TcxControl).ScrollContent(dirDown); // for i := 0 to Abs(WheelDelta) - 1 do // if WheelDelta < 0 then // TScrollBox(MyRecordView).Perform(WM_VSCROLL, 1, 0) // else // TScrollBox(MyRecordView).Perform(WM_VSCROLL, 0, 0); end; end; end; FCurrentWheelControl: TWinControl; FLastMouseMovePoint: TPoint; procedure TEditRecordForm.MyOnMessage(var Msg: TMsg; var Handled: Boolean); begin case Msg.message of WM_MOUSEMOVE: begin if FLastMouseMovePoint <> Msg.pt then begin FLastMouseMovePoint := Msg.pt; FCurrentWheelControl := nil; end; end; end; end; procedure TEditRecordForm.FormCreate(Sender: TObject); begin inherited; FOldApplicationOnMessage := Application.OnMessage; Application.OnMessage := MyOnMessage; end; procedure TEditRecordForm.FormDestroy(Sender: TObject); begin Application.OnMessage := FOldApplicationOnMessage;
oh, out postings crossed, I will also try your workaround, thanks.
I could not get your suggestion with TcxCustomTextEdit.IsMouseWheelHandleNeeded working.
Actually when I managed to apply it all wheel scroll stopped working, strange. I undoed the changes.
NB DoIsMouseWheelHandleNeeded is private so I had to modify access for it.
I've attached the sample recompiled with these changes from the Q538627 thread and it seems it works as expected on my side. Please take a look at the attachment.