ArcGIS MapControl和Ms Access延迟图重绘?

时间:2009-02-06 00:04:48

标签: ms-access vba mapping gis arcgis

这适用于将ESRI MapControl嵌入Access数据库表单。

我有两个访问文件,分为前端和后端。我的后端也是一个PersonalGeoDatabase,ArcGIS用它来存储要在From嵌入式ESRI地图控件上显示的要素类。

要素类存储与特定ProjectID关联的折线,点和多边形。

从前端开始,我有嵌入式mapControl,它会加载绑定到后端的MXD文件。

我有一个名为CenterPoint的VB函数,巧合的是,它将地图包络围绕Project的相关要素类(如果存在)居中,并设置所需的查看范围。如果项目的要素类尚不存在,则会将地图集中在包含所有项目的整个区域中,并给出概述。

所以,如果这一切都有意义,我没有失去你......

我最初在Form_Current事件中调用了CenterPoint子。这是有效的,因为它执行了所需的所有功能;但是,当CenterPoint函数运行时,表单没有响应,阻止更改到另一个记录,直到重新绘制完成。这意味着,如果你希望跳过10个记录,你必须跳1,等待重新绘制,跳转另一个,等待重新绘制等。我通过优化MXD图像来大幅加速重绘层,但它仍然是不可接受的。

接下来,我尝试建立一个几秒的延迟,然后通过运行以下命令调用CenterPoint sub:

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条记录,等待延迟结束,并观看屏幕,它将连续3次重新绘制(即运行CenterPoint)。 / p>

更奇怪的是,它偶尔会给我一个除以零误差的除法:

Do While Timer < s_Start + s_Delay

尽管没有划分界限。

所以,我想我的问题是:

  1. 有没有办法让访问权限只运行一次form_current调用?
    • 如果没有,有没有办法在我调用CenterPoint函数之前确保用户在给定时间内保持当前记录?
  2. 有没有办法将我的小于比较与除以零错误的比较隔离,所以至少,即使它会重新绘制多次,用户也可以快速连续点击记录?

现在,我的工作是将CenterPoint子项作为表单上按钮的单击事件,这可以工作,但并不理想。

如果其中任何一项没有意义,或者需要更多信息,请告诉我。

谢谢, 斯潘塞

2 个答案:

答案 0 :(得分:1)

回答你的问题:
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

答案 1 :(得分:0)

另一种可能性是将调用保持在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事件上。