Reconocimiento
de voz (III)
Como se prometió en el
artículo anterior de la serie, vamos a abordar el primer
proyecto de reconocimiento de comandos por medio de la API Speech.
Controlaremos dos opciones del menú del procesador de textos
Microsoft Word mediante los comandos que dictemos (menú Archivo
y menú Edición).
Para poder controlar otro programa
desde el nuestro, necesitamos crear una aplicación con soporte
DDE. La API Speech no puede hacerlo por sí misma puesto que no
tiene el soporte necesario para efectuar este tipo de tareas. En
realidad, sólo se encarga de informarnos del estado del habla
por parte del usuario para que, seguidamente, hagamos el trabajo
necesario con los datos obtenidos mediante los mensajes de voz
descifrados.
Una aplicación con soporte
DDE es capaz de establecer comunicación directa con otra
aplicación para transferir datos y efectuar tareas según
los datos obtenidos. Visual Basic posee varias instrucciones que
trabajan directamente con la arquitectura DDE, y será una de
ellas la que utilizaremos para enviar los comandos de voz a los demás
programas: SendKeys.
SENDKEYS
Se encarga de enviar una o más
pulsaciones de teclas a la ventana activa, como si se hubieran
presionado desde el teclado. Cuando se reciban comandos hablados por
parte del usuario, enviaremos las teclas necesarias a la aplicación
destino según el comando que se haya dicho por el micrófono.
Por ejemplo, si queremos activar el menú archivo de Microsoft
Word, esperaremos a que el usuario pronuncie la palabra "archivo"
o "menú archivo" y enviaremos las teclas ALT+A para
activar la opción de menú en Word.
SINTAXIS DE LA INSTRUCCIÓN SendKeys string[, wait]
La sintaxis de la instrucción
SendKeys consta de los siguiente argumentos:
|
Parte |
Descripción |
| String: |
Expresión de
cadena que especifica las pulsaciones de teclas que se van a enviar.
(Requerido). |
| Wait: |
Valor Booleano que
indica el modo de espera. Si este valor es False (predeterminado),
se devuelve el control al procedimiento inmediatamente después
de enviar las pulsaciones. Si es True, se procesan las pulsaciones
antes de devolver el control al procedimiento. (Opcional). |
Mediante el soporte DDE,
controlaremos diversos programas simultáneamente utilizando el
reconocimiento de voz
COMENTARIOS
Cada tecla está representada
por uno o más caracteres, de tal forma que para especificar un único
carácter del teclado, se utiliza el carácter propiamente
dicho. Por ejemplo, para representar la letra A, utilizaremos "A"
como string. Si deseamos representar más de un carácter,
agregaremos cada carácter adicional al que lo precede. Por
ejemplo, para representar las letras A, B y C, utilizaremos "ABC".
El signo más (+), el símbolo
de intercalación (^), el símbolo de porcentaje (%), la
tilde (~) y los paréntesis ( ) tienen significados especiales
para SendKeys. Aunque los corchetes ([ ]) no tienen un significado
especial para SendKeys se deben escribir entre llaves debido a que, en
otras aplicaciones los tienen y resulta de gran importancia cuando se
produce un intercambio dinámico de datos (DDE). Para
especificar llaves, utilizaremos {{} y {}}.
Para especificar caracteres que no
se muestran al presionar una tecla (como por ejemplo ENTRAR o TAB) y
teclas que representan acciones, en lugar de caracteres se utilizarán
los códigos de tabla 1.
Para especificar teclas con
cualquier combinación de las teclas MAYUS, CTRL y ALT,
introduciremos delante del código de la tecla uno o más
de los siguientes códigos:
| Tecla |
Código |
| MAYÚS |
+ |
| CTRL(CONTROL) |
^ |
| ALT |
% |
Para especificar que se debe
mantener presionada una combinación cualquiera de las teclas
MAYUS, CTRL y ALT mientras se presionan otras teclas, debemos poner
entre paréntesis el código relativo a esas teclas. Por
ejemplo, para determinar que se debe mantener presionada MAYUS
mientras se presionan las teclas E y C, utilizaremos "+(EC)".
Para especificar que se debe mantener presionada MAYUS mientras se
presiona la tecla E y que luego se debe presionar C sin presionar
MAYUS, utilizaremos "+EC".
Para especificar pulsaciones
repetidas de teclas, utilizaremos el formato {tecla número}.
Debemos dejar un espacio en blanco entre tecla y número. Por
ejemplo, {LEFT 42} significa que se debe presionar la tecla CURSOR
IZQUIERDO 42 veces; {h 10} significa que se debe presionar la tecla h
10 veces.
Nota: No puede utilizar SendKeys
para enviar pulsaciones de teclas a aplicaciones que no estén
diseñadas para funcionar con Microsoft Windows. SendKeys puede
enviar también la pulsación de la tecla IMPR PANT
(PRTSC) a cualquier aplicación.
CONSTRUCCIÓN DEL PROYECTO
Para la creación del proyecto
se utilizarán los siguientes módulos y formularios:
Formulario Form1: Es el encargado de
representar la ventana en la cual se informará del estado del
reconocimiento de voz. Si se dicta un comando reconocido, aparecerá
en el formulario; en caso contrario, aparecerá un mensaje que
informará al usuario que no se ha reconocido el comando
hablado.
Form 1 se encarga de representar la
ventana en la cual se informará del estado del reconocimiento
de voz
Módulo Variables: La tarea de
este módulo consiste en definir las variables que representarán
a los objetos "comandos de voz" y "menú de voz".
Módulo de clase VcmdSink: Consiste en definir las funciones
callbacks para el reconocimiento de los comandos hablados.
A la hora de construir el proyecto,
es necesario agregar en la opción Referencias del menú
Proyecto de Visual Basic las librerías encargadas de gestionar
la API Speech:
- VoiceCommand 1.0 Type library
- VoiceText 1.0 Type library
- Dictctl OLE Control Module
En la figura 2 se puede apreciar el
detalle de la inclusión de estas librerías en el
proyecto.
No es necesario tener en primer
plano nuestra aplicación de reconocimiento para obtener los
comandos hablados
Nota: Estas librerías son
agregadas al disco duro cuando se instala la API Speech de Microsoft.
RANGO DE DESPLAZAMIENTO
Vamos a dar comienzo a la programación
por este módulo, y en primer lugar tendremos que encargarnos de
definir los dos objetos principales que componen el sistema de
reconocimiento de voz:
- Un objeto "comandos de voz"
para gestionar los comandos hablados por el usuario.
- Un objeto "menú de voz"
para delimitar qué comandos se pueden decir. Public VCmd As VCmdAuto.VCmdAuto
Public vmenu As VCmdAuto.IVMenuAuto
En el siguiente procedimiento se
designa como formulario principal Form1: Sub Main()
Form1.Show
End Sub
Módulo de clase VcmdSink
Como se comentó
anteriormente, este módulo de clase gestiona las funciones
callback del reconocimiento. En la primera función
(CommandOther) se gestionan los comandos del usuario que no se han
reconocido. Puede ser debido a una mala colocación del micrófono
o que simplemente no existan en el menú de voz que hemos creado
(formulario Form1).
Si la cadena de caracteres obtenida
en la variable pszCommand es cero, significa que el comando actual no
se ha reconocido y se visualizará en el cuadro de texto del
formulario un mensaje de REPITA, POR FAVOR. De este modo, el usuario
sabrá si su comando se ha reconocido correctamente. Function CommandOther(pszCommand As String,
pszApp As String, pszState As String)
If Len(pszCommand) = 0 Then
Form1.Text1.Text = "REPITA, POR FAVOR"
End If
End Function
En la siguiente función se
gestionan las palabras que han sido reconocidas por el engine de
reconocimiento: Function CommandRecognize(pszCommand
As String, dwID As Long)
En la variable Form1 que representa
al formulario se asignará la cadena de caracteres que
representa al comando reconocido por el engine: Form1.Text1.Text = pszCommand
En primer lugar debemos definir las
condicionales que determinan el comando que reconocer dentro del menú
Archivo de Microsoft Word. Mediante la instrucción AppActivate
definimos el nombre de la aplicación que vamos a controlar,
teniendo en cuenta que este nombre aparecerá en la parte
superior izquierda de la ventana de la aplicación (en nuestro
caso Microsoft Word).
En la instrucción SendKeys
asignaremos los parámetros que determinan la pulsación
de teclas para cada opción del menú. Puesto que para
activar dicho menú se utiliza la tecla ALT, definiremos el carácter
% (véase la tabla anterior relativa a SendKeys). Seguidamente
pondremos entre paréntesis las teclas que deben pulsarse para
llegar hasta la opción correspondiente dentro del menú.
La variable pszCommand debe
igualarse a cualquiera de los comandos que hayamos introducido en el
menú de voz (véase más adelante en la programación
del formulario Form1). Primero definimos las condicionales del menú
Archivo y posteriormente las del menú Edición.
Nota: las demás opciones del
menú de Word no se representan en estas páginas por
motivos de espacio. Su diseño sería análogo:
definir dentro de esta función todas las opciones posibles del
menú y agregarlas al "menú de voz" (definido
en el formulario Form1). Pasamos a partir de este mismo momento a
detallar la definición que corresponde al menú Archivo y
sus opciones: If pszCommand = "Nuevo" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(n)", True
End If
If pszCommand = "Abrir" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(a)",True
End If
If pszCommand = "Cerrar" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(c)", True
End If
If pszCommand = "Guardar" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(g)", True
End If
If pszCommand = "Guardar como" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(u)", True
End If
If pszCommand = "Versiones" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(e)", True
End If
If pszCommand = "Configurar página" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(r)", True
End If
If pszCommand = "Vista preliminar" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(m)", True
End If
If pszCommand = "Imprimir" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(i)", True
End If
If pszCommand = "Enviar a" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(v)", True
End If
If pszCommand = "Propiedades" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(p)", True
End If
If pszCommand = "Salir" Then
AppActivate "Microsoft Word"
SendKeys "%(a)+(s)", True
End If
Definición del menú
Edición y sus opciones: If pszCommand = "Deshacer" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(d)", True
End If
If pszCommand = "Repetir" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(r)", True
End If
If pszCommand = "Cortar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(t)", True
End If
If pszCommand = "Copiar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(c)", True
End If
If pszCommand = "Pegar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(p)", True
End If
If pszCommand = "Pegado especial" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(e)", True
End If
If pszCommand = "Pegar como hipervínculo" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(m)", True
End If
If pszCommand = "Borrar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(a)", True
End If
If pszCommand = "Seleccionar todo" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(s)", True
End If
If pszCommand = "Buscar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(v)", True
End If
If pszCommand = "Reemplazar" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(z)", True
End If
If pszCommand = "Ir a" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(i)", True
End If
If pszCommand = "Vínculos" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(v)", True
End If
If pszCommand = "Objeto" Then
AppActivate "Microsoft Word"
SendKeys "%(e)+(o)", True
End If
End Function
Formulario Form1:
El siguiente procedimiento
representa al botón Registrar del formulario que se encarga de
registrar la aplicación en el engine de reconocimiento. Esta
operación resulta indispensable para inicializar la API.
Nota: se puede registrar la aplicación
de forma automática sin necesidad de pulsar un botón si
definimos un procedimiento que se ejecute al cargar el formulario
principal. Private Sub Command1_Click()
Lo primero que debemos hacer es
borrar el objeto "comandos de voz" (VCmd) antes de efectuar
el registro. Seguidamente, crearemos el objeto mediante la función
CreateObject Set VCmd = Nothing Set VCmd =
CreateObject("Speech.VoiceCommand")
Registramos la aplicación: Call VCmd.Register("")
Definimos la función callback
establecida en el módulo de clase: VCmd.Callback = "comandos.VCmdSink"
Creamos un menú de voz para
poder agregarle los comandos que reconocer: Set vmenu = VCmd.MenuCreate("Comandos de voz",
"prueba", 0, "español", vcmdmc_CREATE_ALWAYS)
Activamos el micrófono para
poder recibir los comandos audibles del usuario: VCmd.Awake = True
Introducimos los comandos del menú
de Word (Archivo y Edición) en el menú de voz creado: Call vmenu.Add(1, "Nuevo", "general", "prueba")
Call vmenu.Add(2, "Abrir", "general", "prueba")
Call vmenu.Add(3, "Cerrar", "general", "prueba")
Call vmenu.Add(4, "Guardar", "general", "prueba")
Call vmenu.Add(5, "Guardar como", "general", "prueba")
Call vmenu.Add(6, "Versiones", "general", "prueba")
Call vmenu.Add(7, "Configurar página", "general", "prueba")
Call vmenu.Add(8, "Vista preliminar", "general", "prueba")
Call vmenu.Add(9, "Imprimir", "general", "prueba")
Call vmenu.Add(10, "Enviar a", "general", "prueba")
Call vmenu.Add(11, "Propiedades", "general", "prueba")
Call vmenu.Add(12, "Salir", "general", "prueba")
Call vmenu.Add(13, "Deshacer", "general", "prueba")
Call vmenu.Add(14, "Repetir", "general", "prueba")
Call vmenu.Add(15, "Cortar", "general", "prueba")
Call vmenu.Add(16, "Copiar", "general", "prueba")
Call vmenu.Add(17, "Pegar", "general", "prueba")
Call vmenu.Add(18, "Pegado especial", "general", "prueba")
Call vmenu.Add(19, "Pegar como hipervínculo", "general",
"prueba")
Call vmenu.Add(20, "Borrar", "general", "prueba")
Call vmenu.Add(21, "Seleccionar todo", "general", "prueba")
Call vmenu.Add(22, "Buscar", "general", "prueba")
Call vmenu.Add(23, "Reemplazar", "general", "prueba")
Call vmenu.Add(24, "Ir a", "general", "prueba")
Call vmenu.Add(25, "Vínculos", "general", "prueba")
Call vmenu.Add(26, "Objeto", "general", "prueba")
Y por último activamos el menú: vmenu.Active = True
End Sub
Este procedimiento es el que se
encarga de representra al botón Cerrar del formulario y se
encarga de finalizar la aplicación. Private Sub Command2_Click()
End
End Sub
Cuando se descargue el formulario,
debemos eliminar los objetos de la API creados (Comandos de voz y menú
de voz): Private Sub Form_Unload(Cancel As Integer)
Set VCmd = Nothing
Set vmenu = Nothing
End
End Sub
Cuando se agregan nuevos comandos al
menú de voz, debemos asegurarnos de que las palabras incluidas
se encuentran en el diccionario del engine. De lo contrario, al
registrar el menú se mostrará un formulario como el
siguiente invitándonos a registrar la nueva palabra en el
diccionario:
Para que el reconocimiento de voz
funcione con Word, este último debe estar encontrarse en
ejecución. También se podría utilizar el método
Shell de Visual Basic para poder ejecutar automáticamente el
procesador de textos cuando se inicie nuestra aplicación de
reconocimiento.
|