There are several good topics in the forum on how to show a specific Visio shape centered in a Visio windows.
The simple tip was just to use Window.CenterViewOnShape but it doesn't work well for me and is unpredictable. I just cannot count on it to just show the specific shape at the center of the window.
Visio Guy and Thomas shared code here I'm going to try it for my purpose: http://visguy.com/vgforum/index.php?topic=6144.0
Then convert it to vb.net for a .NET VSTO add-in. The working vb.net code I'll share here as there is only VBA code available to solve this currently.
Thomas Winkel's code doesnt' work for me, but Visio Guy's code works fine!
Still in VBA here, made a small change to the calling code (I'd rather select a shape, then test the VBA sub).
I need to change the code slightly because I do not want to zoom in just put the shape in the center of the window (leave the zoom level unchanged), but again this is some good code by Visio Guy!
Sub CenterOnSelected()
Dim Sel As Selection
Dim S As Shape
Set S = ActiveWindow.Selection(1)
Call CenterShapeInView(S)
End Sub
Public Sub CenterShapeInView(ByRef visShp As Visio.Shape)
'// Notes:
'// 'w' stands for 'width' and 'window'
'// 'h' stands for 'height',
'// 'l', 't', 'r', 'b' stand for 'left', 'top', 'right', 'bottom'
Dim win As Visio.Window
Set win = visShp.Application.ActiveWindow
If (win.Type = Visio.VisWinTypes.visDrawing) Then
'// Switch the page in the active window so
'// that it is the page that visShp is on:
win.Page = visShp.ContainingPage
'// Select the shape:
Call win.DeselectAll
Call win.Select(visShp, Visio.VisSelectArgs.visSelect)
'// Zoom and pan:
'// Get the dimensions of the active window. These
'// are PAGE coordinates for what is displayed in the
'// window:
Dim wl As Double, wt As Double, ww As Double, wh As Double
Call win.GetViewRect(wl, wt, ww, wh)
'// Get the size and position of the shape:
Dim flags As Integer
flags = Visio.VisBoundingBoxArgs.visBBoxUprightWH
'// Get the left, bottom, right, top of the shape, and
'// calculate the center point:
Dim sl As Double, sb As Double, sr As Double, st As Double
Dim sx As Double, sy As Double
Call visShp.BoundingBox(flags, sl, sb, sr, st)
sx = (sl + sr) * 0.5
sy = (st + sb) * 0.5
'// Calculate the width and height:
Dim sw As Double, sh As Double
sw = Math.Abs(sr - sl)
sh = Math.Abs(st - sb)
'// Add some padding around the shape, because win.SetViewRect
'// doesn't seem to be exact when we try to zoom. Let's take
'// a percentage of the shape's size:
Const PaddingPct# = 0.05 '//...5% padding
Dim padding As Double
If (sw > sh) Then
padding = PaddingPct * sw
Else
padding = PaddingPct * sh
End If
'// Recalculate the shape dimensions with the added padding:
sl = sl - padding
sr = sr + padding
st = st + padding
sb = sb - padding
sw = sr - sl
sh = st - sb
'// Calculate aspect rations of window and shape.
'// Greater-than-one means 'more wide than tall':
Dim arw As Double, ars As Double
arw = ww / wh
ars = sw / sh
'// We will maximize the view of the shape in the
'// window. This means that either the sides of the shape
'// or the shape's top and bottom will be against the
'// edges of the window. We have to figure this out using
'// geometry.
'// We'll set up some new dimensions for the window's view:
Dim wlNew As Double, wtNew As Double, wrNew As Double, wbNew As Double
Dim wwNew As Double, whNew As Double
If (ars > arw) Then
'// The shape is more 'wider' than the window.
'// The window's left and right should match that
'// of the shape:
wlNew = sl
wrNew = sr
wwNew = wrNew - wlNew '//...the new view width
'// Thew window's top and bottom SHOULD be calculated,
'// but since the size of the window won't really change,
'// we COULD enter nonsense values. But we'll try and
'// calculate anyway:
whNew = wwNew / arw '//...width/(width/height) => height
wtNew = sy + wwNew * 0.5
wbNew = sy - wwNew * 0.5
Else
'// The window is more 'wider' than the shape.
'// The window's top and bottom should match that
'// of the shape:
wtNew = st
wbNew = sb
whNew = wtNew - wbNew '//...the new view height
'// Thew window's left and right must be calculated:
wwNew = arw * whNew '//...(width/height)*height => width
wlNew = sx - wwNew * 0.5
wrNew = sx + wwNew * 0.5
End If
'// Set the new window view:
Call win.SetViewRect(wlNew, wtNew, wwNew, whNew)
Else
'// Make the active window a ShapeSheet window to
'// make this happen:
Call MsgBox("Active window is not a drawing window, I'm not sure what to do!")
End If
End Sub
Actually I see Visio Guy's code is really about zooming in on a specific shape, so changing this code to leave the zoom level unchanged is a bit more than a slight change.
Maybe there is some VBA code that just does exactly what I need, which is to put one shape that is selected in the center of the window, keeping the zoom level exactly the same as it was.
Have you tried shape.centerDrawing?
Thank you Wapperdude I understand shape.centerDrawing will cause a shape to move, but the shapes should stay in the exact same position only the Visio window should move to center around the selected shape.