【问题标题】:Using Windows API DrawText with DT_PATH_ELLIPSIS使用带有 DT_PATH_ELLIPSIS 的 Windows API DrawText
【发布时间】:2014-05-06 14:59:27
【问题描述】:

我正在尝试使用 Windows API 函数DrawText,但没有得到我期望的结果。也许我在这里做错了什么,但是当我阅读文档时,我真的没有看到问题。我正在使用以下代码。

function GetEllipsisString(Font: TFont; const Text: string; 
  Width: integer): String;
var
  DC: HDC;
  SaveFont: HFont;
  R: TRect;
begin
  DC := GetDC(0);
  try
    SaveFont := SelectObject(DC, Font.Handle);
    R := Rect (0, 0, Width-1, 0);
    Result := Text+'    ';
    Winapi.Windows.DrawtextW (DC, PChar(Result), Length(Result), R,
      DT_CALCRECT+DT_LEFT+DT_PATH_ELLIPSIS+DT_MODIFYSTRING);
    SelectObject(DC, SaveFont);
  finally
    ReleaseDC(0, DC);
  end;
end;

DT_PATH_ELLIPSIS 似乎什么也没做。我用 DT_END_ELLIPSIS 进行了尝试,这给了我一些结果(参见示例)。当我给参数“Text”一个带有反斜杠(\)的字符串时,它似乎设置了省略号,但该函数忽略了矩形测量值。

示例

Text = 'This text has to many characters to fit.'
DT_END_ELLIPSIS returns 'This text has to m...'#0'characters to fit.    '
DT_PATH_ELLIPSIS returns 'This text has to many characters to fit.    '

【问题讨论】:

  • 您打印的字符串不是路径。您期待什么结果?
  • 我期待的是这样的:“这个文本有......适合的字符。”文档说明:“对于显示的文本,用省略号替换字符串中间的字符,以便结果适合指定的矩形。”
  • 据我所知,反斜杠之间的路径正在缩短。
  • @MBo:这不是“保持沉默”。常量的名称使用 PATH 是有原因的 - 它用于制作包含文件或目录名称的文本,因此是 PATH 一词。
  • 我用DT_PATH_ELLIPSIS 做了ownerdraw listbox 并且可以确认它工作正常。 @TLama 绝对正确,DrawText 缩短了中间路径组件,保留了前导和尾随。

标签: delphi winapi


【解决方案1】:

如果字符串对于给定的矩形来说太宽,这里会绘制一个中间带有省略号的字符串:

procedure DrawTextWithMiddleEllipsis(Canvas: TCanvas; Text: string; DrawRect:
   TRect; Flags: Integer);
var
  S, LastS: string;
  R: TRect;
  Sz: TSize;
  RectWidth, I: Integer;
begin
  S := Text;
  R := DrawRect;
  GetTextExtentPoint32(Canvas.Handle, S, Length(S), Sz);
  RectWidth := DrawRect.Right - DrawRect.Left;
  if Sz.cx > RectWidth then
  begin
    //The string is too wide. Need to cut it down with ellipsis
    //Start with the smallest possible truncated-and-ellipsis-modified string,
    //and expand until we have the biggest one that can fit
    S := '...';
    for I := 1 to Length(Text) div 2 do
    begin
      LastS := S;
      //Get the first I chars, then the ellipsis, then the last I chars
      S := Copy(Text, 1, I) + '...' + Copy(Text, Length(Text) - I + 1, I);
      GetTextExtentPoint32(Canvas.Handle, S, Length(S), Sz);
      if Sz.cx > RectWidth then
      begin
        DrawText(Canvas.Handle, LastS, Length(LastS), DrawRect, Flags);
        Break;
      end;
    end;
  end else
    //The string will fit in the width of the given rect, don't mess with it
    DrawText(Canvas.Handle, S, Length(S), DrawRect, Flags);
end;

这是一个如何调用它的示例(PaintBox1 是 TPaintBox):

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  S: string;
  R: TRect;
begin
  S := 'This is extra long text that should overflow';
  R := PaintBox1.ClientRect;
  DrawTextWithMiddleEllipsis(PaintBox1.Canvas, S, R, DT_LEFT or DT_TOP);
end;

【讨论】:

  • 问题是为什么 DrawText 没有按我的预期工作。我已经编写了自己的函数来完成这项工作(整个单词都会中断)。不过还是谢谢。
【解决方案2】:

基于@jthurman 代码

优点:
*简化,
*更通用
*修复一个错误

享受吧。

 { Takes a long string and truncates it in the middle. Example: '123...789'  }
 function GetEllipsisText(CONST s: string; Canvas: TCanvas; MaxWidth:    Integer; Flags: Integer= DT_LEFT or DT_TOP): string;
var
 NewStr, LastStr: string;
 TextSize: TSize;
 EllipsisSize: Integer;
begin
 NewStr := '...';
 EllipsisSize:= Canvas.TextWidth(NewStr);

 GetTextExtentPoint32(Canvas.Handle, s, Length(s), TextSize);
 if TextSize.cX > MaxWidth
 then
   //Start with the smallest possible truncated-and-ellipsis-modified string, and expand until we have the biggest one that can fit
   for VAR i:= 1 to Length(s) div 2 do
    begin
       LastStr := NewStr;
       NewStr := Copy(s, 1, I) + '...' + Copy(s, Length(s) - I + 1, I);   // Get the first I chars, then the ellipsis, then the last I chars
       GetTextExtentPoint32(Canvas.Handle, NewStr, Length(NewStr), TextSize);
       if TextSize.cx > (MaxWidth - EllipsisSize)
       then Exit(LastStr);
    end
else
   Result:= s;   //The string will fit in the width of the given rect, don't mess with it
end;

【讨论】:

    猜你喜欢
    • 2017-10-31
    • 1970-01-01
    • 2023-03-26
    • 2018-10-28
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 2015-01-04
    相关资源
    最近更新 更多