-
Итак, задача написать свою кнопку-картинку. То есть такая кнопка похожа на TImage, но мы задаем не одну картинку, а несколько (для разных состояний кнопки). В другой моей ветке: http://pda.delphimaster.net/?n=3&id=1206102762DVM дал пример такой кнопки, но там все сделано на основе TBitmap, я хотел бы иметь возможность загружать картинки разных форматов. Требования к кнопке: 1. Возможность задавать разные картинки для разных состояний: Обычная, Не активная, Нажатая, мышь над кнопкой 2. Возможность использоватеь разные форматы картинок из пункта 1. 3. Наличие Caption, которое бы работало так же как и в TButton. 4. Наличие Font. 5. Наличие Action. Тоже должно работать как в обычной кнопке. Вопросы: 1. Кого выбрать родителем? 2. Правильно ли я понял, что если я для картинок буду использовать TPicture, то смогу использовать разные форматы? 3. Action, Caption и Font уже есть у TControl. Если я просто открою к ним доступ, будут лиони работать или придется еще что-то сделать? 4. Код каких компонентов смотреть, в качестве примера? Я например не очень представляю как рисовать картинки, где искать пример? В TImage? 5. Любые замечения. ЗЫ DimaBr пишу свой компонент :).
-
1. Если кнопка будет "реальной", то есть иметь окно (её например можно найти WinAPI и нажать с другого приложения) то родитель TCustomControl, если просто рисунок - TGraphicsControl 2. Правильно, только количество форматов не много (BMP, ICO, EMF, WMF), для изысканных нужно будет подключать библиотеки или свои свои наработки. 3. Action - да, Сарtion & Font - используя их вы будите отрисовывать свой заголовок на кнопке. 4. Например TSpeedButton 5. Замечания Можно не писать кнопку с нуля, а взять готовую и дополнить её. Например, возьмите TSpeedButton, перекройте procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
procedure Paint; override;
-
> для изысканных нужно будет подключать библиотеки или свои > свои наработки.
Я так понял, что, чтобы подключить доп формат (готовый) то нужно просто скачать соотв модуль (например TPNGImage с torry) и в TypeLib прописать путь. После этого он доступен для выбора в диалогах загрузки картинки, так? Я просто не оч. понимаю как этот механизм работает.
1. Если кнопка будет «реальной», то есть иметь окно (её например можно найти WinAPI и нажать с другого приложения) то родитель TCustomControl, если просто рисунок TGraphicsControl Ясно. Наверно окно как раз ненужно.
> Можно не писать кнопку с нуля, а взять готовую и дополнить > её. > Например, возьмите TSpeedButton, перекройте
О, наверно это то, что надо. Я наверно понижу видимость некоторых свойств. Glyph, Flat например. Это оч. плохо? Чем нибудь грозит?
-
Понизить видимость нельзя
-
> Понизить видимость нельзя
Как нельзя? перемещю соотв свойства в protected и все.
-
А зачем нужен FDrawing в Paint у TImage?
-
Я вот думаю, может по аналогии с кодом DVM сделать так: 1. Добавляю поле FCurrentImage: TPicture; 2. Рисование взять из TImage var
Save: Boolean;
begin
if csDesigning in ComponentState then
with inherited Canvas do
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
end;
try
with inherited Canvas do
StretchDraw(DestRect, CurrentImage.Graphic);
finally
end;
end; А вот сам это CurrentImage менять при надобности. Только вот где его менять правильно? Или Надо проверять все состояния в Paint и рисовать нужную картинку? И еще. Как выводит Caption? Я что-то в TSpeedButton ненайду. Просто TextOut?
-
Кулибин. Компонентов таких написано море.
-
Код DVM - я бы сказал не очень. Рисовать в MouseUp - извращение. ActualBmp.Assign(Bmp); - тоже не ахти... Моё предложение. Заводим несколько свойства типа TPicture для разных состояний TMyButtoState = (mbsUp, mbsHot, mbsDown, mbsDisabled);
private
fImages: array[TMyButtoState] of TPicture;
property ImageHot: TPicture index mbsHot read GetImage write SetImage;
Заводим переменную - состояние кнопки fButtonState: TMyButtoState;в зависимости от которого в методе PAINT отрисовываем копку с нужного изображение
-
Буквально за час (правда, без Caption) unit HSFlatImageButton;
interface
uses
Messages, Classes, Graphics, Controls;
type
THSButtonState = (hsbsUp, hsbsDown, hsbsHover, hsbsDisabled);
THSFlatImageButton = class(TGraphicControl)
private
FImages: array[THSButtonState] of TBitmap;
FState: THSButtonState;
procedure SetState(const Value: THSButtonState);
function GetImage(const Index: THSButtonState): TBitmap;
procedure SetImage(const Index: THSButtonState; const Value: TBitmap);
function GetDisabledImage: TBitmap;
function GetDownImage: TBitmap;
function GetHoverImage: TBitmap;
function GetUpImage: TBitmap;
procedure SetDisabledImage(const Value: TBitmap);
procedure SetDownImage(const Value: TBitmap);
procedure SetHoverImage(const Value: TBitmap);
procedure SetUpImage(const Value: TBitmap);
protected
procedure Paint; override;
procedure CMMouseEnter (var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave (var Message: TMessage); message CM_MOUSELEAVE;
procedure MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); override;
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
property State: THSButtonState read FState write SetState;
property UpImage: TBitmap read GetUpImage write SetUpImage;
property DownImage: TBitmap read GetDownImage write SetDownImage;
property HoverImage: TBitmap read GetHoverImage write SetHoverImage;
property DisabledImage: TBitmap read GetDisabledImage write SetDisabledImage;
property OnClick;
end;
implementation
procedure THSFlatImageButton.CMMouseEnter(var Message: TMessage);
begin
if Enabled then
State := hsbsHover;
end;
procedure THSFlatImageButton.CMMouseLeave(var Message: TMessage);
begin
inherited;
if Enabled then
State := hsbsUp;
end;
constructor THSFlatImageButton.Create(AOwner: TComponent);
var
I: THSButtonState;
begin
inherited;
Height := 16;
Width := 16;
ControlStyle := ControlStyle + [csReplicatable];
FState := hsbsUp;
for I := Low(THSButtonState) to High(THSButtonState) do
begin
FImages[I] := TBitmap.Create;
FImages[I].Height := 16;
FImages[I].Width := 16;
end;
end;
destructor THSFlatImageButton.Destroy;
var
I: THSButtonState;
begin
for I := Low(THSButtonState) to High(THSButtonState) do
FImages[I].Free;
inherited;
end;
function THSFlatImageButton.GetDisabledImage: TBitmap;
begin
Result := GetImage(hsbsDisabled);
end;
function THSFlatImageButton.GetDownImage: TBitmap;
begin
Result := GetImage(hsbsDown);
end;
function THSFlatImageButton.GetHoverImage: TBitmap;
begin
Result := GetImage(hsbsHover);
end;
function THSFlatImageButton.GetImage(const Index: THSButtonState): TBitmap;
begin
Result := FImages[Index];
end;
function THSFlatImageButton.GetUpImage: TBitmap;
begin
Result := GetImage(hsbsUp);
end;
procedure THSFlatImageButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Enabled then
State := hsbsDown;
end;
procedure THSFlatImageButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Enabled then
State := hsbsUp;
end;
procedure THSFlatImageButton.Paint;
begin
Canvas.StretchDraw(ClientRect, FImages[FState]);
end;
procedure THSFlatImageButton.SetDisabledImage(const Value: TBitmap);
begin
SetImage(hsbsDisabled, Value);
end;
procedure THSFlatImageButton.SetDownImage(const Value: TBitmap);
begin
SetImage(hsbsDown, Value);
end;
procedure THSFlatImageButton.SetHoverImage(const Value: TBitmap);
begin
SetImage(hsbsHover, Value);
end;
procedure THSFlatImageButton.SetImage(const Index: THSButtonState;
const Value: TBitmap);
begin
FImages[Index].Assign(Value);
if FState = Index then
Invalidate;
end;
procedure THSFlatImageButton.SetState(const Value: THSButtonState);
begin
if FState <> Value then
begin
FState := Value;
Invalidate;
end;
end;
procedure THSFlatImageButton.SetUpImage(const Value: TBitmap);
begin
SetImage(hsbsUp, Value);
end;
end.
-
> > Понизить видимость нельзя > Как нельзя? перемещю соотв свойства в protected и все.
Перемешение ничего не даст, можете проверить
-
> Кулибин. Компонентов таких написано море.
Покажи удовлетворяющий сабжу. Чтобы с Caption и c Action'ом был. > Моё предложение.
Ок. Последую. Только зачем тогда mbsDisabled если можно проверять просто Enabled. mbsHot надо ставить и снимать в CMMouseEnter|Leave, так? А вот где можно понять что кнопка нажата? Так а как рисовать Caption? Нашел это место в TSpeedButton там как-то хитро закручено через TButtonGlyph
-
> Перемешение ничего не даст, можете проверить
Действительно. В результате только CodeInsite не видит свойство, а компиляция идет нормально
Может тогда заглушки сделать?
-
Kolan © (01.04.08 11:41) [11]
Любой наследник TButton,TSpeedButton,TBitBtn будет иметь Action. Перекрытие процедуры Paint дает тебе возможность рисовать хоть черта лысого.
Накачай компонентов с torry.net - там кнопок с картинками как звезд на небе, посмотри, как устроены, пойми почему так, а не иначе.
-
> Буквально за час
> Кулибин
Еще нет Экшена и TPicture :)
Благодарю. Теперь понятно где какие состояния выставлять.
ЗЫ Не увидел где устанавливается Disabled.
-
Kolan © (01.04.08 11:48) [14]
TPicture не нужен.
> ЗЫ Не увидел где устанавливается Disabled.
Не стал делать, но обычно в обработчике сообщение CM_ENABLEDCHANGED
-
> Игорь Шевченко © (01.04.08 11:34) [9]
Класс !!! Проиндексировав картинки можно сокатить код
-
if Enabled then State := XXX; Можно перенести в SetState тогда
procedure THSFlatImageButton.SetState(Value: THSButtonState);
begin
if not Enabled then Value := hsbsDisabled;
if fState = Value then Exit;
fState := Value;
Invalidate;
end;
-
Ок.
-
DimaBr © (01.04.08 12:51) [16]
У меня не вышло проиндексировать :) Я запамятовал, можно ли индексировать свойства, значением которых является объект
|