제 블로그에 있는 글을 옮겨 봅니다.
요즘 프로그램을 보면 검색창 같은데에서 입력하고 어느정도 시간이 흐른뒤에 검색 히스토리를 보여준다든지, 아니면 입력한 것으로 검색을 한다던지 하는 기능들이 자주 보입니다. 사용자 입장에서는 엔터나 기타 다른 버튼을 이용해서 작업하지 않아도 되니 상당히 편한 기능이죠.
이것을 어떻게 하는걸까 잠깐 고민했더니, OnChange 이벤트에서 Timer로 발생하고 그 Timer 이벤트에서 OnChange이벤트를 발생하면 기존 TEdit에서 커다란 변경없이 작업이 가능할 것 같다는 생각이 들었네요.
Edit1.DelayedChange = True;
Edit1.ChangeDelay := 500;
이렇게 설정하면, Edit에서 500ms 사이에 뭔가 다른 변경이 있으면 OnChange 이벤트를 발생하지 않고 입력 이후 500ms 이후에 OnChange 이벤트를 발생하는 하게 합니다. OnChange 이벤트를 발생시키는 Change procedure를 override하면 간단하게 되겠네요.
이렇게 생각으로 완성한 코드는 아래와 같습니다. 물론 콤포넌트 등록해서 써야지요..
unit DelayedChangEdit;
interface
uses
Classes, StdCtrls, ExtCtrls;
type
TCustomDelayedChangeEdit = class(TEdit)
private
FDelayedChange: Boolean;
FChangeDelay: Cardinal;
FChangeTimer: TTimer;
procedure SetDelayedChange(const Value: Boolean);
procedure ChangeTimerTimer(Sender: TObject);
procedure SetChangeDelay(const Value: Cardinal);
protected
procedure Change; override;
public
constructor Create(AOwner: TComponent); override;
// DelayedChanged = True면 OnChangeEvent가 실제 Change 이벤트 발생후
// ChangeDelay이후에 발생한다.
property DelayedChange: Boolean read FDelayedChange write SetDelayedChange;
property ChangeDelay: Cardinal read FChangeDelay write SetChangeDelay;
end;
TDelayedChangeEdit = class(TCustomDelayedChangeEdit)
property DelayedChange default False;
property ChangeDelay default 500;
end;
implementation
uses
SysUtils;
{ TCustomDelayedChangeEdit }
procedure TCustomDelayedChangeEdit.Change;
begin
// DelayedChange=True일 경우는 Change이벤트가 여기가 아니라 Timer에서
// 발생한다.
if not (csLoading in ComponentState) and FDelayedChange then
begin
FChangeTimer.Enabled := False;
FChangeTimer.Enabled := True;
end else
inherited;
end;
procedure TCustomDelayedChangeEdit.ChangeTimerTimer(Sender: TObject);
begin
(Sender as TTimer).Enabled := False;
inherited Change;
end;
constructor TCustomDelayedChangeEdit.Create(AOwner: TComponent);
begin
inherited;
FChangeDelay := 500;
end;
procedure TCustomDelayedChangeEdit.SetChangeDelay(const Value: Cardinal);
begin
if FChangeDelay <> Value then
begin
FChangeDelay := Value;
if Assigned(FChangeTimer) then
FChangeTimer.Interval := FChangeDelay;
end;
end;
procedure TCustomDelayedChangeEdit.SetDelayedChange(const Value: Boolean);
begin
if FDelayedChange <> Value then
begin
FDelayedChange := Value;
if FDelayedChange then
begin
FChangeTimer := TTimer.Create(self);
FChangeTimer.Enabled := False;
FChangeTimer.Interval := FChangeDelay;
FChangeTimer.OnTimer := ChangeTimerTimer;
end else
FreeAndNil(FChangeTimer);
end;
end;
end.
생각보다 소스가 짧군요..
|
콤보박스를 이렇게 만들어도 유용할듯 합니다.