Código fuente de programación avanzada de Gdi
En principio, el propietario de una VCL puede ser responsable de su ciclo de vida, pero se recomienda no hacerlo.
Como herramienta RAD (desarrollo rápido de aplicaciones) similar a Delphi, la poderosa función de c builder no solo se refleja en el desarrollo de bases de datos, sino también en el desarrollo de aplicaciones (estos dos aspectos están bien combinados, es sorprendente). En lo que respecta a las aplicaciones, para aprovechar verdaderamente las ventajas de c builder y desarrollar software de alta calidad, además de arrastrar y soltar, también se necesitan algunas tecnologías avanzadas. Por ejemplo, procesamiento de mensajes, dll, ole, thread, programación SDK. C Builder tiene ventajas más o menos únicas en estos aspectos. Además, es conveniente crear controles personalizados, que también es una característica importante y una función avanzada de c builder. Este artículo demostrará algunos conceptos de producción de controles y procesamiento de mensajes en c builder creando un control de cuadro de diálogo con la barra de título en el lado izquierdo de la ventana, y también implica un poco de programación SDK. Lo que queremos hacer es un cuadro de diálogo, como opendialog, etc. Una vez que se llama al método ejecutar(), aparecerá la ventana que se muestra en la Figura 1. La barra de título de esta ventana está a la izquierda y es verde, con el texto moviéndose de abajo hacia arriba en un glifo de 90 grados. Su función es la misma que la barra de título general. Puede mover la ventana moviendo el mouse.
Primero, complete la ventana y luego úsela para hacer el control del cuadro de diálogo.
Figura 1
Utilice el mensaje wm_nchittest para crear una ventana con un título vertical
. mensaje wm_nchittest
C builder encapsula algunos mensajes de Windows en un evento, pero no puede incluir todos los mensajes, como los mensajes de la serie wm_nc****. El mensaje wm_nchittest aparece cuando se mueve el cursor o cuando se presiona o suelta el mouse, y el valor de retorno indica la posición actual del cursor. Por ejemplo, devuelva hthscroll para indicar que está en la barra de desplazamiento horizontal y devuelva htcaption para indicar que está en la barra de título (consulte la ayuda de win32 SDK). Sus parámetros xpos e ypos representan las coordenadas xey del cursor (en relación con la esquina superior izquierda de la pantalla) respectivamente, correspondientes a la palabra de orden inferior y palabra de orden superior de lparam respectivamente. Si el mensaje wm_nchittest se intercepta de modo que cuando se presiona el mouse en el lado izquierdo de la ventana, el valor de retorno se establece artificialmente en htcaption, el sistema pensará que está en la barra de título, por lo que la ventana se puede mover y el La función de la barra de título está completa. En cuanto al color y el texto, no tiene nada que ver con el mensaje. Su principio se presentará a continuación.
Mensajes de Windows
Los mensajes son eventos enviados a programas por el sistema operativo Windows. Pero hay cientos de eventos y el sistema operativo no diseña una estructura de mensaje diferente para cada evento, sino que utiliza una estructura común para describir el mensaje, que se define como mensaje t en c builder. Además, c builder define una estructura especial para mensajes ordinarios, y los dos son equivalentes. Puede convertir el mensaje directamente en una estructura privada o interpretar el parámetro tmessage usted mismo.
Tomando como ejemplo el mensaje wm_nchittest, su definición es la siguiente:
Estructura twmnchittest
{
Cardinal MSG;
No utilizado durante mucho tiempo;
p>
Alianza
{
Estructura
{
ventanas ::tsmallpoint pos;
Resultado largo;
};
Estructura
{
Xpos cortos
Ypos cortos
};
};
};
Comparación con la definición del mensaje t: p>
Información de la estructura p>
{
Cardenal MSG;
Alianza
{
Estructura
{
palabra wparamlo
palabra wparamhi
palabra lparamlo
palabra lparamhi
palabra resultlo
palabra resulthi
};
Estructura
{
wparam largo
long lparam
Resultado largo;
};
};
};
Puede Se encontrará que el miembro lparam de tmessage corresponde a El miembro pos de twmnchittest son las siguientes dos líneas de declaraciones.
Equivalencia:
tpoint pt = tpoint(msg . lparam); //En este momento, el tipo de mensaje es tmessage.
tpoint pt = tpoint(msg . pos); //En este momento, el tipo de mensaje es twmnchittest.
Macro del constructor C para procesar mensajes.
Es muy conveniente personalizar el procesamiento de mensajes en c builder. Tome wm_nchittest como ejemplo:
Agregue la siguiente definición de macro a la parte protegida de la clase de ventana:
Start_Message_Mapping
Manejador de mensajes (wm_nchittest, tmessage, onnchittest )
Finalizar mapeo de mensajes
Message_handler contiene tres parámetros: wm_nchittest, identificador de mensaje o un mensaje personalizado como wm_mymessage, así que simplemente agregue una macro como #define WM_my message WM_app 1, etc. . El segundo parámetro tmessage representa el tipo de mensaje, o puede ser un tipo de estructura de mensaje personalizado que cumpla con los requisitos, como tmymsg, etc. onnchittest es una función de procesamiento de mensajes. De esta manera, una vez que el mensaje wm_nchittest se envía a tform, la función onnchittest maneja completamente la respuesta al mensaje. La función onnchittest tiene solo un parámetro y su tipo es una referencia al segundo parámetro en message_handler, que es tmessage o tmymsg.
Completa la ventana de la Figura 1.
Inicie una nueva aplicación (nueva aplicación), nombre form1 vcform, el archivo de unidad correspondiente es vcap.cpp y el archivo de encabezado es vcap h. Configure el estilo de borde del formulario VC en bsnone y colóquelo encima. Un botón de mapa de bits bitbtn1, título ok, escriba bkok, agregue una declaración close() en el controlador de eventos onclick.
Luego, en la parte protegida de vcap.h, se agregan la macro de procesamiento de mensajes y la declaración de la función onnchittest mencionada anteriormente para manejar la función de arrastre de la barra de título. Para completar el color y la salida de texto del título, haga doble clic en el evento onpaint de vcform para personalizar la función formpaint. Consulte el código fuente a continuación para obtener código específico. Además, para que la ventana tenga una sensación tridimensional, la función virtual createparams también se sobrecarga para modificar el estilo de la ventana. Los vcap.h y vcap.cpp completos son los siguientes:
//vcap.h
#ifndef vcaph
#Define vcaph
#incluye
#incluye
#incluye
#incluye
#incluye
Clase tvcform: Formulario público
{
_ _ Publicado: // componente administrado por ide
tbitbtn * bit BTN 1;
void _ _ fast llamar al formulario paint(al objeto * remitente);
void _ bit de llamada rápida BTN 1 clic(al objeto * remitente);
Privado: //Declaración de usuario p>
Protegido:
void _ _ llamada rápida onchittest(t mensaje mensaje);
void _ _ llamada rápida create params(tcreateparams params);
Start_message_mapping
Manejadores de mensajes (wm_nchittest, tmessage, onnchittest)
Finalizar asignación de mensajes
Público://declaración de usuario
p>_ _ formulario TVC de llamada rápida (t componente * propietario);
};
paquete externo tvcform * vcform
#endif p>
/ /vcap.cpp
#Incluye
#Notas varias hdrstop
#Incluye "vcap.h"
#paquete pragma (smart_init )
#pragma recurso " *.dfm "
tvcform * vcform
_ _ formulario TVC de llamada rápida::formulario TVC (componente t * propietario)
:t formulario (propietario)
{
}
void _ _ llamada rápida formulario TVC: :form paint(al objeto * remitente)
{
//Dibuja una barra de título verde con un ancho de 20.
rect rc
setrect(rc, 0, 0, ancho del cliente, altura del cliente
lienzo - gt; pluma -> color = clgreen
p>Canvas-gt; Brush-gt; color = clgreen
Canvas-gt; Rectángulo (0, 0, 20, altura del cliente); texto de rotación
char * msg = caption . c _ str();
logfont fontrec
memset(fontrec,0,sizeof(log font));
fuente rec .lf altura =-13;
fuente rec lf peso = fw _ normal
fuente lf escape = 900; Ángulo de rotación 900x0,1 grados = 90 grados.
Lstrcpy(fontrec.lffacename, "ì");
hfont hfont = createfontindirect(fontrec);
hfont hold =::select object(canvas- gt; handle, hfont);
* set rect(RC, 0, 0, 20, altura del cliente);
* settextcolor(canvas- gt; handle, rgb(255, 255, 255));
* textout(canvas- gt; handle, 3, clientheight-3, msg, lstrlen(msg));
* select object(canvas- gt ; manejar, mantener);
*Eliminar objeto (hfont);
}
void _ _ formulario TVC de llamada rápida::bit BTN 1 clic( a objeto * remitente)
{
close();
}
void _ _ llamada rápida TVC form::onnchittest( t mensaje msg)
{
ángulo del punto;
pt x = loword(msg . lparam);
pt y =. hola palabra(msg . lparam);
pt = screentoclient(pt);
rect rc
setrect( rc, 0, 0, 20, altura del cliente );
if (ptinrect(rc, pt))
msg.result = htcaption
Otro
defaulthandler (mensaje);
}
void _ _ formulario TVC de llamada rápida::create params(controls::tcreateparams params)
{
t formulario ::create params(params);
params.style | = ws _ popup
params style ^= ws _ DLG frame;
}< / p>
Presenta el procesamiento de mensajes de vcform y explica brevemente el dibujo de la barra de título. Dado que la fuente tfont de c builder no define el atributo de rotación de texto, se utiliza el método de dibujo tradicional del SDK. canvas-gt; el identificador es el HDC que representa el dibujo GDI.
3 Cree un control de cuadro de diálogo. Antes de crear el control, comente la línea del paquete #pragma (smart_init) en vcap.cpp. Los pasos para crear un control son: crear un archivo de unidad y completar el. Definición de clase y control del control en él. Regístrelo y luego instálelo. Las clases de control normalmente heredan y derivan de clases existentes. La principal diferencia entre crear controles y definiciones de clases generales es que las propiedades y los eventos también son propiedades. Los métodos de acceso a atributos, los valores predeterminados y el editor de atributos están incluidos con el atributo. En aras de la simplicidad, este control sólo implica algunos de los conceptos anteriores, pero puede cubrir el proceso general de realización de controles.
. Inicie un control vacío.
Debido a que la función mínima necesaria del control del cuadro de diálogo es el método ejecutar(), se puede heredar de la clase tcomponent. El control nombrado se llama tvcaptiondlg, el archivo de unidad que define el control se llama vcapdlg.cpp y su archivo de encabezado es vcapdlg. h Utilice el Asistente de componentes o el método manual para completar los siguientes archivos:
//vcapdlg.h
#ifndef vcapdlgh
#Definition vcapdlgh
#includes
#includes
#includes
#includes
Paquete de clases tvcaptiondlg: tcomponent público
{
Privado:
Protegido:
Público:
virtual _ _ fastcall tvcaptiondlg(t componente * propietario);
p>
_ _Publicado:
};
#endif
//vcapdlg.cpp
#includes
#pragma hdrstop
#Contiene " vcapdlg.h "
#paquete pragma (smart_init)
Estático en línea tvcaptiondlg * validctrcheck()
{
Devuelve nuevo tvcaptiondlg(null);
}
Espacio de nombres vcapdlg //Archivo del mismo unidad de definición de control Nombre, primera letra en mayúscula, resto en minúscula.
{
void __fastcall paquete registro()
{
tcomponentclass clase[1]= { _ _ classid(tvcaptiondlg)} ;
registercomponents("Romay", clase, 0);
}
}
_ _ llamada rápida tvcaptiondlg:: tvcaptiondlg (componente t * propietario)
:componente t (propietario)
{
}
Registrar componentes ("Luo Mai", clases, 0) significa que todos los controles contenidos en la matriz de clases se generan en la página Luomai en el panel de control (de lo contrario, se creará la página), aquí hay un control tvcaptiondlg. Por supuesto, el control tvcaptiondlg en este momento no tiene funciones excepto la clase tcomponent.
. Incluya el archivo de formulario a utilizar.
Agregue una línea #include "vcap . CPP" después de #include "VCA PLG . h" en vcaplg.cpp (vcaplg). * y vcap. *en el mismo directorio), y reitere que la línea #pragma package (smart_init) en vcaplg.cpp debe eliminarse. También puede incluir todo el contenido de vcap.cpp y vcap.h en vcapdlg.cpp, de modo que no sea necesario vcap. *documento. En otras palabras, la definición de la clase vcform se coloca en el mismo archivo que vcaplg. De todos modos, vcform es sólo una definición de clase utilizada por vcaplg. Sin embargo, al generar un objeto de instancia de vcform, debe establecer el título, el tipo y otros atributos de bitbtn1 que son diferentes de los valores predeterminados en tiempo de ejecución, porque los atributos no predeterminados se guardan en. archivo dfm.
Esta es la razón por la que las clases que utilizan formularios generalmente se guardan en archivos unitarios separados.
. Agregar atributos de interfaz
Aquí solo se proporciona un atributo de título para que los usuarios de control lean o establezcan el título del cuadro de diálogo. Así que simplemente agregue una variable fcaption ansistring almacenada internamente en el área privada del cuerpo de la declaración como tvcaptiondlg y publíquela en _
Agregue una línea a esta área:
_ _ propiedad ansi ssing caption = { leer = f caption, escribir = fcaption}.
Debido a que el tipo de propiedad es ansistring, no es necesario un editor de propiedades especial para manejar la edición de propiedades en tiempo de diseño. Además, el cambio del valor del atributo no necesita causar ningún procesamiento inmediato ni proceso durante el diseño, por lo que el método de acceso adopta el acceso inmediato más simple (read=fcaption,
write=fcaption).
. Agregar método de ejecución
La función del método ejecutar() de vcaptiondlg es crear un objeto de instancia similar a vcform y mostrarlo en modo. Esto solo requiere el siguiente código:
void _ _ fast call tvcaptiondlg::execute()
{
vcform=new tvcform(apply); p>
p>
Formulario VC- gt;caption=title;
Formulario VC- gt;show modal();
Eliminar vcform
} p>
Donde vcform es una variable de instancia del tipo de clase tvcform declarada en vcap.cpp. Por lo tanto, debe agregar una declaración del método de ejecución en vcapdlg.h.
Además, puede agregar algún código irrelevante, como agregar una declaración de inicialización para variables miembro en el constructor de tvcaptiondlg. En este punto se completa la producción de todo el control. El código de control completo es el siguiente:
//vcapdlg.h
#ifndef vcapdlgh
#Definición vcapdlgh
#Incluye
#includes
#includes
#includes
Paquete de clases tvcaptiondlg: tcomponent público
{
Privado:
Registrando fcaption
Protegido:
Público:
virtual _ _ fastcall tvcaptiondlg(t componente * propietario );
Virtual void _ _ fastcall run();
_ _ Publicado:
_ _ propiedad ansi ssing caption = { leer = f caption, write = fcaption}.
};
#endif
//vcapdlg.cpp
#includes
#pragma hdrstop
#Incluye " vcapdlg.h "
#Incluye "vcap.cpp"
#paquete pragma (smart_init)
TVcaptiondlg estático en línea * validctrcheck()
{
Devuelve nuevo tvcaptiondlg(null);
}
Espacio de nombres vcapdlg
{
void __fastcall paquete registro()
{
tcomponentclass class[1]= { _ _ classid(tvcaptiondlg)};
registercomponents("Romay", clase, 0);
}
}
_ _ llamada rápida tvcaptiondlg::tvcaptiondlg(t componente * propietario)
:t componente (propietario)
{
fcaption= "Muestra de Luo Mai";
}
void _ _ llamada rápida tvcaptiondlg::execute()
{
vcform=new tvcform(aplicación);
Formulario VC- gt;caption=title;
VC form- gt;show modal();
Eliminar vcform
}
No se detallará Describe la instalación del controlador.
4 Conclusión
Este artículo tiene como objetivo demostrar las tecnologías de programación avanzadas de C Builder, como la producción de control, el procesamiento de mensajes y el SDK. Los códigos anteriores se depuraron en pwin98/c builder 3.0. Por cierto, crear componentes personalizados en la documentación de ayuda de c builder es un muy buen tutorial para aprender a escribir controles. Sin embargo, hay dos pequeños defectos en este artículo que hacen del cuadro de diálogo un componente. Primero, el método de usar pragma link vcap.obj mencionado al incluir la unidad de formulario es un método más problemático porque no es tan simple como #include "vcap. CPP" en este artículo porque debe estar en un compilado y generado no relacionado. un archivo obj en el proyecto (o compilar en la línea de comando con parámetros especificados). En segundo lugar, este documento no señala que existen restricciones en este formulario autogenerado, es decir, la línea del paquete #pragma (smart_init) debe estar comentada; de lo contrario, el archivo del paquete se puede generar durante la instalación, pero el control no se puede instalar. . Esta frase no aparece en el ejemplo del cuadro de diálogo. El formulario generado por el IDE generalmente tiene esta oración.