Ver Mensaje Individual
  #8  
Antiguo 09-11-2004
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Sonic
Al final resolví el problema por otros caminos
Sería bienvenida tu explicación de esos otros caminos para quienes en un futuro se encuentren con un problema similar.

Por otra parte, desde que vi este hilo hace tiempo pensé: un RichEdit tiene una propiedad Paragraph.Tabs que es un arreglo de enteros que indican los puntos donde debe detenerse el tabulador.

Como ya bien notaste, un tabulador no corresponde a un número determinado de caracteres o espacios en blanco por una sencilla razón: a menos que la fuente que uses sea de ancho constante- como la Courier New - no tiene caso tratar de establecer el ancho de las tabulaciones en caracteres ya que éstos son de ancho variable.

Así que, en lugar de eso, las tabulaciones se indican en twips desde el margen izquierdo (según la documentación).

Ahora bien, como dije, había visto este hilo y pensado en la propiedad Paragraph.Tabs. Sin embargo no había dicho nada porque al probarlo yo mismo la mentada propiedad no funcionaba. Por más que le especificaba distintas medidas de tabulaciones, era como si no pasase nada y seguí poniendo las tabulaciones por defecto.

Pero yo había hecho esto alguna vez.

Finalmente, buscando en archivos viejos encontré cómo lo hice. Básicamente me olvidé de fijar las tabulaciones a través de la VCL y lo hice directamente mandando el mensaje EM_SETPARAFORMAT al control. En el código tengo algunos comentarios referentes a que la implementación de la VCL es incorrecta pero confieso que ya no recuerdo bien por qué, así como tampoco recuerdo exactamente qué es lo que hace el código.

Pero lo he probado y funciona.

El código está hecho pensando en una fuente de ancho fijo como Courier New de manera que en ese caso sí podía traducir los anchos de las tabulaciones en número de caracateres.

Como te digo, no puedo explicar los detalles porque ya no los recuerdo pero creo que puede servirte a tí o alguien más para ver por donde va el asunto.

El código es para Delphi pero debiera portarse sin problemas a C++.

Código Delphi [-]
(*
  Devuelve el ancho promedio de un caracter según la
  fuente seleccionada en el RichEdit.
*)
function TForm1.GetCharWidth;
var
  DC: HDC;
  TM: TTextMetric;
 
begin
  DC := GetDC(RichEdit1.Handle);
  SelectObject(DC, RichEdit1.Font.Handle);
  GetTextMetrics(DC, TM);
  Result := TM.tmAveCharWidth;
  ReleaseDC(RichEdit1.Handle, DC);
end;
 
(*
  Establece el ancho de las tabulaciones del RichEdit
  Usamos todas las tabulaciones del mismo ancho.
  La fórmula usada para establecer el ancho de cada
  tabulación es
  
    AnchoReal = 15*Value*CharWidth
*)
procedure TForm1.SetTabWidth(Value: Word);
var
  Paragraph: TParaFormat;
  Index: Integer;
 
begin
  // Establecer las posiciones de las tabulaciones
  with Paragraph do
  begin
    cbSize := SizeOf(TParaFormat);
    dwMask := PFM_TABSTOPS;
    cTabCount := MAX_TAB_STOPS;
    for Index := 0 to MAX_TAB_STOPS - 1 do
      rgxTabs[Index] := 15*(Index*Value + 1)*GetCharWidth;
  end;
 
  RichEdit1.Perform(EM_SETPARAFORMAT, 0, LParam(@Paragraph));
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Paragraph: TParaFormat;
 
begin
  // Establecer márgenes izquierdo y derecho
  with Paragraph do
  begin
    cbSize := SizeOf(TParaFormat);
    dwMask := PFM_STARTINDENT or PFM_RIGHTINDENT;
    dxStartIndent := 15*GetCharWidth;
    dxRightIndent := 15*GetCharWidth;
  end;
 
  RichEdit1.Perform(EM_SETPARAFORMAT, 0, LParam(@Paragraph));
end;

La parte del FormCreate fue necesaria ya que la primera tabulación no la ponía donde yo quería de manera que establecí el margen con el mismo ancho que la tabulación.

Hace tiempo que hice este código así que desconozco si actualmente el "problema" con la VCL se ha solucionado. Aunque aparentemente no, o bien es simplemente cuestión de que no sé como usar la mencionada propiedad Paragraph.Tabs directamente.

// Saludos
Responder Con Cita