【问题标题】:How to know max caption length in a TForm in Delphi如何在 Delphi 中知道 TForm 中的最大字幕长度
【发布时间】:2019-02-27 10:30:12
【问题描述】:

在 Delphi VCL 应用程序的主窗口中,我想以这种方式显示标题:

文本1 文本2 文本3

占用所有可用于标题的空间。 text1 与标题左侧对齐,text2 在中间,text3 在右侧。如果我知道当前标题的最大长度,可以计算 text1 和 text2 之间的空格以及 text2 和 text3 之间的空格,以使它们按需要对齐。 问题在于,对于不同的表单大小,标题会改变大小。 我如何知道 (TForm).caption 的当前最大长度?谢谢

编辑
我尝试将标题设置为 300 个字符的长字符串,并等待 show 事件在结尾处显示带有“...”的标题(意思是溢出)。但是当试图在标题中搜索“...”时,没有找到它。如果它找到了“...”,那么就可以知道标题的长度。我怎样才能找到“...”?

【问题讨论】:

  • 是的,我的错误是短字符串
  • @Hector:这听起来是个非常糟糕的主意。窗口标题栏不应该在 Windows 中这样使用。与系统对抗容易失败。
  • 我认为在你达到空间限制之前就有一个字符限制。您正在尝试的可能是个坏主意
  • 您可能必须自己处理WM_NCPAINT 消息才能绘制标题栏。然后你可以用计算出的坐标分别绘制三个字符串。但是你必须绘制整个标题栏,这对于每个新的 Windows 版本都会变得非常棘手。可能最简单的方法是将Caption 留空,然后通过首先调用默认处理程序来处理WM_NCPAINT,然后在操作系统绘制的任何内容上绘制文本
  • @Andreas:Windows 标题栏也没有包含主菜单,但我输入的 Firefox 有这个。但正如雷米所说,它必须是非客户涂料。我同意这可能不是一个好主意,但这是他的决定。

标签: delphi vcl


【解决方案1】:

您可以计算当前字幕的最大长度。

表单的当前 ClientWidth 在运行时可用,并且使用表单设计器可以估计图标占用的空间。 AnsiString 的像素宽度由 Canvas->TextWidth 函数返回。

AnsiString Words = First + Middle + Last;

// store width of text in pixels
WordsWidthInPixels  = Canvas->TextWidth(Words);

空格的数量可以借助一两个空格的TextWidth找到。

更新:

这里是一些使用系统指标而不是设计者估计的代码。我已经将几乎所有代码都放在了一个名为 GetNumSpacesMetric 的函数中。

函数头添加到Form类的头文件中:-

class TForm1 : public TForm
{
__published:    // IDE-managed Components
        void __fastcall FormResize(TObject *Sender);
private:    // User declarations
public:     // User declarations
        __fastcall TForm1(TComponent* Owner);

        int  __fastcall  GetNumSpacesMetric(TObject *Sender, TComponent* AForm);
};

在表单上创建事件OnResize,并添加在调整表单大小时更新Caption的代码。如果表单的名称不是 Form1 则需要在此处的代码中进行更改:-

void __fastcall TForm1::FormResize(TObject *Sender)
{
  // strings
  const AnsiString    First  = AnsiString("First");
  const AnsiString    Middle = AnsiString("Middle");
  const AnsiString    Last   = AnsiString("Last");

  // get number of spaces
  int NumSpacesMetric = GetNumSpacesMetric(Sender, Form1);

  // print the caption
  if( NumSpacesMetric > 0 )      {
      AnsiString Spaces = AnsiString::StringOfChar(' ', NumSpacesMetric);
      AnsiString caption = First + Spaces + Middle + Spaces + Last;
      Form1->Caption = caption;
  }
}

接下来添加 GetNumSpacesMetric 函数定义。在函数头和创建 Image 的位置。

// calculate the number of spaces needed between three words in Form Caption
int  __fastcall  TForm1::GetNumSpacesMetric(TObject *Sender, TComponent* AForm)
{
  const int          NumberOfMenuIcons = 3;
  const AnsiString   Words = "FirstMiddleLast";
  const AnsiString   TwinSpace = AnsiString::StringOfChar(' ', 2);
  const int          Squeeze   = 7 * 8;   //  tweak 1 - squeeze string length
  //const int          FineTune  = 840;     //  tweak 2 - lengthen string when width smaller
  //const int          LimitLength = 980;   //  tweak 3

  static int         WordsPixelWidth;
  static int         TwinSpacePixelWidth = 1;

  // get metric data
  static NONCLIENTMETRICS   ncm;
  static bool done = false;

  // do once
  if(!done)
  {
    ncm.cbSize =  sizeof(NONCLIENTMETRICS);
    SystemParametersInfo( SPI_GETNONCLIENTMETRICS,
                          sizeof(NONCLIENTMETRICS), &ncm, NULL);

    TImage *tmpImage = new TImage(AForm);

    // Font data
    tmpImage->Canvas->Font->Handle = CreateFontIndirect(&ncm.lfCaptionFont);

    // get pixel widths of Words and double space
    WordsPixelWidth     = tmpImage->Canvas->TextWidth(Words);
    TwinSpacePixelWidth = tmpImage->Canvas->TextWidth(TwinSpace);

    DeleteObject(tmpImage->Canvas->Font->Handle);

    done = true;
  }

  int clientwidth = ClientWidth;
  /*
  // limit length of text if required
  if( clientwidth > LimitLength)
    clientwidth = LimitLength;
  */

  // client width minus icon widths and words width
  int NumOfPixelsLeft  =  clientwidth
                       -  ncm.iCaptionWidth
                       - (ncm.iMenuWidth * NumberOfMenuIcons)
                       -  WordsPixelWidth
                       -  Squeeze
                     //  + ((8 * (FineTune - clientwidth))/100)
                       ;

  // return number of pixels available divided by size of two spaces
  return NumOfPixelsLeft / TwinSpacePixelWidth;
}
//---------------------------------------------------------------------------

有一些调整可用于更改程序并在代码中给出简短描述。

更新 2:GetNumSpacesMetric 添加了一个参数,用于传递 Form 对象。

有一组更新的指令可以获取一些指标:-

TITLEBARINFO 结构,TITLEBARINFOEX 结构,GetTitleBarInfo 函数和 GetTitleBarInfoEx 函数。 p>

【讨论】:

  • 如果您提到Form.Canvas,那么这是一个不好的建议,因为Form 的字体不等于操作系统用于绘制标题文本的字体。要获取出现在标题栏上的任何元素的尺寸,最好使用GetSystemMetrics function,这样就不需要看Designer并用眼睛计算标题栏上的空闲空间。但即使你从标题栏中去掉 all 图标和按钮,文本仍然有一个限制:255 个字符。那是你的答案是完全错误的。
  • 好的,谢谢。 Hector 正在寻找表单标题的当前最大长度。
  • @DBB - 改写 Dima 所说的部分内容:除非您检索并为其分配系统标题字体,否则画布无法帮助计算标题文本宽度。详细说明一下:字符串的像素宽度取决于所使用的字体。并且标题不使用您表单的字体。也就是说,你的答案是完全错误的。
  • @Sertac - 您可能完全正确,但如果您个性化桌面并更改活动窗口文本,则窗口文本也会更改。当然程序可以改变字体,但它会被改变。
  • 我删除了我的反对意见,但您最好使用 GetTitleBarInfo 而不是 ClientWidth 来找出最大空间。
猜你喜欢
  • 1970-01-01
  • 2010-11-14
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多