By Adam Nagy
In case of built-in commands like the Extrude command when the user presses the Enter key it has the same effect as if the Apply button was clicked - the changes will be applied and the mini toolbar gets dismissed.
However, when using the MiniToolbar class of the API the Enter key does not dismiss the mini toolbar and there does not seem to be a way to catch the Enter key being pressed either, so that we could dismiss it ourselves. This seems to be an oversight which will be solved in the future, I hope.
In the meantime you can use a keyboard hook to watch out for the Enter key. You could use solutions like this: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
I used the MiniToolbar sample from the API Help file and then added the keyboard hook to it:
Imports Inventor
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class InterceptKeys
Private Const WH_KEYBOARD_LL As Integer = 13
Private Const WM_KEYDOWN As Integer = &H100
Private Shared _proc As LowLevelKeyboardProc =
New LowLevelKeyboardProc(AddressOf HookCallback)
Private Shared _hookID As IntPtr = IntPtr.Zero
Private Shared _mini As MyMiniToolbar
Public Shared Sub SetHook(mini As MyMiniToolbar)
_mini = mini
_hookID = SetHook(_proc)
End Sub
Public Shared Sub UnhookWindowsHookEx()
UnhookWindowsHookEx(_hookID)
End Sub
Private Shared Function SetHook(
proc As LowLevelKeyboardProc) As IntPtr
Using curProcess As Process = Process.GetCurrentProcess()
Using curModule As ProcessModule = curProcess.MainModule
Return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0)
End Using
End Using
End Function
Private Delegate Function LowLevelKeyboardProc(
nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Private Shared Function HookCallback(
nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
If nCode >= 0 AndAlso wParam = New IntPtr(WM_KEYDOWN) Then
Dim vkCode As Integer = Marshal.ReadInt32(lParam)
Dim key As Keys = DirectCast(vkCode, Keys)
System.Diagnostics.Debug.WriteLine(key)
If key = Keys.Enter Then
_mini.m_MiniToolbar_OnOK()
End If
End If
Return CallNextHookEx(_hookID, nCode, wParam, lParam)
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function SetWindowsHookEx(
idHook As Integer, lpfn As LowLevelKeyboardProc,
hMod As IntPtr, dwThreadId As UInteger) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function UnhookWindowsHookEx(hhk As IntPtr) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function CallNextHookEx(
hhk As IntPtr, nCode As Integer, wParam As IntPtr, lParam As IntPtr) _
As IntPtr
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function GetModuleHandle(lpModuleName As String) As IntPtr
End Function
End Class
Public Class MyMiniToolbar
'*************************************************************
' The declarations and functions below need to be copied into
' a class module whose name is "clsMiniToolbarEvents". The name can be
' changed but you'll need to change the declaration in the
' calling function "CreateSketchSlotSample" to use the new name.
Private WithEvents m_EndCenterOneX As MiniToolbarValueEditor
Private WithEvents m_EndCenterOneY As MiniToolbarValueEditor
Private WithEvents m_EndCenterTwoX As MiniToolbarValueEditor
Private WithEvents m_EndCenterTwoY As MiniToolbarValueEditor
Private WithEvents m_Width As MiniToolbarValueEditor
Private WithEvents m_MiniToolbar As MiniToolbar
Private m_DisplayCenterline As MiniToolbarCheckBox
Private m_Sketch As Sketch
Private bCenterline As Boolean
Private bStop As Boolean
Private ThisApplication As Inventor.Application
Public Sub Init(app As Inventor.Application)
ThisApplication = app
Dim oActiveEnv As Environment =
ThisApplication.UserInterfaceManager.ActiveEnvironment
If oActiveEnv.InternalName <> "PMxPartSketchEnvironment" And
oActiveEnv.InternalName <> "AMxAssemblySketchEnvironment" And
oActiveEnv.InternalName <> "DLxDrawingSketchEnvironment" Then
MsgBox("Please activate a sketch environment first!")
Exit Sub
End If
m_MiniToolbar = ThisApplication.CommandManager.CreateMiniToolbar
m_MiniToolbar.ShowOK = True
m_MiniToolbar.ShowApply = True
m_MiniToolbar.ShowCancel = True
Dim oControls As MiniToolbarControls
oControls = m_MiniToolbar.Controls
oControls.Item("MTB_Options").Visible = False
Dim oDescriptionLabel As MiniToolbarControl
oDescriptionLabel = oControls.AddLabel(
"Description",
"This toolbar is to create sketch slot:",
"MiniToolbar sample to show how to create sketch slot.")
oControls.AddNewLine()
' Define the first center position.
Dim oEndCenterOne As MiniToolbarButton
oEndCenterOne = oControls.AddButton(
"FirstCenter: ",
"First Center: ",
"Specify the first center of sketch slot")
m_EndCenterOneX = oControls.AddValueEditor(
"FirstCenterX", "", ValueUnitsTypeEnum.kLengthUnits, "", "X:")
m_EndCenterOneX.Expression = "0"
m_EndCenterOneX.SetFocus()
m_EndCenterOneY = oControls.AddValueEditor(
"FirstCenterY", "", ValueUnitsTypeEnum.kLengthUnits, "", "Y:")
m_EndCenterOneY.Expression = "0"
oControls.AddNewLine()
' Define the second center position.
Dim oEndCenterTwo As MiniToolbarButton
oEndCenterTwo = oControls.AddButton(
"SecondCenter:", "Second Center:",
"Specify the second center of sketch slot")
m_EndCenterTwoX = oControls.AddValueEditor(
"SecondCenterX", "", ValueUnitsTypeEnum.kLengthUnits, "", "X:")
m_EndCenterTwoX.Expression = "3"
m_EndCenterTwoY = oControls.AddValueEditor(
"SecondCenterY", "", ValueUnitsTypeEnum.kLengthUnits, "", "Y:")
m_EndCenterTwoY.Expression = "0"
oControls.AddNewLine()
' Define the width of sketch slot.
m_Width = oControls.AddValueEditor(
"WidthValue", "", ValueUnitsTypeEnum.kLengthUnits, "", "Width:")
m_Width.Expression = "1"
' Define if display the center line of sketch slot.
m_DisplayCenterline = oControls.AddCheckBox(
"DisplayCenterline", "Display center line",
"Check this to display center line of slot", True)
' the position of mini-toolbar
Dim oPosition As Point2d
oPosition = ThisApplication.TransientGeometry.CreatePoint2d(
ThisApplication.ActiveView.Left, ThisApplication.ActiveView.Top)
m_MiniToolbar.Position = oPosition
m_MiniToolbar.Visible = True
m_MiniToolbar = m_MiniToolbar
m_Sketch = ThisApplication.ActiveEditObject
bStop = False
InterceptKeys.SetHook(Me)
Do
ThisApplication.UserInterfaceManager.DoEvents()
Loop Until bStop
InterceptKeys.UnhookWindowsHookEx()
End Sub
Private Sub m_MiniToolbar_OnApply() Handles m_MiniToolbar.OnApply
CreateSlot()
End Sub
Private Sub m_MiniToolbar_OnCancel() Handles m_MiniToolbar.OnCancel
bStop = True
End Sub
Public Sub m_MiniToolbar_OnOK() Handles m_MiniToolbar.OnOK
bStop = True
CreateSlot()
m_MiniToolbar.Delete()
End Sub
Private Sub CreateSlot()
If Not (m_EndCenterOneX.IsExpressionValid And
m_EndCenterOneY.IsExpressionValid And
m_EndCenterTwoX.IsExpressionValid And
m_EndCenterTwoY.IsExpressionValid) Then
MsgBox("Invalid values for end center positions!")
Exit Sub
End If
bCenterline = m_DisplayCenterline.Checked
Dim oTG As TransientGeometry
oTG = ThisApplication.TransientGeometry
Dim oEndCenterOne As Point2d
Dim oEndCenterTwo As Point2d
Dim oEndArcOne As SketchArc
Dim oEndArcTwo As SketchArc
' Start transaction for creating slot.
Dim oTransaction As Transaction =
ThisApplication.TransactionManager.StartTransaction(
ThisApplication.ActiveDocument, "Create slot")
' If the two centers are vertical
If Math.Abs(
m_EndCenterOneX.Value - m_EndCenterTwoX.Value) < 0.000001 Then
If (m_EndCenterOneY.Value > m_EndCenterTwoY.Value) Then
oEndCenterOne = oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value)
oEndCenterTwo = oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value)
Else
oEndCenterOne = oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value)
oEndCenterTwo = oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value)
End If
If oEndCenterOne.IsEqualTo(oEndCenterTwo, 0.000001) Then
MsgBox("The two centers are coincident!")
Exit Sub
End If
' Create the top arc
oEndArcOne = m_Sketch.SketchArcs.AddByCenterStartEndPoint(
oEndCenterOne,
oTG.CreatePoint2d(oEndCenterOne.X + 0.1, oEndCenterOne.Y),
oTG.CreatePoint2d(oEndCenterOne.X - 0.1, oEndCenterOne.Y))
' Create the bottom arc
oEndArcTwo = m_Sketch.SketchArcs.AddByCenterStartEndPoint(
oEndCenterTwo,
oTG.CreatePoint2d(oEndCenterTwo.X - 0.1, oEndCenterTwo.Y),
oTG.CreatePoint2d(oEndCenterTwo.X + 0.1, oEndCenterTwo.Y))
'If the two centers are not vertical
Else
If m_EndCenterOneX.Value < m_EndCenterTwoX.Value Then
oEndCenterOne = oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value)
oEndCenterTwo = oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value)
ElseIf m_EndCenterOneX.Value > m_EndCenterTwoX.Value Then
oEndCenterOne = oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value)
oEndCenterTwo = oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value)
End If
If oEndCenterOne.IsEqualTo(oEndCenterTwo, 0.000001) Then
MsgBox("The two centers are coincident!")
Exit Sub
End If
oEndArcOne = m_Sketch.SketchArcs.AddByCenterStartEndPoint(
oEndCenterOne,
oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value + 0.1),
oTG.CreatePoint2d(
m_EndCenterOneX.Value, m_EndCenterOneY.Value - 0.1))
oEndArcTwo = m_Sketch.SketchArcs.AddByCenterStartEndPoint(
oEndCenterTwo,
oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value + 0.1),
oTG.CreatePoint2d(
m_EndCenterTwoX.Value, m_EndCenterTwoY.Value - 0.1),
False)
End If
Dim dWidth As Double
dWidth = m_Width.Value
' Create center line if required
If bCenterline Then
Dim oCenterline As SketchLine
oCenterline = m_Sketch.SketchLines.AddByTwoPoints(
oEndArcOne.CenterSketchPoint, oEndArcTwo.CenterSketchPoint)
oCenterline.Construction = True
End If
Dim oGround1 As GroundConstraint
Dim oGround2 As GroundConstraint
oGround1 = m_Sketch.GeometricConstraints.AddGround(
oEndArcOne.CenterSketchPoint)
oGround2 = m_Sketch.GeometricConstraints.AddGround(
oEndArcTwo.CenterSketchPoint)
' Create sketch lines of slot
Dim oLine1 As SketchLine
Dim oLine2 As SketchLine
oLine1 = m_Sketch.SketchLines.AddByTwoPoints(
oEndArcOne.StartSketchPoint, oEndArcTwo.EndSketchPoint)
oLine2 = m_Sketch.SketchLines.AddByTwoPoints(
oEndArcOne.EndSketchPoint, oEndArcTwo.StartSketchPoint)
' Add geometric constraints to the sketch entities
Call m_Sketch.GeometricConstraints.AddEqualRadius(
oEndArcOne, oEndArcTwo)
Call m_Sketch.GeometricConstraints.AddTangent(
oLine1, oEndArcOne)
Call m_Sketch.GeometricConstraints.AddTangent(
oLine1, oEndArcTwo)
Call m_Sketch.GeometricConstraints.AddTangent(
oLine2, oEndArcOne)
Call m_Sketch.GeometricConstraints.AddTangent(
oLine2, oEndArcTwo)
' Add dimensional constraints to the sketch entities
Dim oDiameter As DiameterDimConstraint
oDiameter = m_Sketch.DimensionConstraints.AddDiameter(
oEndArcOne, oEndArcOne.CenterSketchPoint.Geometry)
oDiameter.Parameter.Value = dWidth
ThisApplication.ActiveDocument.Update()
oDiameter.Delete()
oGround1.Delete()
oGround2.Delete()
oTransaction.End()
End Sub
End Class
And then you can use it like this from your command's event handler:
Protected Overrides Sub ButtonDefinition_OnExecute(
ByVal context As Inventor.NameValueMap)
Dim mtb As New MyMiniToolbar
mtb.Init(InventorApplication)
End Sub