2017-02-13 1 views
0

Je crée un contrôle personnalisé qui agit comme le TabControl. Je veux que les en-têtes des onglets soient cliquables au moment du design, tout comme le TabControl. En utilisant l'exemple de code que j'ai trouvé sur le site Microsoft, j'ai écrit le code suivant. Cela fonctionne, mais il y a un problème. Comme pour le TabControl réel, si vous cliquez sur un en-tête d'onglet lorsque le TabControl n'a pas été sélectionné, l'onglet sélectionné change, ET le TabControl est sélectionné montrant la bordure de redimensionnement qui a une poignée mobile et un petit bouton pour "TabControl Les tâches".Obtenir un clic de souris dans la conception, mais aussi laisser le contrôle être sélectionné en même temps

Faire la même chose avec mon code ci-dessous ne change que l'en-tête de l'onglet sélectionné; ça ne fait pas que mon contrôle soit sélectionné. Je pense que je dois dire à Visual Studio Designer de sélectionner mon contrôle, d'une manière ou d'une autre. Mais comment?

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); 
      } 
     } 
    } 
} 

Répondre

0

Je ne pouvais pas comprendre comment le faire avec l'approche qui utilise un Adorner comme ci-dessus. Donc, j'ai eu recours à l'utilisation du message Win32 (j'ai essayé d'éviter d'utiliser Win32 pour l'interopérabilité).

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); 
} 

Cela fonctionne, mais le seul problème mineur est que l'index de tabulation change au premier clic lorsque l'onglet n'est pas sélectionné. En cliquant sur un onglet sur un réel TabControl lorsqu'il n'est pas sélectionné ne modifie pas l'onglet, mais seulement sélectionne l'onglet. Mais je suppose que je peux vivre avec cette différence mineure.