ÀúÀ۱ǿ¡ ´ëÇÑ °øÁö
ÀÌ ¹®¼­¿¡ Æ÷ÇÔµÈ ¸ðµç ±Û°ú ¼Ò½º ÄÚµå´Â ÀÛÀÚÀÎ Àú ±è¼ºµ¿ÀÇ ÁöÀû Àç»êÀÌÁö¸¸ ¹«´ÜÀ¸·Î ¹èÆ÷Çϰųª Ã¥À̳ª °­ÀÇ ±³ÀçµîÀ» À§ÇÑ º¹Á¦ µî ÀúÀÛ±ÇÀ» ÀúÇØÇÏ´Â ÇàÀ§¸¦ Á¦¿ÜÇϰí´Â ÀÚÀ¯·Ó°Ô »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.
¶ÇÇÑ ÀÌ ÆäÀÌÁö¿¡ ´ëÇÑ ¸µÅ©´Â ÀÚÀ¯·Ó°Ô ÇÒ ¼ö ÀÖÀ¸³ª Àü¹®À» ÀüÁ¦ÇÏ´Â ÀÏÀº Çã¿ëÇÏÁö ¾Ê½À´Ï´Ù.


2.5. µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®(Data-Aware Component) °³¹ß

2.5.1. µ¥ÀÌÅÍ ¿¬µ¿(Data Aware)
ÀÌÀü Àý±îÁö ÄÞÆ÷³ÍÆ® °³¹ß¿¡ ÇÊ¿äÇÑ Á¦¹Ý »çÇ׿¡ ´ëÇØ¼­ °ÅÀÇ ¾Ë¾Æ º¸¾ÒÀ¸¸ç °£´ÜÇÑ ÄÞÆ÷³ÍÆ®¸¦ °³¹ßÇØ º¸¾Ò´Ù. ÇÏÁö¸¸ ¸¶Áö¸·À¸·Î ÇѰ¡Áö ´õ °øºÎÇØ¾ßÇÒ Ç׸ñÀÌ Çϳª ³²¾Æ ÀÖ´Ù. µ¨ÆÄÀÌ ÄÞÆ÷³ÍÆ® ÆÈ·¹Æ®ÀÇ Data Controls ÆäÀÌÁö¸¦ º¸¸é TDBGrid, TDBText, TDBEdit, TDBMemo µî ¿©·¯ °¡Áö ÄÞÆ÷³ÍÆ®°¡ ÀÖ´Ù. À̵é ÄÞÆ÷³ÍÆ®°¡ ´Ù¸¥ ÆäÀÌÁö¿¡ ÀÖ´Â ÄÞÆ÷³ÍÆ®µé°ú ´Ù¸¥ Á¡Àº ¹Ù·Î ÄÞÆ÷³ÍÆ® ÀÚüÀûÀ¸·Î µ¥ÀÌÅÍ ¼Ò½º¿Í ¿¬°áÀÌ µÇ°í ºÎ°¡ÀûÀÎ Äڵ带 ÀÛ¼ºÇØ ÁÖÁö ¾Ê¾Æµµ µ¥ÀÌÅͺ£À̽ºÀÇ ÇöÀç ·¹ÄÚµåÀÇ ³»¿ëÀ» ÀÚµ¿À¸·Î ¹Ý¿µÇØ ÁÖ°í ¶ÇÇÑ ¼öÁ¤µµ °¡´ÉÇÏ´Ù´Â °ÍÀÌ´Ù. ÀÌ·± ÄÞÆ÷³ÍÆ®µéÀ» µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¶ó Çϴµ¥ À̹ø Àý¿¡¼­´Â °³¹ßÇÑ ÄÞÆ÷³ÍÆ®°¡ µ¥ÀÌÅÍ ¿¬µ¿ ±â´ÉÀ» Áö¿øÇÏ·Á¸é ¾î¶»°Ô ÇØ¾ß ÇÏ´ÂÁö¸¦ ¾Ë¾Æ º¸°Ú´Ù.
µ¥ÀÌÅÍ ¿¬µ¿ ±â´ÉÀº µÎ°¡Áö ÇüÅ·Π±¸ºÐÇÒ ¼ö Àִµ¥ µ¥ÀÌÅÍ ¿­¶÷(Data Browsing)°ú µ¥ÀÌÅÍ ¼öÁ¤(Data Editing)ÀÌ´Ù. µ¥ÀÌÅÍ ¿­¶÷Àº ´Ü¼øÈ÷ ÇöÀç µ¥ÀÌÅͺ£À̽ºÀÇ ³»¿ëÀ» ÄÞÆ÷³ÍÆ®¿¡ ¹Ý¿µÇØ Áֱ⸸ ÇÏ¸é µÇ°í µ¥ÀÌÅÍ ¼öÁ¤Àº µ¥ÀÌÅÍ ¿­¶÷ ±â´É »Ó¸¸ ¾Æ´Ï¶ó ÄÞÆ÷³ÍÆ®¸¦ Á¶ÀÛÇϹǷμ­ µ¥ÀÌÅͺ£À̽ºÀÇ ÇöÀç ·¹ÄÚµåÀÇ ³»¿ëÀ» ¼öÁ¤Çϰųª »õ·Î¿î ·¹Äڵ带 Ãß°¡ÇÒ ¼ö ÀÖ´Â ÇüÅÂÀÌ´Ù. ¶ÇÇÑ µ¥ÀÌÅÍ ¿¬µ¿Àº TDBEditó·³ ±× ¹üÀ§°¡ ´ÜÀÏ Çʵ忡¸¸ ±¹ÇÑµÉ ¼öµµ ÀÖ°í TDBGridó·³ DataSet Àüü¿¡ ¿¬°áµÉ ¼öµµ ÀÖ´Ù.
µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¸¦ °³¹ßÇÒ ¶§´Â ÀÌÀü Àý¿¡¼­Ã³·³ ÄÞÆ÷³ÍÆ®¸¦ ¾î¶² ƯÁ¤ ºÎ¸ð Ŭ·¡½º¿¡¼­ »ó¼Ó ¹Þ¾Æ¼­ ÀÛ¼ºÇØ¾ß ÇÏ´Â °ÍÀÌ ¾Æ´Ï´Ù. ´ë½Å¿¡ µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®´Â ±âÁ¸¿¡ °³¹ßÇÑ ÄÞÆ÷³ÍÆ®¿¡ µ¥ÀÌÅÍ ¿¬µ¿ ±â´ÉÀ» Ãß°¡ÇØ ÁÖ´Â °úÁ¤À̶ó°í »ý°¢ÇÏ¸é ½±´Ù. Áï ÄÞÆ÷³ÍÆ® ³»ºÎ¿¡ µ¥ÀÌÅÍ ¸µÅ©¸¦ »ý¼ºÇØÁÖ°í µ¥ÀÌÅÍ ¿¬µ¿À» À§ÇÑ ¸î°¡Áö ÇÁ·ÎÆÛƼ¸¦ Ãß°¡ÇØÁÖ¸é µÈ´Ù.
2.5.2. µ¥ÀÌÅÍ ¸µÅ©(Data Link)
ÄÞÆ÷³ÍÆ®¿Í µ¥ÀÌÅͺ£À̽º´Â µ¥ÀÌÅÍ ¸µÅ©¸¦ ÅëÇØ¼­ ¿¬°áµÈ´Ù. ÄÞÆ÷³ÍÆ®ÀÇ µ¥ÀÌÅÍ ¿¬µ¿ ÇüÅ¿¡ »ó°ü ¾øÀÌ µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®´Â DataSetÀ» Á¶ÀÛÇϱâ À§ÇØ DataSource ¶ó´Â ÇÁ·ÎÆÛƼ¸¦ ÅëÇØ µ¥ÀÌÅÍ ¸µÅ©¸¦ »ý¼ºÇØ¾ß ÇÑ´Ù. µ¥ÀÌÅÍ ¸µÅ©´Â TDataLink Ŭ·¡½º³ª ±× ÀÚ¼Õ Å¬·¡½º(TFieldDataLink, TGridDataLink µî)À» ÅëÇØ¼­ »ý¼ºµÈ´Ù. ¸¸¾à ÄÞÆ÷³ÍÆ®°¡ ´ÜÀÏ Çʵ带 Á¶ÀÛÇÑ´Ù¸é TFieldDataLink Ŭ·¡½º¸¦ »ç¿ëÇÏ¸ç ´ÙÁß Çʵå¿Í ´ÙÁß ·¹Äڵ带 Á¶ÀÛÇÑ´Ù¸é TDataLinkÀÇ ÀÚ¼Õ Å¬·¡½º¸¦ »õ·Î ¸¸µé¾î¼­ »ç¿ëÇÏ°Ô µÈ´Ù.
¾Æ·¡¿¡ TDataLink¿Í TFieldDataLinkÀÇ Áß¿äÇÑ ÇÁ·ÎÆÛƼ¿Í ¸Þ¼Òµå, ±×¸®°í À̺¥Æ®µé¿¡ ´ëÇØ ³ªÅ¸³»¾ú´Ù.


Ç¥ 2-1 TDataLinkÀÇ ÇÁ·ÎÆÛƼ
ÇÁ·ÎÆÛƼ¼³¸í
ActiveDataSetÀÌ È°¼ºÈ­ »óÅÂÀÎÁö ¾Æ´ÑÁö¸¦ ¼³Á¤ÇÑ´Ù.
ActiveRecordDataSet ³»ºÎ ¹öÆÛ°¡ °¡Áö°í ÀÖ´Â ·¹Äڵ忡¼­ ¸î¹øÂ° ·¹Äڵ尡 ÇöÀç ·¹ÄÚµåÀÎÁö¸¦ ³ªÅ¸³½´Ù. ActiveRecord´Â Àüü ·¹ÄÚµå °³¼ö¿¡¼­ÀÇ ¼ø¹øÀÌ ¾Æ´Ï°í ³»ºÎ ¹öÆÛ¿¡ ÀÖ´Â ·¡Äڵ忡¼­ÀÇ ¼ø¹øÀÓÀ» ÁÖÀÇÇØ¾ß ÇÑ´Ù.
BOFÄ¿¼­°¡ DataSetÀÇ Ã¹¹øÂ° ·¹Äڵ忡 ÀÖÀ½À» ³ªÅ¸³½´Ù.
BufferCount³»ºÎ ¹öÆÛ¿¡ ÀоîµéÀÏ ·¹ÄÚµåÀÇ °³¼ö¸¦ ³ªÅ¸³½´Ù.
DataSetµ¥ÀÌÅÍ ¸µÅ©°¡ ¿¬°áµÈ DataSetÀ» ³ªÅ¸³½´Ù.
DataSourceµ¥ÀÌÅÍ ¸µÅ©ÀÇ ¼ÒÀ¯ÁÖ(µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®)°¡ DataSetÀ» »ç¿ëÇÒ ¶§ »ç¿ëÇÏ´Â DataSource ÄÞÆ÷³ÍÆ®¸¦ ÁöÁ¤ÇÑ´Ù.
EditingDataSetÀÌ ÆíÁý ¸ðµåÀÓÀ» ³ªÅ¸³»´Ù.
EOFÄ¿¼­°¡ DataSetÀÇ ¸¶Áö¸· ·¹Äڵ忡 ÀÖÀ½À» ³ªÅ¸³½´Ù.
ReadOnlyDataSetÀ» ¼öÁ¤ÇÒ ¼ö ÀÖ´ÂÁö¸¦ ³ªÅ¸³½´Ù.
RecordCount³»ºÎ ¹öÆÛ¿¡ ½ÇÁ¦·Î ¸î °³ÀÇ ·¹Äڵ尡 ÀÖ´ÂÁö¸¦ ³ªÅ¸³½´Ù. º¸Åë BufferCount¿Í °°Àº °ªÀÌÁö¸¸ TDBGridó·³ BufferCountº¸´Ù ÀÛÀ» °æ¿ìµµ ÀÖ´Ù.




Ç¥ 2-2 TDataLinkÀÇ ¸Þ¼Òµå
¸Þ¼Òµå ¼³¸í
ActiveChangedActive ÇÁ·ÎÆÛƼ°¡ º¯°æµÉ ¶§ ¸¶´Ù È£ÃâµÈ´Ù.
DataSetChangedDataSetÀÇ ³»¿ëÀÌ º¯°æµÉ ¶§ ¸¶´Ù È£ÃâµÈ´Ù. DataSetÀÇ ³»¿ëÀÌ ¼öÁ¤µÇ°Å³ª »õ·Î¿î ·¹Äڵ尡 Ãß°¡µÇ°Å³ª ·¹Äڵ尡 »èÁ¦µÉ ¶§ È£ÃâµÈ´Ù. ½ÇÁ¦·Î DataSetChanged´Â RecordChanged¸¦ È£ÃâÇÑ´Ù.
EditDataSetÀ» ÆíÁý ¸ðµå·Î º¯°æÇÑ´Ù.
EditingChangedEditing ÇÁ·ÎÆÛƼ°¡ º¯°æµÉ ¶§ ¸¶´Ù È£ÃâµÈ´Ù.
RecordChangedÇöÀç ·¹ÄÚµåÀÇ ÇʵåÀÇ ³»¿ëÀÌ º¯°æµÉ ¶§ ¸¶´Ù È£ÃâµÈ´Ù. ÇʵåÀÇ ³»¿ëÀÌ Æ÷½ºÆ®µÈ ÈÄ¿¡ ¹ß»ýÇÑ´Ù.
UpdateRecordÄÞÆ÷³ÍÆ®°¡ ÇÊ¿äÇÑ °æ¿ì¿¡ È£ÃâÇÒ ¼ö ÀÖÀ¸¸ç ÄÞÆ÷³ÍÆ®ÀÇ »óŸ¦ DataSet¿¡ ¹Ý¿µÇÑ´Ù. ½ÇÁ¦·Î UpdateData¸¦ È£ÃâÇÑ´Ù.




Ç¥ 2-3 TFieldDataLinkÀÇ ÇÁ·ÎÆÛƼ
ÇÁ·ÎÆÛƼ¼³¸í
CanModifyÇʵ带 ÆíÁýÇÒ ¼ö ÀÖ´ÂÁö¸¦ ³ªÅ¸³½´Ù.
ControlField °´Ã¼ÀÇ FocusControl ÇÁ·ÎÆÛƼ¿Í µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¸¦ ¿¬°áÇϱâ À§Çؼ­ TFieldDataLink °´Ã¼¸¦ »ç¿ëÇÏ´Â µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¸¦ ¼³Á¤ÇÑ´Ù.
Field¿¬°áµÈ ÇÊµå °´Ã¼¸¦ ³ªÅ¸³½´Ù.
FieldName¿¬°áµÈ ÇʵåÀÇ À̸§À» ³ªÅ¸³»´Ù.




Ç¥ 2-4 TFieldDataLinkÀÇ À̺¥Æ®
À̺¥Æ®¼³¸í
OnActiveChangeActive ÇÁ·ÎÆÛƼ°¡ º¯°æµÉ ¶§ ¹ß»ýÇÑ´Ù.
OnDataChangeÇʵåÀÇ °ªÀÌ º¯°æµÉ ´ë ¹ß»ýÇÑ´Ù.
OnEditingChangeDataSetÀÇ ¸ðµå°¡ º¯°æµÉ ¶§ ¹ß»ýÇÑ´Ù.
OnUpdateDataÇʵåÀÇ °ªÀÌ ÄÞÆ÷³ÍÆ®ÀÇ °ªÀ¸·Î ¾÷µ¥ÀÌÆ®µÉ ¶§ ¹ß»ýÇÑ´Ù.


2.5.3. µ¥ÀÌÅÍ ¿­¶÷(Data Browsing) ÄÞÆ÷³ÍÆ®
°£´ÜÇÏ°Ô ÀÎ¸Æ Å×À̺íÀÇ ³»¿ëÀ» ¸íÇÔó·³ º¸¿©ÁÖ´Â µ¥ÀÌÅÍ ¿­¶÷ Àü¿ë ÄÞÆ÷³ÍÆ®ÀÎ TdpbNameCard¸¦ ¸¸µé¾î º¸ÀÚ. ¾Æ·¡¿¡ ¿Ï¼ºµÈ TdpbNameCard ÄÞÆ÷³ÍÆ®°¡ µ¿ÀÛÇÏ´Â È­¸é°ú ¼Ò½º Äڵ带 ³ªÅ¸³»¾ú´Ù.

±×¸² 2-13 TdpbNameCard µ¿ÀÛ ¿¹Á¦




¸®½ºÆ® 2.5 dpbNameCard.pas
unit dpbNameCard;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, db, dbTables, ExtCtrls;

type
  TdpbNameCard = Class;

  { µ¥ÀÌÅÍ ¸µÅ© Ŭ·¡½º ¼±¾ð }
  TdpbNameCardDataLink = Class(TDataLink)
  private
    FCard: TdpbNameCard;
  protected
    procedure DataSetChanged; override;
    procedure DataSetScrolled(Distance : Integer); override;
    procedure ActiveChanged; override;
  public
    constructor Create(ACard: TdpbNameCard);
    destructor Destroy; override;
  End;

  TdpbNameCard = class(TCustomControl)
  private
    { Private declarations }
    FBorderStyle : TBorderStyle;
    FDataLink : TdpbNameCardDataLink;
    FStartRecord : Integer;
    FViewConfiguration : TStrings;
    FColCount : Integer;
    FRowCount : Integer;
    FNameFont : TFont;
    FNameColor : TColor;
    FCardWidth : Integer;
    FCardHeight : Integer;
    FCardColor : TColor;
    FCardBorderColor : TColor;

    procedure SetBorderStyle(Value : TBorderStyle);
    function GetDataSource: TDataSource;
    procedure SetDataSource(Value: TDataSource);
    procedure SetViewConfiguration(Value : TStrings);
    procedure Changed(Sender : TObject);
    procedure SetCardWidth(Value : Integer);
    procedure SetCardHeight(Value : Integer);
    procedure SetNameFont(Value : TFont);
    procedure SetCardColor(Value : TColor);
    procedure SetCardBorderColor(Value : TColor);
    procedure SetNameColor(Value : TColor);
    procedure SetVertScrollRange(Const AMin, AMax : Integer);
    procedure SetVertScrollPos(Const APos : Integer);
    procedure AdjustColRow;
    procedure DoVScroll(ScrollCode : TScrollCode);

    procedure DataChanged;
    procedure ActiveChanged;
  protected
    { Protected declarations }
    procedure CreateWnd; override;
    procedure CreateParams(var Params: TCreateParams); Override;
    procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
    procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
              X, Y: Integer); override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;

    procedure UpdateVertScrollBar;
    function  GetCellRect(const ACol, ARow : Integer) : TRect;
    function  VisibleRows : Integer;
  public
    { Public declarations }
    Constructor Create(AOwner: TComponent); Override;
    Destructor Destroy; Override;
    procedure Paint; override;
    procedure Loaded; override;
  published
    { Published declarations }
    Property Align;
    Property BorderStyle : TBorderStyle
             Read FBorderStyle
             Write SetBorderStyle
             Default bsSingle;

    property CardBorderColor : TColor
             read FCardBorderColor
             write SetCardBorderColor
             default clBtnFace;
    property CardColor : TColor
             read FCardColor
             write SetCardColor
             default clWindow;

    property CardHeight : Integer
             read FCardHeight
             write SetCardHeight
             default 90;

    property CardWidth : Integer
             read FCardWidth
             write SetCardWidth
             default 60;

    Property Color;
    property Constraints;
    Property Ctl3D;

    property DataSource: TDataSource
             read GetDataSource
             write SetDataSource;

    Property Font;
    property Hint;

    property NameColor : TColor
             read FNameColor
             write SetNameColor
             default clBtnFace;

    property NameFont : TFont
             read FNameFont
             write SetNameFont;

    Property ParentColor;
    property ParentCtl3D;
    Property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property ViewConfiguration : TStrings
             read FViewConfiguration
             write SetViewConfiguration;

    property OnClick;
    property OnDblClick;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('DPB', [TdpbNameCard]);
end;

function GetWord(AValue : string; AIndex : Integer; ADelimiter : char) : string;
var
  nIndex, DelNum : integer;
begin
  Result := '';
  DelNum := 1;
  for nIndex := 1 to Length(AValue) do
  begin
    if AValue[nIndex] = ADelimiter then
      Inc(DelNum)
    else
    begin
      if DelNum = AIndex then
        Result := Result + AValue[nIndex];
    end;
  end;
  Result := Trim(Result);
end;

function Min( A, B : Integer ) : Integer;
begin
  if A < B then
    Result := A
  else
    Result := B;
end;

{ TdpbNameCardDataLink }

constructor TdpbNameCardDataLink.Create(ACard: TdpbNameCard);
begin
  inherited Create;
  FCard := ACard;
end;

destructor TdpbNameCardDataLink.Destroy;
begin
  FCard := nil;
  inherited Destroy;
end;

procedure TdpbNameCardDataLink.ActiveChanged;
begin
  if FCard <> nil then FCard.ActiveChanged;
end;

procedure TdpbNameCardDataLink.DataSetChanged;
begin
  if FCard <> nil then FCard.DataChanged;
end;

procedure TdpbNameCardDataLink.DataSetScrolled(Distance : Integer);
begin
  if FCard <> nil then FCard.DataChanged;
end;

{ TdpbNameCard }


procedure TdpbNameCard.SetBorderStyle(Value: TBorderStyle);
begin
  if FBorderStyle <> Value then
  begin
    { BorderStyleÀº WindowÀÇ Style·Î ¼³Á¤µÇ±â ¶§¹®¿¡ BorderStyleÀÌ º¯°æµÇ¸é
      À©µµ¸¦ ´Ù½Ã »ý¼ºÇϱâ À§ÇØ RecreateWnd ¸¦ È£ÃâÇÑ´Ù. }
    FBorderStyle := Value;
    RecreateWnd;
  end;
end;

function TdpbNameCard.GetDataSource: TDataSource;
begin
  Result := FDataLink.DataSource;
end;

procedure TdpbNameCard.SetDataSource(Value: TDataSource);
begin
  if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
    FDataLink.DataSource := Value;
  if Value <> nil then Value.FreeNotification(Self);
  if not (csLoading in ComponentState) then ActiveChanged;
end;

procedure TdpbNameCard.SetViewConfiguration(Value: TStrings);
begin
  FViewConfiguration.Assign(Value);
  Invalidate;
end;

procedure TdpbNameCard.SetCardWidth(Value: Integer);
begin
  if FCardWidth <> Value then
  begin
    FCardWidth := Value;
    AdjustColRow;
  end;
end;

procedure TdpbNameCard.SetCardHeight(Value: Integer);
begin
  if FCardHeight <> Value then
  begin
    FCardHeight := Value;
    AdjustColRow;
  end;
end;

procedure TdpbNameCard.SetNameFont(Value: TFont);
begin
  FNameFont.Assign(Value);
  Invalidate;
end;

procedure TdpbNameCard.SetCardBorderColor(Value: TColor);
begin
  if FCardBorderColor <> Value then
  begin
    FCardBorderColor := Value;
    Invalidate;
  end;
end;

procedure TdpbNameCard.SetCardColor(Value: TColor);
begin
  if FCardColor <> Value then
  begin
    FCardColor := Value;
    Invalidate;
  end;
end;

procedure TdpbNameCard.SetNameColor(Value: TColor);
begin
  if FNameColor <> Value then
  begin
    FNameColor := Value;
    Invalidate;
  end;
end;

procedure TdpbNameCard.ActiveChanged;
begin
  if HandleAllocated then
  begin
    UpdateVertScrollBar;
    Invalidate;
  end;
end;

procedure TdpbNameCard.DataChanged;
begin
  if HandleAllocated then
  begin
    UpdateVertScrollBar;
    Invalidate;
  end;
end;

procedure TdpbNameCard.CMCtl3DChanged(var Message: TMessage);
begin
  If FBorderStyle = bsSingle Then
    RecreateWnd;
  Inherited;
end;

constructor TdpbNameCard.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  { ĸ¼ÇÀ» ÀÚµ¿À¸·Î ¼³Á¤ÇÒ Çʿ䰡 ¾øÀ¸´Ï±î csSetCaption Ç÷¡±×¸¦ Áö¿î´Ù. }
  ControlStyle := ControlStyle - [csSetCaption];
  Width := 200;
  Height := 150;
  ParentColor := False;
  Color := clWindow;

  FBorderStyle := bsSingle;
  FCardWidth := 90;
  FCardHeight := 60;
  FCardColor := clWindow;
  FCardBorderColor := clBtnFace;
  FNameColor := clBtnFace;
  FStartRecord := 0;


  { µ¥ÀÌÅÍ ¸µÅ©¸¦ »ý¼ºÇÑ´Ù. }
  FDataLink := TdpbNameCardDataLink.Create(Self);

  FViewConfiguration := TStringList.Create;
  TStringList(FViewConfiguration).OnChange := Changed;

  FNameFont := TFont.Create;
  FNameFont.OnChange := Changed;
end;

procedure TdpbNameCard.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do
  begin
    { ¼öÁ÷ ½ºÅ©·Ñ ¹Ù¸¦ Ãß°¡ÇÑ´Ù. }
    Style := Style or WS_VSCROLL;
    if FBorderStyle = bsSingle then
    begin
      { ÄÞÆ÷³ÍÆ®ÀÇ ¿Ü°û¼±À» °áÁ¤ÇÑ´Ù. }
      if Ctl3D then
        ExStyle := ExStyle or WS_EX_CLIENTEDGE
      else
        Style := Style or WS_BORDER;
    end;
    WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  End;
end;

destructor TdpbNameCard.Destroy;
begin
  FNameFont.Free;
  FViewConfiguration.Free;
  FDataLink.Free;
  inherited Destroy;
end;

procedure TdpbNameCard.Paint;
Const
  FieldAlignment : Array[0..2] Of Integer = (DT_LEFT, DT_CENTER, DT_RIGHT);
var
  nIndex : Integer;
  OldActive : Integer;
  StartRow, StopRow : Integer;
  nCol, nRow : Integer;
  szField, szFormat : String;
  CellRect, TmpRect, FieldRect : TRect;
begin
  Canvas.Brush.Color := Self.Color;
  Canvas.FillRect(ClientRect);

  if FDataLink.Active then
  begin
    { ½ÃÀÛ ·¹ÄÚµå¿Í ¸¶Áö¸· ·¹Äڵ带 ±¸ÇÑ´Ù. }
    StartRow := FDataLink.ActiveRecord;
    for nIndex := 1 to VisibleRows do
      if StartRow > 0 then
        Dec( StartRow );
    StopRow := Min(FDataLink.RecordCount, StartRow + VisibleRows);
    OldActive := FDataLink.ActiveRecord;
  end
  else
  begin
    OldActive := 0;
    StopRow := 0;
  end;

  StartRow := 0;
  for nRow := 1 To FRowCount do
  begin
    for nCol := 1 To FColCount do
    begin
      { Ä«µå°¡ ±×·ÁÁú ¿µ¿ªÀ» ±¸ÇÑ´Ù .}
      CellRect := GetCellRect(nCol, nRow);

      if FDataLink.Active then
      begin
        if StartRow < StopRow then
        begin
          Canvas.Pen.Color := FCardBorderColor;
          Canvas.Brush.Color := FCardColor;
          Canvas.Rectangle(CellRect.Left, CellRect.Top,
                           CellRect.Right, CellRect.Bottom);

          FDataLink.ActiveRecord := StartRow;
          Inc(StartRow);

          { À̸§ ¿µ¿ªÀÇ ¹è°æÀ» ±×¸°´Ù. }
          Canvas.Font.Assign(FNameFont);
          TmpRect := CellRect;
          TmpRect.Bottom := TmpRect.Top + Canvas.TextHeight('A') + 8;
          if FDataLink.ActiveRecord = OldActive then
          begin
            Canvas.Brush.Color := clHighlight;
            Canvas.Font.Color := clHighlightText;
          end
          else
          begin
            Canvas.Brush.Color := FNameColor;
          end;
          Canvas.FillRect(TmpRect);
          InflateRect(TmpRect, -2, -2);

          { À̸§À» Ãâ·ÂÇÑ´Ù. }
          DrawText(Canvas.Handle,
                   PChar(FDataLink.DataSet.FieldByName('Name').DisplayText + ' ' +
                         FDataLink.DataSet.FieldByName('Position').DisplayText ),
                   -1, TmpRect, DT_LEFT or DT_SINGLELINE or DT_VCENTER);

          {
            ±×¸®´Â ·¹Äڵ尡 ÇöÀç ·¹ÄÚµåÀ̰í ÀÔ·Â Æ÷Ä¿½º¸¦ °¡Áö°í ÀÖÀ¸¸é
            Æ÷Ä¿½º¸¦ ³ªÅ¸³»´Â »ç°¢ÇüÀ» ±×·ÁÁØ´Ù.
          }
          if Focused and (FDataLink.ActiveRecord = OldActive) then
            Canvas.DrawFocusRect(TmpRect);
          Canvas.Brush.Color := FCardColor;

          { ±âŸ Çʵ带 ViewConfiguration¿¡ Á¤ÀÇµÈ ¼ø¼­´ë·Î ±×·ÁÁØ´Ù. }
          Canvas.Font.Assign(Self.Font);
          For nIndex := 0 To Pred(FViewConfiguration.Count) Do
          Begin
            If Length(FViewConfiguration[nIndex]) > 0 then
            Begin
              { Çʵå À̸§ }
              szField := GetWord(FViewConfiguration[nIndex], 1, ',');

              { Çʵ尡 ±×·ÁÁú ¿µ¿ª }
              FieldRect.Left := TmpRect.Left +
                StrToIntDef(GetWord(FViewConfiguration[nIndex], 2, ','), 0);
              FieldRect.Top := TmpRect.Bottom +
                StrToIntDef(GetWord(FViewConfiguration[nIndex], 3, ','), 0) + 3;
              FieldRect.Right := FieldRect.Left +
                StrToIntDef(GetWord(FViewConfiguration[nIndex], 4, ','), 0);
              FieldRect.Bottom := FieldRect.Top +
                StrToIntDef(GetWord(FViewConfiguration[nIndex], 5, ','), 0);

              FieldRect.Right := Min(CellRect.Right - 3, FieldRect.Right);
              FieldRect.Bottom := Min(CellRect.Bottom - 3, FieldRect.Bottom);

              { Çʵ带 ±×¸± ¶§ »ç¿ëÇÒ ¹®ÀÚ¿­ Çü½Ä }
              szFormat := GetWord(FViewConfiguration[nIndex], 6, ',');
              DrawText(Canvas.Handle,
                       PChar(Format(szFormat,
                       [FDataLink.DataSet.FieldByName(szField).DisplayText])),
                       -1, FieldRect,
                       { Çʵå Á¤·Ä ¹æ¹ý }
                       FieldAlignment[StrToIntDef(GetWord(FViewConfiguration[nIndex], 7, ','), 0)]
                       or DT_SINGLELINE or DT_VCENTER);
            End;
          End;
        end;
      end;
    end;
  end;
  if FDataLink.Active Then
    FDataLink.ActiveRecord := OldActive;
end;

function TdpbNameCard.VisibleRows: Integer;
begin
  Result := FColCount * FRowCount;
end;

procedure TdpbNameCard.DoVScroll(ScrollCode : TScrollCode);
var
  Offset : Integer;
begin
  Case ScrollCode of
    scLineUp :
      begin
        if not FDataLink.DataSet.BOF then
        begin
          if (FDataLink.ActiveRecord < FColCount) and
             (FDataLink.ActiveRecord > 0) then
          begin
            Offset := FDataLink.ActiveRecord;
            FDataLink.DataSet.MoveBy(-(FColCount + Offset));
            FDataLink.ActiveRecord := FDataLink.ActiveRecord + Offset;
          end
          else
            FDataLink.DataSet.MoveBy(-FColCount);
        end;
      end;
    scLineDown :
      begin
        if not FDataLink.DataSet.EOF then
        begin
          if (FDataLink.ActiveRecord div FColCount) = Pred(FRowCount) then
          begin
            Offset := FColCount - (FDataLink.ActiveRecord mod FColCount) - 1;
            FDataLink.DataSet.MoveBy(FColCount + Offset);
            FDataLink.ActiveRecord := FDataLink.ActiveRecord - Offset;
          end
          else
            FDataLink.DataSet.MoveBy(FColCount);
        end;
      end;
    scPageUp : FDataLink.DataSet.MoveBy(-VisibleRows);
    scPageDown : FDataLink.DataSet.MoveBy(VisibleRows);
    scTop : FDataLink.DataSet.First;
    scBottom : FDataLink.DataSet.Last;
  end;
end;

procedure TdpbNameCard.WMVScroll(var Message: TWMVScroll);
Begin
  With Message Do
  begin
    Case ScrollCode of
      SB_LINEUP, SB_LINEDOWN, SB_TOP, SB_BOTTOM, SB_PAGEUP, SB_PAGEDOWN :
        begin
          DoVScroll(TScrollCode(Message.ScrollCode));
        End;
      SB_THUMBPOSITION :
        begin
          FDataLink.DataSet.RecNo := Pos;
        End;
    End;
  End;
end;

procedure TdpbNameCard.SetVertScrollPos(const APos: Integer);
var
  sc : TScrollInfo;
Begin
  sc.cbSize := SizeOf(TScrollInfo);
  sc.fMask := SIF_POS Or SIF_DISABLENOSCROLL;
  sc.nPos := APos;
  SetScrollInfo(Handle, SB_VERT, sc, True);
end;

procedure TdpbNameCard.SetVertScrollRange(const AMin, AMax: Integer);
var
  sc : TScrollInfo;
Begin
  sc.cbSize := SizeOf(TScrollInfo);
  sc.fMask := SIF_RANGE or SIF_PAGE or SIF_DISABLENOSCROLL;
  sc.nMin := AMin;
  sc.nPage := VisibleRows;
  sc.nMax := AMax;
  SetScrollInfo(Handle, SB_VERT, sc, True);
end;

procedure TdpbNameCard.UpdateVertScrollBar;
begin
  if HandleAllocated then
  begin
    if FDatalink.Active then
    begin
      with FDataLink.DataSet do
      begin
        SetVertScrollRange(1, RecordCount + VisibleRows - 1);
        SetVertScrollPos(RecNo);
      end;
    end
    else
    begin
      with FDataLink.DataSet do
      begin
        SetVertScrollRange(1, 1);
        SetVertScrollPos(1);
      end;
    end;
  end;
end;

procedure TdpbNameCard.CreateWnd;
begin
  inherited CreateWnd;
  FDataLink.BufferCount := VisibleRows;
  UpdateVertScrollBar;
end;

procedure TdpbNameCard.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
var
  nCol, nRow : Integer;
begin
  inherited;
  SetFocus;
  if FDataLink.Active then
  begin
    { ¸¶¿ì½º Æ÷ÀÎÅÍÀÇ À§Ä¡¿¡ µû¶ó ÇöÀç ·¹Äڵ带 Á¶Á¤ÇÑ´Ù. }
    for nRow := 1 To FRowCount do
    begin
      for nCol := 1 To FColCount do
      begin
        if PtInRect(GetCellRect(nCol, nRow), POINT(X, Y)) then
        begin
          FDataLink.DataSet.MoveBy(((nRow-1) * FColCount) + (nCol-1) -
                                   FDataLink.ActiveRecord);
          Exit;
        end;
      end;
    end;
  end;
end;

procedure TdpbNameCard.Changed(Sender: TObject);
begin
  Invalidate;
end;

{ °¢ ¸íÇÔÀÌ ±×·ÁÁú »ç°¢ ¿µ¿ªÀ» ±¸ÇÑ´Ù. }
function TdpbNameCard.GetCellRect(const ACol, ARow: Integer): TRect;
const
  MARGIN = 10;
var
  CellW, CellH : Integer;
begin
  CellW := (ClientWidth - ((FColCount + 1) * MARGIN)) div FColCount;
  CellH := (ClientHeight - ((FRowCount + 1) * MARGIN)) div FRowCount;

  Result.Left := (MARGIN * ACol) + (CellW * (ACol-1));
  Result.Top := (MARGIN * ARow) + (CellH * (ARow-1));
  Result.Right := Result.Left + CellW;
  Result.Bottom := Result.Top + CellH;
end;

procedure TdpbNameCard.WMEraseBkgnd(var Message: TMessage);
begin
  { È­¸é ±ô¹ÚÀÓÀ» ÁÙ¿© ÁØ´Ù. }
  Message.Result := 1;
end;

procedure TdpbNameCard.WMKillFocus(var Message: TWMKillFocus);
begin
  Invalidate;
end;

procedure TdpbNameCard.WMSetFocus(var Message: TWMSetFocus);
begin
  Invalidate;
end;

procedure TdpbNameCard.AdjustColRow;
begin
  FColCount := ClientWidth div FCardWidth;
  FRowCount := ClientHeight div FCardHeight;
  FDataLink.BufferCount := VisibleRows;
  UpdateVertScrollBar;
  Invalidate;
end;

procedure TdpbNameCard.Loaded;
begin
  inherited;
  AdjustColRow;
  ActiveChanged;
end;

procedure TdpbNameCard.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited KeyDown(Key, Shift);
  if FDataLink.Active then
  begin
    case Key of
      VK_LEFT: FDataLink.DataSet.MoveBy(-1);
      VK_RIGHT: FDataLink.DataSet.MoveBy(1);
      VK_UP: DoVScroll(scLineUp);
      VK_DOWN: DoVScroll(scLineDown);
      VK_PRIOR: DoVScroll(scPageUp);
      VK_NEXT: DoVScroll(scPageDown);
      VK_HOME: DoVScroll(scTop);
      VK_END: DoVScroll(scBottom);
      VK_RETURN : DblClick;
    end;
  end;
end;

procedure TdpbNameCard.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  { È­»ìÇ¥ ۸¦ ÀÔ·Â ¹ÞÀ» ¼ö ÀÖµµ·Ï ÇÑ´Ù. }
  Message.Result := DLGC_WANTARROWS;
end;

procedure TdpbNameCard.WMSize(var Message: TWMSize);
begin
  inherited;
  AdjustColRow;
end;

end.


¸ÕÀú TdpbNameCard ÄÞÆ÷³ÍÆ®´Â ÀÎ¸Æ Å×À̺íÀÇ ¿©·¯ ·¹Äڵ带 ¿­¶÷ÇϹǷΠTDataLink¿¡¼­ »ó¼Ó ¹ÞÀº TdpbNameCardDataLink Ŭ·¡½º¸¦ ¸¸µç´Ù.
TdpbNameCardDataLink´Â TDataLink Ŭ·¡½ºÀÇ ActiveChanged¿Í DataChanged ¸Þ¼Òµå¸¦ ¿À¹ö¶óÀ̵åÇØ¼­ DataSetÀÇ Active ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ°Å³ª DataSetÀÇ ÇöÀç ·¹Äڵ尡 º¯°æµÇ´Â »óȲÀ» ÄÞÆ÷³ÍÆ®°¡ ÀÚµ¿À¸·Î ¹Ý¿µÇÒ ¼ö ÀÖµµ·Ï ¸¸µé¾ú´Ù.
´ÙÀ½ TdpbNameCardÀÇ »ý¼ºÀÚ¿¡¼­ TdpbNameCardDataLinkÀÇ ÀνºÅϽº¸¦ »ý¼ºÇÏ°í ¼Ò¸êÀÚ¿¡¼­ ÀνºÅϽº¸¦ ÇØÁ¦ Çϵµ·Ï ÇØ¼­ TdpbNameCard ÄÞÆ÷³ÍÆ®°¡ »ý¼ºµÇ¸é µ¥ÀÌÅÍ ¸µÅ©µµ ¸¸µé¾î Áö°í ÄÞÆ÷³ÍÆ®°¡ ¼Ò¸êµÇ¸é µ¥ÀÌÅÍ ¸µÅ©µµ ¼Ò¸êµÇµµ·Ï ¸¸µé¾ú´Ù. ¸ðµç µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®´Â DataSource¶ó´Â ÇÁ·ÎÆÛƼ¸¦ Á¦°øÇؼ­ ³»ºÎ µ¥ÀÌÅÍ ¸µÅ©¿Í TDataSource ÄÞÆ÷³ÍÆ®¸¦ ¿¬°áÇÒ ¼ö ÀÖµµ·Ï Çϰí ÀÖ´Ù. µû¶ó¼­ TdpbNameCardµµ DataSource ÇÁ·ÎÆÛƼ¸¦ ¸¸µé¾î ÁØ´Ù. DataSource ÇÁ·ÎÆÛƼ´Â º°µµ ¸â¹ö º¯¼ö¸¦ ¸¸µå´Â °ÍÀÌ ¾Æ´Ï°í FDataLinkÀÇ DataSource ÇÁ·ÎÆÛƼ¸¦ ÄÞÆ÷³ÍÆ® »ç¿ëÀÚ¿¡°Ô ³ëÃâ½ÃÄÑ ÁÖ´Â ÇÁ·ÎÆÛƼÀ̹ǷΠGetDataSoruce Àб⠸޼ҵå¿Í SetDataSource ¾²±â ¸Þ¼Òµå¸¦ Á¦°øÇؼ­ FDataLinkÀÇ DataSource ÇÁ·ÎÆÛƼ¸¦ Á¶ÀÛÇϵµ·Ï ÇÑ´Ù. DataSource ÇÁ·ÎÆÛƼ´Â TDataSource ÄÞÆ÷³ÍÆ®¿¡ ´ëÇÑ ·¹ÆÛ·±½ºÀ̹ǷΠÆû ¼³°è ½Ã TDataSource ÄÞÆ÷³ÍÆ®°¡ »èÁ¦µÉ °æ¿ì¸¦ ´ëºñÇØ¼­ Notification ¸Þ¼Òµå¸¦ ¿À¹ö¶óÀ̵åÇØ¼­ ÀûÀýÇÑ Ã³¸®¸¦ ÇØÁÖµµ·Ï ÇÑ´Ù.
¿©±â±îÁö Çϸé ÄÞÆ÷³ÍÆ®ÀÇ µ¥ÀÌÅÍ ¸µÅ©¿Í µ¥ÀÌÅÍ ¼Ò½º°¡ Åë½ÅÇÒ ¼ö Àִ ä³ÎÀº ¸ðµÎ ¸¸µé¾î ÁÖ´Â °ÍÀÌ µÈ´Ù. ³ª¸ÓÁö ÀÎ¸Æ µ¥ÀÌÅ͸¦ ½ÇÁ¦·Î È­¸é¿¡ ±×·Á ÁÖ´Â ÀÏ µîÀº ÀÏ¹Ý ÄÞÆ÷³ÍÆ®¸¦ ¸¸µé ¶§¿Í °°ÀÌ °³¹ßÇÏ¸é µÈ´Ù. TdpbNameCard´Â µ¥ÀÌÅÍ ¼Ò½ºÀÇ ·¹ÄÚµå °³¼ö¿¡ µû¶ó ¼öÁ÷ ½ºÅ©·Ñ¹Ù°¡ ÇÊ¿äÇϹǷΠCreateParams ¸Þ¼Òµå¸¦ ¿À¹ö¶óÀ̵åÇØ¼­ À©µµ ½ºÅ¸ÀÏ¿¡ WS_VSCROLLÀ» Ãß°¡ÇØ ÁÖ°í ÄÞÆ÷³ÍÆ®ÀÇ ¿Ü°û¼±À» º¸±â ÁÁ°Ô Çϱâ À§ÇØ WS_EXCLIENTEDGE³ª WS_BORDER ½ºÅ¸ÀÏÀ» Ãß°¡ÇØ ÁØ´Ù.
±×·±µ¥ ¼Ò½º Äڵ带 º¸¸é ÀÌ»óÇÑ ¸Þ½ÃÁö(CM_CTL3DCHANGED) Çϳª¸¦ ó¸®ÇÏ´Â °ÍÀ» º¼ ¼ö ÀÖÀ» °ÍÀÌ´Ù. Messages.pas¸¦ ã¾Æ ºÁµµ ±×·± ¸Þ½ÃÁö´Â ¾ø´Ù. ÀÌ·± ¸Þ½ÃÁö¸¦ ÄÞÆ÷³ÍÆ® ¸Þ½ÃÁö¶ó°í Çϴµ¥ À©µµ ½Ã½ºÅÛ ¸Þ½ÃÁö°¡ ¾Æ´Ï°í µ¨ÆÄÀÌ¿¡¼­ º°µµ·Î Á¤ÀÇÇÑ Ä¿½ºÅÒ ¸Þ½ÃÁöÀÌ´Ù. ÄÞÆ÷³ÍÆ® ¸Þ½ÃÁö¿¡´Â ÄÞÆ÷³ÍÆ® °³¹ßÀÚ¿¡°Ô À¯¿ëÇÑ ¸Þ½ÃÁöµéÀÌ ¸¹Àºµ¥ 60¿©°³ÀÇ ¸Þ½ÃÁö Áß¿¡ Áß¿äÇÑ ¸Þ½ÃÁö¸¦ ¾Æ·¡ Ç¥¿¡ ³ªÅ¸³»¾ú´Ù. ÄÞÆ÷³ÍÆ® ¸Þ½ÃÁö´Â controls.pas¿¡ Á¤ÀǵǾî ÀÖ´Ù.


Ç¥ 2-5 ÄÞÆ÷³ÍÆ® ¸Þ½ÃÁö
¸Þ½ÃÁö¼³¸í
CM_PARENTFONTCHANGEDParentFont ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_PARENTCOLORCHANGEDParentColor ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_VISIBLECHANGEDVisible ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_ENABLEDCHANGEdEnabled ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_COLORCHANGEDColor ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_FONTCHANGEDFont ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_CTL3DCHANGEDCtl3D ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_TEXTCHANGEDText³ª Caption ÇÁ·ÎÆÛƼ°¡ º¯°æµÇ¾ú´Ù.
CM_MOUSEENTER¸¶¿ì½º Æ÷ÀÎÅͰ¡ ÄÞÆ÷³ÍÆ® ¿µ¿ª ³»¿¡ ÀÖ´Ù.
CM_MOUSELEAVE¸¶¿ì½º Æ÷ÀÎÅͰ¡ ÄÞÆ÷³ÍÆ® ¿µ¿ªÀ» ¹þ¾î ³µ´Ù.
CM_DESIGNHITTEST¼³°è ½Ã¿¡ ¸¶¿ì½º Æ÷ÀÎÅͰ¡ ÄÞÆ÷³ÍÆ® ¿µ¿ª ³»¿¡¼­ ¿òÁ÷ÀÌ¸é ¹ß»ýÇÑ´Ù. ÀÌ ¸Þ½ÃÁöÀÇ Result °ªÀ» 1·Î ÁÖ¸é WM_MOUSEMOVE ¸Þ½ÃÁö°¡ ¹ß»ýÇÑ´Ù. ÀÌ ¸Þ½ÃÁö¸¦ ÀÌ¿ëÇÏ¸é ¼³°è ½Ã¿¡µµ ½ÇÇà ½Ãó·³ µ¿ÀÛÇÏ°Ô ¸¸µé ¼ö ÀÖ´Ù. TDBGrid°¡ ÀÌ ¸Þ½ÃÁö¸¦ ¾ÆÁÖ À¯¿ëÇÏ°Ô »ç¿ëÇÑ´Ù.
CM_WANTSPECIALKEYƯ¼ö Ű(È­»ìÇ¥, ÅÇ, Enter µî)ÀÌ ´­·ÁÁö¸é ¹ß»ýÇÑ´Ù.
CM_GETDATALINKTDBCtrlGrid°¡ ÀÚ½ÅÀÌ Æ÷ÇÔÇϰí ÀÖ´Â µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®µé¿¡°Ô °¢ ÄÞÆ÷³ÍÆ®ÀÇ µ¥ÀÌÅÍ ¸µÅ©¸¦ ±¸Çϱâ À§ÇØ º¸³»´Â ¸Þ½ÃÁöÀÌ´Ù.


2.5.4. µ¥ÀÌÅÍ ¼öÁ¤(Data Editing)
µ¥ÀÌÅ͸¦ ¼öÁ¤ÇÒ ¼ö ÀÖ´Â µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¸¦ ¸¸µå´Â °ÍÀº µ¥ÀÌÅÍ ¿­¶÷ ±â´É¿¡ ´õÇØ¼­ ÆíÁýÇÏ°í ¾÷µ¥ÀÌÆ® ÇÏ´Â ±â´ÉÀ» Ãß°¡ÇØ ÁÖ´Â °ÍÀÌ´Ù. µ¥ÀÌÅÍ ¼öÁ¤ ±â´ÉÀ» Ãß°¡ÇÏ´Â °úÁ¤À» ¼³¸íÇϱâ À§ÇØ TdpbDBNumberEdit¶ó´Â ÄÞÆ÷³ÍÆ®¸¦ ¸¸µé°ÍÀÌ´Ù. TdpbDBNumberEdit´Â TCustomEdit¿¡¼­ »ó¼Ó¹Þ¾Æ¼­ ¸¸µå´Âµ¥ Űº¸µå·Î ÅØ½ºÆ®¸¦ ÀÔ·ÂÇÒ ¶§ ¼ýÀÚ¸¸ ¹Þ¾ÆµéÀ̵µ·Ï ÇÒ °ÍÀÌ´Ù. ¿Ï¼ºµÈ ÄÞÆ÷³ÍÆ®¿Í »ç¿ë ¿¹Á¦¸¦ ¾Æ·¡ ¸®½ºÆ®¿Í ±×¸²À¸·Î ³ªÅ¸³»¾ú´Ù.

±×¸² 2-14 dpbDBNumberEdit ¿¹Á¦ ½ÇÇà È­¸é


TdpbDBNumberEdit´Â ´Ù¸¥ µ¥ÀÌÅÍ ¿­¶÷ ÄÞÆ÷³ÍÆ®¿Í ¸¶Âù°¡Áö·Î µ¥ÀÌÅÍÀÇ ÇöÀç ·¹Äڵ尡 À̵¿µÇ¸é Áï½Ã ÇöÀç ·¹ÄÚµåÀÇ °ªÀ» ÄÞÆ÷³ÍÆ®ÀÇ Value °ªÀ¸·Î ¹Ý¿µÇÑ´Ù. ±×¸®°í ÄÞÆ÷³ÍÆ®ÀÇ Value °ªÀÌ º¯°æµÈ »óÅ¿¡¼­ ·¹Äڵ尡 À̵¿ÇÏ·Á Çϰųª ÀÔ·Â Æ÷Ä¿½º¸¦ ÀÒÀ» ¶§ ÀÚ½ÅÀÇ °ªÀ» ÇöÀç ·¹ÄÚµåÀÇ ÇÊµå °ªÀ¸·Î ÀúÀåÇÑ´Ù.

¸®½ºÆ® 2.6 DpbDBNumberEdit.pas
unit dpbDBNumberEdit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, db, dbctrls;

type
  TdpbDBNumberEdit = class(TCustomEdit)
  private
    FMinValue: LongInt;
    FMaxValue: LongInt;
    FDataLink : TFieldDataLink;

    function GetValue: LongInt;
    function CheckValue (NewValue: LongInt): LongInt;
    procedure SetValue (NewValue: LongInt);
    procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
    procedure CMExit(var Message: TCMExit);   message CM_EXIT;
    procedure WMUndo(var Message: TMessage); message WM_UNDO;
    procedure WMPaste(var Message: TWMPaste);   message WM_PASTE;
    procedure WMCut(var Message: TWMCut);   message WM_CUT;
    procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
    function GetDataField: string;
    function GetDataSource: TDataSource;
    procedure SetDataField(const Value: string);
    procedure SetDataSource(const Value: TDataSource);

    procedure DataChange(Sender: TObject);
    procedure EditingChange(Sender: TObject);
    procedure UpdateData(Sender: TObject);
    function GetReadOnly: Boolean;
    procedure SetReadOnly(const Value: Boolean);

  protected
    procedure Change; override;
    procedure Notification(AComponent: TComponent;
          Operation: TOperation); override;
    function IsValidChar(Key: Char): Boolean; virtual;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure KeyPress(var Key: Char); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Anchors;
    property AutoSelect;
    property AutoSize;
    property Color;
    property Constraints;
    property Ctl3D;
    property DataSource : TDataSource read GetDataSource write SetDataSource;
    property DataField : string read GetDataField write SetDataField;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Font;
    property MaxLength;
    property MaxValue: LongInt read FMaxValue write FMaxValue default 0;
    property MinValue: LongInt read FMinValue write FMinValue default 0;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Value: LongInt read GetValue write SetValue;
    property Visible;

    property OnChange;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('dpb', [TdpbDBNumberEdit]);
end;

{ TdpbDBNumberEdit }

constructor TdpbDBNumberEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  { TDBCtrlGrid¿¡¼­ »ç¿ëÇÏ·Á¸é csReplicatable Ç÷¡±×°¡ ¼³Á¤µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. }
  ControlStyle := ControlStyle - [csSetCaption] + [csReplicatable];

  FMinValue := 0;
  FMaxValue := 0;

  { µ¥ÀÌÅÍ ¸µÅ©¸¦ »ý¼ºÇÑ´Ù. }
  FDataLink := TFieldDataLink.Create;
  { TField °´Ã¼ÀÇ FocusControl ÇÁ·ÎÆÛƼ¿Í µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®¸¦ ¿¬°áÇϱâ À§ÇØ
    µ¥ÀÌÅÍ ¸µÅ©ÀÇ Control ÇÁ·ÎÆÛƼ¸¦ ÀÚ½ÅÀ¸·Î ¼³Á¤ÇÑ´Ù. } 
  FDataLink.Control := Self;
  FDataLink.OnDataChange := DataChange;
  FDataLink.OnEditingChange := EditingChange;
  FDataLink.OnUpdateData := UpdateData;

end;

destructor TdpbDBNumberEdit.Destroy;
begin
  FDataLink.Free;
  inherited Destroy;
end;

procedure TdpbDBNumberEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited KeyDown(Key, Shift);

  { ±ÛÀÚ »èÁ¦³ª »ðÀԽà µ¥ÀÌÅÍ ¸µÅ©¸¦ ¼öÁ¤ ¸ðµå·Î }
  if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then
    FDataLink.Edit;
end;

procedure TdpbDBNumberEdit.KeyPress(var Key: Char);
begin
  { À¯È¿ÇÑ Å°ÀÎÁö Á¶»çÇÑ´Ù. }
  if not IsValidChar(Key) then
  begin
    Key := #0;
    MessageBeep(0);
  end;

  case Key of
    { À¯È¿ÇÑ Å°ÀÎ °æ¿ì µ¥ÀÌÅÍ ¸µÅ©¸¦ ¼öÁ¤ ¸ðµå·Î º¯°æÇÑ´Ù. }
    ^H, ^V, ^X, '0'..'9', '+', '-':
      FDataLink.Edit;
    #27:
      begin
        { ESC ŰÀÎ °æ¿ì Reset }
        FDataLink.Reset;
        SelectAll;
        Key := #0;
      end;
  end;
  if Key <> #0 then inherited KeyPress(Key);
end;

function TdpbDBNumberEdit.IsValidChar(Key: Char): Boolean;
begin
  Result := (Key in ['+', '-', '0'..'9']) or
            ((Key < #32) and (Key <> Chr(VK_RETURN)));
end;

procedure TdpbDBNumberEdit.WMUndo(var Message: TMessage);
begin
  FDataLink.Edit;
  inherited;
end;

procedure TdpbDBNumberEdit.WMPaste(var Message: TWMPaste);
begin
  FDataLink.Edit;
  inherited;
end;

procedure TdpbDBNumberEdit.WMCut(var Message: TWMPaste);
begin
  FDataLink.Edit;
  inherited;
end;

procedure TdpbDBNumberEdit.CMExit(var Message: TCMExit);
begin
  inherited;

  if CheckValue (Value) <> Value then
    SetValue (Value);

  { ÀÔ·Â Æ÷Ä¿½º¸¦ ÀÒÀ» ¶§ º¯°æµÈ °ªÀ» ¾÷µ¥ÀÌÆ® ÇÑ´Ù. }
  try
    FDataLink.UpdateRecord;
  except
    { ¾÷µ¥ÀÌÆ®¿¡ ½ÇÆÐÇÏ¸é Æ÷Ä¿½º¸¦ ´Ù½Ã °¡Á® ¿Â´Ù. }
    SelectAll;
    SetFocus;
    raise;
  end;
end;

procedure TdpbDBNumberEdit.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (FDataLink <> nil) and
    (AComponent = DataSource) then DataSource := nil;
end;

function TdpbDBNumberEdit.GetValue: LongInt;
begin
  Result := StrToIntDef(Text, FMinValue);
end;

procedure TdpbDBNumberEdit.SetValue (NewValue: LongInt);
begin
  Text := IntToStr (CheckValue (NewValue));
end;

function TdpbDBNumberEdit.CheckValue (NewValue: LongInt): LongInt;
begin
  Result := NewValue;
  if (FMaxValue <> FMinValue) then
  begin
    if NewValue < FMinValue then
      Result := FMinValue
    else if NewValue > FMaxValue then
      Result := FMaxValue;
  end;
end;

procedure TdpbDBNumberEdit.CMEnter(var Message: TCMGotFocus);
begin
  if AutoSelect and not (csLButtonDown in ControlState) then
    SelectAll;
  inherited;
end;

function TdpbDBNumberEdit.GetDataField: string;
begin
  Result := FDataLink.FieldName;
end;

function TdpbDBNumberEdit.GetDataSource: TDataSource;
begin
  Result := FDataLink.DataSource;
end;

procedure TdpbDBNumberEdit.SetDataField(const Value: string);
begin
    FDataLink.FieldName := Value;
end;

procedure TdpbDBNumberEdit.SetDataSource(const Value: TDataSource);
begin
  if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
    FDataLink.DataSource := Value;
  if Value <> nil then Value.FreeNotification(Self);
end;

procedure TdpbDBNumberEdit.CMGetDataLink(var Message: TMessage);
begin
  Message.Result := Integer(FDataLink);
end;

function TdpbDBNumberEdit.GetReadOnly: Boolean;
begin
  Result := FDataLink.ReadOnly;
end;

procedure TdpbDBNumberEdit.SetReadOnly(const Value: Boolean);
begin
  FDataLink.ReadOnly := Value;
end;

procedure TdpbDBNumberEdit.DataChange(Sender: TObject);
begin
  { ÇöÀç ÇʵåÀÇ °ªÀ» ÄÞÆ÷³ÍÆ®¿¡ ¹Ý¿µÇÑ´Ù. }
  if FDatalink.Field <> nil then
    Value := FDataLink.Field.AsInteger
  else
  begin
    if csDesigning in ComponentState then
      Text := Name
    else
      Text := '';
  end;
end;

procedure TdpbDBNumberEdit.EditingChange(Sender: TObject);
begin
  inherited ReadOnly := not FDataLink.Editing;
end;

procedure TdpbDBNumberEdit.UpdateData(Sender: TObject);
begin
  { ½ÇÁ¦·Î ÇʵåÀÇ °ªÀ» ¾÷µ¥ÀÌÆ® ÇÑ´Ù. }
  FDataLink.Field.AsInteger := Value;
end;

procedure TdpbDBNumberEdit.Change;
begin
  if FDataLink <> nil then
    FDataLink.Modified;
  inherited Change;
end;

end.


µ¥ÀÌÅÍ ¿¬µ¿À» À§ÇØ ¿©·¯ °³ÀÇ Çʵ带 ÂüÁ¶ÇÏ´Â TdpbNameCard¿Í ´Þ¸® TdpbDBNumberEdit´Â ÇϳªÀÇ Çʵ常 ¿¬°áÇϹǷΠTFieldDataLink °´Ã¼¸¦ »ç¿ëÇÑ´Ù. TFieldDataLink´Â TDataLink¿Í ´Þ¸® µ¥ÀÌÅÍ¿¡¼­ ¹ß»ýÇÏ´Â »ç°ÇÀ» À̺¥Æ®·Î Á¤ÀÇÇØ ³õ¾Ò±â ¶§¹®¿¡ TdpbNameCard¿¡¼­ ó·³ °¡»ó ¸Þ¼Òµå¸¦ ¿À¹ö¶óÀ̵å ÇÏÁö ¾Ê°í À̺¥Æ® Çڵ鷯¸¦ ÀÛ¼ºÇØ ÁÖ¸é µÈ´Ù. ±×¸®°í DataSource ÇÁ·ÎÆÛƼ¿Í ¿¬µ¿ÇÒ µ¥ÀÌÅͺ£À̽º Çʵ带 ÁöÁ¤Çϱâ À§ÇØ DataField ÇÁ·ÎÆÛƼ¸¦ »õ·Î Ãß°¡ÇØ ÁØ´Ù. ´ÙÀ½ µ¥ÀÌÅÍ ¼öÁ¤À» À§ÇÑ ÄÞÆ÷³ÍÆ®µéÀÌ ´ëºÎºÐ °¡Áö°í ÀÖ´Â ReadOnly ÇÁ·ÎÆÛƼ¸¦ FDataLinkÀÇ ReadOnly ÇÁ·ÎÆÛƼ¸¦ ÀÌ¿ëÇØ¼­ ±¸ÇöÇÑ´Ù. ReadOnly ÇÁ·ÎÆÛƼ´Â ÇØ´ç ÇʵåÀÇ °ªÀ» º¯°æÇÏÁö ¸øÇϵµ·Ï Çϴµ¥ »ç¿ëÇÑ´Ù. ±×·±µ¥ TdpbDBNumberEditÀÇ ºÎ¸ð Ŭ·¡½ºÀÎ TCustomEdit´Â ÀÌ¹Ì ReadOnly ÇÁ·ÎÆÛƼ¸¦ °¡Áö°í ÀÖ´Ù. ÀÌ ReadOnly ÇÁ·ÎÆÛƼ´Â ÄÞÆ÷³ÍÆ®°¡ °¡Áö°í ÀÖ´Â Text °ªÀ» »ç¿ëÀÚ°¡ º¯°æÇÏÁö ¸øÇϵµ·Ï Çϴµ¥ »ç¿ëÇÑ´Ù. µû¶ó¼­ µ¥ÀÌÅÍ ¸µÅ©ÀÇ ÇÊµå °ªÀ» ReadOnly·Î ¼³Á¤ÇÏ´Â °Í°ú ÄÞÆ÷³ÍÆ® ÀÚ½ÅÀÇ °ªÀ» ReadOnly·Î ÇÏ´Â °ÍÀ» µ¿±âÈ­ ÇØ¾ßÇÒ Çʿ䰡 ÀÖ´Ù. ±×·¡¼­ EditingChange À̺¥Æ® Çڵ鷯¿¡¼­ µ¥ÀÌÅÍ ¸µÅ©ÀÇ Editing ÇÁ·ÎÆÛƼ°¡ º¯°æµÉ ¶§ ¸¶´Ù ÄÞÆ÷³ÍÆ® ¿ø·¡ÀÇ ReadOnly ÇÁ·ÎÆÛƼµµ ¼³Á¤µÇµµ·Ï Çß´Ù.
DataChange À̺¥Æ® Çڵ鷯¿¡¼­´Â ÇöÀç ÇʵåÀÇ °ªÀ» ÄÞÆ÷³ÍÆ®ÀÇ Value ÇÁ·ÎÆÛƼ¿¡ ¹Ý¿µÇϴµ¥ FDataLinkÀÇ Field ÇÁ·ÎÆÛƼ°¡ ¾ÆÁ÷ ¼³Á¤µÇÁö ¾Ê¾Ò°í ¼³°è ¸ðµåÀÎ °æ¿ì¿¡´Â ÄÞÆ÷³ÍÆ®ÀÇ À̸§À» º¸¿© ÁÖµµ·Ï Çß´Ù.
´ÙÀ½¿¡ »ç¿ëÀÚ°¡ ÄÞÆ÷³ÍÆ®ÀÇ °ªÀ» º¯°æÇϱâ À§ÇØ Å°º¸µå¸¦ ´©¸¦ ¶§ ¸¶´Ù È£ÃâµÇ´Â KeyPress ¸Þ¼Òµå¿¡¼­ ÀÔ·ÂÇÑ Å°°¡ À¯È¿ÇÑ Å°ÀÎÁö Á¶»çÇϰí À¯È¿ÇÏÁö ¾ÊÀº ŰÀÎ °æ¿ì¿¡´Â ±× ۸¦ ¹«½ÃÇÏ°í °æ°íÀ½À» ³»µµ·Ï ¸¸µé¾ú´Ù. ±×¸®°í À¯È¿ÇÑ Å°°¡ ÀԷµǾúÀ» °æ¿ì¿¡´Â µ¥ÀÌÅÍ ¸µÅ©¸¦ ÆíÁý ¸ðµå·Î º¯°æÇØ ÁØ´Ù.
ÄÞÆ÷³ÍÆ®°¡ Űº¸µå ÀÔ·Â Æ÷Ä¿½º¸¦ ÀÒÀ» ¶§ ¹ß»ýÇÏ´Â CM_EXIT ¸Þ½ÃÁö Çڵ鷯¿¡¼­´Â º¯°æµÈ Value °ªÀ» µ¥ÀÌÅÍ ¸µÅ©ÀÇ ÇÊµå °ª¿¡ ÀúÀåÇÑ´Ù. ÀúÀå¿¡ ½ÇÆÐÇÒ °æ¿ì¿¡´Â ÀÒ¾ú´ø Æ÷Ä¿½º¸¦ ´Ù½Ã ã¾Æ ¿Í¼­ ÇÊµå °ªÀ» ´Ù½Ã ÀÔ·ÂÇÒ ¼ö ÀÖµµ·Ï ÇØ ÁØ´Ù.
¸¶Áö¸·À¸·Î ÄÞÆ÷³ÍÆ®ÀÇ Value °ªÀÌ º¯°æµÉ ¶§ ¸¶´Ù OnChange À̺¥Æ®¸¦ ¹ß»ý½Ã۱â À§Çؼ­ Change °¡»ó ¸Þ¼Òµå°¡ È£ÃâµÇ´Âµ¥ ÀÌ ¸Þ¼Òµå¸¦ ¿À¹ö¶óÀ̵åÇØ¼­ µ¥ÀÌÅÍ ¸µÅ©°¡ ´Ù¸¥ ·¹ÄÚµå·Î À̵¿ÇÒ ¶§ Value °ªÀ» ¾÷µ¥ÀÌÆ® ÇÒ ¼ö ÀÖµµ·Ï FDataLinkÀÇ Modified ÇÁ·ÎÆÛƼ¸¦ ¼³Á¤ÇØÁØ´Ù.

µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ® °³¹ßÀº ¾ð¶æ º¹ÀâÇØ º¸ÀÌÁö¸¸ µ¥ÀÌÅÍ ¸µÅ©¿Í ÄÞÆ÷³ÍÆ®°¡ ¿¬°áµÇ´Â °³³äÀ» Àß ÆÄ¾ÇÇØ¼­ µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ®ÀÇ µ¿ÀÛ ¿ø¸®°¡ Àͼ÷ÇØÁö¸é ¾Æ¸¶ º¹ÀâÇÏ´Ù ´À³¢±â º¸´Ù´Â Áö·çÇÑ ÀÛ¾÷À̶ó´Â °ÍÀ» ¾Ë°Ô µÉ °ÍÀÌ´Ù. µ¥ÀÌÅÍ ¿¬µ¿ ÄÞÆ÷³ÍÆ® °³¹ßÀÇ ÇÙ½ÉÀº µ¥ÀÌÅÍ ¸µÅ©¶ó´Â °ÍÀ» ¸í½ÉÇØ¾ß ÇÒ °ÍÀÌ´Ù.


ÀúÀ۱ǿ¡ ´ëÇÑ °øÁö
ÀÌ ¹®¼­¿¡ Æ÷ÇÔµÈ ¸ðµç ±Û°ú ¼Ò½º ÄÚµå´Â ÀÛÀÚÀÎ Àú ±è¼ºµ¿ÀÇ ÁöÀû Àç»êÀÌÁö¸¸ ¹«´ÜÀ¸·Î ¹èÆ÷Çϰųª Ã¥À̳ª °­ÀÇ ±³ÀçµîÀ» À§ÇÑ º¹Á¦ µî ÀúÀÛ±ÇÀ» ÀúÇØÇÏ´Â ÇàÀ§¸¦ Á¦¿ÜÇϰí´Â ÀÚÀ¯·Ó°Ô »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.
¶ÇÇÑ ÀÌ ÆäÀÌÁö¿¡ ´ëÇÑ ¸µÅ©´Â ÀÚÀ¯·Ó°Ô ÇÒ ¼ö ÀÖÀ¸³ª Àü¹®À» ÀüÁ¦ÇÏ´Â ÀÏÀº Çã¿ëÇÏÁö ¾Ê½À´Ï´Ù.