cubrman
cubrman

Reputation: 946

C#'s scroll bar adornments?

When writing a Visual Studio extension, is there any way to influence how it renders map-mode scroll bar for c#?

enter image description here

Upvotes: 2

Views: 1127

Answers (1)

cubrman
cubrman

Reputation: 946

I don't have time for the full answer, but I will write the short one because there is next to zero info about it on the net:

  1. Create VSIX solution.
  2. Add Item and in the "Extensibility" category choose "Editor margin"
  3. In the "[yourEditorMarginName]Factory.cs" file that was created alonside the margin file after you did step 2 set the following lines:

        [MarginContainer(PredefinedMarginNames.VerticalScrollBar)]
        [Order(Before = PredefinedMarginNames.LineNumber)]
    
  4. Go back to the "[yourEditorMarginName].cs" file. Make sure that you remove the following lines in the constructor:

        this.Height = 20;
        this.ClipToBounds = true;
        this.Width = 200;
    
  5. Now you received a reference to IWpfTextView inside the constructor, sign up to its OnLayoutChanged event (or use some other event that suits you):

        TextView.LayoutChanged += OnLayoutChanged;
    
  6. In the OnLayoutChanged, you can do the following to add a rectangle adornment:

        var rect = new Rectangle();
        double bottom;
        double firstLineTop;
        MapLineToPixels([someLineYouNeedToHighlight], out firstLineTop, out bottom);
        SetTop(rect, firstLineTop);
        SetLeft(rect, 0);
        rect.Height = bottom - firstLineTop;
        rect.Width = [yourWidth];
        Color color = [your Color];
        rect.Fill = new SolidColorBrush(color);
    
        Children.Add(rect);
    
  7. And here is MapLineToPixels():

        private void MapLineToPixels(ITextSnapshotLine line, out double top, out double bottom)
        {
        double mapTop = ScrollBar.Map.GetCoordinateAtBufferPosition(line.Start) - 0.5;
        double mapBottom = ScrollBar.Map.GetCoordinateAtBufferPosition(line.End) + 0.5;
        top = Math.Round(ScrollBar.GetYCoordinateOfScrollMapPosition(mapTop)) - 2.0;
        bottom = Math.Round(ScrollBar.GetYCoordinateOfScrollMapPosition(mapBottom)) + 2.0;
        }
    
  8. Yeah the ScrollBar variable is something you can get this way:

    public ScrollbarMargin(IWpfTextView textView, IWpfTextViewMargin marginContainer/*, MarginCore marginCore*/)
    {
        ITextViewMargin scrollBarMargin = marginContainer.GetTextViewMargin(PredefinedMarginNames.VerticalScrollBar);
        ScrollBar = (IVerticalScrollBar)scrollBarMargin;
    

Upvotes: 6

Related Questions