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