Word 2007
Word 2003
Introduction
As you know, there's a really nice feature in Visual Studio called Navidate forward/backward. I started to look for this feature inside Microsoft Word (2003 and later) that works exactly like the one in Visual Studio. After some Googling, I found that Word has a functionality that should solve the problem but has a bug since Word 2000. This functionality is SHIFT+F5.
Using the Code
The most important thing in this project is to keep in some kind of data strucure all navigation locations that we made inside the documents (cursor's moves). For that I've used a simple (but very useful) data structure called "Stack." The stack is a LIFO (Last In First Out) structure and it's perfect for our job. Everytime we "navigate" inside the document we add (or Push) that location to the stack.
You may wonder what this location is that I am talking about... It's nothing more than a Range element and if you'll look inside MSDN for the definition of this class, a Range is "a contiguous area in a document"(for example, Paragraph, Bookmark, Cell or Picture). This interface is in the Microsoft.Office.Interop.Word
namespace.
[Guid("0002095E-0000-0000-C000-000000000046")]
[TypeLibType(4288)]
public interface Range
{
...
}
Managing Events
So, how do we catch these navigation events? The ApplicationClass
has a WindowSelectionChange
event that is triggered every time the selection of an object has changed. So, we're going to implement that event.
In the ThisAddIn_Startup
method, we create the navigation buttons and register our handler for the WindowSelectionChange
event.
ApplicationClass __MyApplication;
Office.CommandBar commandBar;
Office.CommandBarButton __BackwardButton;
Office.CommandBarButton __ForwardButton;
string __NavigateBackwardTag = "Navigate backward";
string __NavigateForwardTag = "Navigate foreward";
Stack<Range> __MyBackwardStack = new Stack<Range>();
Stack<Range> __MyForwardStack = new Stack<Range>();
bool __FromBack, __FromFore;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.BackNavigationToolbar();
this.ForwardNavigationToolbar();
this.__MyApplication = this.Application as ApplicationClass;
__MyApplication.ApplicationEvents3_Event_WindowSelectionChange +=
new ApplicationEvents3_WindowSelectionChangeEventHandler(
__MyApplication_ApplicationEvents3_Event_WindowSelectionChange);
}
void __MyApplication_ApplicationEvents3_Event_WindowSelectionChange(Selection Sel)
{
if (__FromBack == false && __FromFore == false)
__MyBackwardStack.Push(Sel.Range);
else
{
if (__FromBack == true)
__FromBack = false;
if (__FromFore == true)
__FromFore = false;
}
}
As you can see I start by declaring some variables for later use. After that we add the navigation buttons to the Standard toolbar.
private void BackNavigationToolbar()
{
try
{
commandBar = this.Application.CommandBars["Standard"];
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
try
{
__BackwardButton = commandBar.FindControl(1, missing,
__NavigateBackwardTag, missing, true) as Office.CommandBarButton;
if (__BackwardButton == null)
{
__BackwardButton =
(Office.CommandBarButton)commandBar.Controls.Add(1,
missing, missing, missing, true);
}
__BackwardButton.Style = Office.MsoButtonStyle.msoButtonIconAndCaption;
__BackwardButton.Caption = "Navigate backward";
__BackwardButton.Tag = __NavigateBackwardTag;
__BackwardButton.Picture = PictureDispConverter.ToIPictureDisp(
Resources.back);
__BackwardButton.Click += delegate(CommandBarButton Ctrl,
ref bool CancelDefault)
{
try
{
if (__MyBackwardStack.Count > 0)
{
Range rng = this.__MyBackwardStack.Pop();
this.__MyForwardStack.Push(rng);
__FromBack = true;
this.__MyApplication.Selection.SetRange(
rng.Start, rng.End);
rng.Select();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
};
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
and after that I handle the WindowSelectionChange
event.
So, each time we navigate inside the document, we add the Range
object into the stack. But what happens when we click on the navigation buttons? When we click on "Navigate backward" button, we call the Pop()
method, Push(...)
the Range
to the other stack(for Navigation Forward) and then set the Selection.Range
. After that we call Select()
the Range
.
The same thing happens when we click on the "Navigate foreward" button.
Because the Select()
method triggers the WindowSelectionChange
event, we don't want to add the same Range
to the stack. That's why I used the __FromBack
and __FromFore
fields.
History
version 0.1.