• 2005-12-22

    boost::singleton_pool 사용법

    
    struct CharArray512 {};
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        typedef boost::singleton_pool<CharArray512,512> TestPool;
    
        void * pBuf = TestPool::malloc();
        assert( pBuf > 0 );
        TestPool::free(pBuf);
    
        return 0;
    }
    

    singleton_pool 의 첫번째 템플릿 파라미터인 태그는, 동일한 크기의 버퍼에 대해서 각각 풀을 사용해야 할 때 구분자로 사용된다.

  • 2005-12-15

    DB datafile 옮기기

    그동안 사용했던 SQL Server evaluation 이 6개월만에 기한 만료되어 다른 머신에 똑같은 넘을 설치하게 되었다. 복구 방법은 생각보다 간단했는데...

    • .mdf 와 .ldf 파일을 data/ 아래로 복사한다.
    • 엔터프라이즈 관리자를 띄워서 데이터베이스를 클릭한 후 [모든 작업] - [데이터베이스 연결]에서 mdf 파일을 찾아 추가하면 된다.

    방화벽에 TCP, UDP 1433 포트를 열어 주는 것만 잊지 않으면 30분만에 새 서버를 띄울 수 있게 된다. :)

  • 2005-12-11

    유니코드 팁

    Generic Text Mapping

    프로그램을 유니코드에 대응하기 위해서는 모든 single byte char 관련 타입들을 generic macro 를 사용하도록 수정해야 한다.

    • 모든 스트링 리터럴에는 _T 또는 _TEXT 를 붙일 것. 그러나, 특별히 wide string 을 사용할 경우 L"abc" 처럼 L 을 붙일 것
    • 모든 문자 배열에 대해서는 TCHAR 를 사용할 것. 그러나, 특별히 wide char 를 사용할 경우 wchar_t 를 사용할 것.
    • 모든 스트링 포인터에 대해서 LPCTSTR 혹은 LPTSTR 을 붙일 것
    • 스트링 관련 C 함수들에 대한 T 시리즈들을 사용할 것.

    XML 과 유니코드

    유니코드로 인코딩된 XML 에 한글 엘리먼트 이름을 사용한 경우, 중문 혹은 영문 OS 에서 XPath 검색이 안되는 경우가 있다. 이는 프로그램 자체가 Non Unicode 이기 때문이며, 프로그램 자체를 유니코드로 만들면 문제가 없다.

    그러나, 그것이 힘들 경우, Windows XP 이상부터 설정 가능한 Non Unicode Program 의 디폴트 언어를 한글로 지정하면 된다. 단 98 과 같은 오래된 언어에서는 이것이 안되는데, 이를 위해서는 프로그램 코드 자체에 유니코드로 XPath 스트링을 지정하면 된다.

    pNode = pXMLDom->selectNodes( L"//캐릭터정보/*" );

    STL 과 유니코드

    STL은 OS independent 이어야 하므로 vc 전용 매크로인 UNICODE 에 대응되는 어떤 정책도 가지고 있지 않다. 따라서, 개발자가 아래와 같이 자체적으로 typedef 를 해줘야 한다. 단 전자와 같이 새로운 typedef 를 하는 것보다는 이미 존재하는 타입을 사용한 #ifdef 방식이 더 좋다고 한다. (그러고보니 좋은 거 같다.. --)

    
    // ok but not recommended
    typedef basic_string〈TCHAR,  char_traits〈TCHAR〉,  allocator〈TCHAR〉〉 tstring;
    
    // better, recommended
    #ifdef _UNICODE
    #define tstring wstring
    #else
    #define tstring string
    #endif
    

    see also:

    스트링 길이 문제

    • 문자의 개수 : sizeof(szBuffer) / sizeof(TCHAR)
    • 문자열의 길이 : sizeof(szBuffer) * sizeof(TCHAR)
    • 적절한 매크로를 만들어 사용하면 고민에서 해방될까?

    %s 와 %S

    만약 UNICODE 어플리케이션일 경우 %s 는 유니코드 문자열이며 %S 는 ANSI 문자열 포맷팅시 사용된다. 물론 MBCS 일 경우라면 반대가 된다.

  • 2005-12-11

    VB.NET 팁

    레이옷이 추천하는, 온라인 게임 서버 및 운영을 위한 툴을 만드는데 가장 좋은 언어는 바로 VB.Net 이다. 당신이 클라이언트 프로그래머가 아닌 이상 온라인 게임에서 주로 사용되는 툴은, 대체로 시스템 관리, 제어, 모니터링, 분석, 로그에 관련된 툴이 분명하다. (때로는 스크립트 에디터 같은 툴이 필요할 때도 있지만) 진짜 간단한 것은 Python 을 사용한 콘솔 스크립트로 해결할 수 있지만, 프로그래머가 아닌 GM 이나 QA팀, 모니터링팀들이 계속 사용해야 하는 툴들은 이쁘고, 사용하기 쉽고, 자주 수정되어야 하는 특성을 지니는 것이 보통이다. 이럴때 VB.Net을 사용하면, 빠른 개발속도와 높은 생산성, 그리고 아름다운 GUI 를 쉽게 얻을 수 있다.

    특히 VB.Net은 MsSQL과는 거의 찰떡궁합이라고 할 수 있다. MS 특유의 데이터 공유가 한몫한다고 할 수 있다. 예전에는 Oracle과 문제가 좀 있었다고 하는데 지금은 좋다. 하지만 Oracle을 사용할 예정이라면 Developer가 아직도 짱~이다.

    TabControl.SelectedIndex

    사용자가 탭을 변경했을 때 이벤트 핸들러를 작성하고 싶다면 SelectedIndexChanged 이벤트를 이용하면 된다.

    DialogResult

    사용자로부터 입력을 받는 다이얼로그에는 보통 OK/Cancel 버튼이 존재한다. 문제는 사용자가 OK 를 눌렀을 때 입력받은 데이터를 검증하게 되는데, 이때 검증이 실패할 경우의 처리이다.

    Private Sub m_OKButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    Handles m_OKButton.Click

    If UserName.Text = "" Then
    MsgBox("아이디를 입력하세요", MsgBoxStyle.Exclamation)
    Me.DialogResult = DialogResult.None
    Exit Sub
    End If
    If ChangeLog.Text = "" Then
    MsgBox("변경사항을 입력하세요", MsgBoxStyle.Exclamation)
    Me.DialogResult = DialogResult.None
    Exit Sub
    End If
    If GetOldVersion() = GetNewVersion() Then
    MsgBox("상점 버전이 변경되지 않았습니다.", MsgBoxStyle.Exclamation)
    Me.DialogResult = DialogResult.Cancel
    Exit Sub
    End If

    End Sub

    정리하자면,

    • 만약 사용자가 다시 입력하게끔 하려면 Me.DialogResult = DialogResult.None 을 지정
    • 입력을 무시하고 다이얼로그를 닫으려면 Me.DialogResult = DialogResult.Cancel 을 지정

    하면 된다. 또한, 다이얼로그 폼의 {{{AcceptButton/CancelButton}}} 속성을 위의 버튼으로 지정해주면 디폴트 포커스가 OK 버튼으로 가게 되며, Enter/ESC 키로 각 버튼을 실행시킬 수 있어 편하다.

    DataGrid

    VisualBasicDotNet 이 가장 좋은 점은, 바로 어떤 데이터를 표 형식으로 보여주는 작업을 정말 손쉽게 해준다는 데 있다. 다음과 같은 클래스들의 관계를 잘 이해해야만 보다 쉽게 표를 만들 수 있다.

    1. DataGrid - 데이터 그리드 컨트롤.
    2. DataSource - 표를 구성하는 데이터 소스를 의미. SetDataBinding() 으로 지정할 수도 있고, 디자이너의 속성창에서 지정할 수도 있다.
    3. DataSet - 여러 개의 DataTable 을 하위에 가진다. DataSet 은 여러 개의 DataTable 들의 연관 관계도 지정할 수 있다. DataSet 이 Document 라면 DataGrid 는 View 가 된다. 일종의 데이터 캐시로 봐도 무방하다.
    4. Tables : DataTable - 하위 테이블 컬렉션
    5. Relations : DataRelation - 하위 테이블 관계 컬렉션
    6. DataTable - 데이터베이스의 테이블과 유사한 개념으로, 실질적인 데이터를 담고 있는 데이터 객체이다.
    7. Rows : DataRow - 하위 행 컬렉션
    8. Columns : DataColumn - 하위 열 컬렉션
    9. DataRow - 데이터베이스의 행과 유사한 개념.
    10. RowState - 얻어온 행이 바뀌었는가? 삭제되었는가? 등을 나타냄
    11. DataView - 화면상에 출력되는 뷰를 의미한다. 데이터베이스에서의 뷰와도 대략 비슷하다. 정렬, 필터링

    표 만들기

    디자이너 모드에서 다음과 같이 하면 된다.

    1. 도구상자에서 DataGrid 를 Drag & Drop 으로 추가한다.
    2. 도구상자에서 DataSet 을 Drag & Drop 으로 추가한다.
    3. DataGrid.DataSource 속성을 DataSet 으로 지정한다.
    4. DataSet.Tables 속성을 선택, 새로운 DataTable 을 추가한다.
    5. DataTable.Columns 속성을 선택, 새로운 DataColumn 을 추가한다. 컬럼 이름과 속성을 지정하면 그리드로 출력할 표의 형태가 완성된다.

    마우스로 선택한 row 가 가리키는 DataRow 찾기

    일반적으로는 CurrentRowIndex 또는 HitTestInfo 를 사용하면, 마우스의 (x,y) 좌표를 활용, 현재 선택된 row 를 쉽게 찾을 수 있다. 그러나, 그리드가 정렬되어 순서가 바뀌게 되면 이 방식으로 찾기가 곤란하다. 이를 위해서는 DataView 를 잘 활용해야 한다. (더불어 rowIndex 의 바운드 체크에도 주의할 것)

    Dim rowIndex As Integer = EventLogGrid.CurrentRowIndex

    If rowIndex >= 0 Then
    Dim view As DataView = m_DataSet.Tables(0).DefaultView
    Dim rowView As DataRowView = view.Item(rowIndex)
    Dim id As Int32 = rowView.Item("ID")

    ' do something

    End If

    이전 날짜 계산하기

    Dim date As DateTime = sqlDataReader("col name")
    Dim date2 As DateTime = date.AddDays(-15) ' 15 일 이전 날짜를 계산하기

    날짜 포매팅 바꾸기

    데이터베이스와 OS 의 언어 설정이 다를 경우, 그냥 SQL 로 바꿨다가는 에러가 난다. 따라서 강제 포매팅을 해줘야 한다.

    Dim date As DateTime = DateTime.Now()
    date.ToString("yyyy-MM-dd hh:mm:ss")

    DateTimePicker 에서 시간까지 보이게 하기

    DateTimePicker 는 기본적으로 날짜만이 출력된다. 만약 시간까지 보이고 싶게 하려면, 프라퍼티를 다음과 같이 설정하라

    • Format = Custom
    • CustomFormat = yyyy-MM-dd HH:mm:ss (24시간)

    see also: