Option Explicit

' WINDOWS.H constants and declarations
'
Global Const HWND_TOPMOST = -1
Global Const HWND_NOTOPMOST = -2
Global Const SWP_NOACTIVATE = &H10
Global Const SWP_SHOWWINDOW = &H40
Global Const SWP_NOSIZE = &H1
Global Const SWP_NOMOVE = &H2

Declare Sub SetWindowPos Lib "User" (ByVal hWnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer)

' VISIO constants and declarations
'
Global Const S_OBJPRP = 1   ' General properties for object
Global Const R_PAGGEN = 10  ' Page general properties
Global Const C_PGDSZ = 6    ' Drawing size type
Global Const C_PGDST = 7    ' Drawing scale type

' Application title
'
Global Const APP_TITLE = "VISIO Stencil Report Wizard"

' String constants
'
Global Const STR_BACKGROUND = "Background"  ' name of background page

' Error codes and strings
'
Global Const ERR_WARNING = 0
Global Const ERR_FATAL = 1
Global Const ERR_PROMPT = 2

Global Const ERR_NOVISIO = "Cannot get Visio object."
Global Const ERR_NOSTENCILS = "Please open one or more stencils before running this add-on."
Global Const ERR_NOMASTERS = "No masters on stencil."
Global Const ERR_INPLACE = "STNDOC unable to run with in-place instance of Visio."
' Limits
'
Global Const MAX_ROWS = 6
Global Const MAX_COLS = 6

Type RECT
    Left As Double
    Top As Double
    Bottom As Double
    Right As Double
End Type

Type PAGEMETRICS
    DrawingScale As Double      ' drawing scale
    PageScale As Double         ' page scale
    PageHeight As Double        ' page height
    PageWidth As Double         ' page width

    Header As Double            ' header height
    Footer As Double            ' footer height
    LeftMargin As Double        ' page margins
    RightMargin As Double
    TopMargin As Double
    BottomMargin As Double
    TextMargin As Double        ' text margins
    LabelWidth As Double        ' label for shape properties
    LabelHeight As Double
    GridMargin As Double        ' grid margins
End Type

Type GRIDMETRICS
    masters As Integer          ' masters per page
    rows As Integer
    cols As Integer
    RowHeight As Double
    ColWidth As Double
End Type

Type DOCMETRICS
    Filename As String          ' name of stencil
    masters As Integer          ' total number of masters
    PageCount As Integer        ' total number of pages

    ' Options
    '
    Header As Integer           ' show header
    Footer As Integer           ' show footer
    gridlines As Integer        ' show gridlines
    properties As Integer       ' show properties
    resize As Integer           ' resize masters to fit grid
End Type

Global gDoc As DOCMETRICS
Global gPage As PAGEMETRICS
Global gGrid As GRIDMETRICS
Global gGridArray(0 To MAX_ROWS, 0 To MAX_COLS) As RECT

Global gDocDraw As Object      ' drawing document
Global gWinDraw As Object      ' drawing window
Global gPageBack As Object     ' background page

' Make sure there is a running instance of Visio
'
Sub appConnect ()
    Dim stat

    If vaoGetObject() <> visOK Then
	stat = appMessage(ERR_FATAL, ERR_NOVISIO)
    End If

End Sub

' Application initialization
'
Sub appInit ()
    
    ' Initialize document metrics
    docInit

End Sub

Function appMessage (code, message)
    Dim status
    Dim style

    ' Pick icon
    '
    If code = ERR_PROMPT Then
	style = 36  ' Question mark & Yes/No
    Else
	style = 48  ' Exclamation mark & OK
    End If

    Beep
    status = MsgBox(message, style, APP_TITLE)
    If code = ERR_FATAL Then
	End     ' Terminate program
    End If
    appMessage = status
End Function

Sub CheckIfInPlace ()

    If g_appVisio.version < 3 Then
	Exit Sub
    Else
	If g_appVisio.documents.count Then
	    If g_appVisio.documents(1).inplace Then
		MsgBox ERR_INPLACE, 48
		End
	    End If
	End If
    End If

End Sub

Sub docInit ()

    gDoc.Header = True
    gDoc.Footer = True
    gDoc.gridlines = True
    gDoc.properties = True
    gDoc.resize = True

End Sub

Sub formInit (f As Form)
    
    ' Set caption
    '
    f.Caption = APP_TITLE

    ' Center the form
    '
    f.Top = (screen.Height - f.Height) / 2
    f.Left = (screen.Width - f.Width) / 2

    ' Set the form to always be on top
    '
    SetWindowPos f.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOSIZE Or SWP_NOMOVE
End Sub

' Compute grid metrics.
'
Sub gridCompute (ByVal rows, ByVal cols)
    Dim row
    Dim col
    Dim tmp

    '   This routine depends on page metrics.
    '
    pageCompute gPageBack

    gGrid.masters = rows * cols

    '   Switch rows and cols if necessary for best fit on page.
    '
    If (pageIsPortrait(gPageBack) And rows < cols) Or (pageIsLandscape(gPageBack) And cols < rows) Then
	tmp = rows
	rows = cols
	cols = tmp
    End If

    gGrid.rows = rows
    gGrid.cols = cols
    gGrid.ColWidth = (gPage.PageWidth - gPage.LeftMargin - gPage.RightMargin) / gGrid.cols
    gGrid.RowHeight = (gPage.PageHeight - gPage.TopMargin - gPage.BottomMargin - gPage.Header - gPage.Footer) / gGrid.rows

    For row = 0 To gGrid.rows - 1
	For col = 0 To gGrid.cols - 1
	    gGridArray(row, col).Left = gPage.LeftMargin + col * gGrid.ColWidth
	    gGridArray(row, col).Right = gGridArray(row, col).Left + gGrid.ColWidth
	    gGridArray(row, col).Bottom = gPage.BottomMargin + gPage.Footer + row * gGrid.RowHeight
	    gGridArray(row, col).Top = gGridArray(row, col).Bottom + gGrid.RowHeight
	Next
    Next
End Sub

' Compute page metrics
'
Sub pageCompute (page As Object)
    Dim pageSheet As Object         ' page sheet

    ' Page properties
    '
    Set pageSheet = page.Shapes("ThePage")
    gPage.DrawingScale = pageSheet.Cells("DrawingScale")
    gPage.PageScale = pageSheet.Cells("PageScale")
    gPage.PageHeight = pageSheet.Cells("PageHeight")
    gPage.PageWidth = pageSheet.Cells("PageWidth")

    ' Computed values
    '
    gPage.Header = PU2DU(.75)
    gPage.Footer = PU2DU(.25)
    gPage.LeftMargin = PU2DU(.5)
    gPage.RightMargin = PU2DU(.5)
    gPage.TopMargin = PU2DU(.5)
    gPage.BottomMargin = PU2DU(.5)
    gPage.TextMargin = .125
    gPage.LabelWidth = PU2DU(.625)
    gPage.LabelHeight = PU2DU(.75)
    gPage.GridMargin = PU2DU(.25)

End Sub

Function pageIsLandscape (page As Object)
    Dim pageSheet As Object

    Set pageSheet = page.Shapes("ThePage")
    If pageSheet.Cells("PageHeight") < pageSheet.Cells("PageWidth") Then
	pageIsLandscape = True
    Else
	pageIsLandscape = False
    End If
End Function

Function pageIsPortrait (page As Object)
    Dim pageSheet As Object

    Set pageSheet = page.Shapes("ThePage")
    If pageSheet.Cells("PageHeight") >= pageSheet.Cells("PageWidth") Then
	pageIsPortrait = True
    Else
	pageIsPortrait = False
    End If
End Function

'   Change the orientation of the page.
'
Sub pageOrientSwitch (page As Object)
    Dim pageSheet As Object     ' page sheet
    Dim tmp

    Set pageSheet = page.Shapes("ThePage")
    tmp = pageSheet.Cells("PageHeight").formula
    pageSheet.Cells("PageHeight").formula = pageSheet.Cells("PageWidth").formula
    pageSheet.Cells("PageWidth").formula = tmp
End Sub

'   Convert page units to drawing units
'
Function PU2DU (pu) As Double
    PU2DU = pu * gPage.DrawingScale / gPage.PageScale
End Function

Sub shapeBold (shape As Object)
    Dim style

    style = Val(shape.CellsSRC(visSectionCharacter, visRowCharacter, visCharacterStyle))
    style = style Or visBold
    shape.CellsSRC(visSectionCharacter, visRowCharacter, visCharacterStyle).formula = style
End Sub

