Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Dudas TDBGrid y TComboBox en C++Builder6 (https://www.clubdelphi.com/foros/showthread.php?t=96623)

michal 01-03-2024 00:40:44

Dudas TDBGrid y TComboBox en C++Builder6
 
Hola a todos

Cómo puedo centrar el texto de un ComboBox sin usar espacios?
Cómo puedo agregarle el simbolo $ a una celda de un DBGrid, alineado a la izquierda, mientras que el valor monetario lo haga a la derecha?

Gracias

Saludos

Casimiro Notevi 01-03-2024 09:57:19

Código Delphi [-]
ComboBox1.Style := csCenter;



Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  s: string;
  x, y: Integer;
begin
  if Column.Field.DataType = ftCurrency then
  begin
    s := '$' + Column.Field.AsString;
    x := Rect.Right - Canvas.TextWidth(s) - 2;
    y := Rect.Top + 2;
    DBGrid1.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2, '$');
    DBGrid1.Canvas.TextRect(Rect, x, y, s);
  end
  else
    DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

Neftali [Germán.Estévez] 01-03-2024 10:01:11

Cita:

Empezado por michal (Mensaje 554671)
Cómo puedo centrar el texto de un ComboBox sin usar espacios?
Cómo puedo agregarle el simbolo $ a una celda de un DBGrid, alineado a la izquierda, mientras que el valor monetario lo haga a la derecha?


En ambos casos debes utilizar los eventos de pintado (Draw) de los componentes, para redibujar los elementos como desees. (para ello utiliza el Canvas del componente)

En el caso del TCombobox tienes el OnDrawItem, y para el TDBGrid tienes el OnDrawColumnCell y el OnDrawDataCell.

Un ejemplo el Delphi (espero que te sirva) podría ser este:
Código Delphi [-]
procedure TForm3.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  R:TRect;
  str:String;
begin
  R := Rect;
  str := TComboBox(Control).Items[Index];
  InflateRect(R, -1, -1);
  TComboBox(Control).Canvas.TextRect(R, Str, [tfCenter]);
end;


Algo similar deberás realizarlo para el TDBGrid.
Has pruebas con el Canvas.


Si buscas en los foros seguro que encuentras mensajes al respecto (revisa estos métodos de TCanvas; Canvas.TextRect, Canvas,TextOut, Canvas.TextExtent,...).

michal 01-03-2024 14:41:45

Respuesta
 
Gracias por responder tan rápido


Cita:

Empezado por Casimiro Notevi (Mensaje 554678)
Código Delphi [-]ComboBox1.Style := csCenter; <<< Esta propiedad no existe ni en C6 ni en D7

Encontré una variante propuesta por PeterPunk, que sí lo centra, tanto horizontal como vertical, pero anula la propiedad ComboBox1.Text, la cual creo es necesaria para que
el usuario tenga una idea de lo que va a desplegar


////////
procedure TForm3.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var R:TRect; str:String; begin R := Rect; str := TComboBox(Control).Items[Index]; InflateRect(R, -1, -1); TComboBox(Control).Canvas.TextRect(R, Str, [tfCenter]); << Esta opción tampoco funciona, no existe tfCenter end;En que versión de Delphi lo testeaste?? porque en D7 no funciona

Código Delphi [-]procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var s: string; x, y: Integer; begin if Column.Field.DataType = ftCurrency then begin s := '$' + Column.Field.AsString; x := Rect.Right - Canvas.TextWidth(s) - 2; y := Rect.Top + 2; DBGrid1.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2, '$'); DBGrid1.Canvas.TextRect(Rect, x, y, s); end else DefaultDrawColumnCell(Rect, DataCol, Column, State);<<<< Dónde está definido DefaultDrawColumnCell ???? me da error end;


Yo no sé delphi , pero trato de traducirlo cbuilder. Ahora una pregunta, porque será que existe más documentación de Delphi que de C++Builder ???

escafandra 02-03-2024 22:43:36

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 *Controlint Index,
          
TRect &RectTOwnerDrawState State);
private:
  
TWndMethod OldCBProc;
  
void __fastcall CBProc(TMessageMessage);

public:        
// User declarations
  
__fastcall TForm1(TComponentOwner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif 



Este sería el archivo.cpp

Código PHP:

// Realiza un SubClassing sobre un TWinControl
void __fastcall SetSubClass(TWinControl *WCTWndMethod newProcTWndMethod *oldProc)
{
  *
oldProc WC->WindowProc;
  
WC->WindowProc newProc;
}

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
  : 
TForm(Owner)
{
  
// Realizamos el SubClassing
  
SetSubClass(ComboBox1CBProc, &OldCBProc);
   
// Guardamos el Texto en el Tag
  
ComboBox1->Tag = (LONG_PTR)"Elija una Opción";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Controlint Index,
      
TRect &RectTOwnerDrawState State)
{
  
TComboBox *CB dynamic_cast<TComboBox*>(Control);
  if(
CB){
    
Rect.Right -= GetSystemMetrics(SM_CXVSCROLL);
    
SetTextAlign(CB->Canvas->HandleTA_CENTER);
    
CB->Canvas->TextOut(Rect.Right/2Rect.Top + (CB->ItemHeight CB->Font->Height)/2CB->Items->Strings[Index]);
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::CBProc(TMessageMessage)
{
  
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(hDCComboBox1->Font->Handle);
    
TEXTMETRIC Metric;
    
GetTextMetrics(hDC, &Metric);
    
FillRect(hDC, &RectGetSysColorBrush(COLOR_WINDOW));
    
SetTextAlign(hDCTA_CENTER);
       
// Escribimos Text centrado
    
ExtTextOut(hDCRect.Right/2, (Rect.Bottom Metric.tmHeight)/1ETO_CLIPPED, &RectTextstrlen(Text), 0);
   
    
// Liberamos el HDC
    
ReleaseDC(hDCComboBox1->Handle);
  }


Espero que esto responda a tu pregunta.


Saludos.

escafandra 03-03-2024 23:28:06

Ajustando un poco ComboBox1DrawItem para que centre bien la opción elegida al dibujarla en la zona EDIT del ComboBox:


Código PHP:

void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Controlint Index,
      
TRect &RectTOwnerDrawState State)
{
  
TComboBox *CB dynamic_cast<TComboBox*>(Control);
  if(
CB){
    
CB->Canvas->FillRect(Rect);
    if(!
State.Contains(odComboBoxEdit))
      
Rect.Right -= GetSystemMetrics(SM_CXVSCROLL);
    
SetTextAlign(CB->Canvas->HandleTA_CENTER);
    
CB->Canvas->TextOut(Rect.Right/2Rect.Top + (CB->ItemHeight CB->Font->Height)/2CB->Items->Strings[Index]);
  }



El ajuste con GetSystemMetrics(SM_CXVSCROLL) es para que al desplegar el ComboBox no de la sensación de incoherencia en el centrado entre Items y la zona EDIT.


Saludos.


La franja horaria es GMT +2. Ahora son las 18:49:02.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi