C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Как добавить своему компоненту свойство ImageIndex
Rius
Отправлено: 14.05.2005, 09:54


Мастер участка

Группа: Участник
Сообщений: 321



Этого явно недостаточно:
CODE

//---------------------------------------------------------------------------
void __fastcall TButtonImage::SetImageIndex(const TImageIndex Value)
{
   if( FImageIndex != Value)
   {
       FImageIndex = Value;
       if(this) Invalidate();
   }
}
//---------------------------------------------------------------------------
void __fastcall TButtonImage::SetImages(TImageList* Value)
{
   if( FImages != Value)
   {
       FImages = Value;
       if(this)
       {
//            FEditControl.Perform(CM_EDITIMAGECHANGEDEH, ObjectToIntPtr(Self), 0);
//      if Value <> nil then Value.FreeNotification(FEditControl);
       }
   }
}
//---------------------------------------------------------------------------

class PACKAGE TButtonImage : public TButton
{
       typedef TButton Inherited;
private:
TImageIndex FImageIndex;
TImageList* FImages;
void __fastcall SetImageIndex(const TImageIndex Value);
void __fastcall SetImages(TImageList* Value);
__published:
    __property TImageIndex ImageIndex = {read=FImageIndex, write=SetImageIndex, default=-1};
    __property TImageList* Images = {read=FImages, write=SetImages};
};

не выпадает список. может есть какие примеры?
GIZMO
Отправлено: 14.05.2005, 10:29


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (Rius @ 14/05/2005, 09:54)
Этого явно недостаточно:
...
не выпадает список. может есть какие примеры?

Как он тебе выпадет, редактор св-ва надо писать.
Rius
Отправлено: 14.05.2005, 12:42


Мастер участка

Группа: Участник
Сообщений: 321



У многих компонент VCL есть свойство ImageIndex, определенное также. Редактор должен предоставляться средой, как делается для других свойств...
Свой писать — может придется, пока разбираюсь.
Gedeon
Отправлено: 14.05.2005, 12:49


Ветеран

Группа: Модератор
Сообщений: 1742



TImageIndex есть не что иное как int, а конкретно номер рисунка в TImageList, соответственно причем тут редактор? Посмотрите как это реализовано в других компонентах.
И из Первоначального вопроса Rius того, что Вы привели явно достаточно для добавления свойства, а теперь Вам надо позаботиться как достать рисунок и правильно его нарисовать в Вашем компоненте.

Отредактировано Gedeon — 14/05/2005, 12:51
Rius
Отправлено: 14.05.2005, 13:11


Мастер участка

Группа: Участник
Сообщений: 321



Gedeon ImageIndex на самом деле типа Imglist::TImageIndex, что есть переименованный int.
Свойство добавлено, рисунок достать тоже могу, но в инспекторе объектов при выборе ImageIndex должен выпадать список. Вот его-то и нет! Для этого делают редакторы свойств, но этот тип TImageIndex уже должен иметь редактор... Что-то не так делаю.
Перерыл много чего в сети, а нашел один пример в Toolbar2k, там сделан свой редактор свойства, и тот на паскале.

Или у меня синтаксическая ошибка/отличие или очередная "фича" борланда.
здесь удалось добавить выпадающий ImageIndex:
*.pas
CODE
unit ColorButton;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Buttons, ExtCtrls, ImgList;

type
 TDrawButtonEvent = procedure(Control: TWinControl;
   Rect: TRect; State: TOwnerDrawState) of object;

 TColorButton = class(TButton)
 private
   FImages: TImageList;
   FImageIndex: TImageIndex;
   procedure SetImageIndex(const Value: TImageIndex);
   procedure SetImages(const Value: TImageList);
 protected
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
 published
   property Images: TImageList read FImages write SetImages;
   property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default 0;
 end;

procedure Register;

implementation

procedure Register;
begin
 RegisterComponents('RComp', [TColorButton]);
end;

constructor TColorButton.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
end;

destructor TColorButton.Destroy;
begin
 inherited Destroy;
end;

procedure TColorButton.SetImageIndex(const Value: TImageIndex);
begin
 if Value <> FImageIndex then
 begin
   FImageIndex := Value;
   Changed();
 end;
end;

procedure TColorButton.SetImages(const Value: TImageList);
begin
 if Value <> FImages then
 begin
   FImages := Value;
   Changed();
 end;
end;
end.


а здесь — ни в какую!
*.cpp
CODE
//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "ButtonImage.h"

#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TButtonImage *)
{
new TButtonImage(NULL);
}
//---------------------------------------------------------------------------
__fastcall TButtonImage::TButtonImage(TComponent* Owner)
: TButton(Owner)
{
}
//---------------------------------------------------------------------------
namespace Buttonimage
{
   void __fastcall PACKAGE Register()
   {
       TComponentClass classes[1] = {__classid(TButtonImage)};
       RegisterComponents("RComp", classes, 0);
   }
}
//---------------------------------------------------------------------------

void __fastcall TButtonImage::SetImageIndex(const TImageIndex Value)
{
   if( FImageIndex != Value)
   {
       FImageIndex = Value;
       if(this) Invalidate();
       Changed();
   }
}
//---------------------------------------------------------------------------
void __fastcall TButtonImage::SetImages(const TImageList* Value)
{
   if( FImages != Value)
   {
       FImages = (TImageList *)Value;
       Changed();
   }
}
//---------------------------------------------------------------------------


*.h
CODE
//---------------------------------------------------------------------------

#ifndef ButtonImageH
#define ButtonImageH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Windows.hpp>
#include <Messages.hpp>
#include <Graphics.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include <StdCtrls.hpp>
#include <Buttons.hpp>
#include <ExtCtrls.hpp>

#include "uxtheme.h"
#include "tmschema.h"
#include "imglist.hpp"


//---------------------------------------------------------------------------
typedef void __fastcall (__closure *TDrawButtonEvent)
   (System::TObject *Sender, const Types::TRect &Rect, TOwnerDrawState State);
class PACKAGE TButtonImage : public TButton
{
       typedef TButton Inherited;
private:
    TImageList* FImages;
    TImageIndex FImageIndex;
    void __fastcall SetImageIndex(const TImageIndex Value);
    void __fastcall SetImages(const TImageList* Value);
protected:
public:
       __fastcall TButtonImage(TComponent* Owner);
       __fastcall ~TButtonImage();
__published:
    __property TImageIndex ImageIndex = {read=FImageIndex, write=SetImageIndex, default=0};
    __property TImageList* Images = {read=FImages, write=SetImages};
};
//---------------------------------------------------------------------------
#endif


Отредактировано Rius — 14/05/2005, 18:00
Rius
Отправлено: 15.05.2005, 06:59


Мастер участка

Группа: Участник
Сообщений: 321



Написал свой редактор, как правильно переопределить методы ListDrawValue, ListMeasureWidth, ListMeasureHeight? А то ничего не рисуется.
CODE
//---------------------------------------------------------------------------
#pragma hdrstop

#include "MyComponentsRegister.h"
#include "buttonimage.h"
//---------------------------------------------------------------------------
namespace Mycomponentsregister
{
       void __fastcall PACKAGE Register()
       {
               TComponentClass classes[1];
               classes[0] = __classid(TButtonImage);
               RegisterComponents("RComp", classes, 0);

               PTypeInfo ti = *GetPropInfo(__typeinfo(TButtonImage),"ImageIndex")->PropType;
               RegisterPropertyEditor(ti, __classid(TButtonImage),
                   "ImageIndex",__classid(TMyImageIndexPropertyEditor));

       }
}

//---------------------------------------------------------------------------

TPropertyAttributes __fastcall TMyImageIndexPropertyEditor::GetAttributes()
{
return TPropertyAttributes() << paMultiSelect << paValueList << paRevertable;
}
//---------------------------------------------------------------------------

void __fastcall TMyImageIndexPropertyEditor::GetValues(TGetStrProc Proc)
{
 TCustomImageList *ImgList = NULL;
 int i;

 ImgList = GetImageListAt(0);
 if(ImgList != NULL)
 {
   for (i = 0; i < ImgList->Count; i++)
   {
     Proc (IntToStr(i));
   }
 }
}
//---------------------------------------------------------------------------

//TCustomImageList * __fastcall TMyImageIndexPropertyEditor::GetImageListAt (int Index)
//{
//    return NULL;
//}
//---------------------------------------------------------------------------

void __fastcall TMyImageIndexPropertyEditor::ListMeasureHeight(const AnsiString Value, TCanvas *ACanvas,
   int &AHeight)
{
 TCustomImageList *ImgList = NULL;
 ShowMessage(Value);

 ImgList = GetImageListAt(0);
 AHeight = ACanvas->TextHeight(Value) + 2;
 if((ImgList != NULL) && (ImgList->Height + 4 > AHeight))
   AHeight = ImgList->Height + 4;
}
//---------------------------------------------------------------------------

void __fastcall TMyImageIndexPropertyEditor::ListMeasureWidth(const AnsiString Value, TCanvas *ACanvas,
   int &AWidth)
{
 TCustomImageList *ImgList = NULL;
 ShowMessage(Value);

 ImgList = GetImageListAt(0);
 AWidth = ACanvas->TextWidth(Value) + 4;
 if(ImgList != NULL)
   AWidth += ImgList->Width;
}
//---------------------------------------------------------------------------

void __fastcall TMyImageIndexPropertyEditor::ListDrawValue(const AnsiString Value, TCanvas *ACanvas,
   const Types::TRect &ARect, bool ASelected)
{
 TCustomImageList *ImgList = NULL;
 int x;
//  ShowMessage(Result != NULL ? "1" : "0");
 ShowMessage(Value);

 ImgList = GetImageListAt(0);
 ACanvas->FillRect (ARect);
 x = ARect.Left + 2;
 if(ImgList != NULL)
 {
   ImgList->Draw (ACanvas, x, ARect.Top + 2, StrToInt(Value));
   x += ImgList->Width;
 }
 ACanvas->TextOut (x + 3, ARect.Top + 1, Value);
}
//---------------------------------------------------------------------------
TCustomImageList * __fastcall TMyImageIndexPropertyEditor::GetImageListAt (int Index)
{
 TPersistent *C;
 TButtonImage *Item;

 TCustomImageList *Result = NULL;
 //I'm guessing that the Index parameter is a component index (one that
 //  would be passed to the GetComponent function).
 C = GetComponent(Index);
 AnsiString classname = C->ClassName();
//  ShowMessage(classname);
 if( (C != NULL) && (classname == AnsiString("TButtonImage")))
 {
   Item = (TButtonImage *)C;
//    do
//    {
     Result = Item->Images;
//  ShowMessage(Result != NULL ? "1" : "0");
//      if(Result != NULL)
//        break;
//      Item = Item->Parent;
//      if Item = nil then
//        Break;
//      Result := Item.SubMenuImages;
//    while (Result != NULL);
 }
 return Result;
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

*.h
CODE
//---------------------------------------------------------------------------

#ifndef MyComponentsRegisterH
#define MyComponentsRegisterH

#include "designeditors.hpp"
#include "designintf.hpp"
#include <vcleditors.hpp>
//---------------------------------------------------------------------------
//class DELPHICLASS TMyImageIndexPropertyEditor;
//class PASCALIMPLEMENTATION TMyImageIndexPropertyEditor : public Designeditors::TIntegerProperty

//class TMyImageIndexPropertyEditor : public TIntegerProperty// : public ICustomPropertyListDrawing
class TMyImageIndexPropertyEditor : public TCursorProperty// : public ICustomPropertyListDrawing
{
//        typedef Designeditors::TIntegerProperty Inherited;
       typedef TCursorProperty Inherited;
private:
// void *__ICustomPropertyListDrawing; /* Vcleditors::ICustomPropertyListDrawing */
protected:

public:
// operator ICustomPropertyListDrawing*(void) { return (ICustomPropertyListDrawing*)&__ICustomPropertyListDrawing; }
       void __fastcall GetValues(TGetStrProc Proc);
       TPropertyAttributes __fastcall GetAttributes();
       virtual TCustomImageList * __fastcall GetImageListAt (int Index);

   // ICustomPropertyListDrawing
       void __fastcall ListMeasureHeight(const AnsiString Value, Graphics::TCanvas* ACanvas, int &AHeight);
       void __fastcall ListMeasureWidth(const AnsiString Value, Graphics::TCanvas* ACanvas, int &AWidth);
       void __fastcall ListDrawValue(const AnsiString Value, Graphics::TCanvas* ACanvas, const Types::TRect &ARect, bool ASelected);

// void __fastcall ListMeasureHeight(const AnsiString Value, Graphics::TCanvas* ACanvas, int &AHeight);
// void __fastcall ListMeasureWidth(const AnsiString Value, Graphics::TCanvas* ACanvas, int &AWidth);
// HIDESBASE void __fastcall ListDrawValue(const AnsiString Value, Graphics::TCanvas* ACanvas, const Types::TRect &ARect, bool ASelected);

// #pragma option push -w-inl
//  /* TPropertyEditor.Create */ inline __fastcall virtual TMyImageIndexPropertyEditor(const Designintf::_di_IDesigner ADesigner, int APropCount) : Designeditors::TIntegerProperty(ADesigner, APropCount) { }
// #pragma option pop
// #pragma option push -w-inl
// /* TPropertyEditor.Destroy */ inline __fastcall virtual ~TMyImageIndexPropertyEditor(void) { }
// #pragma option pop
__published:

protected:
#pragma option push -w-inl
//    inline __fastcall virtual TMyImageIndexPropertyEditor(const Designintf::_di_IDesigner ADesigner, int APropCount) : Designeditors::TIntegerProperty(ADesigner, APropCount) { }
#pragma option pop
public:
#pragma option push -w-inl
// inline __fastcall virtual ~TMyImageIndexPropertyEditor(void) { }
#pragma option pop

};
//---------------------------------------------------------------------------
#endif
GIZMO
Отправлено: 15.05.2005, 07:45


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (Rius @ 15/05/2005, 06:59)
Написал свой редактор, как правильно переопределить методы ListDrawValue, ListMeasureWidth, ListMeasureHeight? А то ничего не рисуется.
CODE

...

TPropertyAttributes __fastcall TMyImageIndexPropertyEditor::GetAttributes()
{
return TPropertyAttributes() << paMultiSelect << paValueList << paRevertable;
}
...

А где paOwnerDrawList?
Rius
Отправлено: 15.05.2005, 08:41


Мастер участка

Группа: Участник
Сообщений: 321



http://epsilon.narod.ru/rus/progr/delphi_comp1.html
QUOTE
ListDrawValue (const Value: string; Canvas: TCanvas; Rect: TRect; Selected: Boolean) — Рисует пункт в выпадающем списке — OwnerDraw чистой воды, но не верьте Help'у: никакого атрибута paOwnerDrawList в природе не бывает!

и нигде нет определения такой константы.
GIZMO
Отправлено: 15.05.2005, 12:49


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (Rius @ 15/05/2005, 08:41)
http://epsilon.narod.ru/rus/progr/delphi_comp1.html
QUOTE
ListDrawValue (const Value: string; Canvas: TCanvas; Rect: TRect; Selected: Boolean) — Рисует пункт в выпадающем списке — OwnerDraw чистой воды, но не верьте Help'у: никакого атрибута paOwnerDrawList в природе не бывает!

и нигде нет определения такой константы.

Да-а-а, вот это тема. Щас еще покопаюсь...
GIZMO
Отправлено: 15.05.2005, 13:13


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (GIZMO @ 15/05/2005, 12:49)
Да-а-а, вот это тема. Щас еще покопаюсь...

Че-то Я начинаю тупить(воскресенье на работе...), но попробуй объявить так:
CODE

DYNAMIC void __fastcall ListMeasureWidth(const AnsiString Value, Graphics::TCanvas* ACanvas, int &AWidth
 );
DYNAMIC void __fastcall ListDrawValue(const AnsiString Value, Graphics::TCanvas* ACanvas, const Windows::TRect
 &ARect, bool ASelected);
DYNAMIC void __fastcall PropDrawValue(Graphics::TCanvas* ACanvas, const Windows::TRect &ARect, bool
 ASelected);

Rius
Отправлено: 15.05.2005, 14:06


Мастер участка

Группа: Участник
Сообщений: 321



И так пробовал и сяк пробовал, ничего не помогает. Т.к. у меня редактор сейчас основан на TCursorProperty, он мне курсоры и рисует в списке. Кстати, TRect у меня нашелся в namespace Types, а не в Windows.
В дельфях это работает типа через множественное наследование, а здесь как его объявить?
Сапоги для сапожника

Вернуться в Вопросы программирования в C++Builder