2017-02-13 21 views
0

私はTabControlのように動作するカスタムコントロールを作成しています。 TabControlと同じように、デザイン時にタブヘッダーをクリック可能にします。 Microsoftのサイトで見つけたサンプルコードを使用して、次のコードを書きました。それは動作しますが、問題が1つあります。デザイン時にマウスをクリックするだけでなく、同時にコントロールを選択させる

実際のTabControlの場合、TabControlが選択されていないときにタブヘッダーをクリックすると、選択したタブが変更され、タブハンドルが選択され、移動ハンドルと "TabControlタスク "を参照してください。

以下のコードで同じことをすると、選択したタブヘッダーのみが変更されます。私のコントロールを選択することはできません。 Visual Studio Designerにコントロールを何とか選択させる必要があると思います。しかしどうですか?

public class MyDesigner : System.Windows.Forms.Design.ControlDesigner 
{ 
    private Adorner MyAdorner; 
    public override void Initialize(IComponent component) 
    { 
     base.Initialize(component); 

     MyAdorner = new Adorner(); 
     this.BehaviorService.Adorners.Add(MyAdorner); 
     MyAdorner.Glyphs.Add(new MyGlyph(BehaviorService, (MyTabControl)Control)); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing && MyAdorner != null) 
     { 
      BehaviorService b = BehaviorService; 
      if (b != null) 
      { 
       b.Adorners.Remove(MyAdorner); 
      } 
     } 
    } 

    class MyGlyph : Glyph 
    { 
     MyTabControl TargetControl; 
     BehaviorService behaviorSvc; 

     public MyGlyph(BehaviorService behaviorSvc, MyTabControl targetControl) 
      :base(new ClickingBehaviour()) 
     { 
      this.behaviorSvc = behaviorSvc; 
      this.TargetControl = targetControl; 
     } 

     private void OnMouseClick(MouseButtons button, Point adornerPoint) 
     { 
      var screenPoint = behaviorSvc.AdornerWindowPointToScreen(adornerPoint); 
      var targetPoint = TargetControl.PointToClient(screenPoint); 
      TargetControl.DesignTimeClick(button, targetPoint); 
     } 

     public override Rectangle Bounds 
     { 
      get 
      { 
       Point edge = behaviorSvc.ControlToAdornerWindow(TargetControl); 
       Size size = TargetControl.Size; 
       Rectangle bounds = new Rectangle(edge, size); 
       return bounds; 
      } 
     } 

     public override Cursor GetHitTest(Point p) 
     { 
      Cursor handled = null; 
      if (Bounds.Contains(p)) 
      { 
       var screenPoint = behaviorSvc.AdornerWindowPointToScreen(p); 
       var targetPoint = TargetControl.PointToClient(screenPoint); 
       if(TargetControl.IsHeaderArea(targetPoint)) 
        handled = Cursors.Default; 
      } 

      return handled; 
     } 

     public override void Paint(PaintEventArgs pe) 
     { 
     } 

     class ClickingBehaviour : Behavior 
     { 
      public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc) 
      { 
       MyGlyph myG = g as MyGlyph; 
       myG.OnMouseClick(button, mouseLoc); 
       return base.OnMouseDown(g, button, mouseLoc); 
      } 
     } 
    } 
} 

答えて

0

上記のようにAdornerを使用するアプローチでは、どのように行うべきかわかりませんでした。ですから、私はWin32メッセージを使用しました(私は相互運用性のためにWin32の使用を避けようとしました)。

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == 0x0201 && m.WParam.ToInt32() == 0x0001) 
    { 
     var target = (Control as MyTabControl); 
     if (true) //how to know if focused? 
     { 
      var lparam32 = m.LParam.ToInt32(); 
      int lowWord = lparam32 & 0xffff; 
      int highWord = lparam32 >> 16; 
      Point p = new Point(lowWord, highWord); 
      if (target.IsHeaderArea(p)) 
      { 
       target.DesignTimeClick(MouseButtons.Left, p); 
      } 
     } 
    } 
    base.WndProc(ref m); 
} 

これは機能しますが、小さな問題は、タブが選択されていないときに最初のクリックでタブインデックスが変更されることです。実際のTabControlが選択されていないときにそのタブをクリックしてもタブは変更されず、タブのみが選択されます。しかし、私はこの小さな違いで生きることができると思う。

関連する問題