Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TCheckBox.AutoSize, или как вычислить ширину TCheckBox 
V
    Опции темы
shmelina
Дата 6.10.2010, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Добрый день.

Подскажите, как вычислить ширину TCheckBox?
TCheckBox создается динамически и там может быть разный текст. Требуется вычислить ширину контрола и задать ее в соответствии с текстом.
Я так понимаю, нужно сложить: ширина квадратика + расстояния между квадратиком и меткой + ширина метки.

Пробовал разобраться с исходниками TCheckBox, но ничего не понял. Буду очень признателен, за краткий алгоритм решения этой задачи. Предпочитаю удочку, а не рыбу.

Спасибо.
PM MAIL   Вверх
aleksh
Дата 6.10.2010, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: 3
Всего: 13



удочку так удочку, есть функции вычисляющие длину слов, размер чекбокса без надписей можно посмотреть в дизайн-тайме, при создании чекбокса брать минимальную ширину + длину текста
PM MAIL   Вверх
shmelina
Дата 6.10.2010, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



По удочкой я понимал - помочь разобраться как происходит отрисовка в исходниках компонента. Я так понимаю, что достаточно найти с какого места (Left) рисуется метка.

Функцию вычисления ширины текста можно взять у Canvas, метод TextWidth. Так?

Ширину квадратика в дизайне брать как-то не красиво. Не уверен, что при разных обстоятельствах (масштаб, ОС, темы...) она будет одинаковая. Да и расстояние между квадратиком и текстом тоже есть.
PM MAIL   Вверх
Frees
Дата 6.10.2010, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



Цитата(shmelina @  6.10.2010,  23:14 Найти цитируемый пост)
Не уверен, что при разных обстоятельствах (масштаб, ОС, темы...) она будет одинаковая. Да и расстояние между квадратиком и текстом тоже есть.

GetSystemMetrics;

а разве у TCheckBox нет AutoSize?


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
shmelina
Дата 6.10.2010, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Frees @  6.10.2010,  21:02 Найти цитируемый пост)
GetSystemMetrics;

Точно. Там вроде все что нужно есть. 
А сложно будет написать компонент-наследник, в котором будет свойство AutoSize? Я просто в исходниках не понял, как там отрисовка происходит. Знаний не хватает.
Цитата(Frees @  6.10.2010,  21:02 Найти цитируемый пост)
а разве у TCheckBox нет AutoSize? 

Нет. Я сам в шоке.

Я пока пошел простым путем, а там видно будет. Прошу помощи.
1. Нужно ли делать ReleaseDC? Судя по инету - нужно. Но с DC я плохо знаком.
2. Правильно ли я получаю DC? Вернее можно ли его получать вот так.
3. Правильно ли я освобождаю DC?
4. Нужно ли для Canvas указывать шрифт, если я его в CheckBox-е не меняю?

Код

var
  Canvas: TCanvas;
...
with TCheckBox(WinControl) do
begin
  Caption := Value;
  Canvas := TCanvas.Create;
  try
    Canvas.Handle := GetDC(Handle);
    try
      // Canvas.Font ?
      Width := Canvas.TextWidth(Caption) + 16;
    finally
      ReleaseDC(Handle, Canvas.Handle);
    end;
  finally
    Canvas.Free;
  end;
end;


Это сообщение отредактировал(а) shmelina - 6.10.2010, 22:38
PM MAIL   Вверх
XperT
Дата 7.10.2010, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 2
Всего: 4



А если посмотреть как у TLabel организован AutoSize и адаптировать под чекбокс?
Сейчас уже поздно, соображаю плохо, но вроде оно:
Код

procedure TCustomLabel.AdjustBounds;
const
  WordWraps: array[Boolean] of Word = (0, DT_WORDBREAK);
var
  DC: HDC;
  X: Integer;
  Rect: TRect;
  AAlignment: TAlignment;
begin
  if not (csReading in ComponentState) and FAutoSize then
  begin
    Rect := ClientRect;
    DC := GetDC(0);
    try
      Canvas.Handle := DC;
      DoDrawText(Rect, (DT_EXPANDTABS or DT_CALCRECT) or WordWraps[FWordWrap]);
      Canvas.Handle := 0;
    finally
      ReleaseDC(0, DC);
    end;
    X := Left;
    AAlignment := FAlignment;
    if UseRightToLeftAlignment then ChangeBiDiModeAlignment(AAlignment);
    if AAlignment = taRightJustify then Inc(X, Width - Rect.Right);
    SetBounds(X, Top, Rect.Right, Rect.Bottom);
  end;
end;

PM MAIL   Вверх
shmelina
Дата 7.10.2010, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(XperT @  7.10.2010,  00:49 Найти цитируемый пост)
А если посмотреть как у TLabel организован AutoSize и адаптировать под чекбокс?

Тут больше было дело не в отрисовке, а в определении ширины всего контрола. Ну тут уже подсказали про GetSystemMetrics, так что этот вопрос снят пока.

Все еще жду от вас ответов на вопросы по моему исходнику.

Спасибо.
PM MAIL   Вверх
Frees
Дата 7.10.2010, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



Цитата(shmelina @  7.10.2010,  14:00 Найти цитируемый пост)
Все еще жду от вас ответов на вопросы по моему исходнику.

вряд ли твой исходник будет всегда корректно работать, например ты не учел Align. XperT правельно говорит, посмотри как это реализовано в других контролах.

Это сообщение отредактировал(а) Frees - 7.10.2010, 12:47


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
shmelina
Дата 7.10.2010, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Frees @  7.10.2010,  12:47 Найти цитируемый пост)
вряд ли твой исходник будет всегда корректно работать, например ты не учел Align. 

Align мне не страшен. В моей узкой задаче у этих контролов он не используется. Мне нужно было только правильно рассчитать ширину контролов, чтобы они не наезжали без причины на другие контролы. Прошу прощения, что не рассказал об этом подробнее.
Цитата(Frees @  7.10.2010,  12:47 Найти цитируемый пост)
XperT правельно говорит, посмотри как это реализовано в других контролах.

Покопавшись в исходниках CheckBox, я понял, что в этот раз я не осилю эту задачу. Посмотрите, пожалуйста, все ли корректно в исходнике с DC?
PM MAIL   Вверх
Frees
Дата 7.10.2010, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



Цитата(shmelina @  7.10.2010,  18:15 Найти цитируемый пост)
Посмотрите, пожалуйста, все ли корректно в исходнике с DC?


Цитата(shmelina @  7.10.2010,  01:09 Найти цитируемый пост)
 Width := Canvas.TextWidth(Caption) + 16;

+ 16 на GetSystemMetrics; (наверняка есть такая метрика)



--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
shmelina
Дата 7.10.2010, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Frees @  7.10.2010,  16:10 Найти цитируемый пост)
+ 16 на GetSystemMetrics; (наверняка есть такая метрика)

Хорошо, посмотрю. А Font надо указывать для Canvas?
PM MAIL   Вверх
shmelina
Дата 7.10.2010, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



В общем докладываю. Ширину картинки с галочкой нашел быстро, а вот расстояние между галкой и текстом так и не нашел. Перерыл пол-интернета, клянусь! Возможно знание английского недостаточно хорошее. Везде по-разному рекомендуют, где-то Canvas.TextWidth(' '), где-то GetSystemMetrics(SM_CXEDGE) * 2, где-то GetSystemMetrics(SM_CXBORDER) * 4. Методом тыка понял, что подходит число 4. Последние два варианта его же и показывают.

Я выше спрашивал про Canvas.Font - его указывать не обязательно, если он совпадает у CheckBox и у DC. Проверил на разных шрифтах - все работает правильно. Масштаб шрифтов проверять нет уже сил.

Время поиска решения этой задачи превысило все мыслимые пределы. По этому пока останусь на этом варианте:
Код

{ Возможно вместо 4 можно использовать
   GetSystemMetrics(SM_CXEDGE) * 2 или
   GetSystemMetrics(SM_CXBORDER) * 4 или что-то другое }
Width := GetSystemMetrics(SM_CXMENUCHECK) + 4 + Canvas.TextWidth(Caption);


Всем спасибо за помощь. Как всегда выручили.
PM MAIL   Вверх
zubpost
Дата 4.6.2019, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 15.3.2018

Репутация: нет
Всего: нет



Я сделал так - Создал хелпер.
Добавляете этот юнит к поекту. И после того как задали текст вызываете процедуру TCheckBox.correctSize. 


Код

unit uCheckBoxHelper;

interface

uses
  Vcl.StdCtrls, Vcl.Graphics, Winapi.Windows;

type
  TCheckBoxHelper = class helper for TCheckBox
  public
    procedure correctSize;
  end;

implementation

{ TCheckBoxHelper }

procedure TCheckBoxHelper.correctSize;
var
  canvas: TCanvas;
  DC: HDC;
begin

  canvas := TCanvas.Create;
  DC := GetDC(0);
  try
    canvas.Handle := DC;
    canvas.Font:=self.Font;
    self.Width:=GetSystemMetrics(SM_CXMENUCHECK) + 4 + Canvas.TextWidth(Caption);
  finally
    ReleaseDC(0, DC);
  end;
  canvas.Free;
end;

end.


Это сообщение отредактировал(а) zubpost - 4.6.2019, 19:58
PM MAIL   Вверх
Google
  Дата 22.7.2019, 09:15 (ссылка)  





  Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0970 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.