Cómo escribir programas con vc
Parte 1
Agregar modelo de objetos al programa no COM (2)
Inicializar modelo de objetos
Crear una nueva instancia de componente, Llame al método Load para obtener un par de resultados. Primero, conéctese a una copia en ejecución del Bloc de notas. En segundo lugar, abra un documento existente en una ventana del Bloc de notas o cree un documento vacío.
Para combinar con el Bloc de notas, debe tomar el identificador del formulario principal y el identificador del control de edición que cubre toda el área del cliente. Puede utilizar la función API FindWindow de C++ para recuperar la primera ventana abierta que coincida con el nombre de clase de Windows "bloc de notas" del Bloc de notas (Spy++, que es una herramienta de Visual Studio que puede ver a través de la privacidad de Windows, ya puede proporcionar esta información básica). ), puede utilizar el siguiente código C++:
STDMETHODIMP
CNotepadApplication::Load(BSTR bstrFile)
{
m_hwnd = FindWindow( _T("notepad"), NULL);
if (!IsWindow(m_hwnd))
_StartApp(OLE2T(bstrFile));
Cargar método try Encuentra una instancia del Bloc de notas en ejecución. Si tiene éxito, ignora el nombre de archivo ingresado. De lo contrario, genera nodepad.exe y pasa el parámetro bstrFile con la línea de comando.
Ésta es la única forma posible de hacerlo. Puede cambiar el comportamiento del método Load para cumplir con otras reglas. Sin embargo, es importante tener en cuenta que cargar un archivo de texto de forma encubierta dentro de la interfaz de usuario del programa se realiza a través de la línea de comando. En caso contrario deberás recurrir al comando Abrir del menú Archivo, pero este no es automático y está oculto.
Una vez que haya encontrado el identificador del formulario principal del Bloc de notas, puede aprovecharlo y recuperar los controles de edición secundarios usando código C++.
m_hwndEdit = FindWindowEx(
m_hwnd, NULL, _T("edit"), NULL);
La estructura del Bloc de notas proporciona una clase llamada "bloc de notas" ventana, cuyo área de cliente está ocupada por un control de edición, una ventana con el nombre de clase "editar". La función API FindWindowsEx recupera la primera ventana con un nombre de clase "editar", que es hija de m_hwnd.
A continuación, cree una propiedad en el objeto COM que describa el contenido del control de edición secundario. Llame a la propiedad de lectura y escritura denominada Texto. Dale un contenido de texto e inmediatamente afectará el búfer del Bloc de notas.
Establecer npad = CreateObject("NotepadOM.Application")
npad.Load ""
npad.Text = "Texto de muestra"
En el código anterior, creamos un nuevo documento de texto sin nombre y a su contenido se le asignó una cadena determinada. Por supuesto, puedes usar la propiedad Texto para conectar texto a otras variables.
npad.Text = "Texto de muestra"
npad.Text = npad.Text & vbCrLf & "para el artículo"
Incluso si el Bloc de notas es una IDE programa, también puede ser necesario exponer el contenido del texto como un procedimiento de llamada de objeto claro, como operaciones de documentos. Esto es consistente con un diseño de modelo más claro y elegante, pero aún introduce complejidad innecesaria en el diseño arquitectónico. ¿Por qué crear un nuevo objeto ATL sólo para optimizar algunas funciones relacionadas con el texto?
Al implementar la propiedad Texto, se utiliza una característica poco conocida del control de edición de Windows32. No se puede acceder a todos los controles de Windows32 entre procesos.
Por ejemplo, no puede pedirle al cuadro de edición enriquecido de otra aplicación que devuelva su contenido como una cadena. La razón de este problema es que cualquier dirección de memoria solo es válida dentro del alcance de la gestión de procesos. Hay algunas excepciones a esta regla.
Todos los botones, cuadros de lista y controles de edición u otros controles estándar de Windows no infringen esta regla. Su contenido se puede leer o escribir arbitrariamente entre procesos. Esta característica apareció en Windows 95 para mantener la compatibilidad con los programas existentes de Windows 3x y utiliza subclases entre procesos. Esto también existe en Windows XP y Windows 2000.
Puedes utilizar algunos mensajes, como WM_GETTEXT y WM_SETTEXT para obtener o escribir el contenido del cuadro de texto independientemente del proceso real. Del mismo modo, cuando se ejecuta un script VBS, en realidad hay dos procesos diferentes involucrados, el Bloc de notas y wscript.exe, que controlan el script VBS. Utilice C++ para implementar este atributo de texto. El código es el siguiente:
STDMETHODIMP
CNotepadApplication::get_Text(BSTR *pVal)
{
.USES_CONVERSION ;
int nLen = 1 + SendMessage(m_hwndEdit, WM_GETTEXTLENGTH, 0, 0);
LPTSTR pszBuf = new TCHAR[nLen];
SendMessage(m_hwndEdit , WM_GETTEXT, nLen, (LPARAM) pszBuf);
*pVal = SysAllocString(T2OLE(pszBuf));
eliminar [] pszBuf;
return S_OK ;
}
STDMETHODIMP
CNotepadApplication::put_Text(BSTR newVal)
{
USES_CONVERSION;
SendMessage(m_hwndEdit, WM_SETTEXT, 0, (LPARAM) OLE2T(newVal));
return S_OK;
}
Agregar funciones de edición
Acceder al control de edición puede aclarar el conjunto de funciones necesarias para la edición, especialmente la parte sobre la selección de texto. Puede agregar fácilmente métodos para seleccionar todo el texto en el búfer o limitar la selección a un área determinada. SelectAll y SelectText se implementan en C++ de la siguiente manera:
STDMETHODIMP
CNotepadApplication::SelectText(
int nFrom, int nTo) {
SendMessage(m_hwndEdit, EM_SETSEL, nFrom-1, nTo-1);
return S_OK;
}
El mensaje EM_SETSET se puede editar fácilmente Implementar texto selección en el control. En Windows32, el primer carácter opcional está en la posición 0, pero los métodos relacionados hacen que comience en la posición 1. Al especificar el rango de -1 a 0 se puede seleccionar todo el texto.
El nombre de fuente del texto en el cuadro de edición está determinado por un determinado valor registrado lfFaceName. Este valor clave se puede encontrar en la siguiente ubicación:
HKEY_CURRENT_USER
<. p> \Software p>\Microsoft
\Notepad
Establézcalo en el valor clave que desea usar. El Bloc de notas lee esta configuración antes de comenzar. Para que esto funcione, recuerde configurarlo antes de llamar a Load.
set npad = CreateObject("NotepadOM.Application")
npad.Font = "Lucida Console"
npad.Load "readme.txt" p>
p>
Cuando un usuario interactivo hace clic en un menú, como "Archivo | Abrir", el formulario principal envía un mensaje WM_COMMAND, en el que el parámetro WPARAM se proporciona como dos palabras concatenadas. La palabra de orden inferior es el ID del comando y la palabra de orden superior contiene el código de mensaje o valor que representa el activador: un acelerador de teclado o un menú. Utilice C++ para llamar a un comando de menú y enviar un mensaje WM_COMMAND al Bloc de notas. El código es el siguiente:
SendMessage(m_hwnd, WM_COMMAND,
MAKELONG(nCommand,0), 0) ;
p>Se debe utilizar una herramienta especial para especificar el valor correcto para el parámetro nCommand, como Spy++. En este caso, modifiqué ligeramente la versión de DLL descrita en el artículo. "Hook, Line and Sinker" [Diario de desarrolladores de Visual C++, febrero de 2001]. Esta rutina genera y engancha, y luego crea una subclase de Bloc de notas. Filtra todos los mensajes recibidos por la ventana y muestra un cuadro de diálogo que muestra el ID del comando cuando el código del comando es WM_COMMAND.
if (uiMsg == WM_COMMAND) {
// Obtener el valor de LOWORD(wParam)
}
Necesita agregar Un programa que simplemente almacena o muestra códigos de comando. Verifique el ID del comando de menú del bloc de notas principal. Una vez dado esto, llamar al comando de menú es simple, el código es el siguiente:
const NOTAPAD_FILE_OPEN = 10
Set npad = CreateObject("NotepadOM.Application")
npad.InvokeMenu NOTAPAD_FILE_OPEN
Si desea cerrar mediante programación una instancia en ejecución, debe pensar en llamar a DestroyWindows en la ventana del Bloc de notas. Sin embargo, DestroyWindows solo se puede llamar dentro de un proceso que pertenece a una ventana del mismo proceso. Para desinstalar el Bloc de notas, simplemente envíe un mensaje WM_COMMAND con el código de salida usando C++:
SendMessage(m_hwnd, WM_COMMAND,
MAKELONG(28,0), 0);
Algunas funciones no están disponibles en programas no automatizados. Por ejemplo, no es posible abrir un archivo y guardarlo porque el programa no expone este código a través de mensajes o API y requiere escribir código para almacenarlo. Por ejemplo, en el Bloc de notas, almacenar los resultados del tiempo de ejecución requiere responder al comando Guardar o Guardar como, pero ambos son comandos interactivos que requieren que el usuario haga clic en el botón Aceptar o ingrese un nuevo nombre de archivo. Esta es una limitación inherente de la solución original.
Recientemente, encontré un problema similar con un cliente y me pidieron que trabajara en algunos programas tradicionales de Windows (uno de los cuales era el Bloc de notas) en diferentes entornos.
Básicamente, las aplicaciones Win32 hechas a medida toman instrucciones del canal TCP/IP y las convierten para ejecutar aplicaciones nativas de Windows. Solicitar servicios a través de mensajes de Windows32 es muy similar a lo que hicimos aquí. El próximo objetivo es encapsular este patrón de comunicación con el modelo de objetos COM.
Acerca del autor
Dino Esposito es experto en ADO.NET y formador en Wintellect y consultor en Roma. Dino es el autor de "Creación de soluciones web con ASP.NET y ADO.NET" (Microsoft Publishing) y fundador de VB-2-The-Max (<>). Puede comunicarse con Dino en dinoe@wintellect.com.