카테고리 보관물: Delphi

Delphi – 숫자야구 게임

이번에는 간단한 숫자야구를 제작해 보도록 하겠습니다.

숫자야구는 학창 시절에 친구들과 해보신 기억이 있으실 겁니다. 규칙은 간단한데 두 사람이 서로 세자리 수를 중복 없이 정하고 번갈아가며 세자리 숫자를 제시하면 상대방이 자신이 정한 숫자를 보고 Strike와 Ball을 판정해 줍니다. 숫자가 있는 경우에만 Strike와 Ball이 되고 아예 없으면 Out이 됩니다.

숫자가 있으면서 위치가 같으면 Strike, 위치가 같지 않으면 Ball 입니다. 예를 들어 보도록 하겠습니다.

A와 B가 게임을 한다고 가정하고 A는 587을 정했고 B는 698을 정했습니다. 먼저 A가 B에게 123을 제시합니다. B는 자신이 정한 숫자에 123이 들어있지 않으므로 Out이라고 알려줍니다. 이어 B는 A에게 968을 제시합니다. A는 자신의 숫자에 8이 들어 있고 위치한 곳이 세 번째 이므로 1Ball 이라고 알려줍니다. 이런 방법으로 번갈아서 숫자를 주고받으면서 예측을 하여 먼저 맞힌 사람이 승리하는 게임입니다.

이 강좌에서는 컴퓨터가 생성한 임의의 세자리 숫자를 알아맞히는 프로그램을 제작해 보도록 하겠습니다.

새 프로젝트를 시작하고 다음과 같이 폼을 디자인 합니다.

Form Design

Form Design

다음의 표를 참고하여 각 컴포넌트의 속성을 적당하게 변경하고 이름을 구분이 가능하도록 지정합니다.

컴포넌트 속성 설명
Button
 Name  : btn1
 Caption  : 1
 숫자1 버튼
Button
 Name  : btn2
 Caption  : 2
 숫자2 버튼
Button
 Name  : btn3
 Caption  : 3
 숫자3 버튼
Button
 Name  : btn4
 Caption  : 4
 숫자4 버튼
Button
 Name  : btn5
 Caption  : 5
 숫자5 버튼
Button
 Name  : btn6
 Caption  : 6
 숫자6 버튼
Button
 Name  : btn7
 Caption  : 7
 숫자7 버튼
Button
 Name  : btn8
 Caption  : 8
 숫자8 버튼
Button
 Name  : btn9
 Caption  : 9
 숫자9 버튼
Button
 Name  : btnOK
 Caption  : 확인
 확인 버튼
Button
 Name  : btnNew
 Caption  : 새게임
 새게임 버튼
Button
 Name  : btnBackSpace
 Caption  : BS
 BS 버튼
Button
 Name  : btnClear
 Caption  : C
 Clear 버튼
Label
 Name  : lblCount
 Caption  : 시도횟수
 제목 라벨
Edit
 Name  : txtNumber
 Text  :
 Readonly  : True
 숫자입력표시 Edit
Edit
 Name  : txtValue
 Text  :
 Visible  : False
 컴퓨터 생성 숫자 저장 Edit
ListBox
 Name  : lsbResult
 숫자 유추 결과 출력

메인폼의 OnActivate 이벤트에 중복이 되지 않은 세자리 숫자를 생성하도록 합니다. 생성한 숫자를 Visible 속성을 False로 설정한 Edit 컴포넌트(txtValue)의 Text 속성에 저장합니다.

procedure TfrmMain.FormActivate(Sender: TObject);
var
tempLoop : Integer;
createdNumber : Array[1..3] of Integer;
begin

txtNumber.Text := ”;
intTryCount := 0;

Randomize;

//세개의 중복되지 않은 숫자를 만들어 숨겨진 TEdit 컴포넌트에 저장
for tempLoop := 1 to 3 do
begin

//루프의 처음이면 바로 숫자 생성
if tempLoop = 1 then
begin
createdNumber[tempLoop] := RandomRange(1,9);
end
//두번째인경우 첫번째 숫자와 같지 않도록 생성된 숫자와 비교하여
//배열에 저장
else if tempLoop = 2 then
begin
createdNumber[tempLoop] := RandomRange(1,9);

while createdNumber[1] = createdNumber[2] do
begin
createdNumber[tempLoop] := RandomRange(1,9);
end

end
//세번째인경우 첫번째, 두번째 숫자와 같지 않도록 생성된 숫자와 비교하여
//배열에 저장
else if tempLoop = 3 then
begin

createdNumber[tempLoop] := RandomRange(1,9);

while (createdNumber[1] = createdNumber[3]) or (createdNumber[2] = createdNumber[3]) do
begin
createdNumber[tempLoop] := RandomRange(1,9);
end

end;

//숨겨진 TEdit 필드에 저장
txtValue.Text := IntToStr(createdNumber[1]) + IntToStr(createdNumber[2]) + IntToStr(createdNumber[3]);
end;

intFirstNumber := StrToInt(Copy(txtValue.Text, 1, 1));
intSecondNumber := StrToInt(Copy(txtValue.Text, 2, 1));
intThirdNumber := StrToInt(Copy(txtValue.Text, 3, 1));

for tempLoop := 1 to 9 do
ChangeButtonStatus(tempLoop, True);

btnOK.Enabled := True;
btnBackSpace.Enabled := True;
btnClear.Enabled := True;
lsbResult.Items.Clear;
end;

 

루프의 처음이면 일단 숫자를 하나 생성하고 배열변수에 저장합니다. 그 다음으로 첫번째 숫자와 같지 않을 때까지 생성하여 배열변수에 저장합니다. 세번째 숫자도 이전과 같은 방법으로 중복되지 않도록 생성합니다. 그리고 나서 각 숫자를 intFirstNumber, intSecondNumber, intThirdNumber에 대입합니다.

그리고 모든 숫자버튼과 결과출력을 초기화 합니다.

맞추려는 숫자가 생성되었으니 사용자로 부터 입력을 받아 그 결과를 ListBox에 출력하면 됩니다.

procedure TfrmMain.btnOKClick(Sender: TObject);
var
intUserFirstNumber, intUserSecondNumber, intUserThirdNumber : Integer;
intStrikeCount, intBallCount : Integer;
intLoop : Integer;
begin

if Length(txtNumber.Text) = 3 then
begin

intStrikeCount := 0;
intBallCount := 0;

if txtNumber.Text = txtValue.Text then //숫자를 맞춘경우
begin
Inc(intTryCount);

lsbResult.Items.Insert(0, IntToStr(intTryCount) + ‘ : ‘ + txtNumber.Text + ‘ Correct.’);
btnOK.Enabled := False;
btnBackSpace.Enabled := False;
btnClear.Enabled := False;
end
else
begin
intUserFirstNumber := StrToInt(Copy(txtNumber.Text, 1, 1));
intUserSecondNumber := StrToInt(Copy(txtNumber.Text, 2, 1));
intUserThirdNumber := StrToInt(Copy(txtNumber.Text, 3, 1));

//첫번째 숫자
if (intUserFirstNumber = intFirstNumber) then
Inc(intStrikeCount)
else
begin
if (intUserFirstNumber = intSecondNumber) then Inc(intBallCount);
if (intUserFirstNumber = intThirdNumber) then Inc(intBallCount);
end;

//두번째 숫자
if (intUserSecondNumber = intSecondNumber) then
Inc(intStrikeCount)
else
begin
if (intUserSecondNumber = intFirstNumber) then Inc(intBallCount);
if (intUserSecondNumber = intThirdNumber) then Inc(intBallCount);
end;

//세번째 숫자
if (intUserThirdNumber = intThirdNumber) then
Inc(intStrikeCount)
else
begin
if (intUserThirdNumber = intFirstNumber) then Inc(intBallCount);
if (intUserThirdNumber = intSecondNumber) then Inc(intBallCount);
end;

Inc(intTryCount);

lsbResult.Items.Insert(0, IntToStr(intTryCount) + ‘ : ‘ + txtNumber.Text + ‘ ‘ + IntToStr(intStrikeCount) + ‘ S ‘ + IntToStr(intBallCount) + ‘ B’);

for intLoop := 1 to 9 do
ChangeButtonStatus(intLoop, True);

txtNumber.Text := ”;

end;

end

end;

 

입력된 숫자를 각각 분리하여 컴퓨터가 생성한 것과 비교하여 그 결과를 출력합니다. ListBox에 Add가 아니라 Insert로 항목을 출력한 것을 마지막에 입력한 숫자가 가장 위에 나타나도록 하기 위함입니다. 판정된 결과를 시도 횟수와 함께 출력해 주어 사용자가 숫자를 추측하기 편하도록 합니다. 이 강좌에서는 이미 입력된 숫자라고 해도 다시 입력 받는데 받지 않도록 개선하면 더 완성도 높은 프로그램이 될 것입니다.

생성된 숫자를 맞추면 더 이상의 입력이 불가능 하도록 확인 버튼을 비활성화 합니다.

나머지 소스는 올려드린 자료를 참고하시면 됩니다.

이 숫자야구 게임은 간단한 프로그램이라 할 수 있는데 별 다른 생각 없이 PC앞에 앉아 바로 코딩을 진행했습니다. 그런데 숫자버튼의 처리나 비교하는 과정에서 바로 생각나는 대로만 하다 보니 나중에는 비슷한 기능을 하는 함수가 여러 개 만들어 지고 기능은 만들어져 있는데 사용되지 않는 함수도 나타나게 되었습니다. 중요한 루틴만을 제외하여 정리하여 필요한 루틴만이 들어가도록 하였습니다. 이것도 완성도가 높다고는 할 수 없습니다. 버튼을 초기화 하는 부분이 중복이 되어 있고 매끄럽지 못한 부분도 눈에 많이 들어옵니다. 한번 스스로 고쳐보시기 바랍니다.

말씀 드리고 싶은 것은 아무리 간단한 프로그램이라고 하더라도 PC앞이 아니라 책상 앞에 앉아 연습장에 생각을 정리하고 어떻게 진행할 것인가를 계획하라는 것 입니다. 물론 약간의 시간이 더 들고 그렇게 할 필요성이 없다라고 생각되시더라도 습관을 들이시는 것이 좋습니다. 저도 간단하게 생각을 하고 바로 코딩을 했다가 다시 한번 뼈저리게 느낀 사실입니다. 한번 더 생각을 정리하면 나중에 많은 시간과 노력을 줄일 수 있음을 꼭 잊지 마시기 바랍니다.

다운로드 : 소스파일

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의 기능을 아실 수 있습니다.

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

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

다운로드 : 소스파일