Кнопка с пользовательским фоном, текст внутри - C++ Builder

Я хочу создать кнопку с пользовательским фоном и текстом внутри. (при исполнении)

Но текст идет рядом с картинкой, а не внутри.

Кнопка и текст рядом с ней

Вы знаете какой-нибудь способ сделать это?

Для информации, я могу использовать все компоненты пакета TMS

1 ответ

Решение

TSpeedButton иметь Glyph собственность, но IIRC они не объединяют Caption а также Glyph все вместе. К счастью, вы можете создавать свои глифы программно на ходу, используя Graphics::TBitmap используя ваше фоновое изображение и визуализируем текст поверх него... Я не Delphi-кодер, но в конструкторе это будет выглядеть так:

Graphics::TBitmap *bmp=new Graphics::TBitmap;
bmp->LoadFromFile("button_background.bmp");
bmp->Canvas->Font->Color=clWhite;
bmp->Canvas->Brush->Style=bsClear;
AnsiString s="caption1"
int x=(bmp->Width-bmp->Canvas->TextWidth(s))/2;
int y=(bmp->Height-bmp->Canvas->TextHeight(s))/2;
bmp->TextOutA(x,y,s);
bmp->SaveToFile("button1.bmp");
delete bmp;

Таким образом, вы можете создать утилиту, которая создаст все необходимые глифы, которые вы затем используете в IDE для своего проекта. Я никогда не пытался загрузить глифы во время выполнения, но мог бы быть способ (сделать это непосредственно в целевом приложении init).

[Edit1] Наконец-то есть время для тестирования

Свойство Glyph является растровым, поэтому вы можете загружать из файла напрямую... нет необходимости обновлять / удалять. Если вы хотите что-то более надежное, взгляните на это. Я создал пустое новое приложение с несколькими формами TSpeedButtons на нем и установить их размер позиции и Caption вот так:

IDE дизайнер

И я использовал бесшовную текстуру в качестве фона (так что я могу иметь любой размер кнопки без проблем с масштабированием...):

текстура

И инициализировать мои кнопки во время выполнения так:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
void bt_init(TSpeedButton *bt,Graphics::TBitmap *bmp)
    {
    int x,y,xs,ys;
    AnsiString s;
    // clear caption
    s=bt->Caption; bt->Caption="";
    // prepare glyph
    bt->Glyph->PixelFormat=bmp->PixelFormat;
    bt->Glyph->SetSize(bt->Width,bt->Height);
    // render seamless background (repeat texture)
    xs=bmp->Width;
    ys=bmp->Height;
    for (y=0;y<bt->Width;y+=ys)
     for (x=0;x<bt->Width;x+=xs)
      bt->Glyph->Canvas->Draw(x,y,bmp);
    // set transparent color
    bt->Glyph->Canvas->Pixels[0][bt->Glyph->Height-1]=clBlack;
    // render caption
    bt->Glyph->Canvas->Font->Color=clWhite;
    bt->Glyph->Canvas->Font->Style=TFontStyles()<<fsBold;
    bt->Glyph->Canvas->Brush->Style=bsClear;
    x=(bt->Glyph->Width-bt->Glyph->Canvas->TextWidth(s))/2;
    y=(bt->Glyph->Height-bt->Glyph->Canvas->TextHeight(s))/2;
    bt->Glyph->Canvas->TextOutA(x,y,s);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    Graphics::TBitmap *bmp=new Graphics::TBitmap;
    bmp->LoadFromFile("button.bmp");
    bmp->PixelFormat=pf32bit;
    bt_init(SpeedButton1,bmp);
    bt_init(SpeedButton2,bmp);
    bt_init(SpeedButton3,bmp);
    bt_init(SpeedButton4,bmp);
    delete bmp;
    }
//---------------------------------------------------------------------------

Вы можете добавить рамку рендера тоже (другая текстура...). Также вы можете изменить отображение заголовка (больший шрифт или цветную рамку для усиления контраста). Вот предварительный просмотр:

предварительный просмотр

Помните, что нижний левый угол конечного глифа содержит прозрачный цвет. Так что, если вы не используете его, установите его с цветом, не используемым в текстуре, чтобы избежать артефактов.

Также взгляните на это:

для некоторых текстовых идей визуального улучшения.

Другие вопросы по тегам