블로그 이미지
fiadot_old

칼퇴근을 위한 게임 서버 개발 방법론에 대한 심도있는 고찰 및 성찰을 위한 블로그!

Rss feed Tistory
Technical Article/펌 2003. 12. 9. 09:50

3d 디바이스에서 한글 출력

작성자 :  noerror
E 메일 :  noerror@hitel.net
조회수 :  1725
작성일 :  2003-02-10 06:29:14
파아일 :  hangul.zip
제에목 :  3d 디바이스에서 한글 출력
    
가볍게 일반적인 폴리곤 렌더링 환경에서 한글 출력하는 방법을 정리해보도록 하겠습니다.

1. 한글 출력

기본적인 컨셉은 플렛폼과 무관하게 적용 가능한 일반적인 방법의 한글 출력입니다. (d3d 전용, ps2 전용식이 아닌...)
한글은 영문과 다르게 글자의 조합이 많아서, 영문자처럼 글자 이미지를 모두 텍스처에 올려놓고 출력하기에 무리가 있습니다. 대부분 텍스처에 출력할 내용을 조합해서 그린 후에 화면에 해당 텍스처를 찍어주는 방식을 사용하는데, 이 방법에 대해서 가볍게 접근해보겠습니다.
직접 비디오 프레임 메모리에 접근하지 않아도 되기 때문에 대부분의 플렛폼에서 적용 가능하고, 가속을 받을 수 있기 때문에 속도 또한 빨라서 많이 사용되고 있습니다.

2. 한글 방식 선택

일반적으로 한글의 표현 방식은 조합형과 완성형으로 나눌 수 있습니다. 전자의 경우에는 각 조합별로 초성, 중성, 종성 세트를 가지고 글자를 조합해서 구현할 수 있으며, 후자는 모든 글자의 이미지 세트를 이용해서 구현할 수 있습니다. 각 장단점이 있지만 완성형 방식을 사용하기로 하겠습니다.
구지 제가 완성형을 사용하자고 얘기하고 이유는 아래와 같습니다.

- 일반적으로 완성형 폰트의 이미지가 조합형의 것보다 아름답다

논란의 여지는 있지만, 조합형 한글 폰트의 경우 과거 유행하던 16 x 16 크기의 폰트 이외에는 구하기도 힘들고, 좋은 폰트를 찾기가 쉽지 않기 때문에 상대적으로 퀄리티 높은 폰트들이 많이 있습니다. 완성형은 조합에 따른 각 벌을 고려하지 않아도 되기 때문에 이미지를 쉽게 얻어낼 수 있기 때문에, 윈도우상에서 다양한 크기의 벡터 폰트를 이미지로 변환하여 사용할 수 있고, 퀄리티 높은 상용폰트를 구입했을 때 별도의 작업없이 그대로 사용할 수도 있습니다.
그리고 대부분의 조합형 폰트는 단색 모노지만, 완성형은 간단한 프로그래밍으로 안티알리어싱된 폰트를 얻을 수 있습니다.

- 구현과 확장이 용이하다

완성형을 출력하고자 할 때는 한글 코드로 폰트의 인덱스 얻어내서 해당 문자를 출력하기만 하면 되기 때문에 별도의 조합 루틴이 필요없어 루틴이 간단해집니다. 그리고 단순히 코드와 폰트가 매칭되는 방식이기 때문에 중국어/일본어등으로 확장하고자 할 때 추가적인 작업이 많이 줄어듭니다.

- 실제로 용량이 크지 않다

저도 처음에 망설였던 것은 용량 문제였습니다만 실제로 폰트의 이미지는 부담이 될 정도의 크기는 아닙니다. 예를 들어 굴림12 폰트를 단색으로 메모리에 가지고 있을 때 필요한 메모리는 약 50 kb 입니다. 일반적인 16x16 조합형 폰트은 20k 보다 작지만 그 차이는 크지 않다고 할 수 있습니다. (20 메가와 50메가의 차이라면 심각하게 고려해봐야 할 것입니다만...) 퀄리티 좋은 20 크기의 궁서 4 그레이 폰트의 경우 약 270 kb 정도입니다.

이와 같은 이유로 완성형을 추천하지만 실제 구현에선 텍스처에 한글자 한글자 찍는 부분이후의 프로세스는 동일하기 때문에, 조합형을 선택한다고 해서 작업이 크게 틀려지지 않습니다.

3. 폰트 이미지 만들기

윈도우 환경에서 완성형 폰트는 쉽게 얻어낼 수 있습니다. 기본 API 의 TextOut 으로 출력할 수 있기 때문입니다. 비트맵 영역을 만들고 그곳에 한글자씩 출력해서 GetPixel 로 색을 읽는 식으로 간단하게 구현가능합니다. 첨부된 압축파일에 간단하게 만든 폰트 생성 프로그램의 소스를 참고하세요.
윈도우의 설정중에 "Smooth edges of screen fonts" 라는 옵션을 켤 경우 폰트는 안티알리어싱된 상태로 출력됩니다. 첨부된 소스의 샘플 폰트 익스포터에서는 이 이미지를 자체적인 폰트 형태로 저장하거나 이미 볼 수 있도록 bmp 로 출력해 줍니다.
경험해보시면 아시겠지만, 안티알리어싱이 된다고는 하지만 포토샵처럼 부드럽게 안티알리어싱되어 나오지 않습니다. (당연한 얘기지만 MS 워드도 캡쳐해서 보면 마찬가지임을 알 수 있습니다.) 화이트 데이란 게임을 만들 때는, 원하는 폰트사이즈보다 약 2배에서 4배정도의 큰 문자를 비트맵에 찍은 후에 다시 1/2 이나 1/4 사이즈로 필터링하며 리사이즈해서 비교적 양호한 폰트를 얻었습니다. (셈플에도 이것이 구현되어 있습니다만 적용하려면 winmain.cpp 에 있는 SCALE 매크로를 수정한 후에 다시 컴파일해야 합니다.)

index = (codehigh - 0xb0) * 94 + (codelow - 0xa1) + firstidx

관련 자료를 찾아보시면 알겠지만 일반적인 한글 코드로 인덱스를 구하는 공식은 위와 같습니다. 하지만 여기서 좀 다른 방식을 제안합니다.
위의 방식을 사용할 경우 다른 언어로 확장할 경우 인덱스 구하는 공식이 갱신되어야 하는 번거로움이 있습니다. 다국어를 고려할 경우 공식을 정의할 수 있게 만드는 것도 좋은 방법이지만 더욱 쉽고 간단한 방법으로 참조테이블을 만들어 사용할 것을 제안합니다.
인덱스에 해당하는 문자코드 리스트를 폰트에 같이 넣는 것입니다.

for(idx=0; refcode[idx] != code; idx++) ;

그러면 위와 같은 아주 간단한 방식으로 인덱스를 얻어낼 수 있을 것입니다. 일반적인 한글 코드의 영역이 0xb0a1 에서 0xc8fe 뿐 아니라 모든 영역을 사용할 수 있기 때문에 한자를 추가하거나 일어 / 중국어등의 폰트등도 만들 수 있습니다. 폰트의 코드가 일치하는 글자를 출력하는 식이기 때문에 텍스트가 일어이고 폰트가 일어이면 출력 루틴을 전혀 고치지 않고도 처리가 가능해집니다. (unicode 출력하는 것도 필요하다면 구현 가능할 것입니다. )
단, 위의 방식은 글자를 일일이 찾아야 하기 때문에 비효율적인데, 샘플에서의 폰트처럼 폰트 이미지들이 코드 순서대로 소팅되어 있다면 이진 검색으로 빠르게 해당 인덱스를 찾을 수 있습니다.
코드는 첫바이트가 의미상 일반적인 상위 비트에 해당하기 때문에 (bigendian 으로 읽은 것 처럼) 상하위 바이트를 바꿔서 코드를 바꾸고 있으니 참고하세요.

폰트를 만드는 샘플 소스에서 ExportFontThread 부분에 한글 코드들을 추가하는 부분이 있는 데, 그 부분을 수정하면 일본어나 중국어 코드들의 해당 폰트도 얻을 수 있을 것입니다. 그 소스에는 한글 폰트 (0xb0a1 ~ 0xc8fe)와 기역 같은 미완성된 낯자들을 포함하는 글자 영역(0xa4a1 에서 0xa4fe)의 폰트들을 출력하도록 되어 있습니다. (낯자들을 추가하면 IME 등의 입력중인 글자 코드도 화면에 출력할 수 있습니다.)

폰트는 그냥 간단하게 만들기 위해 4칼라로 고정했고, 폰트 영역 최적화 등은 하지 않았고, 툴도 무지막지하게 간단하게 작성했습니다. (툴 만들기엔 영 소질이 없어서...)

4. 폰트 출력하기

폰트를 텍스처에 찍고 그 영역을 저장해서 화면에 출력만 하면 됩니다만 한글자 한글자를 사전식으로 텍스처에 적어놓고 폴리곤화해서 찍는 방식이 아니라면 문제가 생깁니다. (일반적으로는 그 방법은 많이는 사용하지 않는 거 같습니다. - 100글자만 되도 최소한 삼각형 200개는 찍어야 된다는 계산이 되니까 경우에 따라선 좀 비효율적이 될 수도 있습니다.)

당연한 얘기지만 각 문장별로 텍스처를 할당할 수는 없기 때문에, 몇 장의 텍스처를 작업용으로 할당해서 빡빡하게 순서대로 적어야 할 것입니다. (이상적인 것은 가장 적은 텍스처에 가장 많은 글자를 적는 것일 겁니다.) 이때 다음과 같은 문제가 발생합니다.

- 문장이 작업용 텍스처의 가로 길이보다 길다
- 문장이 텍스처 다음 페이지로 넘어간다.

텍스처의 크기를 또 무한정 크게 잡을 수도 없기 때문에 첫번째 문제가 발생합니다. (가로가 20픽셀정도 되는 글자라면 10자만 되어도 200픽셀이 되기 때문에, 텍스처 가로 사이즈 이하로 문장길이를 제한하면 큰 제약이 되겠죠.)
당연한 얘기지만 문장을 여러 개로 잘라야 합니다. 만약 출력하고자 하는 내용이 "평생공짜왕창할인"인데, 6글자정도밖에 출력할 수 없다면

++++++++++++
++++++++++++
평생공짜왕창
할인++++++++
++++++++++++

식으로 텍스처에 쓰고 "평생공짜왕창"와 "할인"을 찍어야 할 것입니다. 여기서 자르는 방식은 두 가지로 나눌 수 있습니다. 픽셀단위로 자르는 방식과, 문자단위로 자르는 방식입니다.
만약 "아"란 글자에서 잘린다면 전자의 방식은 그 라인에 'ㅇ'이 다음 라인에 'ㅏ'가 될 수 있는 것이고, 후자의 방식은 "아" 전까지가 그 라인이고 "아"를 포함한 나머지 문장이 다음 라인이 되는 것입니다. 전자는 텍스처에 가로로 꽉꽉 채울 수 있기 때문에 더 많은 내용을 포함할 수 있지만 출력시 정교하게 연결하기가 쉽지 않다는 단덤이 있습니다. (첨부된 셈플에선 비교해볼 수 있도록 두 가지 모두 구현해 놓았는 데, _SPLIT_CHAR_ 를 정의하면 전자의 방식으로 처리됩니다.)

계속해서 다음 라인으로 넘어가다 보면 더 이상 텍스처에 적을 곳이 없는 경우가 생기는데, 이 때 앞에서 얘기한 두 번째 문제가 발생합니다. 이 경우에는 다음 텍스처에서 그리기를 계속하면 됩니다.

여기선 기본적인 매니징을 해야 하는 데, 만약 NPC가 10분동안 계속해서 얘기를 한다고 했을 때 만약 출력하는 모든 내용을 텍스처에 적으려면 엄청나게 많은 텍스처가 필요할 것입니다. 물론 그럴 필요가 없겠고 다음과 같은 원칙을 두면 될 것이다.

- 이미 텍스처에 적은 내용은 다시 올리지 않고 이전에 작성한 것을 화면에 표시한다
- 과거에 찍은 것들 중에 현재 사용되지 않는 것은 삭제한다

이런 식으로 텍스처를 반복해서 사용하면 적은 수의 텍스처만 사용해서 처리를 할 수 있습니다. (최대 문장이 꽉차는 텍스처보다 한 장정도 많은 것이 적당하다고 생각됩니다.) 아주 난이도가 있는 것은 아니지만 문장의 길이를 미리 예측할 수 없는 경우- 온라인 게임처럼 -에는 좀 더 신중한 처리를 해야 할 것입니다. 텍스처는 3장인데 4장분을 출력하려고 하면 문제가 반드시 생기기 때문입니다. (셈플에서는 m_sparetex 라는 것으로 처리를 했습니다만 깔끔하게는 처리하기는 힘드네요.)

여기서 "한 장 크게 잡고 텍스처 갱신하고 화면에 찍고, 다시 그 위에 찍고 다시 화면에 찍고 하면 안되냐 ?"고 하실 수 있는 데, 특정 하드웨어가 아니라면 정상적인 실행을 보장할 수 없는 방법입니다. (마지막에 갱신된 내용으로 모두 찍힐 가능성이 높습니다.)

텍스처에 올려서 화면에 찍을 때는 잘린 걸 순서대로 잘 이어 붙이는 거 외엔 특별히 추가적으로 생각할 것이 없지만, 찍을 때 텍스처 블랜드 방식을 잘 생각해야 합니다.
밝은 글씨를 찍을 때는 가산 (DEST + SRC[tex * color]) 모드로 찍으면 됩니다. 기본적으로 텍스처에 글자는 흰색, 바탕은 검정색이므로 더하게 되면 검정색 부분은 찍히지 않으므로 흰색 글씨 부분만 찍히게 됩니다. 그리고 텍스처가 흰색이므로 원하는 색을 곱해주면 여러가지 색으로 찍을 수 있습니다. (1 * color = color)
그리고 어둡게 찍고자 한다면 인버스 멀티플라이 (DEST * (1 - SRC[tex * color])) 로 찍으면 됩니다. 실제로 인버스 멀티플라이 모드에선 검정색 부분이 흰색이 되어 찍히지 않고 (DEST * (1 - 0) = DEST) 흰색이 검정색이 되어 그 부분이 어두워지게 됩니다. (말로는 좀 힘드네요.) 만약 흰색 바탕에 초록색의 글씨를 쓰고 싶다면 rgb는 0x00ff00 을 인버스한 0xff00ff 값으로 설정해야 합니다.
인버스 멀티플라이 모드는 어두워지는 부분에 색을 설정할 수 있기 때문에 그림자 찍을 때 많이 사용됩니다. (색을 안 줄 경우 그냥 멀티플라이 (DEST * SRC) 로도 처리할 수 있기 때문에 특별한 의도가 아니면 많이는 사용되지 않는 블랜딩 방법이긴 합니다.)

5. 셈플 설명

fontexp 프로젝트는 폰트를 만드는 파일로, 흐름만 참고하신다면 큰 어려움없이 필요하신 것들을 만드실 수 있을 것입니다.

hangul 프로젝트는 실제 폰트를 출력하는 셈플로 d3d 와 opengl 디바이스에 맞춰져 있습니다. 디바이스는 적당히 껴다 맞춘 것이니 그 부분에는 큰 의미를 두지 마시길 바랍니다. (테스트 코드들 적당히 지우고 하다 보니 실제로 돌아가는 거 말고는 문제가 있을 것입니다.)
실제코드는 font 쪽입니다. 내용이 섞이면 알아보기 힘들어 질 거 같아 의미별로 font 와 텍스처에 폰트를 찍는 fontworkspace 를 나누었고, 실제로 fontmanager 에서 이 두 객체를 이용해 출력하게 했습니다. (fontworkspace 하나에 font 여러 개를 사용할 수 있도록 구성했습니다. - 크게 필요한 기능은 아니지만...)
sample.cpp 에 _D3D_ 정의한 부분 삭제하고 컴파일 하면 opengl 로 작동합니다.

6. 마무리

폰트의 루틴이긴 하지만 텍스처의 일부분을 출력하는 개념의 일반적인 오버레이(2d) 루틴들과 거의 비슷합니다. 아이콘이나 상태창, 아이템들도 비슷하게 관리하고 처리할 수 있을 겁니다. (가능한 화면에 찍지 않는 것들은 텍스처에 올리지 않는 것이 전체적인 성능 향상에 도움이 될 것입니다.)

그 정도까지 필요할까 싶지만 동적으로 폰트에 문자셋을 추가하는 식으로 루틴을 작성하고, IME 루틴을 잘 조합해두면 전혀 모르는 나라에서도 게임을 그대로 즐길 수 있을 지도 모르곘습니다.

ps. 예전부터 d3d 만 접하다 이번 기회에 셈플 만들면서 opengl 해 봤는 데 API가 쉽고 간단하게 잘 되어있네요. (저에겐 직관적이고 좋네요.) 앞으론 공부하고 테스트할 땐 opengl을 더 선호할 거 같습니다. 좋습니다.


  
| 이전글 | 다음글 | 리스트로 | 답글쓰기 | 수정 | 삭제 |  

noerror 폰트 뽑은 셈플 : http://digibath.com/noerror/download/gulim12.gif 2003/04/13


noerror 버퍼에 작성하는 두가지 방법 셈플 : http://digibath.com/noerror/download/font.gif 2003/04/13


아노아 감사합니다 ㅠ _-) 잘쓰겠습니다. 2003/05/20


흠.. 뷁이 출력이...... 2003/08/05


noerror http://www.w3c.or.kr/i18n/hangul-i18n/ko-code.html 페이지 Microsoft의 통합형 한글에 추가코드까지 추출한 폰트를 사용해야 찍힙니다 ^^ 2003/08/25


noerror 참고로, 일본어 출력의 경우 http://www.kanzaki.com/docs/jcode.html 참고하셔서 JIS 코드 영역을 뽑으면 됩니다 2003/08/25


perpet 폰트사이즈가 다른것을 2개를 쓰려고 하면 font 클래스와 fontworkspace 클래스를 각각 2개씩만들어야 하고. fontworkspace클래스 하나에 font클래스2개식으로 하려면 폰트높이값이 가변이기때문에 쓸때마다 항상높이를 체크해서 처리를 해주어야 하네요..참고하세요..하여튼 잘쓰고 있습니다..감사..^^ 2003/09/08


자갈공명 파아일, 제에목...^^;;; 드래그해서 퍼가다가 ...잘쓰겠습니다..^^ 2003/09/24




[출처]

http://www.gamecode.org/article.php3?no=1501&page=0¤t=0&field=tip
,
Technical Article/펌 2003. 9. 16. 11:12

[아파치] 사용자 인증 - by .htaccess & .htpasswd

06 사용자 인증 - by .htaccess & .htpasswd

htpasswd를 이용한 사용자 인증
password를 묻는 대화상자(dialogue box)는 cgi 나 java script으로 만든 것이 아닌 APACHE httpd Server 데몬과, 사용자가 만드는 .htaccess 화일과 .htpasswd 화일을이용한 웹서버의 기본 인증 절차에 의한 것입니다.

이 두 개의 화일들을 패스워드를 걸 페이지가 있는 디렉토리에 두면, 외부인이 브라우저로 그 디렉토리에 있는 화일들(HTML화일들)에 접근을 할 때, 패스워드를 묻는 대화상자를 내보내게 합니다.

.htaccess 파일 만들기
- 인증 하고 싶은 디렉토리에 .htaccess라는 화일을 만들어서 업로드 하면 됩니다.
- .htaccess화일에 다음과 같은 내용을 입력하고 아스키모드로 업로드 합니다.
반드시 "AuthName 과 AuthUserFile" 만 변경하고 나머지는 그대로 둡니다.

AuthName "패스워드박스에 나타나는 메시지" (반드시 따옴표 입력)
AuthType Basic
AuthUserFile /home/LoginID/public_html/admin/.htpasswd (절대경로로)
AuthGroupFile /dev/null
<Limit GET POST>
require valid-user
</Limit>

Server Error가 나는 경우 대부분 AuthUserFiles의 잘못된작성입니다.
" ErrorDocument 401 "the text you want.. "

* 엔터프라이즈(enterprise)서버에서는 .htaccess파일이 아니라 nsconfig파일을 사용하며 위의 사항과 다릅니다. 다음과 같이 .nsconfig 파일을 작성해 줍니다.

<Files *>
RequireAuth userfile=/path/.nspasswd realm="Private Directory"
</Files>
path는 .nspasswd 파일이 있는 물리적 경로입니다. .nspasswd파일은 아래의 htpasswd과 같은 형태로 만들어 줍니다.

.htpasswd 화일만들기 (첫 사용자 ID만들기)
- .htpasswd는 사용자ID와 패스워드가 있는 파일입니다.
- 다른이름으로 설정할 수 있으나 .htaccess의 경로와 일치 해야합니다.
- .htpasswd를 만들기 위해서는 htpasswd라는 프로그램을 사용해야 하는데, 보통 리눅스Linux용 htpasswd는 /usr/sbin 또는 /usr/bin 디렉토리에 있습니다.

1. $ /usr/sbin/htpasswd -c .htpasswd ID_name 명령을 줍니다.
(최초에는 반드시 -c 옵션을 줍니다.)
2. New password: 로그인 할 비밀번호 입력.
3. Re-type new password: 재입력.
4.Adding password for user admin 성공 한 메세지.

사용자 ID 추가하기
- $ /usr/sbin/htpasswd .htpasswd ID_name2 명령을 줍니다.
(-c를 빼고 적어야 됩니다.-c 옵션 추가시 기존 ID는 지워집니다.)
- 암호를 두 번 입력해주면 됩니다.

위와 같이 하면 .htpasswd 파일에 사용자 아이디와 암호화된 패스워드가 저장 됩니다. 이제 .htpasswd 에 입력된 사용자만 해당 디렉토리에 접근할 수 있으며 한 번 로그인 된 브라우저를 재 접속 할 때 암호 창이 뜨지 않고 그냥 접속이 됩니다. 테스트 하기 위해 선 한 번 로그인 된 브라우저를 닫고 새 브라우저를 열고 확인 합니다

로그인 실패시 메시지, 다른 Url로 리디렉션 설정하기
- .htaccess 사용시 아파치 서버의 access.conf파일의 해당 디렉토리에 대한 Allowoverride를 FileInfo로 설정변경해주어야 합니다.
- 그런다음 .htaccess 파일에 원하는 내용 또는 리디렉션할 Url을 맨 앞줄에 추가합니다.
예: ErrorDocument 401 "the text you want.. "
예: ErrorDocument 401 /~yourID/subscription.html "
예: ErrorDocument 401 http://other.com/otherpage.html

- 시스템 관리자의 경우 srm.conf의 마지막줄에 추가하면 됩니다.
예: ErrorDocument 401 "The text you want to show....
예: ErrorDocument 401 /subscription.html


링크 -
http://www.cgkim.co.kr/main.html
,
Technical Article 2003. 8. 27. 11:47

[MFC] 프로퍼티 시트 기본 버튼 이름 바꾸기

Property Sheet에는 네개의 버튼이 있죠?

지우구 싶다면, ShowWindow(SW_HIDE)하면 될테고...
"" 이름을 바꾸고 싶다면, SetWindowText("어쩌구") 하면 되겠지요?

예를 들어서...
GetDlgItem(ID_WIZBACK)->EnableWindow(FALSE);               // disable 시키기
"" SetDlgItemText(ID_WIZNEXT,"다음다음");                                   // 이름 바꾸기
GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);               // 안보이게 하기
GetDlgItem(IDHELP)->EnableWindow(FALSE);                        // disable 시키기

이런식으로다 말이죠~

,
Technical Article/펌 2003. 8. 26. 10:35

[팁] Index Seed값 초기화

제목 : DB 순번 초기화  
다음은 jobs 테이블의 현재 ID 값을 30으로 설정하는 예제입니다.

USE pubs
GO
DBCC CHECKIDENT (jobs, RESEED, 30)
GO

'30' 대신에 '0' 으로 하시면 됩니다.

테이블 내용 삭제시에 truncate table 로 삭제하셔도 됩니다.



> 손님 님이 쓰신  글
> ----------------------------------------------------------
> test DB(Table)를 만든 후
> 올렸던 글들을 모두 삭제하였는데
> 순번은 최종 번호 이후의 순번부터 번호가 올라갑니다.
>
> 어떻게 1번부터 다시 시작할 수 는 없을까요?
>
> 기존 Table을 삭제하고 다시 만들어야 하는지 정말 궁급합니다.
>
> 꼭
,
Technical Article/펌 2003. 8. 6. 10:31

[펌] Windows UI questions에대한 Tip 정리.

번역 : http://www.korone.net/bbs/view.php?id=prog_mfc&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=14


Windows UI questions 2003/07/28 , 조회수 : 488 hits  
작성자 : korone  

본내용은, Codeproject의 The Code Project Visual C++ Forum FAQ을 보고 조병완이 정리한 문서입니다.

4.1. JPGs,PNGs, 또는 그밖의 그래픽 파일 포맷을 Load하거나 Save하는 방법
GDI+ 또는 paintlib, imageMagick, ImageLibrary를 이용하면 된다.
GDI+에 대한 예제는 CodeProject의 "Simple class for drawing pictures."의 내용을 참고하면 된다.

4.2. Dialog에 Background를 설정하거나, 그림을 Background로 설정하는방법
WM_ERASEBKGND 메세지를 재정의 하면 된다.
이에 대한 예제는 MSDN에 "WM_ERASEBKGND"라고 검색하면 몇가지 예제를
확인할 수 있다.

4.3 Dialog에 작업이 길어져서 사용자에게 Cancel버튼을 통한 중지(Abort)를 할 수 있도록 하고 싶은데, 어떻게 해야할까?
싱글 쓰레드(Single-threaded) 실행중에는 Mouse의 응답이 발생하지 않는데,
이는 Message pumping이 현재 실행중인 작업에 영향을 받아 동작하지 않기 때문이다.
이의 해결을 위해 두가지 방법이 존재하는데, Work Thread로 작업을 처리하거나,
작업이 진행되는 동안, Message pumping을 하게 해 주면 된다.
첫번째 방법은 CodeProject "Threads, Processes & Inter-Process Communication"의 섹션을 참조하면 되며
두번째 방법은, 작업이 길어지는 부분의 Loop에 직접 Message Pumping을 해주는 코드를 삽입해 주면 된다.
void ProcessMessages()
{
   CWinApp* pApp = AfxGetApp();
   MSG msg;

   while ( PeekMessage ( &msg, NULL, 0, 0, PM_NOREMOVE ))
       pApp->PumpMessage();
}
이와 같은 함수를 정의해둔뒤에 직접 호출해 주면 된다.

4.4 현재 프로그램의 커서를 바꾸는 방법
WM_SETCURSOR의 메세지를 재정의 해주고, 그 함수안에 SetCursor()를 호출하여 커서를 바꿀 수 있다.
WM_SETCURSOR 메세지의 경우, 마우스가 움직일때마다 발생되는 매우빈번한 메세지 이므로, 이 함수내에서 동작을 느리게 하는 작업은 피하는것이 좋다.
(예, 파일처리등...)

4.5 현재 윈도우를 감추는 방법
보여줄때에는 아래의 함수의 인자에 SW_SHOW를 넣고, 감출때는 SW_HIDE를
써주면 된다.
// MFC:
  wndYourWindow.ShowWindow ( SW_SHOW );

// Win32 API:
  ShowWindow ( hwndYourWindow, SW_SHOW );

4.6 Dialog 내의 Control(button, edit box, etc...)을 Enable, Disable 시키는 방법
아래의 함수 인자에 FALSE, TRUE를 설정해 준다.
FALSE:Disable, TRUE:Enable
// MFC:
  wndYourControl.EnableWindow ( FALSE );

// Win32 API:
  EnableWindow ( hwndYourControl, FALSE );

4.7 다른윈도우 보다 가장 최상위로 보이게 하는방법
// MFC:
  wndYourWindow.SetWindowPos ( &wndTopMost, 0, 0, 0, 0, 0,
                               SWP_NOMOVE|SWP_NOSIZE );

// Win32 API:
  SetWindowPos ( hwndYourWindow, HWND_TOPMOST, 0, 0, 0, 0,
                 SWP_NOMOVE|SWP_NOSIZE );

다시 원래대로 돌리는방법
// MFC:
  wndYourWindow.SetWindowPos ( &wndNoTopMost, 0, 0, 0, 0,
                               SWP_NOMOVE|SWP_NOSIZE );

// Win32 API:
  SetWindowPos ( hwndYourWindow, HWND_NOTOPMOST, 0, 0, 0, 0,
                 SWP_NOMOVE|SWP_NOSIZE );

4.8 List Control의 Report모드에서 한줄을 모두 선택하게 하는 방법
// MFC:
  wndYourList.SetExtendedStyle ( LVS_EX_FULLROWSELECT );

// Win32 API:
  ListView_SetExtendedListViewStyle ( hwndYourList, LVS_EX_FULLROWSELECT );

4.9 Static Control의 Background를 바꾸는 방법
Win32일때에는 WM_CTLCOLORSTATIC메세지를 핸들링하면 되고
// Win32 API:
LRESULT CALLBACK YourDlgProc(HWND hDlg, UINT message,
                             WPARAM wParam, LPARAM lParam)
{
static HBRUSH hbrBkcolor;

    switch (message)
        {
        case WM_INITDIALOG:
            hbrBkcolor = CreateSolidBrush ( RGB(255,0,0) );
            return TRUE;
        break;

        case WM_CTLCOLORSTATIC:
            {
            HDC hdc = (HDC) wParam;
            HWND hwndStatic = (HWND) lParam;

            if ( hwndStatic == GetDlgItem ( hDlg, IDC_LABEL1 ))
                {
                SetBkMode ( hdc, TRANSPARENT );
                return (LRESULT) hbrBkcolor;
                }
            }
        break;
        // ...
        }

    return FALSE;
}

MFC일때에는 WM_CTLCOLOR메세지를 핸들링 하면 된다.
// MFC:
HBRUSH CYourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
    if ( pWnd->GetSafeHwnd() == GetDlgItem(IDC_LABEL1)->GetSafeHwnd() &&
         CTLCOLOR_STATIC == nCtlColor )
        {
        // m_bkbrush is a CBrush member variable
        m_bkbrush.CreateSolidBrush ( RGB(255,0,0) );

        pDC->SetBkMode ( TRANSPARENT );
        return m_bkbrush;
        }

    return hbr;
}

CDC::SetBkMode()함수는 text를 출력할때, 투명하게(transparently) 만든다.
이때 text의 background는 gray색으로 보여주게 되는데, 만약 다른 배경색을 원한다면 CDC:SetBkColor()를 이용해서 바꾼다.

4.10 List Control의 특정Row를 선택되게 하는 방법
nItemToSelect이 변수에 원하는 Row를 써주면 된다.
// MFC:
  wndYourList.SetItemState ( nItemToSelect, LVIS_SELECTED,
                             LVIS_SELECTED );

// Win32 API:
  ListView_SetItemState ( hwndYourList, nItemToSelect,
                          LVIS_SELECTED, LVIS_SELECTED );
만약, 해당위치로 Foucs를 위치시키려면 LVIS_FOCUSED를 설정해 주면 된다.

4.11 내가 생성한 List 또는 Tree Control이 Debug 모드 에서는 잘 되지만, Release모드에서는 되지 않는이유는?
LVITEM나 TVINSERTSTRUCT의 구조체가 제대로 초기화 되지 않아서 발생되는 문제이다.  아래와 같이 초기화시킨후 사용하면 된다.
LVITEM lvi = {0};
TVINSERTSTRUCT tvins = {0};
더 자세한 사항은 "Surviving the Release Build."를 참조하면 된다.

4.12 Multi-line edit control에서 newline을 집어넣기
"\r\n" 이렇게 써주면 된다. 만약 "\r" 이나 "\n" 이나 "\n\r"이렇게 써준다면
Control에 작은 블락(litte blocks)을 볼 수 있다.

4.13 사용자가 선택한 디렉토리 확인하는 방법은?
SHBrowseForFolder() API를 사용한다. MSDN에 "SHBrowseForFolder"라고 검색한다면 이와 관련된 몇가지 예제를 찾아볼 수 있다.
Codeproject의 "this canned search"를 보면 이와 관련된 예제를 찾아볼 수 있다.

4.14 현재 마우스가 위치한 곳의 Text를 읽어오는 방법
화면에 Text가 표시된것은 bitmap이기 때문에 읽을수 있는 글자가 아니다. 따라서 Text를 일고싶다면, OCR(optical character recognition)을 이용해서 bitmap을 글자로 바꾸는 작업을 해야한다.

4.15 Frame Window나 Dialog의 Title 설정하는 방법
// MFC:
  wndYourWindow.SetWindowText, _T("New text here") );

// Win32 API:
  SetWindowText ( hwndYourWindow, _T("New text here") );

4.16 Frame Window나 Dialog의 Icon을 설정하는 방법
먼저 프로그램의 resource로 등록한다음 윈도우의 현재 아이콘으로 불러오면 된다.
이때 사용되는 아이콘은 large(32x32), small(16x16)두가지인데.
large 아이콘은 Alt-Tab 윈도우를 눌렀을때 표시되는 아이콘이고, small 아이콘은
타이틀이나 아래 작업표시줄에 표시되는 아이콘이다.

MFC의 AppWizard는 small icon을 설정하는 코드가 생성되지 않는다. 이는 LoadIcon이 32x32아이콘의 생성만을 지원하기 때문이다.
따라서, 16x16 즉 small 아이콘을 생성하려면 LoadImage()를 이용해서 생성해야한다.
// MFC:
HICON hLargeIcon = AfxGetApp()->LoadIcon ( IDI_NEW_ICON );
HICON hSmallIcon = (HICON) ::LoadImage ( AfxGetResourceHandle(),
                                         MAKEINTRESOURCE(IDI_NEW_ICON),
                                         IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );

  wndYourWindow.SetIcon ( hLargeIcon, TRUE );
  wndYourWindow.SetIcon ( hSmallIcon, FALSE );

// Win32 API:
HICON hLargeIcon = LoadIcon ( hinstYourModuleInstance,
                              MAKEINTRESOURCE(IDI_NEW_ICON) );
HICON hSmallIcon = (HICON) LoadImage ( hinstYourModuleInstance,
                                       MAKEINTRESOURCE(IDI_NEW_ICON),
                                       IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );

  SendMessage ( hwndYourWindow, WM_SETICON, ICON_BIG, hLargeIcon );
  SendMessage ( hwndYourWindow, WM_SETICON, ICON_SMALL, hSmallIcon );

4.17 다른 프로세스로 실행중인 프로그램의 EditBox에서 Text를 가지고 오는법
다른 프로세서로 실행중인 프로그램의 경우 GetWindowText() 다르게 동작된다.
이의 해결책은 MSDN Magazine의 내용 첫 질문내용중에 그 답을 찾을 수가 있다.

4.18 윈도우 사이즈를 사용자가 지정한 크기로 제한시키는(restrict) 방법
WM_GETMINMAXINFO 메세지를 핸들링 한다음 lParam의 값을 MINMAXINFO값으로 casting하여 아래와 같이 원하는값으로 설정한다.
LRESULT OnGetMinMaxInfo ( WPARAM wParam, LPARAM lParam )
{
MINMAXINFO* pmmi = (MINMAXINFO*) lParam;

  pmmi->ptMinTrackSize.x = 100;
  pmmi->ptMinTrackSize.y = 150;
  pmmi->ptMaxTrackSize.x = 600;
  pmmi->ptMaxTrackSize.y = 400;

  return 0;
}

정리끝.
위 내용에 대한 궁금증이나, 오역사항에 있어서 의견있으신분 글 남겨주시거나
korone@korone.net으로 메일 주세요.


    

어라!  Button의 배경색 바꾸는 법 없냐?
눈깔 책(?)에서도 Static에 대해서는 있는디.. Button을 가지고 노는건 엄떠라.  2003/08/04


korone  단순 배경색을 바꾸고 싶은거냐?
http://www.codeguru.com/buttonctrl/color_button.shtml 이것을 참조하고.

만약, 배경그림을 바꾸고 싶으면
CBitmapButton을 이용하면 된다. ^^
,
Technical Article/펌 2003. 7. 23. 01:22

마이크로소프트 잡지(DirectX강좌-실전강의실)

Direct3D 8
2001년 2월~4월
2002년 3월~4월

Direct3D 9
2003년 2월~x

DirectDraw 7
2002년 6월~9월
,
Technical Article/펌 2003. 7. 18. 15:45

TXT로 result set 저장!

> DTC 를 이용하여 파일 내보내는 방식이 아니 다른 방식으로 파일 만드는 법을 알고 싶습니
다.
>
> SELECT * FROM AAA 한 결과를 파일로 바로 저장 할수 있는 방법이 있는지 궁금 합니다.
>
> 제가  마이크로에서 제공하는 TDC 를 이용 할려구 하는데요..
>
> TDC 는 .TXT 파일을 바운딩 하는 방법만 제가 알고 있는데..
>
> 쿼리한 결과를 .TXT 파일로 저장 했다가..
> TDC 에서 .TXT 파일을 가지고 바운딩 처리 할려구 합니다.
>
> SQL 에서 쿼리문을 .TXT 파일로 바로 저장 할수 있는 방법을 좀 알려 주십시요...
>
> mybofb@coorditech.co.kr  메일 주소 입니다.
> 답변 부탁드립니다.


쿼리 분석기(Query Analyzer)를 이용하여 저장할 수 있습니다.
도구메뉴 -> 옵션  -> 결과 Tab 선택
    결과대상을  '파일결과로 저장...'을 선택
    결과출력형식 선택

쿼리를 실행하면 저장할 파일이름과 경로를 지정하는 Dialog 창이 뜹니다.
저장하시면 됩니다.(rpt 형식으로 저장됩니다. 확장자를 txt로 바꾸시면됩니다.)
,
Technical Article/펌 2003. 7. 17. 17:07

[펌] Using Ogg Vorbis with DirectSound 8

Using Ogg Vorbis with DirectSound 8
--------------------------------------------------------------------------------

based on the source found at
http://www.freelists.org/archives/directmusic/03-2003/fullthread1.html

Download This
oggclass.zip(http://www.icarusindie.com/devzone/downloads/oggclass.zip)



Setting up the Server
Add these files to your project
dsclass.cpp
dsclass.h

Libraries to include in your project
Ogg Vorbis SDK(http://www.vorbis.com/download_win.psp)

Link the following files to your project:
vorbisfile_static.lib
vorbis_static.lib
ogg_static
dsound.lib
Also be sure your include paths contain the SDK.

Features
Arbitrary number of sound buffers
Variable size buffers
Removed excess code that wasn't actually needed.

Sample source:

#include "dsclass.h"

...
        OggPlayer ogg;

        ogg.InitDirectSound(hWnd);

        ogg.OpenOgg("song.ogg"); //the first file loaded is put in buffer 0, the second in buffer 1, etc.
                                 //the included h file sets the number of buffers at 32
                                 //but there's no real limit.
                                 //The maximum size of the sound uncompressed is 60MB but that can
                                 //also be changed in the h file.

        ogg.Play(0,false);  //first argument is the buffer number.  
                            //the second argument is whether or not to loop the sound

        Ogg.IsPlaying(0); //if you want a sound to loop, call IsPlaying
                                  //with the buffer number every once in awhile (1 sec or more )
                                  //to make it loop.
                                  //This is a byproduct of the original source which didn't allow
                                  //for variable size buffers which resulted in the sound being
                                  //over but the DSound pointer not being at the end of the buffer
                                  //resulting in DSound not being able to loop them right.
                                  //In the play function you could simply set it to looping and
                                  //take out the loop handling in "IsPlaying."

        Ogg.Close();                  //clears all the buffers and DirectSound

...


Written by Ben Kucenski 2003
www.icarusindie.com  
,
Technical Article/펌 2003. 7. 16. 17:49

Reaction Quake 3 Replacement Model Guide

http://screenshots.rq3.com/bird/exporting_guide/guide.html
,
Technical Article/펌 2003. 7. 15. 17:15

[펌]온라인게임과 PC게임의 궁극적 차이

http://www.lordwhite.com/wwbd.htm
,
TOTAL TODAY