Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Собственная цветная кнопка, неверно удаляется объект 
V
    Опции темы
petlyura
Дата 28.5.2013, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Здравствуйте, Винградовцы smile

создаю свою цветную кнопку.. 
Код

class TColorButton : public TButton
{
public:
  __fastcall TColorButton(TComponent* Owner);
 
__published:
  __property TColor Color =
  {read = GetColor, write = SetColor};
  __property TColor ColorLo =
  {read = ColorLo_, write = SetColorLo,
   default = clBtnShadow};
  __property TColor ColorHi =
  {read = ColorHi_, write = SetColorHi,
   default = clBtnHighlight};
 
protected:
  // inherited member functions
  virtual void __fastcall CreateParams(
  TCreateParams& Params);
  virtual void __fastcall SetButtonStyle(
  bool ADefault);
 
  // introduced member functions
  virtual void __fastcall DoDrawButtonFace(
  const TOwnerDrawState& state);
  virtual void __fastcall DoDrawButtonText(
  const TOwnerDrawState& state);
 
private:
  TColor ColorLo_;
  TColor ColorHi_;
  std::auto_ptr<TCanvas> Canvas_;
  bool draw_as_default_;
 
  TColor __fastcall GetColor();
  void __fastcall SetColor(TColor Value);
  void __fastcall SetColorLo(TColor Value);
  void __fastcall SetColorHi(TColor Value);
 
  MESSAGE void __fastcall CNDrawItem(
  TMessage& Msg);
  MESSAGE void __fastcall WMLButtonDblClk(
  TMessage& Msg);
  MESSAGE void __fastcall CMFontChanged(
  TMessage& Msg);
  MESSAGE void __fastcall CMEnabledChanged(
  TMessage& Msg);
 
public:
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(
  CN_DRAWITEM, TMessage, CNDrawItem)
  MESSAGE_HANDLER(
  WM_LBUTTONDBLCLK, TMessage, WMLButtonDblClk)
  MESSAGE_HANDLER(
  CM_FONTCHANGED, TMessage, CMFontChanged)
  MESSAGE_HANDLER(
  CM_ENABLEDCHANGED, TMessage, CMEnabledChanged)
END_MESSAGE_MAP(TButton)
};

отсюда скопитырил http://www.cyberforum.ru/cpp-builder/thread183819-page2.html

какая у меня беда. По закрытию формы удаляется объект, по ходу очищается память и вот этого указателя std::auto_ptr<TCanvas> Canvas_; и после этого я прилетаю в обработчик CNDrawItem. Ну и соответственно errorы пошли. Как избежать этой проблемы?
Спасибо
PM MAIL   Вверх
Dem_max
Дата 28.5.2013, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Держи пример
Buttons


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
petlyura
Дата 28.5.2013, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Цитата(Dem_max @ 28.5.2013,  18:38)
Держи пример
Buttons

спасибо. код скопировать у меня вышло без проблем. Хватило ч.1. На его основе создал свой компонент через наследование. Короче, моя программа с высокой частотой проверяет различные условия и в зависимости от них меняет цвет, текст и т.д. Проблема происходит при закрытии формы. Т.е. с одной стороны я удаляю цветную кнопку (х.з., может безграмотно, но вижу что auto_ptr очищается), а потом почему-то прилетает сообщение CN_DRAWITEM. Так вот, я думаю, что нужно доработать в обработчике этого сообщения, чтобы понять, что ничего в нем уже делать не надо. Ошибка выскакивает вот здесь 

// bind Canvas_ to the target DC
  Canvas_->Handle = pDrawItem->hDC;

Код

void __fastcall TColorButton::CNDrawItem(TMessage& Msg)
{

  // grab pointer to the DRAWITEMSTRUCT
  const DRAWITEMSTRUCT* pDrawItem = reinterpret_cast<DRAWITEMSTRUCT*>
    (Msg.LParam);
 
  // store the current state of
  // the target DC
  SaveDC(pDrawItem->hDC);

  // bind Canvas_ to the target DC
  Canvas_->Handle = pDrawItem->hDC;
  try
  {
  // extract the state flags...
  TOwnerDrawState state;
  // if the button has keyboard focus
  if (pDrawItem->itemState & ODS_FOCUS)
  {
    state = state << odFocused;
  }
  // if the button is pushed
  if (pDrawItem->itemState & ODS_SELECTED)
  {
    state = state << odSelected;
  }
  // if the button is disabled
  if (pDrawItem->itemState & ODS_DISABLED)
  {
    state = state << odDisabled;
  }
 
  // draw the button's face
  DoDrawButtonFace(state);
 
  // draw the button's text
  DoDrawButtonText(state);
  }
  catch (...)
  {
  // clean up
  Canvas_->Handle = NULL;
  RestoreDC(pDrawItem->hDC, -1);
  }
  // clean up
  Canvas_->Handle = NULL;
  RestoreDC(pDrawItem->hDC, -1);
 
  // reply TRUE
  Msg.Result = TRUE;

}

Canvas_ уже удален к тому времени. Но тупо проверка на if(Canvas_) не годится

Это сообщение отредактировал(а) petlyura - 28.5.2013, 19:13
PM MAIL   Вверх
Dem_max
Дата 28.5.2013, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Если прилетает  CNDrawItem то значит объект еще существует TColorButton
так как в WndProc окна идет проверка если TColorButton существует то вызвать CNDrawItem

Это сообщение отредактировал(а) Dem_max - 28.5.2013, 19:24


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
petlyura
Дата 29.5.2013, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Цитата(Dem_max @ 28.5.2013,  19:21)
Если прилетает  CNDrawItem то значит объект еще существует TColorButton
так как в WndProc окна идет проверка если TColorButton существует то вызвать CNDrawItem

спасибо. я подумал, что надо правильно удалить компоненты.
создавались компоненты где-то вот так, и добавлялись в ListDo типа TList*:
Код
case deNewColorBut:
                       {
                        TNewColorBut* obj = new TNewColorBut( Owner, TPoint(0,0), drv); 
                        obj->Visible = false;
                        obj->Tag = Tag;
                        obj->Read(is);
                        obj->Draw1(false);
                        ListDo->Add(obj);

удалял я вот так:
Код


  for(int i=0; i < ListDo->Count; i++)       // delete all dynamic objects
    delete (TComponent*)ListDo->Items[i];
  delete ListDo;

сейчас переписал удаление след.образом:
Код
int count = ListDo->Count;
  for(int i=0; i < count; i++)       // delete all dynamic objects
    ListDo->Delete(count-i-1);
  delete ListDo;


я тут не совсем уверен, что удаляю сами объекты. Я их удаляю только из списка. Но ошибка уже не вылетает, в CNDrawItem после этого не захожу. И потом там еще форма удаляется (не главная форма программы, а просто один из кадров), и как я понимаю, вместе с ней все эти объекты.
Покритикуйте. Спасибо
PM MAIL   Вверх
petlyura
Дата 29.5.2013, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Цитата(Dem_max @ 28.5.2013,  18:38)
Держи пример
Buttons

Dem_max, еще есть одна проблема. Эта кнопка постоянно получает фокус ввода, а мне надо этого избежать. Что еще нужно дописать? и где? Раньше я создавал свои кнопки-компоненты на основе SpeedButton, там фокуса нет. Пока не возникла проблема, что кнопка должна и цвет текста и цвет фона менять, мне хватало speedbutton. Даже натягивал рисунок на speedbutton, но оформлять текст в виде рисунка на некотором фоне некомильфо, т.к. что часто нужно менять размеры кнопок, а соответственно плывет и текст (сжимается, растягивается). Пришлось создавать собств.цветную кнопку через TColorButton. Если есть приемлемый вариант для SpeedButton, буду тоже рад.
PM MAIL   Вверх
petlyura
Дата 29.5.2013, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



вот набросал что-то такое для эксперимента со SpeedButton. Рисунок появился на кнопке, а текст - нет :(
Почему не получилось?  smile 
Код
AnsiString Capt  = "Hello!";
AnsiString Image0Name = "Picture.bmp";
if(!Image0Name.IsEmpty())
    SpeedButton1->Glyph->LoadFromFile(Image0Name.Trim());

  TPoint pt;

  TRect rect;
  rect.Left = 0;
  rect.Right = SpeedButton1->Width;
  rect.Top = 0;
  rect.Bottom = SpeedButton1->Height;
    pt = CenterPoint(rect);
    SpeedButton1->Glyph->Canvas->Brush->Style = bsClear;
   int w = SpeedButton1->Glyph->Canvas->TextWidth(Capt)/2;
   int h = SpeedButton1->Glyph->Canvas->TextHeight(Capt)/2;
    SpeedButton1->Glyph->Canvas->TextOut(pt.x -  w, pt.y - h, Capt);


PM MAIL   Вверх
petlyura
Дата 29.5.2013, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



Цитата(petlyura @ 29.5.2013,  15:30)
вот набросал что-то такое для эксперимента со SpeedButton. Рисунок появился на кнопке, а текст - нет :(
Почему не получилось?  smile 


потому что размер картинки меньше, чем текста, выводимого на канве  smile 
так определенно лучше.
Код
  AnsiString Capt  = "Hello!";
  AnsiString Image0Name = "Background.bmp";
  if(!Image0Name.IsEmpty())
    SpeedButton1->Glyph->LoadFromFile(Image0Name.Trim());

  TPoint pt;

  TRect rect;
  rect.Left = 0;
  rect.Right =   SpeedButton1->Glyph->Width;
  rect.Top = 0;

  rect.Bottom =   SpeedButton1->Glyph->Height;
  pt = CenterPoint(rect);
  SpeedButton1->Glyph->Canvas->Brush->Style = bsClear;

  SpeedButton1->Glyph->Canvas->Pen->Color = clBlack;

  int w = SpeedButton1->Glyph->Canvas->TextWidth(Capt)/2;
  int h = SpeedButton1->Glyph->Canvas->TextHeight(Capt)/2;
  SpeedButton1->Glyph->Canvas->TextOut(pt.x -  w, pt.y - h, Capt);


PM MAIL   Вверх
petlyura
Дата 29.5.2013, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 162
Регистрация: 30.1.2008
Где: Харьков

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



спасибо, тему закрываю. Написал функцию, которая загружает фон и текст. Все работает
Код

void TColorBut::Rendering(AnsiString ImageName, AnsiString txt, TFont* fnt)
{
        if(!ImageName.IsEmpty())
          Glyph->LoadFromFile(ImageName);

        TPoint pt;
        TRect rect;
        rect.Left = 0;
        rect.Right = Glyph->Width;
        rect.Top = 0;
        rect.Bottom = Glyph->Height;
        pt = CenterPoint(rect);

        Glyph->Canvas->Brush->Style = bsClear;
        Glyph->Canvas->Font = fnt;
        int w = Glyph->Canvas->TextWidth(txt)/2;
        int h = Glyph->Canvas->TextHeight(txt)/2;
        Glyph->Canvas->TextOut(pt.x -  w, pt.y - h, txt);
}



Код
class TColorBut: public TSpeedButton
{
//...
void Rendering (AnsiString ImageName, AnsiString txt, TFont*  fnt);
//...
};



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

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


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

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


 




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


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

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