在设计时点击鼠标,同时也可以同时选择控件

时间:2017-02-13 16:10:49

标签: c# custom-controls

我正在创建一个类似于TabControl的自定义控件。我希望标签标题在设计时可以点击,就像TabControl一样。使用我在Microsoft站点上找到的示例代码,我编写了以下代码。它有效,但有一个问题。

对于真实TabControl,如果在未选择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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分: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上的选项卡,则不会更改选项卡,只会选择选项卡。但我想我可以忍受这种微小的差异。