Получение координат диапазона только для диапазонов на экране

#c# #ms-word #vsto #netoffice

#c# #ms-word #vsto #netoffice

Вопрос:

В настоящее время я использую следующий метод для нахождения координат Range в документе:

 private Rectangle GetRangeCoordinates(Window w, Range r)
{
    int left = 0;
    int top = 0;
    int width = 0;
    int height = 0;

    w.GetPoint(out left, out top, out width, out height, r);

    return new Rectangle(left, top, width, height);
}
  

Это работает действительно хорошо, если Range не находится за пределами экрана с довольно большим отрывом (довольно много страниц), и в этом случае я получаю следующее исключение:

System.Runtime.Службы взаимодействия.COMException (0x800A1066): сбой команды в Microsoft.Офис.Interop.Word.Окно.Получить точку (Int32amp; ScreenPixelsLeft, Int32amp; ScreenPixelsTop, Int32amp; ScreenPixelsWidth, Int32amp; ScreenPixelsHeight, Object obj) в [Имяпроекта].[Имя панели задач].Получаем rangecoordinates(окно w, диапазон r) в […somePath …][Имя панели задач].cs: строка 66

Есть ли способ выяснить, есть ли Range на экране или нет, чтобы я мог вызывать этот метод только тогда, когда он есть?

Комментарии:

1. Чтобы вычислить, присутствует ли выбранный диапазон в документе, вам нужно знать размеры документа. Далее следует выбранная начальная точка прямоугольника. С помощью размера экрана и начальной точки прямоугольника вы можете создать пороговое значение того, насколько большим может быть выбранный диапазон.

2. @Innominatum проблема в том, что я не могу вызывать GetPoint диапазоны, которые (значительно) находятся за пределами экрана, потому что я получаю COMException, чего я не могу catch

3. Вы не можете добавить блок catch try вокруг вызывающего метода и перехватить COMException?

4. Не могли бы вы предоставить нам более подробную версию COMException?

5. @Innominatum — Я смог перехватить исключение, мне просто интересно, есть ли способ получше…

Ответ №1:

Вот как я это сделал.

Я создал несколько методов расширения для Application и Range :

 public static class ApplicationExensions
{
    // more (rather than less)
    // does not do headers and footers
    public static Range GetCurrentlyVisibleRange(this Application application)
    {
        try
        {
            Window activeWindow = application.ActiveWindow;
            var left = application.PointsToPixels(activeWindow.Left);
            var top = application.PointsToPixels(activeWindow.Top);
            var width = application.PointsToPixels(activeWindow.Width);
            var height = application.PointsToPixels(activeWindow.Height);
            var usableWidth = application.PointsToPixels(activeWindow.UsableWidth);
            var usableHeight = application.PointsToPixels(activeWindow.UsableHeight);

            var startRangeX = left;//   (width - usableWidth);
            var startRangeY = top;//   (height - usableHeight);

            var endRangeX = startRangeX   width;//usableWidth;
            var endRangeY = startRangeY   height;//usableHeight;

            Range start = (Range) activeWindow.RangeFromPoint((int) startRangeX, (int) startRangeY);
            Range end = (Range) activeWindow.RangeFromPoint((int) endRangeX, (int) endRangeY);

            Range r = application.ActiveDocument.Range(start.Start, end.Start);

            return r;
        }
        catch (COMException)
        {
            return null;
        }
    }
}

public static class RangeExtensions
{
    public static bool Intersects(this Range a, Range b)
    {
        return a.Start <= b.End amp;amp; b.Start <= a.End;
    }

    public static Rectangle? GetCoordinates(this Range range)
    {
        try
        {
            Application application = range.Application;
            Window window = application.ActiveWindow;

            int left = 0;
            int top = 0;
            int width = 0;
            int height = 0;

            window.GetPoint(out left, out top, out width, out height, range);

            return new Rectangle(left, top, width, height);
        }
        catch (COMException e)
        {
            return null;
        }
    }
}
  

И затем я использовал их следующим образом:

 Range currentlyVisibleRange = application.GetCurrentlyVisibleRange();

if (currentlyVisibleRange.Intersects(rng)){
    var coords = rng.GetCoordinates();
}