winAPI와 C를 사용하여 아주 간단한 창 하나 만들 때
글쓴이: kashmir / 작성시간: 화, 2006/02/14 - 6:05오전
요즘 MSVC++2005를 사용하여 C/C++를 배워볼까 하고 공부를 시작하였습니다.
WINAPI에 대하여 http://www.winprog.org/tutorial/에서 보고 있는데 다음의 코드를 빌드하여 실행하였을 때 이상한 결과가 나오네요.
#include <windows.h> const char g_szClassName[] = "myWindowClass"; // Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_LBUTTONDOWN: { char szFileName[MAX_PATH]; HINSTANCE hInstance = GetModuleHandle(NULL); GetModuleFileName(hInstance, szFileName, MAX_PATH); MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Step 3: The Message Loop while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }
아주 간단한 창 하나를 만드는데 창 제목이 이상하게 나옵니다. 만약 영어로 쓰면 이상한 중국어가 뜨고, 한글로 쓰면 네모로 나오네요.
뭐가 잘못된 걸까요 ? 아니면 언어 설정을 따로 해줘야 하는건가요 ?
Forums:
Properties에 가서 이것저것 찾다가Project Defau
Properties에 가서 이것저것 찾다가
Project Defaults에서 Character Set를 Unicode에서 Multi-Byte로 바꾸니까 잘 나오네요.
유니코드가 더 새로운 것이라 하던데 - 솔직히 뭔지 잘 모릅니다 - 어떻게 하면 Unicode로도 잘 나올까요 ? 아니면 이건 아직 초보한테는 어려운 욕심인가요 ?
TEXT라는 키워드 사용해 보셨는지요?그리고 wchar 같은 것을
TEXT라는 키워드 사용해 보셨는지요?
그리고 wchar 같은 것을 사용하는 것 같던데..
:)
-----------------
한글을 사랑합니다.
UNICODE로 만들기
소스를 보시면 아시겠지만 유니코드가 고려되지 않은 소스입니다.
lovian님 말씀대로 유니코드로 바꾸시려면
wchar_t value = L"알라뷰"; 식으로 사용하셔야만 합니다.
하지만 이건 문자열 리터럴에만 해당되는 얘기고 특정 구조체나 API는 와이드버전과 아스키버전으로 나뉩니다.
가령 위 소스에선 WNDCLASSEX구조체가
lpszMenuName;
lpszClassName;
라는 문자열포인터 멤버를 갖고 있기 때문에 W형과 A형으로 나뉩니다.
VC++는 #define UNICODE나 #define _UNICODE가 설정되어있으면 WNDCLASSEX를 WNDCLASSEXW로 대치하고 아니면 A로 대치합니다.
문자열(혹은 문자열포인터)를 인자로 받는 API의 경우도 이런식으로 처리됩니다.
유니코드로 컴파일을 하면 어느나라권 윈도우즈에서라도 글자가 이쁘게 표현되겠지만 단점으론 Win9x커널에선 동작하지 않습니다.
이유는 RegisterClass() API가 W형이 엔트리가 있긴 하지만 곧바로 0을 리턴해버립니다. 즉 9x계열에선 정상동작을 할수가 없습니다.
그럼 MBCS(Multi-byte Character Set)와 UNICODE, 두가지 버전의 소스를 관리해야할까요?
Windows에선 이를 해결하기 위한 몇가지 꽁수를 지원합니다.
위와 마찬가지로 문자형을 TCHAR을 쓰면 MBCS에선 char가, UNICODE에선 wchar_t로 바꿔줍니다.
그리고 문자열 리터럴은 L을 붙이는것보다 위에 lovian님께서 말씀하신대로
TCHAR *lpText = TEXT("한글최고");식으로 하시면 유니코드일때만 L을 붙여줍니다. 하지만 좀더 간편하게 __T("한글최고")나 _T("한글최고")로 단축매크로를 자주 사용합니다.
그리고 C의 문자열 처리 함수들도 strlen()대신 _tcslen()처럼 _t군을 호출해주어야합니다.(역시 마찬가지로 유니코드일땐 와이드버전을 호출해줍니다)
여기까지가 윈도우즈에서 유니코드컴파일하는 방법이였습니다.
아참, 그리고 윈도우즈의 유니코드 인코딩은 많은 분들께(그리고 저에게도)사랑받는 UTF-8은 아닙니다.
2바이트만을 사용하는 UCS-2입니다.
답변들 감사합니다. 아직 뭐가 뭔지 어리버리하지만 재밌네요 :)
답변들 감사합니다.
아직 뭐가 뭔지 어리버리하지만 재밌네요 :)
[quote]아참, 그리고 윈도우즈의 유니코드 인코딩은 많은 분들께(그리
UTF8 은 중간에 데이타를 건네주는 입장에서는 편리한 인코딩 이지만,
데이타를 직접 처리하는 입장에서는 불편한 인코딩 입니다..
직접 데이타를 처리할때에는 결국 UCS2 로 바꿔야
처리가 가능합니다..
아마도 VI 도 UTF8 파일을 읽어서 내부적으로 메모리에는 UCS2(wchar_t)
로 들고 있을껍니다.
utf8은 기존 ascii 코드를 처리하는 프로그램이나 라이브러리에서
utf8은 기존 ascii 코드를 처리하는 프로그램이나 라이브러리에서
유니코드를 별 문제 없이 처리하기 위해 고안한 인코딩 방식이죠.
[quote="Anonymous"]utf8은 기존 ascii 코드를 처리
그러게요. 사실 전 qt나 gtk에서 내부적으로 UCS-[24]를 사용하지 않고 UTF-8을 사용하도록 한 정책에 대해 좀 불만입니다.
IO용 인코딩으로서는 모를까 내부 처리용으론 (특히 CJK에게) UTF-8은 별로인거 같습니다.
댓글 달기