Delphi – 간단한 주소록 제작

이번에는 간단한 주소록 관리 프로그램을 만들어 보도록 하겠습니다. 너무 간단하여 실제 활용은 어렵지만 이것을 바탕으로 더 나은 주소록 관리 프로그램을 제작해 보시기 바랍니다. DBMS는 SQL Server를 사용하고 델파이 7 기준으로 작업하도록 하겠습니다.

먼저 입력된 자료를 저장할 데이터베이스를 지정하고 테이블을 생성하도록 하겠습니다. 엔터프라이즈 매니저를 이용하여 작업을 할 텐데 SQL Server 자체의 설명은 생략하도록 하겠습니다. 다른 서적을 참고 하셔서 공부하시기 바랍니다. 단순히 하나의 테이블만 생성하므로 긴 설명은 필요가 없을 듯 합니다.

먼저 엔터프라이즈 매니저를 실행하시고 테이블을 생성할 데이터베이스를 선택합니다. 예제에서는 home이라는 데이터베이스를 선택하였습니다. 마우스 오른쪽 버튼을 클릭하여 새 테이블을 선택하시고 그림과 같이 테이블을 생성합니다. 주소록 관리 프로그램이라고 하면 많은 정보 항목이 있겠지만 간단한 예제이므로 몇가지 항목의 필드만 생성하였습니다.

테이블 생성

테이블 생성

테이블 필드 설정

테이블 필드 설정

테이블의 이름은 address_book으로 하도록 하겠습니다.

이제 델파이를 실행시키고 New > Application을 선택합니다.

새 프로젝트

새 프로젝트

그러면 새로운 폼이 나타나게 되는데 Object Inspector에서 폼의 Caption과 Name을 변경합니다. 주어진 이름 그대로 써도 상관을 없지만 정해진 규칙을 바탕으로 일관성 있게 변경해 주면 추후 유지 보수시에 많은 도움이 됩니다.

이 예제에서는 DB연결을 위하여 ADO 컴포넌트를 사용할 것입니다. DB와 연결방법은 여러가지가 있지만 각각의 방법이 일장일단이 있어서 어떤 것이 가장 좋다고 말하기는 어렵습니다. 다만 ADO를 이용한 것이 Visual Basic이나 Active Server Page로 프로그래밍 해 보신분들에게 익숙할 것 같아 선택하게 되었습니다.

예전에는 BDE를 통하여 연결을 하였는데 성능은 좋았지만 부가적으로 따라다녀야 하는 파일이 너무 많아 배보다 배꼽이 더 커지는 모순이 발생하였습니다. 프로그램을 간단한 설치로 올바르게 동작하도록 만들 수 없을까 고민하게되었습니다. 그러는 중에 ADO를 이용하여 간단한 프로그램을 만들게 되었고 그 결과 별다른 설정과 추가적인 파일의 설치없이 MDAC의 버전만 최신버전으로 맞추어 주면 잘 동작하는 것을 알 수 있었습니다. 물론 ADO를 이용한 방법말고도 다른 좋은 방법은 얼마든지 있을 것입니다. 다만 제가 보여드리는 것이 아주 작은 일부라는 것 입니다.

Form에 ADO Palette에 있는 ADOConnection 컴포넌트를 추가 합니다. 기본으로 정해져 있는 이름을 알맞게 바꾸시고 LoginPrompt 프로퍼티를 False로 선택합니다. ture이면 DB에 접속될 때 마다 아이디와 비밀번호를 묻는 대화상자가 나타납니다. 그 다음으로 ConnectionString을 지정하기 위하여 Object Inspector에서 항목을 클릭하면 오른쪽에 … 버튼을 클릭합니다.

ADO Palette

ADO Palette

Connection String 설정

Connection String 설정

… 버튼을 클릭하면 다음과 같은 대화상자가 나타나게 됩니다.

Connection String 대화상자

Connection String 대화상자

Build 버튼을 클릭하면 다음과 같은 대화상자가 나타납니다. 예제에서는 SQL Server를 이용하고 있으므로 Microsoft OLE DB Provider for SQL Server를 선택합니다. 그리고 다음 버튼을 클릭합니다.

데이터 연결 속성

데이터 연결 속성

다음 화면에서 서버를 선택하고 로그인 정보를 입력한 후 데이터베이스를 선택합니다. 올바른 정보를 입력하였다면 SQL Server에 등록된 데이터베이스 정보가 나타나게 됩니다.

데이터 연결 속성

데이터 연결 속성

예제에서는 사용자 이름이 sa로 되어 있는데 실제 프로젝트에서는 전체 관리자인 sa를 사용하시면 안됩니다. 프로젝트 단위별로 별도의 계정을 생성하여 각 데이터베이스 별로 영향이 없도록 관리하셔야 합니다. 올바른 정보를 입력하셨다면 연결 테스트가 별다른 문제 없이 진행됩니다. 연결 테스트 버튼을 눌러 다시한번 확인 합니다. 연결테스트가 정상적으로 되면 확인버튼을 클릭합니다. 설정을 마치면 다음과 같이 데이터베이스 접속에 필요한 ConnectionString이 생성되게 됩니다. OK 버튼을 클릭하여 설정을 마무리 합니다. Object Inspector의 ConnectionString Property에 방금 생성되어진 정보가 입력되어 있음을 알 수 있습니다.

생성된 Connection String

생성된 Connection String

메인폼에 다음과 같이 각 항목을 보기 좋게 배열합니다. 크기 조절이 하지 않을 것 같아 BorderStyle Property는 bsDialog로 지정하였습니다. 같은 종류의 컨트롤을 계속 추가 하려면 Palette의 항목을 Shift 키를 누른채로 클릭하면 파란 테두리가 표시되는데 폼에 마우스 클릭만으로 추가할 수 있습니다. 다 추가 하였으면 화살표 모양을 클릭하면 됩니다. 그리고 폼의 폰트를 미리 변경해 놓으면 그 후에 추가되는 컨트롤들은 폼의 설정을 따르게 되어 있습니다. 처음에 지정을 해 놓으면 컨트롤마다 따로따로 설정해야 하는 불편함을 없앨 수 있습니다.

예전에는 기능에만 충실하면 그만이었는데 요즈음은 같은 기능을 하는 프로그램이라 하더라도 보기에 더 좋은 것이 상품가치가 높습니다. 예제라서 겉모습에 신경을 쓰지는 않았지만 본격적인 프로그램을 제작하실 때에는 반드시 고려해야 할 사항입니다.

Form Design

Form Design

ADO Palette에서 ADOQuery 컴포넌트를 추가 하고 SQL Property의 … 버튼을 클릭하여 SQL문을 편집합니다. 아래의 내용과 같이 입력합니다.

SQL 편집

SQL 편집

메인폼의 OnShow 이벤트에 다음과 같이 입력합니다.

try
//DB접속
DBConn.Open;
//StringGrid 헤더 정의
HeaderSetting();
//등록자료 가져오기
LoadList()
except
MessageDlg(‘DB서버에 접속할 수 없습니다.’, mtError, [mbOK], 0);
Application.Terminate;
end;

 

try .. except 구문을 이용하여 DBMS에 접속이 불가능 한 경우에도 오류메시지를 출력해 줄 수 있도록 합니다. DB에 접속하고 StringGrid의 헤더를 정의하여 주고 마지막으로 등록되어 있는 자료를 가지고 와서 StringGrid에 채워줍니다.

HeaderSetting 프로시저의 내용은 다음과 같습니다.

procedure TfrmMain.HeaderSetting();
begin
sgdList.ColCount := 7;
sgdList.Cells[1,0] := ‘일련번호’;
sgdList.Cells[2,0] := ‘이름’;
sgdList.Cells[3,0] := ‘휴대전화’;
sgdList.Cells[4,0] := ‘전화’;
sgdList.Cells[5,0] := ‘우편번호’;
sgdList.Cells[6,0] := ‘주소’;
end;

 

StringGrid에 사용할 컬럼의 개수를 지정하고 각 헤더에 들어갈 제목을 셀에 대입하여 헤더를 초기화 합니다.

실제로 자료를 읽어와 StringGrid에 채우는 LoadList 프로시저의 내용은 다음과 같습니다.

procedure TfrmMain.LoadList();
var
i : Integer;
record_count : Integer;
sequence, name, cellular_phone, telephone, zipcode, address : String;
begin
qry1.Open;    record_count := qry1.RecordCount;if record_count = 0 then
sgdList.RowCount := 2
else
sgdList.RowCount := record_count + 1;for i := 0 to record_count – 1 do
begin
sequence := qry1.FieldByName(‘sequence’).AsString;
name := qry1.FieldByName(‘name’).AsString;
cellular_phone := qry1.FieldByName(‘cellular_phone’).AsString;
telephone := qry1.FieldByName(‘telephone’).AsString;
zipcode := qry1.FieldByName(‘zipcode’).AsString;
address := qry1.FieldByName(‘address’).AsString;sgdList.Cells[1, i + 1] := sequence;
sgdList.Cells[2, i + 1] := name;
sgdList.Cells[3, i + 1] := cellular_phone;
sgdList.Cells[4, i + 1] := telephone;
sgdList.Cells[5, i + 1] := zipcode;
sgdList.Cells[6, i + 1] := address;

//처음자료인 경우 Edit컨트롤에 자료채움
if i = 0 then
begin
txtSequence.Text := sequence;
txtName.Text := name;
txtCellular_phone.Text := cellular_phone;
txtTelephone.Text := telephone;
txtZipcode.Text := zipcode;
txtAddress.Text := address;
end;

qry1.Next;
end;

qry1.Close;

//각 텍스트 필드 비활성화
DisabledTextField();

current_mode := ‘LIST’;

EnabledButtons(current_mode);

sgdList.Row := 1;

end;

 

미리 지정된 SQL문으로 address_book 테이블의 모든 자료를 가져와 처음자료부터 마지막 자료까지 반복하면서 StringGrid의 Cell에 채워넣는 코드 입니다. 자료를 읽어오고 나서는 항상 첫번째 행이 선택되도록 하였습니다. 그래서 처음 자료이면 Edit 컨트롤에 각 자료를 채워 넣도록 하였습니다. 마지막 부분에 sgdList.Row := 1; 이 부분이 가장 처음 행을 선택하도록 하는 코드입니다.

DisabledTextField();EnabledButtons(current_mode); 프로시저는 현재의 모드에 따라서 Edit컨트롤과 Button 컨트롤을 활성화/비활성화 하는 기능을 합니다. 가급적 반복적으로 사용될 수 있는 부분은 프로시저로 분리해 놓는 것이 추후에 수정할 때 유리합니다.

이제 각 버튼에 작동 이벤트에 적절한 코드를 넣으면 됩니다.

먼저 입력 버튼 클릭 이벤트 코드를 입력합니다.

procedure TfrmMain.btnInsertClick(Sender: TObject);
begin
//현재 모드 셋팅
current_mode := ‘INSERT’;    //버튼 비 활성화
DisabledButtons(current_mode);EnabledTextField();//Edit control 초기화
txtName.Text := ”;
txtCellular_phone.Text := ”;
txtTelephone.Text := ”;
txtZipcode.Text := ”;
txtAddress.Text := ”;txtName.SetFocus;
end;

 

각 Edit 컨트롤의 내용을 지우고 이름 입력 Edit컨트롤에 포커스를 줍니다. 입력, 수정 버튼을 클릭하는 경우에는 DB에 저장이 되거나 수정이 되는 것이 아니고 확인 버튼을 클릭하였을 때 현재 입력된 내용을 바탕으로 하여 실제 입력과 수정 작업이 이루어 지게 됩니다.

폼에 ADO Palette에 있는 ADOCommand 컴포넌트를 추가합니다. 이름을 cmd1으로 바꿉니다.

ADO Command

ADO Command

확인 버튼 이벤트의 내용을 보도록 하겠습니다.

procedure TfrmMain.btnOKClick(Sender: TObject);
var
tempSQL : string;
begin
if current_mode = ‘INSERT’ then //입력모드
begin        tempSQL := ‘insert into address_book (name, cellular_phone, telephone, zipcode, address, reg_datetime) values (‘;
tempSQL := tempSQL + ”” + txtName.Text + ”’,’;
tempSQL := tempSQL + ”” + txtCellular_phone.Text + ”’,’;
tempSQL := tempSQL + ”” + txtTelephone.Text + ”’,’;
tempSQL := tempSQL + ”” + txtZipcode.Text + ”’,’;
tempSQL := tempSQL + ”” + txtAddress.Text + ”’,’;
tempSQL := tempSQL + ‘getdate())’;cmd1.Connection := DBConn;cmd1.CommandType := cmdText;

cmd1.CommandText := tempSQL;

cmd1.Execute;

LoadList();
end
else if current_mode = ‘EDIT’ then //수정모드
begin
tempSQL := ‘update address_book set’;
tempSQL := tempSQL + ‘ name = ”’ + txtName.Text + ”’,’;
tempSQL := tempSQL + ‘ cellular_phone = ”’ + txtCellular_phone.Text + ”’,’;
tempSQL := tempSQL + ‘ telephone = ”’ + txtTelephone.Text + ”’,’;
tempSQL := tempSQL + ‘ zipcode = ”’ + txtZipcode.Text + ”’,’;
tempSQL := tempSQL + ‘ address = ”’ + txtAddress.Text + ””;
tempSQL := tempSQL + ‘ where sequence = ‘ + txtSequence.Text;

cmd1.Connection := DBConn;

cmd1.CommandType := cmdText;

cmd1.CommandText := tempSQL;

cmd1.Execute;

LoadList();
end;

end;

 

확인 버튼 클릭 이벤트에는 현재의 모드에 따라서 Edit컨트롤에 입력된 내용을 기반으로 DB에 실제로 Insert나 Update 작업을 행하는 코드를 위의 내용과 같이 입력합니다.

삭제 버튼 이벤트에 추가된 코드는 다음과 같습니다. 자료 삭제시에는 사용자가 실수로 버튼을 누른 것인 수도 있으므로 반드시 확인 과정을 한번 거쳐야 합니다. 예제에서는 무조건 삭제가 되도록 하였는데 한번 확인을 하여 삭제가 맞다고 한 경우에만 삭제가 되도록 수정해 보시기 바랍니다.

procedure TfrmMain.btnDeleteClick(Sender: TObject);
var
tempSQL : string;
begin
tempSQL := ‘delete from address_book’;
tempSQL := tempSQL + ‘ where sequence = ‘ + txtSequence.Text;    cmd1.Connection := DBConn;cmd1.CommandType := cmdText;cmd1.CommandText := tempSQL;

cmd1.Execute;

LoadList();

end;

 

폼에 txtSequence라는 숨겨진 Edit컨트롤을 추가하고 여기에 자료의 키가 되는 값을 넣어놓고 수정이나 삭제할 때 사용합니다. StringGrid상의 자료를 클릭했을 때 각 Edit컨트롤의 값이 변하게 되는데 이때에 키가되는 값도 대입하여 수정이나 삭제시의 조건값으로 사용하게 됩니다.

StringGrid에 사용자가 클릭을 했을 때 발생되는 이벤트의 코드를 살펴보도록 하겠습니다. 셀이 선택되었을 때 발생되는 이벤트를 사용하였습니다. OnSelectCell이라는 이벤트인데 선택한 행과 열의 위치를 알 수 있어서 Edit컨트롤에 값을 바꾸어 줄 때 편리합니다. 이 예제에서는 Edit컨트롤에 입력되는 자료가 StringGrid 컬럼에 모두 표시가 되어 있어 각 Cell의 값을 읽어와 대입하였습니다. 그렇지 않은 경우에는 키값을 기준으로 값을 DB에서 가져와 Edit컨트롤에 채워주면 됩니다.

procedure TfrmMain.sgdListSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
begin
txtSequence.Text := sgdList.Cells[1, ARow];
txtName.Text := sgdList.Cells[2, ARow];
txtCellular_phone.Text := sgdList.Cells[3, ARow];
txtTelephone.Text := sgdList.Cells[4, ARow];
txtZipcode.Text := sgdList.Cells[5, ARow];
txtAddress.Text := sgdList.Cells[6, ARow];
end;

 

StringGrid에서 선택된 열의 각 항목의 값을 Edit컨트롤에 대입한 것을 보실 수 있습니다.

이제까지 간략하게 SQL Server와 ADO를 이용한 간단한 주소록 관리프로그램을 예제로 만들어 보았습니다. 부족한 기능도 많고 세련되지 못한 코드로 작성이 되어 있습니다. 제가 제시하여 드린 방법이 최선의 방법은 아닙니다. 분명히 여러분께서 더 나은 방법으로 개선을 하실 수 있으리라 생각합니다.

예제의 개선사항 몇가지를 알려드리겠습니다.

1. 입력, 수정 버튼을 눌렀을 때 취소할 수 있는 방법이 없다.
2. 자료 삭제시 묻지 않고 바로 삭제한다.
3. 입력, 수정, 삭제시에 자료를 반복적으로 읽어 출력하는 문제.

이 세가지 외에도 개선할 사항이 정말 많습니다. 하나하나 기능을 추가 하시다 보면 쓸만한 주소록 관리 프로그램이 되리라 생각합니다.

프로그램을 작성하다 보면 수많은 Property와 Method가 나오는데 잘 모르는 내용이 나오면 도움말을 적극적으로 찾아보시기 바랍니다. 그것만 잘 참조하셔도 그리 어렵지 않게 여러가지 Property와 Method의 기능을 아실 수 있습니다.

저도 아직 그렇지만 많은 분들이 프로그램을 제작하다 보면 머리에 떠오르는 생각만으로 컴퓨터 앞에 앉아 코딩을 하는 버릇이 있습니다. 프로그램이 예제의 수준이거나 어떤 기능을 잠시 테스트 해볼 때는 상관이 없지만 규모가 조금이라도 커지고 여러가지 기능이 추가되면 코딩만으로는 감당할 수 없는 상황이 되고 급기야 처음부터 틀을 다시 잡고 만드는 경우가 생깁니다. 처음에 빨리 코딩하는 것이 중요한 것이 아니라 조금이라도 많이 생각을 하고 여러가지 수정사항이나 기능 추가를 손쉽게 할 수 있는 구조를 갖추어야 합니다.

마지막으로 이런 강좌를 했으면 좋겠다고 생각하시는 분을 코멘트를 달아주시기 바랍니다. 잘 모르는 부분이면 저도 공부해 가면서 올려보도록 노력하겠습니다.

다운로드 : 소스파일

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Time limit is exhausted. Please reload the CAPTCHA.