2016-08-05 7 views
2

カスタムコントロールを作成する際に、私はカスタムコントロール内のコンテナであるCanvas上でマウスの位置を取得しようとしています。問題は、カスタムコントロールをテストアプリケーションに配置すると、ウィンドウ内のグリッドだけです。マウスの位置は常にウィンドウ自体にありますが、マウスの位置はカスタムコントロール上にありません。CustomControlの一部でマウスの位置を取得する方法

public class HueWheel : Control 
{ 
    static HueWheel() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(HueWheel), new FrameworkPropertyMetadata(typeof(HueWheel))); 
    } 
    private bool _isPressed = false; 
    //private Canvas _templateCanvas = null; 
    private Canvas _PART_FirstCanvas; 
    private Canvas _PART_SecondCanvas; 
    private Slider _PART_Slider; 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     _PART_FirstCanvas = (Canvas)GetTemplateChild("PART_FirstCanvas"); 
     _PART_SecondCanvas = (Canvas)GetTemplateChild("PART_SecondCanvas"); 
     _PART_Slider = (Slider)GetTemplateChild("PART_Slider"); 
    } 

    protected override void OnMouseMove(MouseEventArgs e) 
    { 
     if (_isPressed) 
     { 
      const double RADIUS = 150; 
      Point newPos = e.GetPosition(_PART_SecondCanvas); 
      double angle = MyHelper.GetAngleR(newPos, RADIUS); 
      _PART_Slider.Value = (_PART_Slider.Maximum - _PART_Slider.Minimum) * angle/(2 * Math.PI); 
     } 
    } 

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) 
    { 
     _isPressed = true; 
    } 

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
    { 
     _isPressed = false; 
    } 
} 

これはGeneric.xaml

<Style TargetType="{x:Type local:HueWheel}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:HueWheel}"> 
       <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
        <Slider x:Name="PART_Slider"> 
         <Slider.Template> 
          <ControlTemplate> 
           <Canvas x:Name="PART_FirstCanvas" Width="300" Height="300"> 
             <Image Stretch="Fill" Source="Assets/HueCircle.PNG" Focusable="False" Height="300" Width="300" RenderTransformOrigin="0.5,0.5"> 
              <Image.RenderTransform> 
               <TransformGroup> 
                <ScaleTransform/> 
                <SkewTransform/> 
                <RotateTransform Angle="270"/> 
                <TranslateTransform/> 
               </TransformGroup> 
              </Image.RenderTransform> 
             </Image> 
             <Ellipse Fill="Transparent" Width="300" Height="300" Canvas.Left="0" Canvas.Top="0"/> 
             <Canvas x:Name="PART_SecondCanvas"> 
              <Line Stroke="Transparent" StrokeThickness="5" X1="150" Y1="150" X2="150" Y2="0"/> 
              <Ellipse Fill="Black" Width="20" Height="20" Canvas.Left="140" Canvas.Top="30"/> 
              <Canvas.RenderTransform> 
               <RotateTransform CenterX="150" CenterY="150"> 
                <RotateTransform.Angle> 
                 <MultiBinding Converter="{StaticResource ValueAngleConverter}"> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum"/> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/> 
                 </MultiBinding> 
                </RotateTransform.Angle> 
               </RotateTransform> 
              </Canvas.RenderTransform> 
             </Canvas> 
            </Canvas> 
          </ControlTemplate> 
         </Slider.Template> 
        </Slider> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

に含まれるXAMLはまた、マウスの位置は、マウスがキャンバス上にある場合にのみ出力されるので、一種の半分...ここで少し混乱を働いています。

public static double GetAngle(double value, double maximum, double minimum) 
{ 
    double current = (value/(maximum - minimum)) * 360; 
    if (current == 360) 
     current = 359.999; 

    return current; 
} 


public static double GetAngleR(Point pos, double radius) 
{ 
    Point center = new Point(radius, radius); 
    double xDiff = center.X - pos.X; 
    double yDiff = center.Y - pos.Y; 
    double r = Math.Sqrt(xDiff * xDiff + yDiff * yDiff); 

    double angle = Math.Acos((center.Y - pos.Y)/r); 

    if (pos.X < radius) 
     angle = 2 * Math.PI - angle; 

    if (Double.IsNaN(angle)) 
     return 0.0; 
    else 
     return angle; 
} 

どれヒント:

これらは私が角度の計算に使用する2つの機能がありますか?

あなたのコードで

+0

[wpfでウィンドウ内の要素の絶対位置を取得]の可能な複製(http://stackoverflow.com/questions/386731/get-absolute-position-of-element-within-the-window-in-wpf ) – stijn

+1

私はウィンドウ内ではなく、カスタムコントロール内の位置を取得しようとしているので、重複していません。 – lecloneur

答えて

1

_PART_SecondCanvas_PART_FirstCanvasはnullです。したがって、あなたはHueWheelのGetTemplateChild()と連絡を取ることはできません。一度How do I get the Children of a ContentPresenter?

public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 
    //_PART_FirstCanvas = (Canvas)GetTemplateChild("PART_FirstCanvas"); 
    //_PART_SecondCanvas = (Canvas)GetTemplateChild("PART_SecondCanvas"); 
    _PART_Slider = (Slider)GetTemplateChild("PART_Slider"); 

    _PART_Slider.ApplyTemplate(); 

    var sliderTemplate = _PART_Slider.Template; 
    _PART_FirstCanvas = (Canvas)sliderTemplate.FindName("PART_FirstCanvas", _PART_Slider); 
    _PART_SecondCanvas = (Canvas)sliderTemplate.FindName("PART_SecondCanvas", _PART_Slider); 
} 

出典:

OnApplyTemplate()では、canvas要素を見つけるために、その後、第1のスライダを見つけ、そのテンプレートを適用し、最終的にそのテンプレートにFindName()を呼び出す必要がありますあなたは実際に_PART_SecondCanvas_PART_FirstCanvasを見つけます、あなたのOnMouseMove()関数はあなたが期待することをするはずです。

1

Point ControlPos = e.GetPosition (this); 
Point WindowPos = e.GetPosition(Application.Current.MainWindow); 

ありがとうはあなたを与えるだろう - コントロールの座標とウィンドウの座標を。彼らは子供スライダーのコントロールテンプレートではなく、 『メイン』 HueWheelテンプレートに属しているため

+0

しかし私は私のcustomcontrolコードでマウスの位置を取得して再利用できるようにしたい。 – lecloneur

+0

あなたの提案に「私」とは何ですか? – lecloneur

+0

そして、 'e.GetPosition(Application.Current.MainWindow);を直接呼び出すこともできます。 –

関連する問題