Para conseguir que un ComboBox estilo csOwnerDrawFixed escriba el Texto cuando su ItemIndex es -1, es decir, cuando no se ha elegido ninguna opción, podemos realizar un SubClassing y manejar el mensaje WM_PAINT.
Dado que la propiedad Text del ComboBox queda inhabilitada, en el ejemplo uso el Tag para almacenar un puntero char pero el texto se puede manejar como se quiera, siempre y cuando la función CBProc que va a tratar el Mensaje WM_PAINT tenga acceso a él.
Nótese que el tratamiento de WM_PAINT se realiza con API y no con VCL, esto es debido a que WM_PAINT empieza a ser llamado antes de que el Canvas del ComboBox esté operativo.
Muestro un ejemplo completo de un formulario con un ComboBox.
Este sería el archivo.h
Código PHP:
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TComboBox *ComboBox1;
void __fastcall ComboBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State);
private:
TWndMethod OldCBProc;
void __fastcall CBProc(TMessage& Message);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Este sería el archivo.cpp
Código PHP:
// Realiza un SubClassing sobre un TWinControl
void __fastcall SetSubClass(TWinControl *WC, TWndMethod newProc, TWndMethod *oldProc)
{
*oldProc = WC->WindowProc;
WC->WindowProc = newProc;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// Realizamos el SubClassing
SetSubClass(ComboBox1, CBProc, &OldCBProc);
// Guardamos el Texto en el Tag
ComboBox1->Tag = (LONG_PTR)"Elija una Opción";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State)
{
TComboBox *CB = dynamic_cast<TComboBox*>(Control);
if(CB){
Rect.Right -= GetSystemMetrics(SM_CXVSCROLL);
SetTextAlign(CB->Canvas->Handle, TA_CENTER);
CB->Canvas->TextOut(Rect.Right/2, Rect.Top + (CB->ItemHeight + CB->Font->Height)/2, CB->Items->Strings[Index]);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CBProc(TMessage& Message)
{
OldCBProc(Message); // Permitimos que primero se traten por defecto todos los mensajes
// Tratamos nuestro WM_PAINT
if((Message.Msg == WM_PAINT || Message.Msg == WM_SETFOCUS) && ComboBox1->ItemIndex < 0){
// Preparamos el Texto
char *Text = (char*)ComboBox1->Tag;
// Preparamos el rectángulo apropiado
TRect Rect = ComboBox1->ClientRect;
InflateRect(&Rect, -2, -2);
Rect.Right -= GetSystemMetrics(SM_CXVSCROLL); // Para salvar el botón del ComboBox
//Preparamos un HDC con la fuente del ComboBox y seleccionamos la alineación al centro
HDC hDC = GetDC(ComboBox1->Handle);
SelectObject(hDC, ComboBox1->Font->Handle);
TEXTMETRIC Metric;
GetTextMetrics(hDC, &Metric);
FillRect(hDC, &Rect, GetSysColorBrush(COLOR_WINDOW));
SetTextAlign(hDC, TA_CENTER);
// Escribimos Text centrado
ExtTextOut(hDC, Rect.Right/2, (Rect.Bottom - Metric.tmHeight)/2 + 1, ETO_CLIPPED, &Rect, Text, strlen(Text), 0);
// Liberamos el HDC
ReleaseDC(hDC, ComboBox1->Handle);
}
}
Espero que esto responda a tu pregunta.
Saludos.