2009/02/23

[STL] map 의 맨 마지막 원소에 접근하기 (map.end() 는 마지막 원소가 아니다!!)

vector 나 list의 경우 크기를 가져와 마지막 원소에 쉽게 접근 할 수 있지만 map의 경우 Key 에 의해 접근으로 find() 멤버함수를 이용하여 iterator를 가져와서 접근할 수 있다.

그러면 맨 마지막 값을 가져오기 위해서는 맨 마지막 iterator를 가져오기만 하면 되는데...
map 의 member 함수 중 end() 함수가 있는데 이는 맨 마지막 iterator를 가리키기 않는다. end() 함수는 맨마지막 원소를 넘어선 map의 가장 마지막을 가르킨다. 그래서 end() 함수를 활용하여 맨 마지막 원소에 접근하려면 증감연산자(--)를 이용해 한단계 앞으로 iterator를 옮겨 주면 된다. 그리고 map 에는 rbegin() 이라는 함수도 제공하는데 이는 현재 map에 있는 원소를 거꾸로 하였을때 맨 처음 원소를 가리킨다.


map< int, Data* > mpData;

// end() 의한 마지만 원소 접근
map< int, Data* >::iterator it = --mpData.end();
Data* pData = it->second;

// rbegin() 에 의한 마지막 원소 접근
map< int, Data* >::reverse_iterator it = mpData.rbegin();
Data* pData = it->second;



위의 코드중 end() 함수에 의한 접근은 위험 요소를 갖고 있다. map에 저장된 데이터가 하나도 없을 경우 에러를 발생한다. end()에 의한 접근 전에 map의 크기를 검사 하는 루틴을 포함해 주어야한다.


Original Post : http://neodreamer-dev.tistory.com/257

2009/02/19

[STL] vector 에서 [] 과 at() 의 차이점

vector 의 원소에 접근하는 방법은 배열의 접근 방법과 갈은 [] 를 이용하는 방법과 멤버 함수인 at() 을 이용하는 방법이 있다.
이 두가지 방법의 차이점은 첨자의 범위를 체크하는지 여부와 범위를 벗어난 접근일 경우 예외 발생 여부이다.


배열 접근 기호인 [] 에의한 접근은 첨자의 범위를 체크하지 않기 때문에 범위를 벗어난 접근을 시도할 경우 예외를 발생하지 않고 에러를 발생한다.



멤버함수 at() 를 이용한 접근은 첨자의 범위를 체크하여 벗어난 접근을 시도할 경우 std::out_of_range 예외를 발생 한다.


범위내의 접근을 보장할 경우 별도의 범위 체크가 필요 없으므로 []의해 원소에 접근하며
for ( int n = 0; n < (int)vInt.size(); ++n )

{

int a = vInt[ n ];

:

}



그렇지 않을 경우 at() 의한 접근으로 예외를 처리해 준다.
void foo( int n )

{

try

{

int a = vInt.at( n );

}

catch (std::out_of_range& e)

{

AfxMessageBox( _T("Catch the std::out_of_range") );

}

}


Original Post : http://neodreamer-dev.tistory.com/256

2009/02/18

[STL] remove algorithm 은 실제로 지우지 않는다.

vector 를 사용하다 특정 원소를 삭제하기 위해 algorithm 의 remove 를 이용하였다. vector 자체에는 remove 를 지원하지 않기 때문에... 하지만 결과는 예상을 빗나가 버렸다.

remove를 하면 원소는 사라지는 것 처럼 보이는데 vector의 크기는 그대로였다.
그래서 remove에 대한 정보를 찾아보았다.

remove 의 기능은 지정된 시작위치부터 끝위치까지 탐색하여 지워야하는 원소가 있을 경우 그 위치에 다음의 지우지 않을 원소를 덮어 써서 뒤쪽의 일부 영역을 무효화 한다.
그렇게 삭제(?)를 마치면 뒤쪽의 무효화 영역이 시작되는 iterator 를 반환한다.

실제로 지우기 위해서는 이 iterator 부터 마지막까지 erase 로 지워야한다. erase 할 경우 마지막까지 지우지 않고 iterator 만 지울 경우 다수의 원소를 삭제하고자 할 경우 정확하게 지워지지 않는다.



vector< int > vInt;
vector< int >::iterator it;

vInt.push_back( 2 );
vInt.push_back( 3 );
vInt.push_back( 4 );
vInt.push_back( 12 );
vInt.push_back( 15 );
vInt.push_back( 35 );
vInt.push_back( 2 );
vInt.push_back( 62 );
vInt.push_back( 24 );
vInt.push_back( 15 );
vInt.push_back( 91 );

TRACE0("\nsource : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

it = remove( vInt.begin(), vInt.end(), 15 );
TRACE0("\nremove 15 : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

//vInt.erase( it );
vInt.erase( it, vInt.end() );
TRACE0("\nerase : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

it = remove( vInt.begin(), vInt.end(), 2 );
TRACE0("\nremove 2 : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

//vInt.erase( it );
vInt.erase( it, vInt.end() );
TRACE0("\nerase : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

결과
////////////////////////////////////////////////////////////////////////////////
// remove로 받은 iterator 만을 지울 경우 : vInt.erase( it )
source : 2 3 4 12 15 35 2 62 24 15 91

remove 15 : 2 3 4 12 35 2 62 24 91 15 91
// 15 삭제시 15 두 개가 삭제되고 뒤쪽의 원소들로 앞쪽으로 덮어 씌운다.
// 마지막 두 원소는 유령처럼 살아있다.
// 반환된 iterator 는 끝에서 두 번째 원소를 가리킨다.
erase : 2 3 4 12 35 2 62 24 91 91
// 반환받은 iterator 위치의 원소를 삭제할 경우 마지막에서 두 번째 원소만
// 삭제한다. 마지막 91은 여전히 살아있다.

remove 2 : 3 4 12 35 62 24 91 91 91 91
erase : 3 4 12 35 62 24 91 91 91

////////////////////////////////////////////////////////////////////////////////
// remove로 받을 iterator 에서 마지막까지 지울 경우 : vInt.erase( it, vInt.end() )
source : 2 3 4 12 15 35 2 62 24 15 91

remove 15 : 2 3 4 12 35 2 62 24 91 15 91
// 15 삭제시 15 두 개가 삭제되고 뒤쪽의 원소들로 앞쪽으로 덮어 씌운다.
// 마지막 두 원소는 유령처럼 살아있다.
// 반환된 iterator 는 끝에서 두 번째 원소를 가리킨다.
erase : 2 3 4 12 35 2 62 24 91
// 반환받은 iterator 위치부터 마지막까지 삭제할 경우 원하는 결과를 얻을 수 있다.

remove 2 : 3 4 12 35 62 24 91 24 91
erase : 3 4 12 35 62 24 91

Original Post : http://neodreamer-dev.tistory.com/255

SQLite Release 3.6.11

Changes associated with this release include the following:

    * Added the hot-backup interface.
    * Added new commands ".backup" and ".restore" to the CLI.
    * Added new methods backup and restore to the TCL interface.
    * Improvements to the syntax bubble diagrams
    * Various minor bug fixes


SQLite 3.6.11
SQLite 3.6.11 Dll
SQLite 3.6.11 Source

SQLite3 v3.6.9 Library for C++ Builder







SQLite3 v3.6.9 Libary for Visual C++









C++ Builder 용 SQLite 정적 라이브러리 만들기
Visual C++ 용 SQLite 정적 라이브러리 만들기
Original Post :
http://neodreamer-dev.tistory.com/254

2009/02/14

TurboC++ Explorer 에서 Indy9 사용하기

[출처]
볼랜드 포럼 : 김태선 님
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=858

TurboC++ Explorer 버전에는 Indy 9과 Indy 10이 모두 들어 있습니다.
다만 컴포넌트로 설치되어 있지 않아 디자인 타임에 쓸 수 없을 따름입니다.
하지만 코드로 동적 생성해서 사용하는 것은 아무런 문제가 없습니다.

Indy 9은 9.0.50 버전이 들어 있어 Indy 9을 잘 쓰는 분들은 9.0.18 쓰듯이 쓸 수 있습니다.

코딩으로는 아래처럼 동적 생성해서 사용할 수 있습니다.



#include <idbasecomponent.hpp>
#include <idcomponent.hpp>
#include <idtcpclient.hpp>
#include <idtcpconnection.hpp>
#include <idtcpserver.hpp>

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TCPServer = new TIdTCPServer(this);
TCPServer->DefaultPort = 80;

Caption = TCPServer->Version;
}
//---------------------------------------------------------------------------

하지만 링크에서 에러를 내는데, 이는
Install Packages->Runtime Packages에 한줄로 패키지 명이 나열되어 있는 끝에
;indy 를 추가해 주면 됩니다.
그러면 링크 및 실행화일 만들어 내는데 아무런 문제 없이 잘 됩니다.
하지만 단독실행 화일을 만들때는 안되므로 이때는 코드 중에
#pragma link "indy.lib"
를 한줄 넣어주면 됩니다.

코딩으로 일일이 인디를 쓰자면 조금 답답한 면이 있는데,
이는 Builder 6 Personal 버전에 Indy9를 설치하면 디자인타임에 쓸수 있으므로, 같은 코딩을 해보면
Include 파일 및 이벤트 핸들러 프로토타입 형태의 코드가 생성되므로
이를 그대로 TurboC++ Explorer 버전에 복사해서 쓰면 됩니다.


이는 TurboC++ Explorer 설치시 Indy 9을 선택한 뒤라 이렇게만 해도 되는데,
인디 10을 선택한 경우는 Search Path를 Indy9으로 재조정해야 합니다.


그럼

Original Post : http://neodreamer-dev.tistory.com/253

2009/02/12

국산 블럭 암호 알고리즘 SEED / ARIA

국산 암호화 기술은 SEED와 ARIA가 있는데 민간분야과 공공분야에 표준화되어 있는 이 두 알고리즘은 지금까지 무료로 배포되고 있었다.

하지만 자료의 접근에있어서 쉽지 않았다.

하지만 이번에 국가사이버안전센터와 한국정보보호진흥원에서는 이 두 알고리즘의 보다 많은 확산을 위해 서로 협력하여 배포를 하기로 하였다.

그리고 문제가 많았던 알고리즘 코드에 대한 접근을 개선하여 SEED는 간단한 양식을 작성해 입력하면 바로 메일로 코드를 받아볼 수 있었다. 이전에는 양식을 관리자가 검토하여 승인을 얻은뒤 메일로 전송해 주었는데 일반적으로 하루 정도 소요되며 주말이 포함되면 관리자의 부재로 인하여 몇일을 기다려야만 했다. 하지만 이제는 곧 바로 받아 볼 수 있게되었다.
ARIA 는 이보다 더 쉽게 접근을 할 수 있다. 웹페이지를 방문하여 바로 다운로드 받으면 된다.

한국정보진흥원 암호이용 활성화 페이지
Seed 알고리즘 보급 신청 페이지 (간단한 양식 접수 후 바로 메일로 받음)

국가정보원 ARIA 알고리즘 소개 페이지
ARIA 알고리즘 기술 문서및 소스 코드 다운로드 페이지 (웹페이지를 방문하여 바로 다운 받을 수 있음

Original Post : http://neodreamer-dev.tistory.com/252

2009/02/11

SyntaxHighlighter 2.0.287 Released!!

얼마전 2.0 버전 (278) 버전을 발표한 SyntaxHighlighter 가 버전업을 하였다.

이번 버전에 수정된 내용.
    * Added 'c#' alias to C# brush.
    * Fixed blogger double lines style error.

2.0 버전 부터는 프로젝트 웹페이지를 새로 단장하면서 Hosting 까지 지원을 하여서 보다 쉽게 SyntaxHighlighter를 적용할 수 있을 뿐만 아니라 업데이트또한 쉬워졌다.
참조 경로만을 바꾸는 것으로 업데이트를 할 수 있다.

SyntaxHighlighter project

2009/02/04 - [Com. Story/Tips] - Tistory에 SyntaxHighlighter 2.0 적용하기


Original Post : http://neodreamer-dev.tistory.com/251

2009/02/10

[MFC] CString 의 문자/문자열 삭제 및 치환하기

CString 의 멤버 함수인 Remove 와  Replace 의 활용 예이다.

Remove 함수는 문자열에서 지정된 문자를 삭제하고 Replace 는 문자열에서 지정된 문자 또는 문자열을 다를 문자나 문자열로 치환한다.

    strValue = _T("Hello World!!");

int nCh = strValue.Replace( _T('l'), _T('w') );
TRACE2( "Replaced %d : %s
\n", nCh, strValue );

nCh = strValue.Replace( _T("ww"), _T("ll") );
TRACE2( "Replaced %d : %s
\n", nCh, strValue );

nCh = strValue.Remove( _T('!') );
TRACE2( "Removed %d : %s
\n", nCh, strValue );

#결과
Replaced 3 : Hewwo Worwd!!
Replaced 1 : Hello Worwd!!
Removed 2 : Hello Worwd



MSDN 사이트에서 발췌한 Replace 사용 예.

http://msdn.microsoft.com/en-us/library/aa300582(VS.60).aspx

//First example, with old and new equal in length.

CString strZap("C--");
int n = strZap.Replace('-', '+');
ASSERT(n == 2);
ASSERT(strZap == "C++");

//Second example, old and new are of different lengths.

CString strBang("Everybody likes ice hockey");
n = strBang.Replace("hockey", "golf");
ASSERT(n == 1);
n = strBang.Replace("likes", "plays");
ASSERT(n == 1);
n = strBang.Replace("ice", NULL);
ASSERT(n == 1);
ASSERT(strBang == "Everybody plays golf");

// note that you now have an extra space in your
// sentence. To remove the extra space, include it
// in the string to be replaced, i.e.,"ice ".



MSDN 사이트에서 발췌한 Remove 사용 예.

http://msdn.microsoft.com/en-us/library/aa300579(VS.60).aspx

//remove the lower-case letter 't' from a sentence:

CString str("This is a test.");
int n = str.Remove('t');
ASSERT(n == 2);
ASSERT(str == "This is a es.");

Original Post : http://neodreamer-dev.tistory.com/250

2009/02/05

Tistory 새로운 관리자 모드의 글쓰기의 심각한 버그!!

티스토리의 새로운 관리자 모드는 산뜻하고 잘 다듬어진 UI를 갖고는 있지만 글쓰기 기능에 심각한 버그가 있다.

편집시에 HTML 모드와 EDIT(위지윅) 모드를 전환을 하다보면 쓸데 없는 줄넘김 태그(BR)가 붙는다.

소스 코드를 자주 올리는 나에게는 큰 문제이다. 이전 관리모드에서 테스트를 해 보았지만 그런 문제는 발생하지 않았다.



HTML 모드에서 아래와 같이 작성을 한 후

<PRE>
void main()
{
printf("Hello World");
}
</PRE>


EDIT(위지윅) 모드로 전환

void main()
{
printf("Hello World");
}


HTML 모드로 전환

<pre>void main()<br />
{<br />
printf("Hello World");<br />
}<br />
</pre>


EDIT(위지윅) 모드로 전환

void main()

{

printf("Hello World");

}



HTML 모드로 전환

<pre>void main()<br />
<br />{<br />
<br /> printf("Hello World");<br />
<br />}<br />
<br /></pre>


EDIT(위지윅) 모드로 전환

void main()


{


printf("Hello World");


}



HTML 모드로 전환

<pre>void main()<br />
<br /><br />
{<br />
<br /><br />
printf("Hello World");<br />
<br /><br />
}<br />
<br /><br />
</pre>


EDIT(위지윅) 모드로 전환

void main()




{




printf("Hello World");




}






HTML 모드로 전환

<pre>void main()<br />
<br /><br />
<br /><br />
{<br />
<br /><br />
<br /><br />
printf("Hello World");<br />
<br /><br />
<br /><br />
}<br />
<br /><br />
<br /><br />
</pre>


EDIT(위지윅) 모드로 전환

void main()







{







printf("Hello World");







}








Original Post : http://neodreamer-dev.tistory.com/249

2009/02/04

Tistory에 SyntaxHighlighter 2.0 적용하기

2.0이 발표되고 내용을 살펴 보았다.



뭐가 크게 바뀌었나 설치를 해 보고 싶었는데 기존 1.5.1 버전을 삭제하고 다시 할 경우 호환이 되는지를 먼저 파악해야 했다. 2.0으로 업데이트 하면서 기존의 글들을 수정해야 된다면 여간 큰일이 아닐 수 없기 때문이다.

다행이 2.0에서 하위 호환성을 지켜주고 있었다. 1.5 버전을 위한 shBrushBash.js 를 포함시켜주고 이전의 Highlighter 적용 코드를 추가 해 주면 된다. 그에 대한 자세한 내용을 이 글 마지만에 다시 언급 하겠다.



우선 2.0 을 Tistory에 적용하는 방법은 두 가지가 있다.

소스 코드를 직접 올려서 적용하는 방법과 SyntaxHighlighter Project 페이지에서 호스팅하는 소스를 호출해 주면 된다.



먼저 소스 코드를 직접 올리는 방법이다.

SyntaxHighlighter 2.0 소스를 다운로드 받아서 scripts 와 styles 폴더의 모든 파일을 스킨 편집의 직접 올리기를 통해 업로드 한다.



scripts 와 styles 폴더의 파일 구성 보기



그리고 스킨의 HTML/CSS 소스 수정에서 Head tag 를 닫기 전에 아래의 코드를 추가해 준다.



<head>
:
<script type="text/javascript" src="images/shCore.js"></script>
<script type="text/javascript" src="images/shLegacy.js"></script>
<script type="text/javascript" src="images/shBrushBash.js"></script>
<script type="text/javascript" src="images/shBrushCpp.js"></script>
<script type="text/javascript" src="images/shBrushCSharp.js"></script>
<script type="text/javascript" src="images/shBrushCss.js"></script>
<script type="text/javascript" src="images/shBrushDelphi.js"></script>
<script type="text/javascript" src="images/shBrushDiff.js"></script>
<script type="text/javascript" src="images/shBrushGroovy.js"></script>
<script type="text/javascript" src="images/shBrushJava.js"></script>
<script type="text/javascript" src="images/shBrushJScript.js"></script>
<script type="text/javascript" src="images/shBrushPhp.js"></script>
<script type="text/javascript" src="images/shBrushPlain.js"></script>
<script type="text/javascript" src="images/shBrushPython.js"></script>
<script type="text/javascript" src="images/shBrushRuby.js"></script>
<script type="text/javascript" src="images/shBrushScala.js"></script>
<script type="text/javascript" src="images/shBrushSql.js"></script>
<script type="text/javascript" src="images/shBrushVb.js"></script>
<script type="text/javascript" src="images/shBrushXml.js"></script>
<link type="text/css" rel="stylesheet" href="styles/shCore.css">
<link type="text/css" rel="stylesheet" href="styles/shThemeDefault.css">
<script type="text/javascript">
SyntaxHighlighter.all();
</script>
</head>




이제 SyntaxHighlighter 를 사용할 준비가 되었다.



다음으로 SyntaxHighlighter project 페이지에서 제공하는 호스팅 서버에서 소스를 받아 사용하는 방법이다. 파일을 직접 올리기 귀찮은 사람은 이 방법이 더 편할 것이다.



호스팅 주소는 http://alexgorbatchev.com/pub/sh/[VERSION] 이고 현재 마직막 버전은 2.0.278 으로 정확한 주소는 http://alexgorbatchev.com/pub/sh/2.0.278/ 이다.

따라서 javascript 주소를 베이스를 위의 주소로 설정해 주면 된다.



<head>
:
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shCore.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushBash.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushCpp.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushCSharp.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushCss.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushDelphi.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushDiff.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushGroovy.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushJava.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushJScript.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushPhp.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushPlain.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushPython.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushRuby.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushScala.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushSql.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushVb.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushXml.js"></script>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/2.0.278/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/2.0.278/styles/shThemeDefault.css"/>
<script type="text/javascript">
SyntaxHighlighter.all();
</script>
</head>






그리고 아래 코드로 테스트 해 본다.



<pre class="brush: js">
alert("Hello world");
</pre>






위의 코드는 2.0에서 지원하는 코드이지만 tistory 에서는 1.5 버전에서 사용하던 방식인 TEXTAREA 태그를 활용하는 것이 HTML 편집과 위지윅 편집을 번갈아 가면서 편집하는데 더 편하다.

<textarea name="code" class="js" rows=3 cols=30>
alert("Hello world");
<textarea>




마지막으로 1.5.1 버전으로부터 업그레이드할 경우 몇 가지 알아 두어야 할 사항이 있다.



1.5.1 버전을 사용할 때 작성한 코드가 실행 되게 하기 위해서는 brush Script 중에서 shLegacy.js 를 호출 해 주어야 하고 BODY 태그의 OnLoad 에 Syntax Highlighter 를 적용하는 코드를 추가해 주어야 한다.



<head>
:
:
<script type="text/javascript" src="images/shLegacy.js"></script>
:
:
</head>
<body OnLoad="dp.SyntaxHighlighter.HighlightAll('code');">




그리고 Brush Alias 가 바뀐 내용도 알아 두어야한다. 이전에 Brush Alias로 class="c++" 나 class="c#" 을 사용했을 경우 "cpp" 와 "csharp" 으로 바꾸어 주어야 한다. 자세한 내용은 아래 페이지를 참고 하면 된다.


1.5 버전의 지원 언어와 Alias : http://code.google.com/p/syntaxhighlighter/wiki/Languages

2.0 버전의 지원 언어와 Alias : http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes
Original Post :
http://neodreamer-dev.tistory.com/248

SyntaxHighlighter 가 업데이트 버전(2.0) 을 발표 하였다.

이전 버전은 1.5.1 버전 이였고 새롭게 프로젝트 페이지를 만들고 2.0을 발표 하였다.


SyntaxHighlighter 는 소스코드를 웹페이지 상에서 상당히 보기 좋게 출력해 준다. 아래 이미지는 1.5.1 버전이 적용된 모습니다.


SyntaxHighlighter 1.5.1

SyntaxHighlighter 1.5.1



새로운 2.0 버전은 새로운 기능이 추가도 UI의 변화가 생겼다.

SyntaxHighlighter 2.0

SyntaxHighlighter 2.0



상당의 코드보기, 복사, 인쇄 기능이 플래시에서 이미지로 바뀌고 오른쪽 구석으로 이동 하였다.


새롭게 추가된 기능은 pre tag에 property 형태로 highlight 지원이 추가 되고 가로 방향의 스크롤바가 생성되지 않도록 줄넘김 기능이 추가 되었다.


아래는 SyntaxHighlighter 사이트에서 발췌해 온 1.5 와 2.0 과의 비교 자료이다.





프로젝트 페이지를 새단장 하면서 SyntaxHighlighter Hosting 도 지원하여 어디서나 쉽게 사용할 수 있게 되었다. 그에 대한 내용은 정리를 하여 다시 올릴 계획이다.


SyntaxHighlighter project site
Original Post :
http://neodreamer-dev.tistory.com/247

2009/02/03

실행시간에 툴바의 툴팁 바꾸기

다국어 프로그래밍에대한 정보를 찾다가 알게된 정보이다.
실생시간에 툴바의 툴팁을 바뀌기 위해서는 TTN_NEEDTEXTA, TTN_NEEDTEXTW 메세지를 받아 처리하면 된다.

TTN_NEEDTEXTA 는 Ascii 형식의 툴팁 데이터를 요구할때 발생하며 Win95에서 발생하고 TTN_NEEDTEXTW는 유니코드 형식의 툴팁 데이터를 요구할 때 발생하며 WinNT 이상에서 발생한다.

이 메세지를 처리하기 위한 메세지 맵을 작성한다.


ON_NOTIFY_EX_RANGE( TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE( TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)


실행시간에 컨트롤 아이디에 맞는 툴팁을 생성하기 위한 함수와 TTN_NEEDTEXTA, TTN_NEEDTEXTW 메세지를 핸들링할 함수를 작성한다.

아래 소스는 다국어 처리를 하기 위한 소스 중 일 부분으로 툴팁에 대한 메세지를 테스트한 내용의 소스이다.


BOOL GetToolTip( UINT nID, CString& strTipText, CString& /*strMessage*/);
virtual afx_msg BOOL OnToolTipText(UINT nID, NMHDR* pNMHDR,
LRESULT* pResult );

BOOL CMainFrame::GetToolTip( UINT nID, CString& strTipText,
CString& /*strMessage*/)
{
CString strFullString;

switch( nID )
{
case ID_FILE_NEW: // have to handle all toolbar tool tip messages here
theApp.m_Lang.GetMenuTip2( strTipText, _T("ID_FILE_NEW") );
break;

case ID_FILE_OPEN:
theApp.m_Lang.GetMenuTip2( strTipText, _T("ID_FILE_OPEN") );
break;

case ID_FILE_SAVE:
theApp.m_Lang.GetMenuTip2( strTipText, _T("ID_FILE_SAVE") );
break;

case ID_EDIT_CUT:
case ID_EDIT_COPY:
case ID_EDIT_PASTE:
case ID_FILE_PRINT:
case ID_APP_ABOUT:
if (strFullString.LoadString(nID))
AfxExtractSubString ( strTipText, strFullString, 1,'\n');
break;
}

return TRUE;
}

BOOL CMainFrame::OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT* pResult )
{
ASSERT ( pNMHDR->code == TTN_NEEDTEXTA || TTN_NEEDTEXTW );

TOOLTIPTEXTA* pTTTA = ( TOOLTIPTEXTA *)pNMHDR;
TOOLTIPTEXTW* pTTTW = ( TOOLTIPTEXTW *)pNMHDR;

CString strTipText;
CString strMessage;

if( GetToolTip( (UINT)pNMHDR->idFrom, strTipText, strMessage))
{
#ifndef _UNICODE
if(pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText,strTipText,_countof(pTTTA->szText));
else
_mbstowcsz(pTTTW->szText,strTipText,_countof(pTTTW->szText));
#else
if(pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText,strTipText,_countof(pTTTA->szText));
else
lstrcpyn(pTTTW->szText,strTipText,_countof(pTTTW->szText));
#endif

// change status bar message here need pointer to CMainFrame
// SetMessageText(strMessage);

// ok we handled the message, the buck stops here
return TRUE;

}

// we did not handle the message, pass it on
return CMainFrame::OnToolTipText(nID,pNMHDR,pResult);
}

Original Post : http://neodreamer-dev.tistory.com/246

2009/02/02

[MFC] AfxFormatString1() 과 AfxFormatString2()를 이용한 파라메터 스트링의 활용

void AfxFormatString1(
   CString& rString,
   UINT nIDS,
   LPCTSTR lpsz1
);

void AfxFormatString2(
   CString& rString,
   UINT nIDS,
   LPCTSTR lpsz1,
   LPCTSTR lpsz2
);

이 함수들은 AfxExtractSubString() 함수에 대한 정보를 찾다가 알게된 함수들이다.
AfxFormatString1 함수는 String Table 의 String 중 %1 을 특정 문자열로 치환 해주고 AfxFormatString2 함수는  %1,%2 를 특정 문자열로 치환해 준다.

예들 들어 String Table 에 다음과 같은 문자열이 정이 되어 있을때.
IDS_TEST "파일 %1을 찾을 수 없습니다."

CString strTest;
AfxFormatString1( strTest, IDS_TEST, _T("version.dat") );

strTest 는 "파일 version.dat 을 찾을 수 없습니다." 란 문자열이 들어가게 된다.

문자열만 치환 할 수 있고 개수도 한개 또는 두 개로 제한적이라서 활용 범위는 크지 않지만 가끔 유용하게 사용할 수 도 있을것 같다.

아래는 MSDN 사이트에서 발췌한 사용 예이다.(http://msdn.microsoft.com/en-us/library/f1w5d2h2.aspx)
void DisplayFileNotFoundMessage(LPCTSTR pszFileName, LPCTSTR pszDirectory)
{
CString strMsg;

// The IDS_FILENOTFOUND string resource contains "Error: File %1 not
// found in directory %2"
AfxFormatString2(strMsg, IDS_FILENOTFOUND2, pszFileName, pszDirectory);
// In the previous call, substitute the actual file and directory
// names into the message string
AfxMessageBox(strMsg); // Display the error message
}

Original Post : http://neodreamer-dev.tistory.com/245

[MFC] 간단하게 부분 문자열을 추출하는 방법 - AfxExtractSubString()

Toolbar 의 ToolTip 을 변경하고 싶어서 자료를 찾던 도중 알게된 함수이다.

이 함수는 전체 문자열 중에서 지정된 구분자로 구분하였을때 특정 위치의 문자열을 찾아 준다.

다음은 함수 원형이다.
BOOL AFXAPI AfxExtractSubString (
   CString& rString,
   LPCTSTR lpszFullString,
   int iSubString,
   TCHAR chSep = '\n'
);

MSDN 사이트에서 발췌한 사용예(http://msdn.microsoft.com/en-us/library/aa991543.aspx)

// The following example extracts a series of name, value pairs from a
// given source string:

// Input string consisting of a number of name, value pairs
LPCTSTR lpszSource = _T("\"Name\"=\"John Smith\"\n")
_T("\"Company\"=\"Contoso, Ltd\"\n\"Salary\"=\"25,000\"");

CString strNameValue; // an individual name, value pair

int i = 0; // substring index to extract
while (AfxExtractSubString(strNameValue, lpszSource, i))
{
// Prepare to move to the next substring
i++;

CString strName, strValue; // individual name and value elements

// Attempt to extract the name element from the pair
if (!AfxExtractSubString(strName, strNameValue, 0, _T('=')))
{
// Pass an error message to the debugger for display
OutputDebugString(_T("Error extracting name
\n"));
continue;
}

// Attempt to extract the value element from the pair
if (!AfxExtractSubString(strValue, strNameValue, 1, _T('=')))
{
// Pass an error message to the debugger for display
OutputDebugString(_T("Error extracting value element
\n"));
continue;
}

// Pass the name, value pair to the debugger for display
CString strOutput = strName + _T(" equals ") + strValue + _T("
\n");
OutputDebugString(strOutput);
}


Original Post : http://neodreamer-dev.tistory.com/244

[MFC] 실행시 CStatusBar 의 Prompt 문자열 제어하기

다국어 지원 프로그램을 테스트 하다 필요해 찾아본 정보인다. 메뉴나 툴바의 Prompt String 을 지정하면 실행시 마우스로 가리킬때 상태바에 Prompt String 이 출력된다.

실행시에 이 메세지를 변경을 해야할 필요가 있어 그 방법을 찾아 보았다.

실생시에 Prompt String을 제어하기 위해서는 MainFrame 의 GetMessageString 함수를 재정의(Override)하면 된다.

GetMessageString 은 다음과 같은 원형을 갖고 있다. (MSDN 발췌)

virtual void GetMessageString(
   UINT nID,
   CString& rMessage
) const;

Parameters

nID
    Resource ID of the desired message.

rMessage
    CString object into which to place the message.

GetMessageString 함수를 재정의 하며 필요한 컨트롤의 Prompt String 을 실생 시간에 제어할 수 있다.
아래는 그 예이다.

void CMainFrame::GetMessageString(UINT nID, CString& rMessage) const
{
switch ( nID )
{
case ID_FILE_NEW:
theApp.m_Lang.GetMenuTip2( rMessage, _T("ID_FILE_NEW") );
return;
break;
}

return CFrameWnd::GetMessageString(nID, rMessage);
}




Original Post : http://neodreamer-dev.tistory.com/243