Avoiding undesirable scroll

  • Thread starter Scott McPhillips [MVP]
  • Start date
S

Scott McPhillips [MVP]

I am programmatically inserting material in a Word 2007 document, sometimes
off-screen and earlier in the doc than where the user is working. If the
insertion is long it causes an annoying scroll where the user is working.
In searching for a way to prevent this I haven't found a way to figure out
how much it scrolled (so I could unscroll it), and I also haven't found a
way to detect when the user scrolls or uses page up/down (so I could
postpone the insertion until then). Any ideas for other approaches?

One vague possibility for measuring changes in the number of lines seems to
be the Rectangles collection (2007), which provides some information about
number of lines. But the precise nature of the Rectange(s) is not clear
from the help. Are they something that Word always creates?
 
M

macropod

Hi Scott,

Application.ScreenUpdating = False
' your code to manipulate the document goes here
Application.ScreenUpdating = True

usually works.

If you want to scroll to the same position in the document afterwards, bookmark the user's insertion point (or at least the first
word on the visible page, then scroll to that (and delete the bookmark afterwards). The only real problem I see with this is that,
if that locale is replaced via you code, there goes the bookmark and your means of scrolling to it.

Cheers
 
S

Scott McPhillips [MVP]

Thanks very much, I'll give it a try.

How do I find the first word on the visible page?

--
Scott McPhillips [VC++ MVP]

-------------------------------
macropod said:
Hi Scott,

Application.ScreenUpdating = False
' your code to manipulate the document goes here
Application.ScreenUpdating = True

usually works.

If you want to scroll to the same position in the document afterwards,
bookmark the user's insertion point (or at least the first word on the
visible page, then scroll to that (and delete the bookmark afterwards).
The only real problem I see with this is that, if that locale is replaced
via you code, there goes the bookmark and your means of scrolling to it.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
I am programmatically inserting material in a Word 2007 document,
sometimes off-screen and earlier in the doc than where the user is
working. If the insertion is long it causes an annoying scroll where the
user is working. In searching for a way to prevent this I haven't found a
way to figure out how much it scrolled (so I could unscroll it), and I
also haven't found a way to detect when the user scrolls or uses page
up/down (so I could postpone the insertion until then). Any ideas for
other approaches?

One vague possibility for measuring changes in the number of lines seems
to be the Rectangles collection (2007), which provides some information
about number of lines. But the precise nature of the Rectange(s) is not
clear from the help. Are they something that Word always creates?
 
M

macropod

Hi Scott,

Here's how you can find the first word on the page, bookmark it, then scroll to and clear the bookmark when you're finished with it:

Option Explicit
Dim BkMkNm As String

Sub SetScrollPoint()
Dim MyRange As Range
BkMkNm = "BkMrk"
With ActiveDocument
Set MyRange = Selection.Range
Set MyRange = MyRange.GoTo(What:=wdGoToBookmark, Name:="\page")
MyRange.Collapse (wdCollapseStart)
'MyRange.Expand Unit:=wdWord
.Bookmarks.Add BkMkNm, MyRange
End With
End Sub

Sub ClearScrollPoint()
With Selection
.GoTo What:=wdGoToBookmark, Name:=BkMkNm
.Bookmarks.Item(BkMkNm).Delete
'.Collapse (wdCollapseStart)
End With
End Sub

The two lines I've commented out attach the bookmark to the first word, then collapse the range after the bookmark is deleted. You
can probably get away without those two lines. If you can be confident that the user's current selection won't be deleted during the
update, you could reduce the first sub to one that just bookmarks that selection.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
Thanks very much, I'll give it a try.

How do I find the first word on the visible page?

--
Scott McPhillips [VC++ MVP]

-------------------------------
macropod said:
Hi Scott,

Application.ScreenUpdating = False
' your code to manipulate the document goes here
Application.ScreenUpdating = True

usually works.

If you want to scroll to the same position in the document afterwards, bookmark the user's insertion point (or at least the first
word on the visible page, then scroll to that (and delete the bookmark afterwards). The only real problem I see with this is
that, if that locale is replaced via you code, there goes the bookmark and your means of scrolling to it.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
I am programmatically inserting material in a Word 2007 document, sometimes off-screen and earlier in the doc than where the user
is working. If the insertion is long it causes an annoying scroll where the user is working. In searching for a way to prevent
this I haven't found a way to figure out how much it scrolled (so I could unscroll it), and I also haven't found a way to detect
when the user scrolls or uses page up/down (so I could postpone the insertion until then). Any ideas for other approaches?

One vague possibility for measuring changes in the number of lines seems to be the Rectangles collection (2007), which provides
some information about number of lines. But the precise nature of the Rectange(s) is not clear from the help. Are they
something that Word always creates?
 
S

Scott McPhillips [MVP]

That is an eye-opening technique. Thank you.

But... I think I would need to find and bookmark the word at the top of the
screen, not top of page. (So I can scroll the screen back to that same
point after the disturbance.)

--
Scott McPhillips [VC++ MVP]

-----------------------------------
macropod said:
Hi Scott,

Here's how you can find the first word on the page, bookmark it, then
scroll to and clear the bookmark when you're finished with it:

Option Explicit
Dim BkMkNm As String

Sub SetScrollPoint()
Dim MyRange As Range
BkMkNm = "BkMrk"
With ActiveDocument
Set MyRange = Selection.Range
Set MyRange = MyRange.GoTo(What:=wdGoToBookmark, Name:="\page")
MyRange.Collapse (wdCollapseStart)
'MyRange.Expand Unit:=wdWord
.Bookmarks.Add BkMkNm, MyRange
End With
End Sub

Sub ClearScrollPoint()
With Selection
.GoTo What:=wdGoToBookmark, Name:=BkMkNm
.Bookmarks.Item(BkMkNm).Delete
'.Collapse (wdCollapseStart)
End With
End Sub

The two lines I've commented out attach the bookmark to the first word,
then collapse the range after the bookmark is deleted. You can probably
get away without those two lines. If you can be confident that the user's
current selection won't be deleted during the update, you could reduce the
first sub to one that just bookmarks that selection.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
Thanks very much, I'll give it a try.

How do I find the first word on the visible page?

--
Scott McPhillips [VC++ MVP]

-------------------------------
macropod said:
Hi Scott,

Application.ScreenUpdating = False
' your code to manipulate the document goes here
Application.ScreenUpdating = True

usually works.

If you want to scroll to the same position in the document afterwards,
bookmark the user's insertion point (or at least the first word on the
visible page, then scroll to that (and delete the bookmark afterwards).
The only real problem I see with this is that, if that locale is
replaced via you code, there goes the bookmark and your means of
scrolling to it.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

"Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message
I am programmatically inserting material in a Word 2007 document,
sometimes off-screen and earlier in the doc than where the user is
working. If the insertion is long it causes an annoying scroll where
the user is working. In searching for a way to prevent this I haven't
found a way to figure out how much it scrolled (so I could unscroll it),
and I also haven't found a way to detect when the user scrolls or uses
page up/down (so I could postpone the insertion until then). Any ideas
for other approaches?

One vague possibility for measuring changes in the number of lines
seems to be the Rectangles collection (2007), which provides some
information about number of lines. But the precise nature of the
Rectange(s) is not clear from the help. Are they something that Word
always creates?
 
M

macropod

Hi Scott,

I don't know how one can bookmark something at the top of the active pane.

Do note, though, that the code I posted doesn't necessarily take you back to the top of the page; but to wherever on the page the
bookmark now appears. As mentioned, you could bookmark the current selection/insertion point and provided it doesn't get deleted,
you'll scroll back to there. Doing that is as simple as deleting the line "Set MyRange = MyRange.GoTo(What:=wdGoToBookmark,
Name:="\page")". Perhaps that'll do?

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
That is an eye-opening technique. Thank you.

But... I think I would need to find and bookmark the word at the top of the screen, not top of page. (So I can scroll the screen
back to that same point after the disturbance.)

--
Scott McPhillips [VC++ MVP]

-----------------------------------
macropod said:
Hi Scott,

Here's how you can find the first word on the page, bookmark it, then scroll to and clear the bookmark when you're finished with
it:

Option Explicit
Dim BkMkNm As String

Sub SetScrollPoint()
Dim MyRange As Range
BkMkNm = "BkMrk"
With ActiveDocument
Set MyRange = Selection.Range
Set MyRange = MyRange.GoTo(What:=wdGoToBookmark, Name:="\page")
MyRange.Collapse (wdCollapseStart)
'MyRange.Expand Unit:=wdWord
.Bookmarks.Add BkMkNm, MyRange
End With
End Sub

Sub ClearScrollPoint()
With Selection
.GoTo What:=wdGoToBookmark, Name:=BkMkNm
.Bookmarks.Item(BkMkNm).Delete
'.Collapse (wdCollapseStart)
End With
End Sub

The two lines I've commented out attach the bookmark to the first word, then collapse the range after the bookmark is deleted.
You can probably get away without those two lines. If you can be confident that the user's current selection won't be deleted
during the update, you could reduce the first sub to one that just bookmarks that selection.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Scott McPhillips said:
Thanks very much, I'll give it a try.

How do I find the first word on the visible page?

--
Scott McPhillips [VC++ MVP]

-------------------------------
Hi Scott,

Application.ScreenUpdating = False
' your code to manipulate the document goes here
Application.ScreenUpdating = True

usually works.

If you want to scroll to the same position in the document afterwards, bookmark the user's insertion point (or at least the
first word on the visible page, then scroll to that (and delete the bookmark afterwards). The only real problem I see with this
is that, if that locale is replaced via you code, there goes the bookmark and your means of scrolling to it.

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

"Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message I am programmatically inserting material in a Word 2007 document, sometimes off-screen and earlier in the doc than where the
user is working. If the insertion is long it causes an annoying scroll where the user is working. In searching for a way to
prevent this I haven't found a way to figure out how much it scrolled (so I could unscroll it), and I also haven't found a way
to detect when the user scrolls or uses page up/down (so I could postpone the insertion until then). Any ideas for other
approaches?

One vague possibility for measuring changes in the number of lines seems to be the Rectangles collection (2007), which
provides some information about number of lines. But the precise nature of the Rectange(s) is not clear from the help. Are
they something that Word always creates?
 
K

Klaus Linke

Hi Scott,

Maybe you could use GetPoint to remember the old top coordinate of the selection, and later scroll back to it.

Not too elegant, but it should get you back to within a line.

Regards,
Klaus

Dim pLeft As Long
Dim pTop As Long
Dim pTopOld As Long
Dim pWidth As Long
Dim pHeight As Long
Dim rngOld As Range

ActiveWindow.GetPoint pLeft, pTopOld, pWidth, pHeight, _
Selection.Range

Set rngOld = Selection.Range.Duplicate

' Do your insertions here...
Selection.HomeKey Unit:=wdStory

' Go back:
rngOld.Select
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
ActiveWindow.ScrollIntoView obj:=Selection.Range
While pTop > pTopOld
ActiveWindow.SmallScroll Down:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
While pTop < pTopOld
ActiveWindow.SmallScroll Up:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
 
S

Scott McPhillips [MVP]

Thank you Klaus. It's an interesting idea and I will give it a try.

-----------------------------------
Hi Scott,

Maybe you could use GetPoint to remember the old top coordinate of the
selection, and later scroll back to it.

Not too elegant, but it should get you back to within a line.

Regards,
Klaus

Dim pLeft As Long
Dim pTop As Long
Dim pTopOld As Long
Dim pWidth As Long
Dim pHeight As Long
Dim rngOld As Range

ActiveWindow.GetPoint pLeft, pTopOld, pWidth, pHeight, _
Selection.Range

Set rngOld = Selection.Range.Duplicate

' Do your insertions here...
Selection.HomeKey Unit:=wdStory

' Go back:
rngOld.Select
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
ActiveWindow.ScrollIntoView obj:=Selection.Range
While pTop > pTopOld
ActiveWindow.SmallScroll Down:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
While pTop < pTopOld
ActiveWindow.SmallScroll Up:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
 
J

Julian

Or you could try something like this... as long as you assign aRange to the
beginning of the (then) current selection

ActiveWindow.ScrollIntoView obj:=aRange, start:=True

However, if I recall correctly, it probably won't change the scroll position
if the range is already in view... if that is true then you can always
deliberately scroll it *out* and then ScrollIntoView...

In Word 2002 I am using this to leap around large tables... it places the
selected row about 25% down in the active window.

HTH

--
Julian I-Do-Stuff

Some Vista stuff, but mostly just Stuff at http://berossus,blogspot.com
Hi Scott,

Maybe you could use GetPoint to remember the old top coordinate of the
selection, and later scroll back to it.

Not too elegant, but it should get you back to within a line.

Regards,
Klaus

Dim pLeft As Long
Dim pTop As Long
Dim pTopOld As Long
Dim pWidth As Long
Dim pHeight As Long
Dim rngOld As Range

ActiveWindow.GetPoint pLeft, pTopOld, pWidth, pHeight, _
Selection.Range

Set rngOld = Selection.Range.Duplicate

' Do your insertions here...
Selection.HomeKey Unit:=wdStory

' Go back:
rngOld.Select
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
ActiveWindow.ScrollIntoView obj:=Selection.Range
While pTop > pTopOld
ActiveWindow.SmallScroll Down:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
While pTop < pTopOld
ActiveWindow.SmallScroll Up:=1
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
Wend
 
S

Scott McPhillips [MVP]

Thanks Julian, and thanks to Klaus too.

I got something working based on the technique shown by Klaus. With
ScreenRefresh added before and after to hide the action. It restores the
original caret location on-screen within less than one line. And sometimes,
it hits exactly the right pixel location. It is pretty wild to watch!
 
K

Klaus Linke

Scott McPhillips said:
Thanks Julian, and thanks to Klaus too.

I got something working based on the technique shown by Klaus. With
ScreenRefresh added before and after to hide the action. It restores the
original caret location on-screen within less than one line. And sometimes,
it hits exactly the right pixel location. It is pretty wild to watch!


Good to hear!

Regards,
Klaus
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top