2016-03-01 3 views
2

У меня есть форма, которая встроена в окно прокрутки. Я реализую прокрутки в окне прокрутки, как так:Подавлять события прокрутки мыши на определенных элементах управления, но не их родителя?

procedure TfrmPO.sbItemsMouseWheelDown(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
begin 
    sbItems.Perform(WM_VSCROLL, SB_PAGEDOWN, 0); 
end; 

procedure TfrmPO.sbItemsMouseWheelUp(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
begin 
    sbItems.Perform(WM_VSCROLL, SB_PAGEUP, 0); 
end; 

Это делает трюк только штрафом, но есть также ряд элементов управления поле со списком в этой форме. Если фокус находится в одном из них, он также прокручивает элементы в этом поле со списком. Поэтому мне нужно отключить такие эффекты.

Я пробовал два решения, которые действительно работают, однако оба решения также вносят новую проблему: родительский блок прокрутки никогда не получает сообщений и, таким образом, не прокручивает по желанию. Если фокус находится в другом элементе управления, родитель выполняет прокрутку, но если фокус находится в поле со списком, ничего не прокручивается.

Попытка 1:

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; 
    WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); 
begin 
    if Screen.ActiveControl is TComboBox then Handled := True; 
end; 

Попытка 2:

type 
    TComboBox = class(Vcl.StdCtrls.TComboBox) 
    protected 
    function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override; 
    end; 

..... 

{ TComboBox } 

function TComboBox.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; 
    MousePos: TPoint): Boolean; 
begin 
    Result:= True; 
end; 

Как я могу отключить колесо мыши прокрутки в определенных элементов управления, не отключив его от своих родителей?

ответ

3

Сообщения колесика мыши передаются в родительскую цепочку элемента управления, которые принимают их, пока не будет обработано. Поэтому установите Handled в true, где вы на самом деле их обрабатываете, в прокрутке. Не помещайте обработчик сообщений нигде, чтобы сообщение было отправлено родительскому элементу.

procedure TfrmPO.sbItemsMouseWheelDown(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
begin 
    Handled := True; 
    sbItems.Perform(WM_VSCROLL, SB_PAGEDOWN, 0); 
end; 
+0

Я предполагаю, что фактическое действие прокрутки не выполняется до тех пор, пока не закончится распространение, а не в момент получения сообщения. Верный? –

+0

@Jerry, это верно, обработчик по умолчанию вызывается только в том случае, если никто не установил обработчик. Вы можете увидеть в последней строке TControl.WMMouseWheel, Message.Result - 1, если принимающий элемент управления или один в родительской цепочке * обрабатывает * сообщение. –