ArcGIS MapControl и Ms Access задерживают перерисовку карты? - PullRequest
2 голосов
/ 06 февраля 2009

Это относится к встраиванию ESRI MapControls в формы базы данных Access.

У меня есть два файла доступа, разделенных на фронтенд и бэкэнд. Моим бэкэндом является также PersonalGeoDatabase, который ArcGIS использует для хранения класса пространственных объектов для отображения во встроенном элементе управления карты ESRI From.

Класс пространственных объектов хранит полилинии, точки и полигоны, связанные с конкретным ProjectID.

Из внешнего интерфейса у меня есть встроенный mapControl, который загружает файл MXD, привязанный к бэкэнду.

У меня есть функция VB CenterPoint, которая, по совпадению, центрирует конверт карты вокруг связанного класса объектов проекта (если он существует) и устанавливает желаемые экстенты просмотра. Если класс объектов для проекта еще не существует, он центрирует карту по всему региону, в котором содержатся все проекты, что дает общий обзор.

Итак, если это все имело смысл, и я не потерял тебя ...

Первоначально я вызывал подпункт CenterPoint в событии Form_Current. Это сработало, так как выполнило все необходимые функции; однако, пока выполнялась функция CenterPoint, форма не отвечала, не позволяя перейти к другой записи до завершения повторного рисования. Это означало, что если вы хотите прыгнуть через 10 записей, вам нужно будет прыгнуть 1, подождать перерисовки, перепрыгнуть другую, подождать перерисовки и т. Д. Я значительно ускорил перерисовку, оптимизировав изображения MXD и слоев, но это было все еще неприемлемо.

Затем я попытался установить задержку в несколько секунд, прежде чем он вызвал подпрограмму CenterPoint, выполнив следующее:

Private Sub Form_Current()
    Dim s_Start As single
    Dim s_Delay As single
    s_Start = Timer
    Do While Timer < s_Start + s_Delay
        DoEvents
    Loop

CenterPoint

End Sub

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

К сожалению, он, очевидно, кэширует все вызовы Form_Current, и, если я пропущу, скажем, 3 записи, дождусь окончания задержки и посмотрю на экран, он будет перерисовывать (т.е. запускать CenterPoint) 3 раза подряд.

Еще более странно, это время от времени дает мне ошибку деления на ноль для строки:

Do While Timer < s_Start + s_Delay

несмотря на отсутствие деления в строке.

Итак, я думаю, мои вопросы:

  1. Есть ли способ получить доступ только один раз запустить вызов form_current?
    • Если нет, есть ли способ убедиться, что пользователь оставался в текущей записи в течение определенного времени, прежде чем я вызову функцию CenterPoint?
  2. Есть ли способ изолировать мое сравнительное сравнение от деления на нулевую ошибку, поэтому, по крайней мере, даже если он будет перерисовываться несколько раз, пользователь может быстро просмотреть записи?

В настоящее время моя работа заключается в том, чтобы использовать сабвуфер CenterPoint в качестве события щелчка для кнопки в форме, что работает, но не идеально.

Если что-то из этого не имеет смысла или требуется дополнительная информация, пожалуйста, дайте мне знать.

Спасибо, Спенсер

Ответы [ 2 ]

1 голос
/ 06 февраля 2009

В ответ на ваши вопросы:
1) Form_ Current всегда будет запускаться всякий раз, когда вы переключаете записи. Нет выбора. Поэтому следующий лучший вариант - переместить вызов в CenterPoint на другое событие. Я бы использовал событие таймера формы и сбрасывал таймер каждый раз, когда вы проходите через Form_ Current, когда таймер заканчивается, он выключает CenterPoint.

Private Sub Form_Current()
    Me.TimerInterval = 10000
End Sub

Private Sub Form_Timer()
    CenterPoint
End Sub

2) Если вы используете событие таймера формы, вам, вероятно, больше не нужен этот код; Однако,

Private Sub Form_Current()
Dim l_Start As long 
Dim l_Delay As long 
Dim l_endTime As long 'or integers - time is returning the number of seconds 
                      'since midnight, not a real... this may be the source 
                      'of your problem

    l_Delay = 1000 ' I didn't see you set s_Delay any where
    l_Start = Timer
    l_endTime = l_Start + l_Delay 'lets do the calculation only once.

'This might break down if the user switch records just before midnight
'(never ending loop)
'    Do While Timer < l_endTime 
'        DoEvents
'    Loop

    'Instead I would do this
    Do While (Timer <= l_endTime) _
                and (l_start <= timer)
        DoEvents
    Loop

    CenterPoint

End Sub
0 голосов
/ 07 февраля 2009

Другой возможностью было бы сохранить вызов в событии OnCurrent, но использовать флаг времени вне OnCurrent, чтобы определить, следует ли вызывать подпрограмму.

  Static s_Start As Single
  Dim s_Delay As Single

  If s_Start = 0 Then
     s_Start = Timer
  End If
  If Timer > s_Start + s_Delay
     Call CenterPoint
     s_Start = 0
  End If

Так вот, это воздушный код, так что я могу допустить одну или две ошибки, но идея в том, что вы запускаете код только после истечения задержки. И как только он истечет, вы установите время начала обратно на 0, чтобы счетчик запустился снова.

В результате вызов CenterPoint будет происходить только в тех событиях OnCurrent, которые происходят после истечения вашей задержки.

...