Eventos de Teclado.Esto implica recurrir a una serie de eventos diferente, los eventos de teclado. El acceso a los eventos de teclado se hace a partir del objeto KeyboardEvents. Será necesario declarar una variable de objeto para ello. Private WithEvents oEventosTeclado As KeyboardEvents Este objeto habilita un conjunto de eventos que pueden ser recibidos por la aplicación cliente en el momento en que se pulsa una tecla estando iniciado el objeto InteractionEvents. Contrariamente a lo que parece entenderse de los ejemplos contenidos en la ayuda de programación de Autodesk Inventor, cuando se vigilan los eventos del teclado la propiedad InteractionDisabled deberá establecerse como Verdadero (True) en lugar de como Falso (False). Esta propiedad, según su descripción en la ayuda, establece si se disparará o no cualquiera de los eventos de Selección (SelectEvents), del Ratón (MouseEvents) o del Teclado (KeyboardEvents). La ayuda explica que si su valor es Falso NO se disparará ninguno de estos eventos. Sin embargo, al explicar los eventos de teclado se indica que los eventos del teclado pueden ser recibidos por el cliente cuando una tecla es presionada mientras esté iniciado el objeto InteractionEvents y el indicador InteractionDisabled tenga el valor de False. Una de las dos afirmaciones (o quizás ambas) tendrá que estar equivocada. Según las comprobaciones realizadas en los talleres de programación se llega a la conclusión de que para recibir los eventos del teclado la propiedad InteractionDisabled debe establecerse como Verdadera (True). El valor de esta propiedad parece no afectar a los eventos de selección. Los eventos del teclado disponibles son OnKeyDown, OnKeyPress y OnKeyUp. OnKeyDownOnKeyDown es el evento que se dispara cuando el usuario presiona una tecla. Sólo las teclas especificadas en el enumerador se gestionan mediante este evento. OnKeyDown( Key As Long, ShiftKeys As ShiftStateEnum) El argumento Key devuelve un código de tecla, por ejemplo kKeyF1 (para la tecla F1) o kKeyHome (para la tecla INICIO). Los códigos están definidos en la lista de constantes KeyCodeEnum. El argumento ShiftKeys devuelve una constante de enumeración que corresponde al estado de las teclas SHIFT, CTRL, y ALT cuando la tecla especificada en el argumento Key fue presionada. Las constantes corresponden a estar presionadas una o más de esas teclas. Cada una de ellas corresponde a un bit: la tecla SHIFT al bit 0, la tecla CTRL al bit 1, y la tecla ALT al bit 2. Estos bits corresponden a los valores decimales 1, 2, y 4, respectivamente. El enumerador ShiftStateEnum especifica combinaciones de estas teclas. Por ejemplo, si solo hubiera sido presionada la tecla ALT, la constante kShiftStateAlt que corresponde al valor numérico entero 4 serÃa devuelta como valor del argumento ShiftKeys. Si hubieran estado pulsadas CTRL y ALT, se devolverÃa la constante kShiftStateCtrlAlt de valor 6. OnKeyPressOnKeyPress es el evento que se dispara cuando el usuario presiona y suelta una tecla. Se devuelve el valor ANSI de la tecla pulsada. OnKeyPress( KeyASCII As Long) El argumento KeyASCII devuelve un código numérico correspondiente a la norma ANSI. El código que corresponde a la tecla INTRO es el 13, Asc(vbCr). Otros códigos que corresponden a teclas que no tienen una representación gráfica son 8, Asc(vbBack) para RETROCESO, 9 para el TABULADOR, Asc(vbTab) y 10, Asc(vbLf) para el salto de lÃnea. OnKeyUpOnKeyUp es el evento que se dispara cuando el usuario suelta una tecla que ha pulsado. Sólo se tienen en cuenta las teclas especificadas en el enumerador ShiftStateEnum. El argumento Key representa la tecla pulsada. OnKeyUp( Key As Long, ShiftKeys As ShiftStateEnum) Los argumentos corresponden a los ya descritos para el evento OnKeyDown. Establecer una referencia al objeto Eventos de Teclado.Para emplear los eventos de teclado será necesario establecer una referencia a este objeto. Set oEventosTeclado = oEventosInteraccion.KeyboardEvents Para controlar el final de la interacción mediante la pulsación de alguna tecla será necesario definir el código correspondiente al evento que deseemos emplear. La opción más sencilla será emplear el evento OnKeyPress, aunque una opción más pudiera estar en los otros que además comprueban si se han pulsado teclas modificadoras como CTRL, ALT o SHIFT. El código que se muestra a continuación detendrá la selección en el momento que se pulse INTRO. Private Sub oEventosTeclado_OnKeyPress(ByVal KeyASCII As Long)    If KeyASCII = 13 Then       bolEnSeleccion = False    End If End Sub Devolver los datos sobre las caras seleccionadas.Al ser múltiple la selección, no bastará con devolver la primera cara del conjunto de selección. Para ello habrÃan diversas opciones. Empleando los recursos nativos del lenguaje de programación serÃa posible devolver un Array que contenga las diferentes caras seleccionadas.Pero el API de Inventor ofrece un recurso para solucionar este tipo de situaciones: la colección de objetos (ObjectCollection). Demostraremos a continuación las dos posibilidades. Array.Para ello deberá declararse un array de tipo Object: Dim arrCaras() As Object Debe observarse que este array se crea en tiempo de compilación al cargar el proyecto, pero aún no se sabe el tamaño que este array tendrá. El tamaño del Array sólo puede conocerse una vez que haya concluido la selección, una vez que se conozca el número de elementos que contendrá. El número de elementos estará dado por la propiedad Count de la selección: numCaras = oEntsSelecc.Count Para dimensionar en tiempo de ejecución el array se usa la instrucción de Visual Basic ReDim. ReDim arrCaras(1 To numCaras) Ahora será necesario incluir en el array los objetos seleccionados. Esto se deberá hacer en un bucle que recorra los Ãtems del conjunto de selección: Dim i As Integer i=1    Set arrCaras(i) = oEntsSelecc.Item(i -1)    i=i+1 Loop Until i > oEntsSelecc.Count Por último será necesario asignar al método que realiza la selección (que llamaremos Designa) este array. Designa deberá haber sido declarado como del tipo Variant. Designa = arrCaras ObjectCollectionEl objeto ObjectCollection es uno de los "objetos transitorios" (TransientObjects) que suministra el API de Inventor, utilizados como contenedores temporales durante la ejecución del programa. En nuestro caso servirá como contenedor de las caras seleccionadas. Para emplear el ObjectCollection añadiremos al código de la función Designa la definición de una variable de ese tipo:Dim oCaras As ObjectCollection Una vez concluida la selección, comprobaremos si se ha seleccionada una o más caras. Si asà fuera crearemos un nuevo objeto objeto ObjectCollection empleando el método CreateObjectCollection del objeto TransientObjects, que asignaremos a la variable oCaras. Set oCaras = ThisApplication.TransientObjects.CreateObjectCollection Para poblar la colección con las caras seleccionadas, que habremos obtenido como ObjectsEnumerator a partir de la propiedad SelectedEntities de los eventos de selección (SelectEvents), implementaremos un ciclo iterativo.        Do            oCaras.Add oEntsSelecc.Item(i)            i = i + 1        Loop Until i > numCaras Donde numCaras representa la cantidad de caras seleccionadas obtenidas a partir de la propiedad Count de las entidades seleccionadas:    Dim numCaras As Integer    numCaras = oEntsSelecc.Count Detener la selección si se cancela el comando.Cuando el usuario selecciona un comando diferente o pulsa la tecla Escape el bucle de selección deberá cancelarse, cosa que no sucederá hasta que la variable que le sirve de control no adopte el valor de Falso. Para ello se puede aprovechar el evento OnTerminate del objeto InteractionEvents que en esos casos se produce incluyendo el código necesario en el procedimiento que se activa por este evento: Private Sub oInteraccion_OnTerminate()    ' Indicador de que hemos concluido.    bolEnSeleccion = False End Sub Ejercicio.Implementar el ejercicio anterior utilizando la selección interactiva múltiple.Para ello será necesario:
Modificaciones a clsSelecc.El primer aspecto a modificar se encuentra en la declaración de variable s globales dentro de la clase, incorporando los eventos de teclado:Option Explicit 'Declarar los objetos de evento, Interacción y Selección: Private WithEvents oEventosInteracc As InteractionEvents Private WithEvents oEventosSelecc As SelectEvents Private WithEvents oEventosTeclado As KeyboardEvents Private m_Flt As SelectionFilterEnum Private m_Msj As String Habrá que incorporar el procedimiento de respuesta al evento KeyPress como se ha explicado más arriba. La otra modificación estará en la función Designa que reproducimos a continuación. En este código recurrimos al ObjectCollection para agrupar las caras seleccionadas. Public Function Designa() As ObjectCollection       bolEnSeleccion = True    Set oEventosInteracc = _    ThisApplication.CommandManager.CreateInteractionEvents    Set oEventosTeclado = oEventosInteracc.KeyboardEvents    oEventosInteracc.InteractionDisabled = False    oEventosInteracc.StatusBarText = m_Msj    Set oEventosSelecc = oEventosInteracc.SelectEvents    oEventosSelecc.AddSelectionFilter m_Flt    oEventosInteracc.Start       Do While bolEnSeleccion        DoEvents    Loop       Dim oEntsSelecc As ObjectsEnumerator    Set oEntsSelecc = oEventosSelecc.SelectedEntities    Dim numCaras As Integer    numCaras = oEntsSelecc.Count    If numCaras > 0 Then        Dim oCaras As ObjectCollection        Set oCaras = ThisApplication.TransientObjects.CreateObjectCollection        Dim i As Integer        i = 1        Do            oCaras.Add oEntsSelecc.Item(i)            i = i + 1        Loop Until i > numCaras    End If    Set Designa = oCaras    oEventosInteracc.Stop    Set oEventosSelecc = Nothing    Set oEventosInteracc = Nothing End Function Modificaciones al código del formulario:La primera modificación estarÃa en la declaración de la variable global oSelCaras para contener el ObjectCollection devuelto por la función Designa.Option Explicit Dim oSelCaras As ObjectCollection A esta variable se asignará, en el procedimiento de respuesta al evento Clic del botón cmdSeleccion, lo devuelto por Designa. Private Sub cmdSeleccion_Click()    Dim oSelecc As New clsSelecc    oSelecc.Filtro = kPartFaceFilter    oSelecc.Mensaje = "Seleccione una cara"    Me.Hide    Set oSelCaras = oSelecc.Designa    lblResultado.Caption = "Pulse Calcular para ver el resultado"    Me.Show End Sub Y debemos entonces modificar el procedimiento asociado al botón cmdAceptar de manera que procese cada una de las caras. Se implementará un ciclo que prepare un mensaje con las áreas de cada una de las caras y la suma del área total que será presentada en la etiqueta lblInfo. Private Sub cmdAceptar_Click()    Dim oDoc As PartDocument    Set oDoc = ThisApplication.ActiveDocument    Dim oUOM As UnitsOfMeasure    Set oUOM = oDoc.UnitsOfMeasure    Dim eUnidad As UnitsTypeEnum    eUnidad = oUOM.LengthUnits    Dim sUnidad As String    sUnidad = oUOM.GetStringFromType(eUnidad)    Dim sUnidadArea As String    sUnidadArea = sUnidad & "^2"    Dim strArea As String    strArea = ""    Dim Datos As String    Datos = ""    Set oDoc = ThisApplication.ActiveDocument    Dim dblArea As Double    Dim dblTotal As Double    Dim strTotal As String    Dim i As Long    i = 1    If oSelCaras.Count > 0 Then        Do            dblArea = oSelCaras(i).Evaluator.Area            dblTotal = dblTotal + dblArea            strArea = oUOM.GetStringFromValue(dblArea, sUnidadArea)            Datos = Datos & "El área de la cara " & i & " = " & strArea & vbCrLf            i = i + 1        Loop Until i > oSelCaras.Count        strTotal = oUOM.GetStringFromValue(dblTotal, sUnidadArea)        lblResultado.Caption = Datos & "Area total= " & strTotal    Else        lblResultado.Caption = "Ninguna cara seleccionada"    End If End Sub El proyecto correspondiente a este ejercicio puede descargarse desde el enlace situado al final de esta página. |