2013-08-22 3 views
5

Windows XE2, TVirtualStringTreeTComboBox을 제자리 편집기로 사용하고 있습니다.마우스 휠이 잘못된 컨트롤로 메시지를 보내고 있습니다.

폼에 직접 TComboBox을 배치하면 런타임에 목록을 드롭 다운 할 수 있으며 마우스 휠은 목록의 항목을 원하는대로 위아래로 스크롤합니다. 그러나 실행시에 TVirtualStringTree을 내부 편집기로 만들면 새로 만든 콤보 상자에 포커스가 있더라도 마우스 휠 WM_MOUSEWHEEL 메시지가 콤보 상자가 아닌 트리 컨트롤로 보내집니다.

콤보 상자 드롭 다운 목록의 항목이 스크롤되지 않기 때문에 분명합니다. 대신 콤보 상자 뒤의 트리 컨트롤이 스크롤됩니다. 콤보 상자의 고정 부분은 트리와 함께 이동하지만 드롭 다운 목록은 콤보 상자의 고정 부분에서 연결이 끊어지고 이동하지 않습니다 (그림과 같이).

Example of how the tree control scrolled behind the drop-down list

이 두 경우는 TComboBox.StylecsDropDownList로 설정된다. 마우스를 가져 가면된다

FCBox := TComboBox.Create(TreeControl); 
FCBox.Visible := False; 
FCBox.Parent := TreeControl; 
// ... add items to combo box ... 
FCBox.Visible := True; 
FCBox.SetFocus; 
FCBox.DroppedDown := True; 

그것은 중요하지 않습니다 : 콤보 상자가 트리의 현재 위치에서 편집기로 생성 될 때,이 방법을 수행합니다. 콤보 상자 드롭 다운 목록의 항목 바로 위에있을 수 있으며 배경의 트리 컨트롤은 여전히 ​​스크롤됩니다. 콤보 상자의 항목을 스크롤하는 유일한 방법은 해당 스크롤 막대를 사용하는 것입니다.

포커스가있는 컨트롤의 부모가 컨트롤 (이 경우 TComboBox) 대신 마우스 휠 메시지를 수신하게되는 원인은 무엇입니까?

+0

메시지가 컨트롤로 전송되었다고 설명하는이 문서 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx) 핸들을 처리하지 않으면 처리 될 때까지 체인까지 상위로 보내집니다. 'TVirtualStringTree'가'TComboBox'가 메시지를 처리하는 방식을 바꿀만한 일을하는지 살펴 보겠습니다. –

답변

1

VirtualTrees.pasTBaseVirtualTree 클래스에서 다음과 같은 선언을 포함 : 그가 처음 수직하고 수평으로 스크롤 할 수 있도록

private 
    procedure CMMouseWheel(var Message: TCMMouseWheel); message CM_MOUSEWHEEL; 

구성 요소 작성자가 마우스 휠 메시지를 캡처. 사용자 지정 코드는 마우스 휠 메시지가 TComboBox 대신 TVirtualStringTree으로 전송되는 이유입니다. 그의 코드를 주석 처리하고 TComboBox 드롭 다운 목록을 예상대로 스크롤했습니다.

TBaseVirtualTree 코드를 정말로 제거하고 싶지 않으므로, 다음 코드를 사용하여 직접 편집자로 사용할 TMyComboBox 코드를 만들었습니다. 이제 스크롤은 드롭 다운 목록과 트리 컨트롤에서 올바르게 작동합니다. 이 처리 할 수있는 TControl.DoMouseWheel() 방법 트리 컨트롤과 손이 전달되기 전에

interface 

type 
    TMyCombBox = class(TComboBox) 
    private 
    procedure CMMouseWheel(var Message: TCMMouseWheel); message CM_MOUSEWHEEL; 
    end; 

implementation 

procedure TMyComboBox.CMMouseWheel(var Message: TCMMouseWheel); 
begin 
    if DoMouseWheel([], Message.WheelDelta, SmallPointToPoint(Message.Pos)) then 
    Message.Result := 1; 
end; 

이것은 CM_MOUSEWHEEL 메시지를 캡처합니다.

+0

내부 편집기의 메시지를 처리하는 것은 일반적인 관례입니다. 그렇게한다면, (당신의 inplace editor에 의해) 당신이 처리 한'WM_MOUSEWHEEL'을 말할 것이고, 그래서 당신이 기술 한 것은 아무것도 일어나지 않을 것입니다. – TLama

+0

감사합니다. @TLama - 문제는 메시지가 내부 편집자에게 전송되지 않았기 때문입니다.대신에, 즉시'TComboBox'를 우회하여 트리 컨트롤에 보내졌습니다. 커스텀'TComboBox'에서 메시지를 다시 얻어 와서 작동시켜야했습니다. 내 대답에 해결책을 추가 할 것입니다. –

+0

메시지가 콤보 상자로 전송되었지만 그 작은 짐승은 그냥 무시했습니다. (처리하지 못했습니다) :-) 콤보 상자에서 변경되는 항목은 시스템에서 제어하며 콤보 상자에서는 마우스 휠을 사용하므로 VCL에서이 메시지를 무시한다는 것은 아닙니다. – TLama