MFC에서 SQLite3에 한글 문자열을 저장하고 다시 불러오는 간단한 예제를 만들어보았습니다.
이쪽 분야를 전문적으로 작성하지 않기 때문에 좀 이상하게 작성된게 있을 수도 있습니다^^;
MFC에서 사용할 SQLIte를 다운로드 받아야 합니다.
https://www.sqlite.org/download.html 에서 SQLite 소스 코드와 DLL 파일을 다운로드 합니다.
생성한 프로젝트에 따라 x86 또는 x64 DLL을 사용합니다. 본 포스트에서는 x64를 사용합니다.
압축을 풀어서 C:\SQLite3에 복사해줍니다.
개발자 명령 프롬프트 또는 Developer Command Prompt를 검색하여 실행합니다.
Visual Studio 2019에서도 동일하게 진행할 수 있습니다.
다음 명령을 사용하여 lib 파일을 생성합니다.
32비트인 경우에는 x64대신 x86을 사용하면 됩니다.
lib /def:sqlite3.def /machine:x64
새로운 MFC 프로젝트를 생성합니다.
응용 프로그램 종류로 대화 상자 기반을 선택하고, SDL은 체크해제 한 후, 마침 버튼을 클릭합니다.
솔루션 플랫폼을 x64로 변경합니다.
메뉴에서 프로젝트 > 속성을 선택하고 구성을 모든 구성으로 변경합니다.
왼쪽 메뉴에서 C/C++를 선택한 후, 추가 포함 디렉토리 항목에 C:\SQlite3을 입력합니다.
왼쪽 메뉴에서 링커를 선택하고 추가 라이브러리 디렉터리 항목에 C:\SQLite3을 입력합니다.
왼쪽 메뉴에서 디버깅을 선택한 후, 환경 항목에 다음을 입력합니다.
PATH=C:\SQLite3;%PATH%
프로젝트 창에서 리소스 뷰를 선택합니다.
Dialog 항목에 있는 IDD_ABOUTBOX 아래에 있는 다이얼로그를 선택합니다.
리소스 뷰가 보이지 않는 경우 메뉴에서 보기 > 리소스 뷰를 선택하세요.
다음처럼 UI를 구성하고 변수를 추가해줍니다.
리스트 컨트롤의 속성에서 Single Selection을 True로 변경합니다.
View를 Report로 변경합니다.
파일 이름에 Dlg가 포함된 cpp 파일에 코드를 추가할 차례입니다.
제 경우에는 SQLite3_ExampleDlg.cpp 입니다.
필요한 헤더파일과 함수 그리고 SQLite 라이브러리를 로드하기 위한 코드를 추가합니다.
#include "sqlite3.h" #include <assert.h> #pragma comment(lib, "sqlite3.lib") // SQLite는 UTF8을 사용하기 때문에 코드 변환이 필요합니다. // 출처 - http://dolphin.ivyro.net/file/algorithm/SQLite/tutoria03.html int AnsiToUTF8(char* szSrc, char* strDest, int destSize) { WCHAR szUnicode[255]; char szUTF8code[255]; int nUnicodeSize = MultiByteToWideChar(CP_ACP, 0, szSrc, (int)strlen(szSrc), szUnicode, sizeof(szUnicode)); int nUTF8codeSize = WideCharToMultiByte(CP_UTF8, 0, szUnicode, nUnicodeSize, szUTF8code, sizeof(szUTF8code), NULL, NULL); assert(destSize > nUTF8codeSize); memcpy(strDest, szUTF8code, nUTF8codeSize); strDest[nUTF8codeSize] = 0; return nUTF8codeSize; } int UTF8ToAnsi(char* szSrc, char* strDest, int destSize) { WCHAR szUnicode[255]; char szAnsi[255]; int nSize = MultiByteToWideChar(CP_UTF8, 0, szSrc, -1, 0, 0); int nUnicodeSize = MultiByteToWideChar(CP_UTF8, 0, szSrc, -1, szUnicode, nSize); int nAnsiSize = WideCharToMultiByte(CP_ACP, 0, szUnicode, nUnicodeSize, szAnsi, sizeof(szAnsi), NULL, NULL); assert(destSize > nAnsiSize); memcpy(strDest, szAnsi, nAnsiSize); strDest[nAnsiSize] = 0; return nAnsiSize; } |
초기에 필요한 데이터베이스 파일 생성, 테이블 생성을 합니다.
그리고 데이터베이스로부터 데이터를 가져와 리스트 컨트롤에 보여줍니다.
BOOL CSQLite3ExampleDlg::OnInitDialog() { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // TODO: 여기에 추가 초기화 작업을 추가합니다. // 한줄 선택 m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); // 리스트 컨트롤에 컬럼 이름 입력 m_list.InsertColumn(0, L"이름"); m_list.SetColumnWidth(0, 120); m_list.InsertColumn(1, L"전화번호"); m_list.SetColumnWidth(1, 240); // 데이터베이스 파일 생성 및 열기 sqlite3 *db; sqlite3_stmt *stmt; char *errmsg = NULL; int rc = sqlite3_open("test.db", &db); if (rc != SQLITE_OK) { printf("Failed to open DB\n"); sqlite3_close(db); exit(1); } //SQL 테이블 생성 char *sql; sql = "CREATE TABLE IF NOT EXISTS DB(" "ID INTEGER PRIMARY KEY AUTOINCREMENT," "NAME TEXT NOT NULL," "TEL TEXT NOT NULL);"; rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg); if (rc != SQLITE_OK) { printf("create table"); sqlite3_free(errmsg); sqlite3_close(db); exit(1); } // 테이블을 읽어와 리스트 컨트롤에 보여주기 sqlite3_prepare_v2(db, "select * from db", -1, &stmt, NULL); while (sqlite3_step(stmt) != SQLITE_DONE) { int i; int num_cols = sqlite3_column_count(stmt); char szAnsi[300]; UTF8ToAnsi((char *)sqlite3_column_text(stmt, 1), szAnsi, 300); CString name(szAnsi); UTF8ToAnsi((char *)sqlite3_column_text(stmt, 2), szAnsi, 300); CString tel(szAnsi); int nItem = m_list.InsertItem(0, name); m_list.SetItemText(nItem, 1, tel); } sqlite3_finalize(stmt); sqlite3_close(db); return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다. } |
추가 버튼 클릭시 실행되는 코드입니다.
void CSQLite3ExampleDlg::OnBnClickedAdd() { // 에디터 박스에 입력된 데이터를 리스트컨트롤에 입력합니다. CString name; m_name.GetWindowText(name); CString tel; m_tel.GetWindowText(tel); int nItem = m_list.InsertItem(0, name); m_list.SetItemText(nItem, 1, tel); m_name.SetWindowTextW(L""); m_tel.SetWindowTextW(L""); sqlite3 *db; int rc = sqlite3_open("test.db", &db); if (rc != SQLITE_OK) { printf("Failed to open DB\n"); sqlite3_close(db); exit(1); } char * s_name; int sLen = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); s_name = new char[sLen + 1]; WideCharToMultiByte(CP_ACP, 0, name, -1, s_name, sLen, NULL, NULL); char szName[100]; AnsiToUTF8(s_name, szName, 100); delete[]s_name; char * s_tel; sLen = WideCharToMultiByte(CP_ACP, 0, tel, -1, NULL, 0, NULL, NULL); s_tel = new char[sLen + 1]; WideCharToMultiByte(CP_ACP, 0, tel, -1, s_tel, sLen, NULL, NULL); char szTel[100]; AnsiToUTF8(s_tel, szTel, 100); delete[]s_tel; char *errmsg = NULL; char sql[255] = { 0 }; sprintf(sql, "insert into db(name, tel) values('%s','%s');", szName, szTel); if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { printf("insert"); } sqlite3_close(db); } |
삭제 버튼 클릭시 실행되는 코드입니다.
void CSQLite3ExampleDlg::OnBnClickedRemove() { // 리스트 컨트롤에서 선택한 아이템을 제거합니다. int row = m_list.GetSelectionMark(); CString name = m_list.GetItemText(row, 0); char * s_name; int sLen = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); s_name = new char[sLen + 1]; WideCharToMultiByte(CP_ACP, 0, name, -1, s_name, sLen, NULL, NULL); char szName[100]; AnsiToUTF8(s_name, szName, 100); delete[]s_name; sqlite3 *db; int rc = sqlite3_open("test.db", &db); if (rc != SQLITE_OK) { printf("Failed to open DB\n"); sqlite3_close(db); exit(1); } char *errmsg = NULL; char sql[255] = { 0 }; sprintf(sql, "delete from db where name = '%s';", szName); if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { printf("delete"); } sqlite3_close(db); m_list.DeleteItem(row); } |
작성 2020. 3. 23