|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Компонент на основе TCustomControl
Здравствуйте!
Столкнулся с ситуацией, объяснения которой найти не могу. Суть такова: Создаю класс, на основе TCustomControl, в методе Paint прорисовываю так сказать "подложку", после чего вызываю функцию CreateWindowEx, которая создает поле ввода, с параметрами описанными в первом попавшемся примере (при компиляции примера проблем нет). После компиляции получаю следующее: Поле ввода отображается, но при открытии диспетчера задач видно, как каждую секунду количество используемой приложением памяти увеличивается. Не могу найти причину - дело в неправильном вызове CreateWindowEx или все гораздо сложнее и создавать подобные элементы необходимо не прямым вызовом функций api? на всякий случай вот код функции: Код:
hEdit := CreateWindowEx(WS_EX_CLIENTEDGE,'edit', '', WS_CHILD or WS_VISIBLE or ES_LEFT or WS_TABSTOP, 10, 10, 80, 20, Handle, 0, hInstance, nil); Подскажите, в какую сторону копать Заранее спасибо! |
#2
|
||||
|
||||
Ну ты гигант мысли. Событие OnPaint (WM_PAINT) вызывается системой при каждом случае, когда требуется перерисовать окно. Перерисовали, и что дальше? Дальше у тебя создаётся ещё одно, неизвестно кому нужное, окно. И это может происходить десятки раз в секунду. Вот и считай.
Кстати, а чем TCustomEdit не угодил? Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. Последний раз редактировалось angvelem, 26.09.2011 в 01:59. |
#3
|
|||
|
|||
angvelem, спасибо! Теперь ситуация начинает проясняться. TCustomEdit не угодил тем, что кроме поля ввода должены быть еще элементы управления. В таком случае создавать окна нужно до наступления события OnPaint, а в OnPaint уже только отображать/перерисовывать?
Не совсем понятен принцип. Когда нужно рисовать свои окна так, чтобы это было правильно? |
#4
|
||||
|
||||
создавать в constructor"е, удалять в destructor"е. не забыв переписать SetParent, Notification и SetBounds. посмотри реализацию TLabeledEdit для начала.
Пишу программы за еду. __________________ |
#5
|
|||
|
|||
NumLock, спасибо!
Боюсь это был не последний вопрос. *ушел смотреть реализацию TLabeledEdit* |
#6
|
|||
|
|||
NumLock,
в TLabeledEdit создается экземпляр класса класса TBoundLabel, могу ли я действовать по тому же принципу, если я использую не готовый класс, а рисую через api? |
#7
|
||||
|
||||
нарисуй в MS Paint как должен выглядеть твой компонент и что должен делать?
Пишу программы за еду. __________________ |
#8
|
|||
|
|||
Все просто. Есть Edit и Button. При нажатии на кнопку открывается окно, в котором есть некий справочник, в нем выбирается значение и вставляется в Edit. Но сразу предупрежу, что создание внутри компонента экземпляров TEdit и Tbutton неприемлимо в моем случае, вот поэтому и необходимо нарисовать.
|
#9
|
||||
|
||||
не понятно почему неприемлемо использование TEdit и TButton? это куда проще, чем самому реализовывать эти объекты графически: рисовать кнопку и ее нажатие, рисовать поле и текст в нем, навигация и редактирование текста в поле ввода...
Пишу программы за еду. __________________ |
#10
|
|||
|
|||
Это слишком ресурсоемкий вариант, очень важна производительность. Может посоветуете какую-нибудь литературу, где рассматривается хотя бы частично мой вопрос?
Я уже много всего просмотрел, не могу найти ничего подобного. |
#11
|
||||
|
||||
Код:
unit EditButtonControl; interface uses // Dialogs, Windows, Messages, SysUtils, Classes, Graphics, Controls; type TEditButtonControl = class(TCustomControl) private FEdit: String; FButton: String; FOnClick: TNotifyEvent; procedure SetEdit(const Value: String); procedure SetButton(const Value: String); protected procedure Paint; override; procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; public constructor Create(AOwner: TComponent); override; procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; published property Edit: String read FEdit write SetEdit; property Button: String read FButton write SetButton; property OnClick: TNotifyEvent read FOnClick write FOnClick; end; procedure Register; implementation procedure Register; begin RegisterComponents('Internet', [TEditButtonControl]); end; { TEditButtonControl } constructor TEditButtonControl.Create(AOwner: TComponent); begin inherited Create(AOwner); FEdit:='TEdit'; FButton:='TButton'; end; procedure TEditButtonControl.Paint; var ARect: TRect; begin Canvas.Brush.Color:=clBtnFace; Canvas.FillRect(ClientRect); ARect:=Rect(0, 0, Width, Height); DrawEdge(Canvas.Handle, ARect, EDGE_RAISED, BF_RECT); ARect:=Rect(10, 10, Width-10, 10+21); Canvas.Brush.Color:=clWindow; Canvas.FillRect(ARect); DrawEdge(Canvas.Handle, ARect, EDGE_SUNKEN, BF_RECT); InflateRect(ARect, -4, 0); DrawText(Canvas.Handle, PChar(FEdit), -1, ARect, DT_LEFT or DT_SINGLELINE or DT_VCENTER); ARect:=Rect(10, 10+21+10, 10+75, 10+21+10+25); Canvas.Brush.Color:=clBtnFace; Canvas.FillRect(ARect); DrawEdge(Canvas.Handle, ARect, EDGE_RAISED, BF_RECT); DrawText(Canvas.Handle, PChar(FButton), -1, ARect, DT_CENTER or DT_SINGLELINE or DT_VCENTER); end; procedure TEditButtonControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin AWidth:=200; AHeight:=76; inherited SetBounds(ALeft, ATop, AWidth, AHeight); end; procedure TEditButtonControl.WMLButtonDown(var Message: TWMLButtonDown); begin inherited; if (Message.XPos>=10) and (Message.XPos<=85) and (Message.YPos>=10+21+10) and (Message.YPos<=10+21+10+25) then begin if Assigned(FOnClick) then FOnClick(Self); // Edit:=InputBox('InputBox', 'Text:', ''); end; end; procedure TEditButtonControl.SetEdit(const Value: String); begin if Value<>FEdit then begin FEdit:=Value; Invalidate; end; end; procedure TEditButtonControl.SetButton(const Value: String); begin if Value<>FButton then begin FButton:=Value; Invalidate; end; end; end. http://data.cod.ru/125935 Пишу программы за еду. __________________ |
#12
|
|||
|
|||
NumLock, спасибо за очень познавательный пример!! Но для меня это усложненный путь, может подскажете как правильно создавать окна внутри компонента?
|
#13
|
|||
|
|||
http://codege.org/projects/visg/
мне как-то помогал, возможно уже есть другие альтернативы |
#14
|
||||
|
||||
Код:
unit EditButtonControl; interface uses StdCtrls, Windows, Messages, SysUtils, Classes, Graphics, Controls; type TEditButtonControl = class(TCustomControl) private FEdit: TEdit; FButton: TButton; FOnClick: TNotifyEvent; procedure OnButtonClick(Sender: TObject); protected procedure Paint; override; procedure SetParent(AParent: TWinControl); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; published property OnClick: TNotifyEvent read FOnClick write FOnClick; end; procedure Register; implementation procedure Register; begin RegisterComponents('Internet', [TEditButtonControl]); end; { TEditButtonControl } constructor TEditButtonControl.Create(AOwner: TComponent); begin inherited Create(AOwner); FEdit:=TEdit.Create(Self); FButton:=TButton.Create(Self); FButton.Caption:='Click me...'; FButton.OnClick:=OnButtonClick; end; destructor TEditButtonControl.Destroy; begin // if Assigned(FEdit) then FEdit.Free; // if Assigned(FButton) then FButton.Free; inherited Destroy; end; procedure TEditButtonControl.Paint; var ARect: TRect; begin Canvas.Brush.Color:=clBtnFace; Canvas.FillRect(ClientRect); ARect:=Rect(0, 0, Width, Height); DrawEdge(Canvas.Handle, ARect, EDGE_RAISED, BF_RECT); end; procedure TEditButtonControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin AWidth:=200; AHeight:=76; if Assigned(FEdit) then begin FEdit.Left:=ALeft+10; FEdit.Top:=ATop+10; if Assigned(FButton) then begin FButton.Left:=ALeft+10; FButton.Top:=ATop+10+FEdit.Height+10; end; end; inherited SetBounds(ALeft, ATop, AWidth, AHeight); end; procedure TEditButtonControl.SetParent(AParent: TWinControl); begin inherited SetParent(AParent); if Assigned(FEdit) then FEdit.Parent:=AParent; if Assigned(FButton) then FButton.Parent:=AParent; end; procedure TEditButtonControl.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if (AComponent=FEdit) and (Operation=opRemove) then FEdit:=nil; if (AComponent=FButton) and (Operation=opRemove) then FButton:=nil; end; procedure TEditButtonControl.OnButtonClick(Sender: TObject); begin Windows.Beep(1000, 10); end; end. Пишу программы за еду. __________________ |
#15
|
|||
|
|||
Цитата:
|