C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[69] [강좌] VirtualTreeView #6 : inline 에디터
볼레롱 [bolero] 22891 읽음    2005-06-24 11:36
edit1.jpg 54.8KB 실행 캡쳐 화면입니다.
edit3.jpg 63.8KB 실행 캡쳐 화면입니다.
edit2.jpg 50.3KB 실행 캡쳐 화면입니다.
phonebook2.zip 27.4KB 소스및 실행파일
안녕하세요.

VirtualTreeView는  소스가 델파이로 되어 있으면,
델파이나 BCB에서 사용가능한 형태의 콤포넌트로 제공되고 있습니다.

소스가 델파이다 보니  BCB에서 사용할때는  정보가 좀 부족한 면이 있습니다.

그래서 이 강좌를 시작한 이유기도 하구요 ^^


저도 처음 이 콤포넌트의 막강한 기능을 접하고는  감동이었지요.
그런데,  inline 에디터의 예제가 델파이로 되어 있어서  구현하려니 참 나감하더군요ㅡ.ㅡ

그러던중. VirtualTreeView 홈페이지 ( http://www.soft-gems.net/ ) 에 갔더니

BCB로 만들어진 inline 에이터 예제와 소스 샘플이 있더군요.

http://www.soft-gems.net/VirtualTreeview/
이 위치의
" IVTEditLink demo for BCB 5 "
이 예제를 받아 보시면 됩니다.

그런데, 이 예제를 받아 보면  실행은 되는데,  제대로 다 만들어 놓은 것은 아니더군요.
버그도 좀 있구요.

아무튼 이것을 바탕으로  수정및 업데이트 된  inline 에디터에 대해서 다루어 보겠습니다.


1.  inline 에디터 유닛

EditorUnit.cpp 와  EditorUnit.h 란  인라인 에디터 소스는  위에서 설명한  소스를 가져다가 제가 업데이트한 것입니다.
업데이트의 주 내용은 
   
    * 범용적으로 사용가능하도록 소스의 의존성 제거
    * 다수의 버그 수정

등 입니다.

이 소스도 최종본이라고 하기는 뭐하구요.  각 필요에 따라서 수정을 더 해 나아갸 합니다.
저도 제 필요에 따라서 조금씩 업데이트 하기 때문에,  아지 모든 기능이 동작하는 것은 아닙니다 ^^

EditorUnit 의 소스는 첨부파일을 보시구요.

EditorUnit.h  파일에 보시면,


typedef enum {
   ptNone,
   ptEdit,
   ptCombo,
//   ptNumber,
   ptDate
} TPropertyTyp;


typedef struct {
   TPropertyTyp    PropertyTyp;         // editory type
   WideString      Value;               // data value
   bool            Changed;             // 변경 여부
} TPropertyData, *lpPropertyData;


이런 형 정의가 있는데요.

TPropertyTyp  은  inline 에디터에서 사용할  에디팅 형식 입니다.
  
   ptNone     --> 에이터를 사용하지 않음.
   ptEdit        --> TEdit 형태의 에디터를 제공.
   ptCombo  --> 콤포박스 형태의 에디터 제공
   ptDate      --> 날짜 선택 (TDateTimePicker) 에디터 제공


TPropertyData 은    VTV에서 한 셀(Cell) 에 해당하는 데이타의 형입니다.
      Node 나 Row 의 데이타가 아닙니다.  주의 하세요.



이 정도만 아시고,

EditorUnit.cpp 와  EditorUnit.h  를  inline 에디터를 사용할 프로젝트에 추가 하시면 됩니다.


2.  데이타 구조 선언

이번 예제는  3번째 강좌에서 보여 드렸던 phonebook  예제에서   생일 컬럼을 하나더 추가한 형태로 만들어 보겠습니다.

       이름, 전화번호, 성별,  생일

을 가지고 있는 것으로 만들어 보겠습니다.


#include "EditorUnit.h"

데이타 구조를 선언하시 곳에  위와 같이 include를 추가해 주시구요.

typedef struct tagPhonebook {
    TPropertyData Colunms[4];   // 0 - 이름, 1 - 전화번호, 2- 성별 , 3 - 생일
} structPhonebook;

데이타 선언은 위와 같이 합니다.   Column이  4개 라서  4개짜리 배열로 만들었습니다.


3.  VTV 의 기본 Events 구현

기본 Events는 이전에도 계속 말씀 드렸지만,

    OnGetNodeDataSize
    OnGetText

이구요. 

이미지를 출력할 것이라면

    OnGetImageIndex

까지 구현해 주시면 됩니다.  이번예제는  이미지는 없습니다 ^^

void __fastcall TForm1::VirtualStringTree1GetNodeDataSize(
      TBaseVirtualTree *Sender, int &NodeDataSize)
{
    NodeDataSize = sizeof(structPhonebook);
}

OnGetNodeDataSize 는  변경되는 것이 없지요


void __fastcall TForm1::VirtualStringTree1GetText(TBaseVirtualTree *Sender,
      PVirtualNode Node, TColumnIndex Column, TVSTTextType TextType,
      WideString &CellText)
{
    if (!Node)
        return;

    structPhonebook *pPhonebook = (structPhonebook *)Sender->GetNodeData(Node);

    CellText = pPhonebook->Colunms[Column].Value;
}

OnGetText는  배열을 사용하면서  소스가 더 간단해 졌습니다^^



4. VTV의 속성 변경

VTV가  처음  폼에 올려 놓으면  Column 0 만을 선택할 수 있습니다.
그러므로,  Column 0을 제외한 다른 Column을 편집하기 위해서는  선택 모드를 변경해 주어야 합니다.

TreeOptions -> SelectionOptions -> toExtendedFocus  : true

이 값을  true로 해 주어야 각 컬럼별로 선택할 수가 있습니다.


5.  inline 에디터 관련  Events  구현

inline 에디터를 구현하기 위해서는  최소  2개의 Event를 구현해 주서야 하는데요.

    OnCreateEditor    :  각 셀에서  에디팅이 시작할 때 에디터를 생성해주는  시간을 제공합니다.
    OnEditing            :   각 셀의 에디팅을  허용할 것인지 말것인지 결정합니다.



OnCreateEditor 이벤트를 구현할때,   에디터의 형식이  ptCombo 일때와 아닐경우가 다른데요.

ptCombo는  콤보박스 형태의 에디팅이 되기 때문에,   콤보박스에 보여질 데이타를 전달해 주어야 합니다.

그래서,

    __fastcall TPropertyEditLink(TVirtualStringTree* Tree, TVirtualNode* Node, int Column, TPropertyData* Data, TStringList *combolist);

생성자를 위의 것으로 사용하고,   콤보박스에 보여질 항목을 TStringList로 만들어서 전달해 주어야 합니다.

그외의 경우는  아래의 생성자를 이용하면 됩니다.

__fastcall TPropertyEditLink(TVirtualStringTree* Tree, TVirtualNode* Node, int Column, TPropertyData* Data);



아래에  OnCreateEditor 이벤트를 구현한 예제가 있는데요.
Column 2 에서만   ptCombo로 생성한 예제 입니다.


void __fastcall TForm1::VirtualStringTree1CreateEditor(
      TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column,
      IVTEditLink *EditLink)
{
    if (!Node) return;

    TPropertyEditLink* PropertyLink;
    structPhonebook *pPhonebook = (structPhonebook *)Sender->GetNodeData(Node);

    if (pPhonebook)
    {
        if (Column == 2)
        {  // ComboBox 형태의 편집을 지원할 경우

            TStringList* MyList = new TStringList();
            try
            {
              MyList->Add("남자");
              MyList->Add("여자");

              PropertyLink = new TPropertyEditLink((TVirtualStringTree*)Sender, Node, Column, &(pPhonebook->Colunms[Column]), MyList);
            }
            __finally
            {
              delete MyList;

            }

        }
        else // ComboBox 형태가 아닐경우
            PropertyLink = new TPropertyEditLink((TVirtualStringTree*)Sender, Node, Column, &(pPhonebook->Colunms[Column]));
           
        PropertyLink->QueryInterface(__uuidof(IVTEditLink), (void**)EditLink);
    }
}

OnCreateEditor 이벤트를 구현해 줍니다.

이 이벤트에 들어 오면,    노드의 데이타를 가져와서
각 컬럼에 해당하는 값 (pPhonebook->Colunms[Column])으로  

TPropertyEditLink  클래스를 생성해 주구요.  (이 클래스가 EditorUnit.cpp 에 있는 것입니다)

PropertyLink->QueryInterface(__uuidof(IVTEditLink), (void**)EditLink);

를 이용해서,   EditLink  파라미터를  채워주면 됩니다.




void __fastcall TForm1::VirtualStringTree1Editing(TBaseVirtualTree *Sender,
      PVirtualNode Node, TColumnIndex Column, bool &Allowed)
{
    Allowed = false;
    if (!Node) return;                                                //  only for safety the program !
    structPhonebook * pPhonebook = (structPhonebook *)Sender->GetNodeData(Node);
    if (pPhonebook)
        Allowed = (pPhonebook->Colunms[Column].PropertyTyp != ptNone);
}

OnEditing 이벤트에서   에이터를 허용할 셀을  알려 주는데요.

pPhonebook->Colunms[Column].PropertyTyp 이  ptNone 가 아닌 경우만 

Allowed 를  true로  넣어 주는 것입니다.



자 이제  모든 필요 이벤트는 다 만들었구요.


7.  데이타 넣기

데이타를 넣는 버튼을 하나 만들어서 

그 버튼이 눌렸을때,  데이타를 넣어 주면 됩니다.


void __fastcall TForm1::Button1Click(TObject *Sender)
{
    PVirtualNode Node;
    structPhonebook *pPhonebook;

    Node = VirtualStringTree1->AddChild(NULL);
    if (Node)
    {
        pPhonebook = (structPhonebook *)VirtualStringTree1->GetNodeData(Node);
        pPhonebook->Colunms[0].Value = "볼레롱";
        pPhonebook->Colunms[0].PropertyTyp = ptEdit;
        pPhonebook->Colunms[0].Changed = false;

        pPhonebook->Colunms[1].Value = "02-1234-5678";
        pPhonebook->Colunms[1].PropertyTyp = ptEdit;
        pPhonebook->Colunms[1].Changed = false;

        pPhonebook->Colunms[2].Value = "남자";
        pPhonebook->Colunms[2].PropertyTyp = ptCombo;
        pPhonebook->Colunms[2].Changed = false;

        pPhonebook->Colunms[3].Value = "1970-3-2";
        pPhonebook->Colunms[3].PropertyTyp = ptDate;
        pPhonebook->Colunms[3].Changed = false;
    }
}

위 예에서 보시면,   Columns 0 ~ 2 까지는 ptEdit 란 형태로 넣었구요.
Column 3 만  ptDate를 넣었습니다.


실행해 보신 후에  각 셀은 편집은    F2를 누르시거나  마우스로 클릭하고 잠시 기다리면   편집모드로 들어 갑니다.

실행해서 편집해 보세요.


오늘 여기까지 합니다 ^^

아무쪼록  이글이 도움이 되길 바랍니다.
남병철.레조 [lezo]   2006-10-13 20:41 X
많은 도움이 되었습니다. ^^
히이로유이 [hiiroyui]   2010-10-05 15:09 X
편집 하실때 그냥 마우스 클릭이 아니라 그 셀이 선택 되어 있을때 클릭 해야 되네요.
그리고 ptDate의 날짜 구분자가 윈도우에서 /로 되어 있는지 아니면 - 로 되어 있는지 확인 해서 하시길 바랍니다.
왜 달력이 않나오지 한참 고민 하다 보니 결국 구분자 때문이였네요.

+ -

관련 글 리스트
69 [강좌] VirtualTreeView #6 : inline 에디터 볼레롱 22891 2005/06/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.