如何在Delphi中的TForm中知道最大字幕长度

时间:2018-09-23 21:25:02

标签: delphi vcl

在Delphi VCL应用程序的主窗口中,我想要这样的标题:

text1 text2 text3

占用字幕的所有可用空间。 文本1对齐标题的左侧,文本2对齐中间,文本3对齐右侧。如果我知道当前字幕的最大长度,则可以计算text1和text2之间的间隔以及text2和text3之间的间隔,以根据需要对齐它们。 问题在于,使用不同的表单大小,标题会更改大小。 我怎么知道(TForm).caption的当前最大长度?谢谢

修改
我试图将标题设置为300个字符的长字符串,并等待show事件在最后显示“ ...”的标题(表示溢出)。但是,当试图在标题中搜索“ ...”时,找不到它。如果找到“ ...”,则可以知道字幕的长度。我如何找到“ ...”?

1 个答案:

答案 0 :(得分: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 功能。