2010-03-01 16 views
7

Sí, esta es otra vez esta pregunta:¿Cómo se puede cambiar el color de la fuente de un control habilitado por tema?

¿Cómo puedo cambiar el color de fuente de un TCheckBox (o cualquier control manejado) con Delphi7-> Delphi2007 en una aplicación habilitada por temas?

Después de leer mucho en internet y en este sitio, me encontré con 4 tipos de respuesta:

  1. y más populare (incluso de control de calidad): No se puede, que está diseñado de esa manera por Microsoft.
  2. Cree un componente que le permita dibujarlo como desee.
  3. Compre componentes caros que se dibujen como desee.
  4. No utilice temas.

Bien, pero todavía no estoy contento con eso.

Darle a un usuario comentarios de color para el estado de una propiedad/datos que tiene en un formulario, me parece legítimo.

Luego acabo de instalar la edición MSVC# 2008 Express, y qué sorpresa, pueden cambiar el color de la fuente (propiedad ForeColor de la casilla de verificación) ¿Entonces qué?

No parece ser "diseñado así por Microsoft". entonces ahora la pregunta otra vez:

¿Cómo puedo cambiar el color de la fuente de un TCheckBox (o cualquier control manejado) con Delphi 7 a través de Delphi 2007 en una aplicación habilitada para temas?

+0

Qué le hace pensar los desarrolladores de Visual Studio no usaron simplemente la opción 2? –

+0

Bueno, no tuve que hacerlo, al tratar de reproducir que "está diseñado así, por Microsoft". en C#. He configurado ForeColor en rojo y obtengo un título rojo para mi casilla de verificación. –

Respuesta

0

Opción 5. Use la opción de control como una opción base y anule todos los mensajes de pintura en el control (sí puede llamarlo componente pero control es el nombre de los componentes visibles, así que debería usarlo). Simplemente atrapa el WM_PAINT, posiblemente el WM_NCPAINT, puedes dibujar el control en tu propio estilo. Al menos puedes reutilizar toda la funcionalidad desde el control. Siempre que no cambie el diseño, solo los colores no necesitarán cambiar los mousedowns de los hittest. hasta movimientos, etc.

Nota: Tengo la experiencia de anular TCustomEdit para permitir todo tipo de colores, texto de fondo, botones adicionales, etc. Me llevó bastante tiempo hacerlo bien y leer todos los documentos de MSDn y KB para asegurarme de que el control hizo lo que yo quería que hiciera.

+0

Entiendo que no como la opción 5, sino como la opción 2a y mi opción 2 como la opción 2b; ^)! Pero, ¿por qué C# no necesita reemplazar el método wm_paint para cambiar el color del color de fuente de un componente Checkbox? –

+0

@Edouard. Lo que hay en un nombre ... sobre C# no lo necesita: C# tiene su propia capa de control (Microsoft inventa uno nuevo para el entorno .NET cada tantos años), Delphi usa los mismos controles que existen desde Windows 95. Por lo tanto, mucho más estabilidad, pero a veces se paga por algo simple que se vuelve más difícil; GDI es antiguo, pero creo que en 10 años GDi todavía está presente y ¿qué debería hacer con su aplicación WinForms? ¡Piénsalo! –

+0

Sé que el GDI es bastante viejo, comencé a trabajar con él, cuando di mi primer paso en Pascal Objeto Pascal en "Windows 2" algo así como 1988. Lo que estás diciendo es: C# puede hacer eso, porque están usando un grupo de controles totalmente diferente al utilizado por Delphi mientras los temas están habilitados? Como el tema es responsable de dibujar las cosas nuevas, supongo que delphi está usando los mismos componentes (ort al menos biblioteca) que el uso de C#. –

2

¡Oh, pero puedes!

Simplemente coloque este antes de la declaración de su formulario:

TCheckBox = class(StdCtrls.TCheckBox) 
public 
    procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC; 
end; 

Esta re-declaración de TCheckBox ahora se utiliza en tiempo de ejecución como el tipo transmitido desde DFM de su forma. Ahora poner en práctica el mensaje como este:

procedure TCheckBox.CNCtlColorStatic(var Message: TWMCtlColorStatic); 
begin 
    SetTextColor(Message.ChildDC, ColorToRGB(clRed)); // or RGB(255,0,0)); 
    SetBkMode(Message.ChildDC, TRANSPARENT); 
    Message.Result := GetStockObject(NULL_BRUSH); 
end; 

Esto atrapa el mensaje WM_CTLCOLORSTATIC y cambia el color del texto a rojo. Esto funciona en modo no temático para mí (utilizando WinXP classic), pero no en modo temático.

Debe saber que para permitir que los controles temáticos le envíen este mensaje, el control debe suministrar la bandera DTPB_USECTLCOLORSTATIC a la API de dibujo de tema. Lamentablemente, ese no es el comportamiento predeterminado, y tampoco sé cómo hacerlo. Mira this pregunta también.

1

Así es como he resuelto esto en mi aplicación:

  1. Retire el título de la casilla de verificación y hacerlo más pequeño - lo suficientemente grande para mostrar la casilla de verificación real sin el título.
  2. Ponga un TLabel al lado de la casilla de verificación para que actúe como leyenda.
  3. En el evento OnClick de la etiqueta, alternar el estado de la casilla de verificación.
  4. Si la etiqueta tiene un acelerador de teclado Alt + letter, haga que el formulario maneje el mensaje CM_DIALOGCHAR. Copie el controlador de mensajes del código fuente de TLabel y agregue una línea para alternar el estado de la casilla de verificación.

No es una casilla de verificación real, y es un poco más trabajo de lo que me gustaría, pero funciona lo suficientemente bien en mi aplicación (que tiene solo una casilla de verificación que necesita este tratamiento).

4

Esto necesita un poco de pellizco ser una solución perfecta, pero funcionó para mí:

Añadir 2 método para su componente casilla

FOriginalCaption: string; 
    _MySetCap: Boolean; 
    procedure WMPaint(var msg: TWMPaint); message WM_PAINT; 
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; 

e implementar de esta manera:

procedure TMyCheckbox.CMTextChanged(var Message: TMessage); 
begin 
    inherited; 
    if _MySetCap then Exit; 
    FOriginalCaption := Caption; 
end; 

procedure TMyCheckbox.WMPaint(var msg: TWMPaint); 
var 
    BtnWidth: Integer; 
    canv: TControlCanvas; 
begin 
    BtnWidth := GetSystemMetrics(SM_CXMENUCHECK); 

    _MySetCap := True; 
    if not (csDesigning in ComponentState) then 
    Caption := ''; 
    _MySetCap := False; 
    inherited; 
    canv := TControlCanvas.Create; 
    try 
    canv.Control := Self; 
    canv.Font := Font; 
    SetBkMode(canv.Handle, Ord(TRANSPARENT)); 
    canv.TextOut(BtnWidth + 1, 2, FOriginalCaption); 
    finally 
    canv.Free; 
    end; 
end; 
+0

Creo que esto debería marcarse como respuesta, ¡buen trabajo! –

Cuestiones relacionadas