Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61

Проблемы написания хорошего компонента

29.06.2011, 22:16. Показов 2124. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток. У меня такая проблема я создаю компонент с большим набором кнопок с картинками и для решения проблемы нажатия на них я создал компонент кнопки на основе TCustomControl и разместил на нем набор TImage'ов где 1 - рисунок в статичном положение кнопки, второй в зажатом третий в заблокированном и т.д.
Все эти кнопки я расположил на еще одном TCustomControl'е. Также я создал специальную платформу на основе Tcontrol которая ловит нажатие мышки на сам компонент-панель, проблема заключается в том что TCustomControl перекрывает Tcontrol и не дает ему выйти на верх всех подкомпонентов, в следствие чего, он не может ловить нажатие...
Пожалуйста подскажите, как расположить TControl поверх остольных подкомпоннентов.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.06.2011, 22:16
Ответы с готовыми решениями:

Проблемы при ручном создании компонента
Делаю свой компонент-кнопку. Просто как компонент создается на ура, НО как только пытаюсь изменить шрифт type TSkinedBtn =...

Помогите с СИ (Проблемы написания программ)
Помогите пожалуйста... Как вытащить переменную с обработчика прерываний? Например с АЦП. Вот код. #include <avr/io.h> ...

С помощью компонента SpinEdit организуйте управление количеством строк компонента Stringgrid
помогите решить) Поместите на форму компоненты Stringgrid и SpinEdit. С помощью компонента SpinEdit организуйте управление количеством...

15
4052 / 2663 / 583
Регистрация: 11.09.2009
Сообщений: 9,501
30.06.2011, 05:30
Kellendros, уточните:
Фактически вам надо, чтобы нажатие кнопки мыши обрабатывалось OnClick панели, даже если нажатие было на Button, расположеный на этой панели? То есть, нажатие на любой компонент на панели должно обрабатываться одной и той же процедурой?
Если так - может быть просто написать OnClick панели и назначить его всем остальным компонентам на этой панели?
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
30.06.2011, 09:47  [ТС]
Поясняю, я создаю общий класс обработчика мыши, который создан на основе Tcontrol, в нем есть событие OnClick который отлавливает нажатие на него, и хранит в себе номер элемента, на который нажали. суть заключается в том что бы не прописывать для каждого подкомпонента отдельно событие, а сделать обработчик общего вида.
(Пример обработчика:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  TMCClick = procedure (Sender : TObject; Id:Integer) of object;
 
  TMCEvents = class(TControl)
  private
    FCybiks:Array[1..20,1..4] of Integer; //виртуальный прямоугольники объектов(для возврата id)
    FCybikCount:integer;                      //Колличество виртуальных кубов
    FOnMCClick:TMCClick;                    
    procedure WMLButtonDown(var Msg : TWMMouse); message WM_LBUTTONDOWN;
    Function TakeMCMouseCoord(x,y:integer):Integer; //возвращает id объекта для (x,y)
  protected
  public
    Constructor Create(AOwner: TComponent); override;
    Procedure AddCybik(x1,y1,x2,y2:integer);//создает виртуальный куб
    Procedure DeleteCybik(id:integer);          //удаляет виртуальный куб
    Procedure ChangeCybik(id,x1,y1,x2,y2:integer);//изменяет виртуальный куб
    Procedure FreeAll; //Очещает весь массив
  published
    property OnMCClick:TMCClick read FOnMCClick write FOnMCClick; //Событие ловли клика и возврата id на клике.
  end;
)
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
02.07.2011, 23:19  [ТС]
Прошу, хоть кто-нибудь, помогите, просто я уже и не знаю, что можно сделать...
0
4052 / 2663 / 583
Регистрация: 11.09.2009
Сообщений: 9,501
03.07.2011, 02:14
Kellendros, если "озвучите" тут функцию
TakeMCMouseCoord(x,y:integer):Integer; //возвращает id объекта для (x,y)
, может ваш вопрос станет понятнее...
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
03.07.2011, 02:16  [ТС]
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function TMCEvents.TakeMCMouseCoord(x,y:integer):Integer;
var Temp:TPoint;
    id,i:integer;
begin
  GetCursorPos(Temp);
  Temp.X:=x;
  Temp.Y:=y;
  id:=0;
  for i:=1 to 20 do
    if CheckIn(FCybiks[i,1],FCybiks[i,2],FCybiks[i,3],FCybiks[i,4],Temp.X,Temp.Y) then
      id:=i;
 
  TakeMCMouseCoord:=id;
end;
 
Function CheckIn(x1,y1,x2,y2,x3,y3:Integer):Boolean;
begin
  if (x1 < x3) and (y1 < y3) and (x2 > x3) and (y2 > y3) then
    Result:=True
      else
        Result:=False;
end;
она пробегает по массиву виртуальных кнопок(они задана координатами) и проверяет какая именно подходит для заданных координат...

а непосредственно вызов её производится вот так.
Delphi
1
2
3
4
5
procedure TMCEvents.WMLButtonDown(var Msg : TWMMouse);
begin
  if assigned(FOnMCClick) then
    OnMCClick(Self, TakeMCMouseCoord(Msg.XPos,Msg.YPos));
end;
0
4052 / 2663 / 583
Регистрация: 11.09.2009
Сообщений: 9,501
03.07.2011, 19:48
Цитата Сообщение от Kellendros Посмотреть сообщение
проблема заключается в том что TCustomControl перекрывает Tcontrol и не дает ему выйти на верх всех подкомпонентов, в следствие чего, он не может ловить нажатие...
Если это исходный вопрос, то я, например, вообще перестал понимать... И чем дальше - тем больше:
У вас именно TakeMCMouseCoord не возвращает индекс элемента?
А вообще должна? Там, например, сначала в Temp заносятся координаты курсора, а потом тут же заменяются...
Delphi
1
2
3
  GetCursorPos(Temp);  
  Temp.X:=x;
  Temp.Y:=y;
Может, поясните логику?

Где именно, в какой процедуре, у вас не те координаты курсора?
Или у вас что-то вообще не вызывается?
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
04.07.2011, 07:08  [ТС]
вся проблема в том, что когда я создаю основной компонент, на который я кладу кномпки и TMCEvent? кнопки ложатся поверх него... из-за этого TMCEvent не может отлоовить нажатие(сам по себе он работает нормально.) вся проблема - положить его поверх остальных компонентов(он написан на основе Tcontrol, кнопки на основе - TWinControl)
0
4052 / 2663 / 583
Регистрация: 11.09.2009
Сообщений: 9,501
04.07.2011, 21:49
Kellendros, по-моему, потомок TControl вообще не может перекрыть TWinControl. Если не ошибаюсь, TWinControl имеют Handle и отрисовывают себя сами в любом порядке, в отличие от потомков TControl, которых отрисовывает родитель.

Только вот мне кажется, что вы пытаетесь "собрать" компонент из каких-то надёрганных из разных мест кусочков, особо не озадачиваясь "стройностью изложения". Да и уточняющие вопросы вы игнорируете. Вы вообще посмотрели, в TakeMCMouseCoord - ошибка, рудимент старого кода, или так задумано?
Пожалуй, я воздержусь от дальнейшего обсуждения.
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
05.07.2011, 00:00  [ТС]
Дело в том чт я писал весь компонент сам, и могу объяснить его от и до. Дело в том, что я как и любой программист могу допускать ошибки, и в особенности при изменение методов решения задачи, объясню задачу по другому, в надежде на помощь:
Задача: создать удобную структуру для создания интерфейса игры.
Я создаю платформу на которой будут распологаться составляющие интерфейс окна на основе tcustomcontrol, и на нем размещаю массив кнопок(tmcbutton - мой компонент, созданный на основе тогоже tcustomcontrol, и двух картинок(зажатая не зажатая)) также я размещаю набор прочих элементов, необходимых панеле. Затем поверх я хочу положить какой нибудь компонент, который будет полностью ловить все взаимодействия мыши с главным компонентом, и в случае нажатия на одни из кнопок из массива возвращать ее Id, так как проще будет обработать именно через Id, в случае к примеру сумки чара, где предметов может быть не определенное колличество. (если я в чем то не прав, так и скажите как будет правильнее) я пытался использовать image за основу и tcontrol но они оба не хотят ложиться поверх tcustomcontrol, а все потомки twincontrol уже не прозрачные, но именно у него появляется возможность наложение на него компонентов.
Подскажите, как можно решить мою проблему(напоминаю, моя проблема - создать компонент, который будет лежать на самом верхнем слое, будет прозрачен и будет отлавливать все функции мыши.)
И на счет getcursorpos сначала я внутри процедуры отлавливал координаты курсора, а потом я решил их передовать, вот и весь фокус
0
Эксперт функциональных языков программированияЭксперт по математике/физике
4313 / 2105 / 431
Регистрация: 19.07.2009
Сообщений: 3,205
Записей в блоге: 24
05.07.2011, 10:44
Мне кажется, что будет более логично (по крайней мере, с точки зрения ООП) вовсе не использовать дополнительный слой поверх компонента, поскольку действия с кнопками должны обрабатываться кнопками, а действия с панелью — самой панелью.

В качестве примера того, что я хочу сказать, могу привести код, который я писал во времена изучения ООП. Это экспериментальный код, пытался туда засунуть всё, что изучил/узнал: инкапсуляцию, полиморизм, метаклассы, перегрузки/перезапись, абстрактность. Решает он где-то ту же задачу, что у тебя.

Я пройдусь только по декларациям, реализация там очевидна.
TItem основывается на TComponent, но вообще имеет ту же суть (сущность), что и кнопка.
TTable суть носитель (панель). Тебе же советую сделать так же: разделить сущности (вещь в рюкзаке/рюкзак) и реализацию (TControl с двумя имиджами/панель с наворотами) разными уровнями абстракции, как у меня разделено TItem (который почти полностью абстрактен) и TSelectiveItem (который уже несет в себе реализацию)
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
type
 
  TItem = class(TComponent)
  protected
    function GetPosition: TRect; virtual; abstract;
    procedure SetPosition(Rect: TRect); virtual; abstract;
    { only references }
    procedure SetPos(Index: Integer; Value: Integer);
    function GetPos(Index: Integer): Integer;
    property Left: Integer index 0 read GetPos write SetPos;
    property Top: Integer index 1 read GetPos write SetPos;
    property Width: Integer index 2 read GetPos write SetPos;
    property Height: Integer index 3 read GetPos write SetPos;  
  public
    function HasParent: Boolean; override;
  end;
 
  TItemClass = class of TItem;
 
  TTable = class(TCustomPanel)
  private
    FItemType: TItemClass;
    FProportions: Real;
    procedure SetProportions(Value: Real);
    function GetItem(Index: Word): TItem;
    function GetItemCount: Word;
  protected
    FItems: array of TItem;
    procedure EvalItemSize(var ItemWidth, ItemHeight: Integer); virtual;
    property ItemType: TItemClass read FItemType;
    property ItemCount: Word read GetItemCount;
    constructor Create(AOwner: TComponent; ItemType: TItemClass); virtual;
  public
    property BevelInner;
    property BevelOuter;
    property BevelWidth;
    property BorderStyle;
    property BorderWidth;
    property Color;
    property ParentColor;
    property Enabled;
    property OnClick;
    property Visible;
    property OnResize;
    procedure Resize; override;
  public
    function NewItem: TItem; virtual;
    procedure ReBuild; dynamic;
    property Proportion: Real read FProportions write SetProportions;
    procedure Assign(Source: TPersistent); override;
  end;
TImageTableItem содержит в себе указание того, что элемент должен выражаться панелью с размещенной на ней картинкой. Засунул всё в протектед, чтобы был доступ в случае чего.
TSelectingTableItem добавляет в свой интерфейс возможность устанавливать onclick.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
type
 
  TImageTableItem = class(TItem)
  private
    procedure SetImageByFileName(Value: String);
    procedure SetImageByPicture(Value: TPicture);
    function GetImage: TPicture;
    //procedure SetImageClick(Value: TNotifyEvent);
    class function IsTITIC(AType: TItemClass): Boolean;
  protected
    FPanel: TPanel;
    FImage: TImage;
    function GetPosition: TRect; override;
    procedure SetPosition(Rect: TRect); override;
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property ImageFile: String write SetImageByFileName;
    property Image: TPicture read GetImage write SetImageByPicture;
  end;
 
  TSelectingTableItem = class(TImageTableItem)
  private
    FOnClick: TNotifyEvent;
    procedure ImageClick(Sender: TObject);
  protected
    procedure HighLight;
  public
    property OnClick: TNotifyEvent read FOnClick write FOnClick;
    procedure Click;
    constructor Create(AOwner: TComponent); override;
    procedure Assign(Source: TPersistent); override;
  end;
 
  TITIC = class of TImageTableItem;
 
  TImageTable = class(TTable)
  public
    constructor Create(AOwner: TComponent; ItemType: TItemClass); override;
    procedure AddImage(FileName: String); overload;
    procedure AddImage(Picture: TPicture); overload;
    function IsPictureLoaded(Sample: TPicture): Integer;
  end;
 
  TSelectingTable = class(TImageTable)
  private
    FSelected: Integer;
    FOnSelecting: TNotifyEvent;
    procedure ItemClick(Sender: TObject);
    function GetSelectedPic: TPicture;
    procedure Select(Index: Word);
    procedure SetDefaultChoice(Value: Integer);
  public
    constructor Create(AOwner: TComponent; ItemType: TItemClass); override;
    function NewItem: TItem; override;
    property SelectedItem: Integer read FSelected;
    property SelectedPicture: TPicture read GetSelectedPic;
    property OnSelecting: TNotifyEvent read FOnSelecting write FOnSelecting;
    property DefaultSelection: Integer read FSelected write SetDefaultChoice;
    procedure Assign(Source: TPersistent); override;
  end;
tl;dr
Короче, мне кажется, что лучше будет не вводить новый компонент по перехвату событий, а реализовать то, что тебе нужно доступными средствами, используя реально нужные компоненты.
Вложения
Тип файла: rar Demo.rar (19.5 Кб, 22 просмотров)
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
05.07.2011, 12:00  [ТС]
я может чего то не понимаю, но я действительно не понимаю как можно без такой панели реализовать отловлю нажатия, с возвращением именно id кнопки, на которую нажали, имее масси этих кнопок.
0
Эксперт функциональных языков программированияЭксперт по математике/физике
4313 / 2105 / 431
Регистрация: 19.07.2009
Сообщений: 3,205
Записей в блоге: 24
05.07.2011, 14:21
Тебе нужно отловить нажетие на кнопку? Так лови это КНОПКОЙ, а не какой-то левой панелью. У тебя панель (носитель) усведомлен о всех распольженных на ней кнопках, пусть она раздаст им id. В свою очередь кнопки пусть сами вылавливают нажатие, TImage (или что ты используешь) позволяет.

Например, имаджу onclick присваешь обработчик, принадлежащий панели, который определяет по Sender id твоей кнопки.

(С предыдущего поста)
Delphi
1
2
3
4
5
6
7
8
9
procedure TSelectingTable.ItemClick(Sender: TObject); // <-- Sender это твоя кнопка
var a: integer;
begin
     for a:=0 to high(FItems) do
         if FItems[a] = Sender
            then FSelected:=a; // <-- тут ты уже знаешь id
     if @FOnSelecting <> nil
        then FOnSelecting(Self)
end;
1
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
05.07.2011, 14:25  [ТС]
спасибо, буду пробовать.
0
4052 / 2663 / 583
Регистрация: 11.09.2009
Сообщений: 9,501
06.07.2011, 00:57
Kellendros, из-за неумения слушать, вы потратили кучу своего и чужого времени. Жаль.

Первый ответ в этой ветке:
Цитата Сообщение от i8085 Посмотреть сообщение
может быть просто написать OnClick панели и назначить его всем остальным компонентам на этой панели?
0
28 / 28 / 5
Регистрация: 29.06.2011
Сообщений: 61
06.07.2011, 00:59  [ТС]
того ответа что мне был нужен, я в итоге так и не получил, но продолжать эту тему дальше мне показалось бессмысленно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.07.2011, 00:59
Помогаю со студенческими работами здесь

Создание компонента, при добавлении автоматически получить Parent фокусированного компонента
Привет всем, вот ни разу не писал еще компоненты, начал разбираться, все просто, понятно, доступно, удобно.. но как мне задать Parent...

Использование компонента TreeView как переключатель вкладок компонента TabControl
И так, есть форма на которой расположились компоненты TabControl и TreeView. Вопрос, можно ли Скрыть вкладки у TabControl, а узлы или ветви...

Как с одной строки компонента, сохранить информацию в другую строку другого компонента?
Здравствуйте, у меня возник вопрос, когда выделяешь строку в TreeView1, тот файл который прикреплен(грузится при нажатии на эту строку),...

Создание своего компонента на основе компонента Timer
нужно создать свой компонент какбы который наследует компонент Таймер нужно хотя бы добавить несколько свойств помогите с идеей !!!!...

Создание визуального компонента наследника базового компонента
Добрый день! В VS 2005 было возможно создать элемент Windows Forms control library на базе стандартного элемента, скажем Button. Я...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru