무식하게 소수 판별하는 방법


__int64 isPrime(__int64 n)

{

for(__int64 i=2;i<n;i++)

if(n%i==0)

return 0;

return 1;

}


__int64로하는 것은 큰 숫자 판별하기 위해서...

근데 사실 i7으로 돌려도 10개이상은 몇십분이상 걸린다...

그리고 그 이상으로 숫자가 커지면 기하급수적으로 시간이 걸림...

왜 암호화에서 소수를 사용하는지 알것만도 같다.

'Programming > C/C++' 카테고리의 다른 글

C++에서 복사생성자를 사용하는 이유.  (0) 2011.03.16
우분투(코분투) 10.04 버전 이상에서, Sun JDK를 설치 할 경우.
sudo apt-get install sun-java6-jdk
명령어로 하면, 안된다.

보통, 저렇게 하면, 됬었는데 10버전 이상에서는 안된다.
그러면, 어떻게 해야 되는지 찾아 보았다.

sudo add-apt-repository 

를 이용해서 서버를 추가 하면된다.
그래서 2~3개 해봤는데 안된다.

물론, 
sudo apt-get update는 해준다.

하지만 안된다.

결국, 불굴의 한국인으로서 해결책은 찾았다.

결과적으로 말하면, 서버가 바뀌었다. 그래서 백날 옛날 서버 주소를 repositroy에 추가 해봤자 안됬던거다.

그러므로 뭘 치면 되느냐?

sudo add-apt-repositroy ppa:ferramroberto/java

이거다.

후... 2시간동안 이것때문에 별짓을 다 했네.


설치환경 : 노트북, 코분투 11.04버전. 
오랜만에 올리는 프로그래밍 이다.
몇일에 걸쳐, 자바 기본문법 을때고, 이제 슬슬 졸업 작품을 준비하기 위해 통신 프로그램등을 공부하게 되었다. 그중에 가장 간단한 소켓 프로그램에 대해 포스팅 해보도록 하겠다.

우선 코드를 보자.



자잘한건. 뭐 넘어가도록 하고. 
여기서  신경 쓸 것은.

ServerSocket
Socket
socket.getInputStream();
DataInputStream
socket.getOutputStream();
DataOutputStream
Scanner scan = new Scanner(System.in);

din.readUTF();
dou.writeUTF(msg); 


뭐 이정도 일까?

우선 소켓 프로그래밍이란 것은. 내가 이해한 용도는 '버퍼' 이다. 스트림하고도 연관이 되겠지.
중간에 완충 역할을 해주는 것이라고 이해를 해준 것이다.
예전에 TCP/IP 소켓프로그래밍이란 책을 보면서 약간 이해를 했지만, 그래도 그저 아직은 중간 완충 해주는 '서비스'의 일종으로 이해하고 있다. 그정도면 아직까진 충분하지 않겠는가?

자, 그리고 InputStream과 OutputStream. 이 내용은 자바 기본 문법중 stream에 관한 것에대해서 공부를 해야 한다. 기본적인 바이트코드를 DataInputStream/DataOutputStream을 이용해서 우리가 읽을 수 있게 해준다고 생각해 주면 된다.

 잡 이야기는 여기까지 하도록 하고, 서버용 프로그램을 보도록 하자.
 우선 클라이언트와는 다르게 서버에서는 ServerSocket을 사용한다. 서버로서의 소켓을 정해줘야 갑과 을을 정해서 누가 주동적으로 역할을 수행할 지를 정하는 것이다.
 그리고 API 문서에 보면 수많은 생성자가 있지만, 이 프로그램에서는 그냥 9999라는 포트만을 넘겨줘서 생성해 주고 있다.
 그리고 나온 매소드중 accept()라는 매소드는. 다른 소켓이 server에 접속하기까지 포트를 열고 대기한다.  그리고 해당하는 새로운 소켓을 return 한다.

 그리고 din.readUTF()가 뭔가 하면, 우선 InputStream에 소켓의 getInputStream 메소드를 넘긴다. 소켓의 스트림에 들어있는 내용을 반환한다. 그리고 그것을 데이터 스트림에 대입하여 인간이 읽을 수 있도록 변환한다.

 아웃풋도 마찬가지의 이야기이다.

 거기에 있는 데이터를 UTF형식으로 하여 msg에 대입하라는 내용인 것이다.

 그리고 만약 그 내용이 exit면, dou.writeUTF("END") 즉, 클라이언트 측에 END라는 문자를 날리고 소켓 종료, 서버소켓 종료하고 반복문을 종료-> 프로그램 종료 를 하라는 이야기가 완성이 된다.

 만약 아니라고 한다면, server측에서도 하고 싶은 이야기를 건네 클라이언트 측에 전달하는 것이지 :) 

이번에는 클라이언트 측을 살펴보도록 하자. 



 가장 처음에 보면, 서버용 IP를 넣는 것이 보인다. 이것을 args로 받아도 되고, 아니면 따로 입력받도록 고쳐도 좋을 것 같다. 하지만, 우선 실험용이기 떄문에 임의로 입력을 했다.
 그리고 소켓을 생성한다. 앞에서 만들어 놨던 IP와 포트 9999를 이용한다.

 그 후 한 문장을 입력 받고, 서버에 전송한다. 그리고 대기 하다가 서버측에서 메시지가 도착하면 메시지에 디스플레이 하고, 그 문장이 (END)가 아니라면, 반복문을 계속하여 메시지를 전달한다.





사실 서버 측에서 쓰레드를 이용한 FULL duplex를 만들고 싶었으나, 콘솔용에서 FULL duplex는 뭔가 안맞다 싶었다. 완전히 만지려면, 콘솔 프로그램 자체를 바꿔야 한다.
 뭐, 버퍼를 이용해서 하는 방법이 있지만......... 자, 어서어서 다음꺼 해야지^^ㅋ 

'Programming > JAVA' 카테고리의 다른 글

우분투에서 SUN JDK 설치.  (0) 2012.03.01
HBRUSH CreateSolidBrush(COLORREF crColor);
HBRUSH CreateHatchBrush(int fnStyle, COLORREF crColor);

위에는 그냥 단색의 브러쉬
아래는 색칠하는 스타일을 정할수 있다.
HS_BDIAGONAL : 좌하향 줄무늬
HS_CROSS 바둑판
HS_DIAGCROSS 좌하향 및 우하향
HS_FDIAGONAL 우하향
HS_HORIZONTAL 수평선
HS_VERTICAL 수직선

'Programming > Visual C++' 카테고리의 다른 글

그래픽3. PEN  (0) 2011.06.30
그래픽2. StockObject  (0) 2011.06.30
그래픽 1. GDI Object  (0) 2011.06.30
기타. SendMessage - Message 강제 호출  (0) 2011.06.30
타이머.  (0) 2011.06.29

HPEN CreatePen(int fnPenStyle,int nWidth,COLORREF crColor);

fnPenStyle은 점선이냐 실선이냐, 실선은 얼마나 할꺼냐의문제. 단, nWidth!=1, PS_SOLID가 자동으로 선택된다.

PS_SOLID
PS_DASH
PS_DOT
PS_DASHDOT
PS_DASHDOTDOT


nWidth는 굵기.
1이 기본값이고
2,3으로 하면 두꺼워진다. 0으로 하면 무조건 1 pixel의 두께.

crColor
선의 색상을 정한다. COLORREF형. RGB매크로 함수를 사용하면 된다.

다음은 예제

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("First");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style = CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd = CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);

 while(GetMessage(&Message,NULL,0,0))
 {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 HPEN MyPen, OldPen;

 switch(iMessage)
 {
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  MyPen=(HPEN)CreatePen(PS_SOLID,5,RGB(0,0,255));
  (HBRUSH)SelectObject(hdc,GetStockObject(GRAY_BRUSH));
  SelectObject(hdc,MyPen);
  Rectangle(hdc,50,50,300,200);
  DeleteObject(MyPen);
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY : PostQuitMessage(0);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

여기서 한가지. CreatePen을 한경우에는 메모리를 할당해준것이기 때문에 DeleteObject를 해주어야한다.

'Programming > Visual C++' 카테고리의 다른 글

그래픽4. Brush  (0) 2011.06.30
그래픽2. StockObject  (0) 2011.06.30
그래픽 1. GDI Object  (0) 2011.06.30
기타. SendMessage - Message 강제 호출  (0) 2011.06.30
타이머.  (0) 2011.06.29

GDI에서 기본적으로 제공하는 Object.

HGDIOBJ GetStockObject(int fnObject);

BLACK_BRUSH
GRAY_BRUSH
NULL_BRUSH(투명)
WHITE_BRUSH
DKGRAY_BRUSH
LTGRAY_BRUSH
DC_BRUSH(색상 브러시, SetDCBrushColor로 색 설정)
BLACK_PEN
WHITE_PEN
NULL_PEN
DC_PEN(색상 펜, SetDCPenColor 함수로 설정)
ANSI_FIXED_FONT 고정폭 폰트
ANSI_VAR_FONT 가변폭 폰트
DEFAULT_PALETTE 시스템 기본 팔레트


사용 예

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("First");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style = CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd = CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);

 while(GetMessage(&Message,NULL,0,0))
 {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 HBRUSH MyBrush,OldBrush;

 switch(iMessage)
 {
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  (HBRUSH)SelectObject(hdc,GetStockObject(GRAY_BRUSH));
  Rectangle(hdc,50,50,300,200);
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY : PostQuitMessage(0);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

'Programming > Visual C++' 카테고리의 다른 글

그래픽4. Brush  (0) 2011.06.30
그래픽3. PEN  (0) 2011.06.30
그래픽 1. GDI Object  (0) 2011.06.30
기타. SendMessage - Message 강제 호출  (0) 2011.06.30
타이머.  (0) 2011.06.29
GDI(Graphic Device Interface) Object. 화면, 프린터등의 모든 출력 장치를 제어하는 윈도우즈 핵심 모듈중 하나.
 EX) 펜, 브러시, 비트맵, 폰트 등.

DC가 일종의 GDI를 모아놓은 것.
사용자는 DC를 사용할때 적절한 Object를 선택해서 사용할수 있다.(적절한 펜, 브러쉬, 폰트 등)
만약 선택하지 않으면 알아서 Default로 선택되는 것들도 있다.

펜 HPEN 선을 그릴때 사용, (Default)검정색의 가는 실선
브러시 HBRUSH 면을 채울때 사용 (Default) 흰색
폰트 HFONT 문자 출력에 사용되는 글꼴(Default)시스템 글꼴
비트맵 HBITMAP 비트맵 이미지 (Default)없음
팔레트 HPALETTE 색상을 선택할수 있는 팔레트 (Default)없음


'Programming > Visual C++' 카테고리의 다른 글

그래픽3. PEN  (0) 2011.06.30
그래픽2. StockObject  (0) 2011.06.30
기타. SendMessage - Message 강제 호출  (0) 2011.06.30
타이머.  (0) 2011.06.29
기타. WM_CREATE  (0) 2011.06.29
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam,LPARAM lParam);
강제로 메시지가 발생한것처럼 만든다.
Timer같은경우에도 함수 발생후 1초가 지나야 메시지가 발생하므로 그것을 강제로 하기위해서 필요하다.

case WM_CREATE:
SetTimer(hWnd,1,1000,NULL);
SendMessage(hWnd,WM_TIMER,1,0);

요롷게 해주면된다.

'Programming > Visual C++' 카테고리의 다른 글

그래픽2. StockObject  (0) 2011.06.30
그래픽 1. GDI Object  (0) 2011.06.30
타이머.  (0) 2011.06.29
기타. WM_CREATE  (0) 2011.06.29
입력5. 마우스  (0) 2011.06.29


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 SYSTEMTIME st;
 static TCHAR sTime[128];

 switch(iMessage)
 {
 case WM_CREATE:
  SetTimer(hWnd,1,1000,NULL);
  return 0;
 case WM_TIMER:
  GetLocalTime(&st);
  wsprintf(sTime,TEXT("지금 시간은 %d:%d:%d입니다."),st.wHour,st.wMinute,st.wSecond);
  InvalidateRect(hWnd,NULL,TRUE);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,100,100,sTime,lstrlen(sTime));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  KillTimer(hWnd,1);
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

자, 여기서
UINT SetTimer(HWND hWnd,UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
에 대해 알아보도록하자.

nIDEvent는 타이머의 번호를 지정한다.
uElapse는 타이머의 주기를 설정한다. 단위는 1/1000초. == 1초에 한번씩 타이머 메시지가 hWnd로 전달된다.
10000이면 10초에 한번씩 타이머 메시지가 발생한다.
TIMERPROC lpTimerFunc는 타이머 메시지가 발생할 때마다 호출될 함수를 지정. 사용하지 않을경우 NULL.

'Programming > Visual C++' 카테고리의 다른 글

그래픽 1. GDI Object  (0) 2011.06.30
기타. SendMessage - Message 강제 호출  (0) 2011.06.30
기타. WM_CREATE  (0) 2011.06.29
입력5. 마우스  (0) 2011.06.29
입력3. TranslateMessage  (0) 2011.06.29
WndProc에서 첫 번째로 처리하는 메시지로 윈도우가 처음 생성될 때 발생, 초기화에 이용.

'Programming > Visual C++' 카테고리의 다른 글

기타. SendMessage - Message 강제 호출  (0) 2011.06.30
타이머.  (0) 2011.06.29
입력5. 마우스  (0) 2011.06.29
입력3. TranslateMessage  (0) 2011.06.29
입력2. WM_KEYDOWN  (0) 2011.06.29
다음은 마우스 입력 메시지다. 직관적이라 잘 알수 있을듯.

WM_LBUTTONDOWN
WM_RBUTTONDOWN
WM_MBUTTONDOWN
WM_LBUTTONUP
WM_RBUTTONUP
WM_MBUTTONUP
WM_LBUTTONDBLCLK
WM_RBUTTONDBLCLK
WM_MBUTTONDBLCLK


 그리고 여기서 하나더, 마우스 메시지는 lParam의 상위 워드에 마우스 버튼이 눌러진, y좌표, 하위 워드에 x좌표를 가지며 좌표값을 검출해 내기 위해 HIWORD, LOWORD등의 매크로 함수를 사용한다. 즉 마우스 메시지가 발생한 위치의 조표는  (LOWORD(lParam),HIWORD(lParam))이 된다.

 또한 다중모니터의 경우 이 좌표값이 음수가 될수도 있다.

wParam에는 마우스 버튼의 상태와 키보드 조합키의 상태가 전달된다.

MK_CONTROL Ctrl버튼이 눌러져 있음
MK_LBUTTON 마우스 왼쪽버튼이 눌러져 있음.
MK_RBUTTON 마우스 오른쪽 버튼이 눌러져 있음.
MK_MBUTTON 마우스 중간버튼이 눌러져 있음.
MK_SHIFT Shift버튼이 눌러져 있음.

이외에도 마우스가 움직일때 전달되는 WM_MOUSEMOVE, 휠마우스 상태를 정해주는 WM_MOUSEWHEEL등이 있다.

'Programming > Visual C++' 카테고리의 다른 글

타이머.  (0) 2011.06.29
기타. WM_CREATE  (0) 2011.06.29
입력3. TranslateMessage  (0) 2011.06.29
입력2. WM_KEYDOWN  (0) 2011.06.29
입력1. WM_CHAR  (0) 2011.06.29
키보드에서 A라는 글자가 눌렀다 뗏을 경우.

발생하는 메시지는 순서대로
WM_KEYDOWN, WM_CHAR, WM_KEYUP이 발생한다.
하지만 사실 WM_CAHR는 사용자로부터 발생한것은 아니다. WM_KEYDOWN이 오면, 그값을 토대로 WM_CHAR를 발생시킨다. 이 발생시키는 것이 TranslateMessage다.
 이 TranslateMessage라는 놈은 많은 걸 보고 판단해서 WM_CHAR를 발생시킨다. 예를들어 눌렀을때의 Shift키라던가 Caps Lock라던가, 현재 운영체재의 언어설정이라던가 말이다.

'Programming > Visual C++' 카테고리의 다른 글

기타. WM_CREATE  (0) 2011.06.29
입력5. 마우스  (0) 2011.06.29
입력2. WM_KEYDOWN  (0) 2011.06.29
입력1. WM_CHAR  (0) 2011.06.29
출력5. MessageBox & MessageBeep  (0) 2011.06.28

WM_CHAR가 문자만 받는다면 WM_KEYDOWN은 문자이외에도 키보드가 눌리면 발생하는 이벤트 메시지다. 각각의 값은 다른데서 찾아보시고.
wParam값에 키보드가 눌러진 값이 반환이 된다.

다음은 WM_KEYDOWN의 예제이다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 static int x=100;
 static int y=100;

 switch(iMessage)
 {
 case WM_KEYDOWN:
  switch(wParam)
  {
  case VK_LEFT:
   x-=8;
   break;
  case VK_RIGHT:
   x+=8;
   break;
  case VK_UP:
   y-=8;
   break;
  case VK_DOWN:
   y+=8;
   break;
  }
  InvalidateRect(hWnd,NULL,TRUE);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,x,y,TEXT("A"),lstrlen(TEXT("A")));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
  }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
 }


그리고 다음 예제는 스페이스가 눌리면 A와 #이 토글되는 예제이다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 static BOOL sp_in=FALSE;
 static int x=100;
 static int y=100;
 LPCTSTR a=TEXT("A");

 switch(iMessage)
 {
 case WM_KEYDOWN:
  switch(wParam)
  {
  case VK_LEFT:
   x-=8;
   break;
  case VK_RIGHT:
   x+=8;
   break;
  case VK_UP:
   y-=8;
   break;
  case VK_DOWN:
   y+=8;
   break;
  case VK_SPACE:
   sp_in=!sp_in;
   break;
  }
  InvalidateRect(hWnd,NULL,TRUE);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  if(sp_in==FALSE)a=TEXT("A");
  else if(sp_in==TRUE) a=TEXT("#");
  TextOut(hdc,x,y,a,lstrlen(a));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
  }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
 }

'Programming > Visual C++' 카테고리의 다른 글

입력5. 마우스  (0) 2011.06.29
입력3. TranslateMessage  (0) 2011.06.29
입력1. WM_CHAR  (0) 2011.06.29
출력5. MessageBox & MessageBeep  (0) 2011.06.28
출력4. 기타  (0) 2011.06.28

 일반적으로 도스에서 입력하는걸 생각해보자. 그러면 생각할것없이 키보드가 갖고 있는 고유의 값을 받아서 프로그램에서 문자로 해석해 모니터로 쏴주면 된다.
 그럼 윈도우에서는 어떠한가? 멀티테스킹이란 것으로 윈도우의 여러개의 창들이 있고 내가 실행하고 있는 프로그램중에서도 내가 원하는 위치에 글자를 출력해야 한다.
 이렇게 어디에 글자를 출력할것인지 선택하는걸 "포커스"라고 한다.
 키보드에서 입력받은 문자는 "활성화"된 프로그램의 CP부터 글자가 출력이 된다.(기본적으로)

 활성화를 "선택" 이라고 보면 되고 포커스를"집중"이라고 생각하면 쉽다.

자, 그럼 WM_CHAR의 활용을 보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 static TCHAR str[256];
 int len;

 switch(iMessage)
 {
 case WM_CHAR:
  len=lstrlen(str);
  str[len]=(TCHAR)wParam;
  str[len+1]=0;
  InvalidateRect(hWnd,NULL,FALSE);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,100,100,str,lstrlen(str));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}


여기서 집중해야 할것은 음...
 case WM_CHAR:
  len=lstrlen(str);
  str[len]=(TCHAR)wParam;
  str[len+1]=0;
  InvalidateRect(hWnd,NULL,FALSE);
  return 0;

이정도면 충분할것 같군.

대충 해석을 해보자면, 정수형 len에 str의 현재 길이를 구한다.
가장 처음 상태에선 아무것도 없는 0이 반환이 되겠지?
그럼 str[0]에 wParam글자가 온다.
여기서 WM_CHAR메시지는 은 입력된 문자의 코드를 wParam으로 전달한다.

여담으로 lParam도 한번 보고 가자. WM_CHAR의 경우 lParam에는 비트별로
0~15비트에는 반복카운트,
16~23 스캔코드
24 : 오른쪽 Alt, 오른쪽 Ctrl등 101키에만 있는 확장키가 눌러졌을경우 1
25~28 : 미사용
29 : Alt키가 눌렸으면 1
30 : 메시지가 보내기전에 키가 눌러져 있었으면 1
31 : 키가 놓아지면 1, 눌러지면 0

자 여담은 여기서 마치도록 하고

  len=lstrlen(str);
  str[len]=(TCHAR)wParam;
  str[len+1]=0;

이걸 조금더 자세히 보자면,
str[0]에 글자가 들어가고 그다음 배열에 널을 넣어 문자의 종료를 알린다.
그리고 만약또다시 뭔가가 들어온다싶으면 lstrlen(str)==1 이되므로.
str[1]에 글자가 넣어진다. 그리고 str[2]에 널문자가 오게 되겠지.
한글자 한글자씩 문자를 넣고 널문자를 하나씩 미루는 형식으로 되어있다.

자, 여기서 끝내고 글자가 짠! 하고 나타나면 좋겠지만, 하나 부족한것이 있다면, 출력하는 코드가 보이지 않는다. 화면에 표시하는코드는? 아, WM_PAINT에 있군. 그렇다면 WM_PAINT를 호출하는 시점은?

1. 프로그램을 시작할때.
자, 프로그램을 시작할때 str은 비어있다. 아무리 글자를 쳐봐도 화면에 나오지 않는 이유가 그것이다.
호출하는 시점이 틀려먹었잖아. 그렇다면 또 언제 호출을 하지?

2. 화면을 다시 그릴때.
 화면을 다시 그릴땐 WM_PAINT에 저장되있는것이 다시 호출이 된다. 음.. 언제 다시 호출이 되지? 윈도우창이 가려지고 다시 나타날때 다시 그려진다.

자, 이 화면을 다시그리라는 명령을 해주는 함수가 있으니

  InvalidateRect(hWnd,NULL,FALSE);

요 함수다.
이 함수는 윈도우의 작업영역을 무효화 하여 운영체제가 WM_PAINT메시지를 다시 호출하도록 한다.
첫번째 hWnd는 그 대상이 된다. 뭐, 다른 윈도우를 대상으로 할 수도 있다.
그다음은 CONST RECT *lpRect인데. 무효화할 사각형을 지정한다. 이 값이 NULL값이면, 윈도우의 전영역이 무효화 된다. 하지만 NULL값으로 두면 그릴것이 많아질수록 속도가 느려질수 있는 단점이 있다.
세번째는 BOOL bErase로 무효화되기 전에 배경을 모두 지운후 다시 그릴 것인지 아니면 배경을 지우지 않고 그릴것인지를 지정한다. TRUE면 배경을 지운호 다시그리고, FALSE면 배경을 지우지 않고 다시 그린다.

'Programming > Visual C++' 카테고리의 다른 글

입력3. TranslateMessage  (0) 2011.06.29
입력2. WM_KEYDOWN  (0) 2011.06.29
출력5. MessageBox & MessageBeep  (0) 2011.06.28
출력4. 기타  (0) 2011.06.28
출력3. DrawText  (0) 2011.06.28
MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCation, UINT uType);
핸들값, 메시지 박스에 넣을 글자, 타이틀에 나올글자, 메시지 박스에 나타날 버튼의 종류

MB_ABORTRETRYIGNORE Abort, Retry Ignore 세개의 버튼이 나타난다.
MB_OK, OK버튼 하나만 나타난다.
MB_OKCANCEL, OK, CANCEL 두개의 버튼이 나타난다.
MB_RETRYCANCEL, Retry, Cancel 두개의 버튼이 나타난다.
MB_YESNO
MB_YESNOCANCEL

이것뿐아니라 아이콘또한 표시할 수 있다.
MB_ICONEXCLAMATION,MB_ICONWARNING.
MB_ICONINFORMATION,MB_ICONASTERISK.
MB_ICONQUESTION
MB_ICONSTOP, MB_ICONERROR,MB_ICONHAND

그리고 이 MessageBox의 리턴값은 사용자가 누른 버튼값을 되돌려준다.
IDABORT Abort 버튼을 눌렀다.
IDCANCEL
IDIGNORE
IDNO
IDOK
IDRETRY
IDYES

EX)
if(MessageBox(hWnd,Text("응? 뭐라고?"),TEXT("야!!"),MB_YESNO==IDYES){}
else{}

요롷게;



BOOL MessageBeep(UINT uType);
비프음을 내는 함수
0xffffffff  pc스피커를 통해 음을 낸다.
MB_ICONASTERISK Asterisk 비프음
MB_ICONEXCLAMATION Exclamation 비프음
MB_ICONQUESTION Question 비프음
MB_OK 시스템 디폴트 비프음.





'Programming > Visual C++' 카테고리의 다른 글

입력2. WM_KEYDOWN  (0) 2011.06.29
입력1. WM_CHAR  (0) 2011.06.29
출력4. 기타  (0) 2011.06.28
출력3. DrawText  (0) 2011.06.28
출력2. WM_Paint  (0) 2011.06.28
COLORREF Set Pixel(hdc, nXPos, nYPos, clrref)
지정한 좌표에 clrref색 하나의 점을 찍는다.

DWORD MoveToEX(hdc, x, y, lpPoint);
BOOL LineTo(hdc,xEnd,yEnd);

LineTo는 CP부터 지정한 좌표까지 선을 긋는다. 그리고 CP를 지정한 좌표로 업데이트한다. 따라서 LineTo를 계속 호출하면 연속된 선을 그을수 있다.
MoveToEx는 CP를 지정한 좌표로 이동시키고 필요한경우 이전 CP의 좌표를 lpPoint에 담는다. 필요하지 않을경우(현재수준에서는 계속해서) NULL값을 주면 된다.

Rectangle(hdc, nLeftRect,nTopRect,nRightRect,nBotomRect);
Ellipse(hdc, nLeftRect,nTopRect,nRightRect,nBottomRect);

Rectangle은 네모를
Ellipse는 동그라미를 그린다.
둘다 왼쪽 위x,y, 오른쪽 아래,x,y좌표 순서대로 입력하면 된다.

SetWindowText(HWND hWnd,LPCWSTR lpString);
윈도우 타이틀바에 표시할때 사용. 뭔가 문자열 테스트할때도 많이 사용한다.
이것또한 wsprintf문을 사용할수 있다.

'Programming > Visual C++' 카테고리의 다른 글

입력1. WM_CHAR  (0) 2011.06.29
출력5. MessageBox & MessageBeep  (0) 2011.06.28
출력3. DrawText  (0) 2011.06.28
출력2. WM_Paint  (0) 2011.06.28
출력1. TextOut  (0) 2011.06.28
TextOut에서 발전하면서도 디테일한 것을 만질수 있는 함수다.
int DrawText(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);

뭐 DC는 알테고 그 다음은 출력할 글자,
그 다음에 있는 nCount는 문자열 안에 있는 만자의 갯수를 나태내는 int형 변수다. 만약 이 것이 -1이면 DrawText는 마지막에 null 값을 가지는 포인터가 있는 것으로 가정하고 문자의 갯수는 자동으로 카운트 한다.
그다음은 Rect의 주소값. 즉, 글자가 들어갈 사각형을 표시해준다.
uFormat은 출력 형식인데,
DT_LEFT 수평 왼쪽정렬
DT_Right 수평 오른쪽 정렬
DT_CENTER 수평 중앙정렬
DT_BOTTOM 사각영역의 바닥에 문자열 출력
DT_VCENTER 사각영역의 수직 중앙에 문자열 출력
DT_WORDBREAK 사각영역의 오른쪽 끝에서 자동 개행
DT_SINGLELINE 한줄로 출력
DT_NOCLIP 사각영역의 경계를 벗어나도 문자열을 자르지않고 그대로 출력
등이 있다.

'Programming > Visual C++' 카테고리의 다른 글

출력5. MessageBox & MessageBeep  (0) 2011.06.28
출력4. 기타  (0) 2011.06.28
출력2. WM_Paint  (0) 2011.06.28
출력1. TextOut  (0) 2011.06.28
How to Programming by Unicode in windows programming - 3  (1) 2011.06.25

자, 이번엔 Paint에 대해서 알아보도록 하겠다.
dc의 경우엔 사실 Invalidate()가 자동적으로 이루어지지 않았다.(2010, windows7에서는 자동으로 되는듯 싶지만) WM_Paint를 사용하면 Uncover가 자동적으로 이루어진다. 음... 정확하진 않다.
일단 사용방법은.

 PAINTSTRUCT 구조체를 사용하는 방법이다.

자, 자세한 예제를 보면,
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;

switch(iMessage)
{
case WM_DESTROY:PostQuitMessage(0);return 0;
case WM_PAINT :
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 100,100,TEXT("Beautiful Korea"),15);
EndPaint(hWnd,&ps);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam);
}

자, 여기서 새로나온걸 보자면 PAINTSTRUCT 구조체와 BeginPaint, EndPaint다.
PAINTSTRUCT의 안을 들여다보면
typedef struct tagPAINTSTRUCT
{
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL flncUpdate;
BYTE rgbReserved[16];
} PAINTSTRUCT;

MSDN에서의 설명을 그냥 번역해보자면
hdc

A handle to the display DC to be used for painting.
그리기를 위해 사용될 DC를 표시할 핸들.

fErase

Indicates whether the background must be erased. This value is nonzero if the application should erase the background. The application is responsible for erasing the background if a window class is created without a background brush. For more information, see the description of the hbrBackground member of the WNDCLASS structure.
지시한다 배경이 지워져야만 할것인지 아닌지. 만약 이 어플이 배경을 지운다면 이 값은 0이 아니다. 만약 윈도우 클래스가 배경색 프러쉬없이 만들어진다면, 이 어플은 배경을 지울 책임이 있다. 뭔가 더 궁금하면 WNDCLASS구조체의 hbrBackground멤버 설명을 좀더 보면 이해가 될수도 있을껄?

rcPaint

A RECT structure that specifies the upper left and lower right corners of the rectangle in which the painting is requested, in device units relative to the upper-left corner of the client area.
그리기가 요청된 위 왼쪽, 아래, 오른쪽 코너들을 특정짓는 사각형(RECT) 구조. 디바이스 유닛에서는 클라이언트영역의 왼쪽위로 연결된다.

fRestore

Reserved; used internally by the system.
시스템 내부적으로 예약되어 있음. 건들지 마셈.

fIncUpdate

Reserved; used internally by the system.
시스템 내부적으로 예약되어 있음. 건들지 마셈.

rgbReserved

Reserved; used internally by the system.
시스템 내부적으로 예약되어 있음. 건들지 마셈.

 
자, 한마디로 말하자면, 알필요 없는 구조체네. 그저 BeginPaint를 사용하기 위한 전초전이라 생각해도 편할듯 싶다.
 
BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
자, 그럼 이 코드를 보자면, BeginPaint다. 음.. GetDC, ReleaseDC와 마찬가지로
BeginPaint를 해주면, 반드시 EndPaint를 해줘야 한다.
자, 그리고 넘겨주는것에는 HWND와 LPPAINTSTRUCT. LP는 포인터를 의미한다. 따라서 저기 선언해 놓은 PAINTSTRUCT ps;의 주소값을 넘겨주면 된다.
 





















'Programming > Visual C++' 카테고리의 다른 글

출력4. 기타  (0) 2011.06.28
출력3. DrawText  (0) 2011.06.28
출력1. TextOut  (0) 2011.06.28
How to Programming by Unicode in windows programming - 3  (1) 2011.06.25
윈도우즈 프로그래밍에서 유니코드로 코딩법 2  (1) 2011.06.25
자, 이제 공부를 더 하기 위해서 음.. 뭔가에 대해서 깊숙히 들어가기 보단, 기록과 기억의 측면에서 포스팅을 해보기로 하자.
 이번에 공부할것은 출력. 몇일 전에 했던 LPCTSTR의 문자열 출력이 아닌 이상에야 뭐 그리 어려울건 없다. 따라서 윈도우즈 툴에서 출력하는 방법과 출력하는 함수들의 원형 및 사용방법을 익히면 될것이다.

시작해보자.

우선, 출력이라는 것에 있어서의 필요한것에 대해 알아보자, 일단 출력이란, 우리가 가장 간단하게 상상할수 있는 console style의 문자열이 있겠다. console style만 보더라도, 흰색글자에 검은색 바탕화면, 맨 왼쪽 위부터 출력이 차례대로 진행된다. 하지만 이거슨 도스시절의 이야기. 윈도우와 도스의 가장큰 차이점중 하나를 꼽으라면 뭐가 있을까? 일단 멀티테스킹이 있겠다. 그러면서 윈도우창이 바뀌고, 윈도우창이 움직일수도 있다.
 자, 그러면 두개의 프로그램을 실행중에 있는데 한나의 프로그램에서 출력하고 있던것은 다른 프로그램이 활성화가 된다면 비활성화가 된 프로그램과 같이 보이지 않아야하고 다시 그 프로그램을 활성화 시킨다면 다시 보여져야 한다.
 그리고 윈도우 창을 움직인다면 그 출력이 따라서 움직여야 할것이다.
 그리고 도스시절부터 있을수 있었던 이야기인, 함수의 원형에 무엇이 들어가야 하는가?에 대한 문제이다. 일단, 글자의 시작위치가 들어갈수 있겠다. 도스에서는 그냥저냥 첫줄부터 했지만, 윈도우에서는 어디서부터라도 글자나 그림의 위치가 실행이 가능하다. 글자의 크기, 폰트, 색깔, 등등등 여러가지가 있다. 음... 하지만 정작 생각을 해보면, 시작위치, 프로그램의 핸들만 알려주면 그냥 디폴트 정해주면 안되? 라고 해서 만든것이 DC(Device Context)다. 이 DC에 기타 여러가지의 기능들을 디폴트로 해놓든가 따로 수정을 해주면 알아서 해줄수 있도록 편하게 만들어 놓았다.

자, 그럼 간단한 코드를 보도록 하겠다.

LRESULT CALLBACK WndProc(HWND, hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;

switch(iMessage)
{
case WM_DESTROY: PostQuitMessage(0);return 0;
case WM_LBUTTONDOWN:
hdc=GetDC(hWnd);
TextOut(hdc,100,100,Text("Beautiful Korea"),15);
ReleaseDC(hWnd,hdc);
return 0;  
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

자, 여기서 중요한건, HDC와 GetDC, TextOut, ReleaseDC
뭐, 다중요하네 ㅋㅋ

일단 HDC는 DC의 식별번호(Handle)를 담을수 있는 거고, GetDC는 hWnd를 GetDC 함수에 넘겨줘서 리턴값을 hdc로 대입한다. 핸들은 카테고리처럼 프로그램마다 지정되는거니까 :)
자, 그리고 TextOut을 보기전에 오선 ReleaseDC를 보자하면, 이거슨 생성자와 소멸자, 아니, new와 delete의 관계에 가깝다. 반드시 해줘야한다는 것이지.
 자, 그러면 Text Out을 보도록 하자, TextOut의 경우는
 TextOut(HDC hdc, int x, int y, LPCWSTR lpString, int c);
요롷게 된다. 맨처음은, dc를 사용할 핸들값이겠고, x,y는 출력할 xy의 좌표이다. 이 xy좌표의 원점. 즉, 0,0은 메뉴 부분(non-client area)를 제외한 가장 왼쪽 위부터 시작된다.따라서 오른쪽으로 1만큼 아래로 1만큼 움직이려면, 1, -1이 되는것이다.
 그리고 나오는 LPCWSTR은 물론 LPCTSTR도 사용할수 있으며 출력할 값을 나타낸다.
 그리고 그 뒤에오는 int c는 lpString의 최대길이를 나타낸다.
 만약 마지막의 이것을 쓰기 귀찮은 경우에는

void MyTextOut(HDC hdc, int x, int y, LPCTSTR Text)
{TextOut(hdc,x,y,Text,lstrlen(Text));}

이것과 같이 마지막을 lstrlen(Text)를 해줘서 없애고 MyTextOut이란 함수를 만들면 된다.


그리고 아래는 좌표에 따른 정렬방법.

SetTextAlign(HDC hdc, UINT align);

align::
TA_TOP 지정한 좌표가 상단 좌표
TA_BOTTOM  " 하단 좌표
TA_CENTER   " 중앙 좌표
TA_LEFT " 왼쪽 자좌표
TA_RIGHT " 오른쪽 좌표.
TAUPDATECP  지정한 좌표 대신CP(Current Position)를 사용하여 문자열 출력후에 CP를 저장하고 다음에 출력할 경우 그 CP 다음에 출력한다.
TA_NOUPDATECP CP를 사용하지 않고 지정한 좌표를 사용하며 CP를 변경하지 않는다.

보통 CP는 TA_LEFT|TA_TOP 에 Default로 있다가 어느 한 Text아웃이 발생하면 그 Text의 끝에 붙는다.
따라서 만약 이 CP를 옮기고 싶지 않을때는 TA_NOUPDATECP를 해주어야 한다.

그리고 중간에 변수를 넣을 경우에는 wsprintf나 sprintf를 사용해주면 된다.
wsprintf(LPWSTR, LPWSTR,...);
이것인데, 처음에는 LPWSTR은 버퍼.
그다음 LPWSTR은 버퍼에 넣을 서식이고, ... 는 인수값들이다.


How to Programming by Unicode in windows programming - 3

자, 이제 실전이다. 뭐, 다들 책이나 기본적인 윈도우즈 프레임 툴은 어떻게 짜는지 알것이다.

내가 배운것은

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCSTR lpszClass="First";

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style = CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd = CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);

 while(GetMessage(&Message,NULL,0,0))
 {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 switch(iMessage)
 {
 case WM_DESTROY : PostQuitMessage(0);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

요코드다. 자, 그렇다면 유니코드를 해놓고 비주얼 스튜디오 2010에서 돌리면 어디가 에러가 나는가?
바로 hWnd=CreateWindow 요 줄에 있는 두번째 배개변수 lpszClass가 문제다. 왜냐하면 윈도우즈 함수에서는 분명히 유니코드를 이용하겠다고 했는데 이 lpszClass는 아직 유니코드가 아닌갑다. 그래서 나는 이 lpszClass의 유니코드명이 뭔지 한참이나 찾았으나 인터넷에는 도저히 나와있지 않다. 왜냐하면!! lpszClass는 내가 코드안에서 생성해준 변수명이잖아-_ -;;;;

자, 5번줄을 보면
LPCSTR lpszClass="First";
요게 있었어..
복습을 해보자.
LPCSTR은 Const하고 long pointer하고 str인것이다. 유니코드의 흔적조차 없다.
그러면 어떻게 해야할까?

그거야 바로 LPC와 STR사이에
W나 T를 넣어주면 된다. 다른 코드들과의 이식성을 위해 일부러 연습을 위해서라도 LPCTSTR을 사용해주기로 한다.
자, 이제 해결?!

5번줄만 바꿔서
LPCTSTR lpszClass="First";
자, 디버깅 해보자.

으악! 에러다. 에러다. 에러다. ㅠㅜㅠ 아 도대체 왜!!!
자, 읽어보자면
error C2440: '초기화 중' : 'const char [6]'에서 'LPCTSTR'(으)로 변환할 수 없습니다.
라고 뜬다.
즉슨, 그럼 "First" 가 5자리+NULL의 문자열 상수일테고 왼쪽은 LPCTSTR이다.
음.. LPCTSTR은 틀릴리가 없고, 그럼 const char [6]이 틀렸다는 건데.
일단 내가 짠것은 유니코드니 wchar_t const * != const char[6] 라는 소리겠지.
틀린말은 아니다, "First"는 분명한 문자열 상수고 그것을 다른 자료형에 넣을순 없는거니까.
자, 그러면 형변환이다!

자, 그럼 유니코드 안에서 LPCTSTR == wchar_t const * 이니까
LPCTSTR lpszClass == (wchar_t const *)"First";

라고 고 치고 해보자.... 와우!!! 디버깅 에러 없고, 컴파일 제대로 되..... 었지만 출력물이 이상하다. 무슨 이상한 한자하고 잡스러운게 많이 나온다. ㅠㅠㅠㅠㅠㅠ 앙데 ㅠㅠ

음... 이것의 이유는 찾아본 결과 일단, 강제 형변환에 있다. 일반적인 char 형과 유니코드의 공간 할당 크기가 다르고 이것을 강제적으로 형변환을 할때 그 할당공간 크기 차이의 빈자리를 쓰레기값이 들어가 쓰레기 글자가 나오게 되는 것이다.

 그래서 자연스레 형변환을 해주는 접두어가 있었으니 그거슨 바로 L이다.
 라이토는 아니고, 음... 정확히 찾아보진 못했지만. L이다.

 사용방법은. 그냥 일반 접두어처럼 사용하면 된다.
 
LPCTSTR lpszClass=L"First";

요롷게 하면 디버깅도 되고 컴파일도 되고 실행도 된다. 제대로 출력도 된다.
하지만 이렇게 하면 사실 LPCTSTR을 쓴 의미가 없어진다. 왜냐하면 이 L은 유니코드형으로의 형변환이다. 선택적 형변환을 하기 위해선 TEXT()함수를 사용해야한다. 이 TEXT한수를 사용할 경우엔 이것도 T와 마찬가지로 알아서 유니코드면 유니코드, 일반 ANSI면 일반 char로 알아서 변환한다.

다시 말해

LPCTSTR lpszClass=TEXT("First");

가 최종 답안이라는거지 :)
아.. 여기까지 달려오시느라 참 수고 많으셨고(다 읽었을리는 없겠지만)
최종 코드를 공개하겠다.(거창하진 않지만)

아래 코드로 컴파일 하여 실행한다면 유니코드든 멀티바이트든 에러없이 실행 된다:)

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("First");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style = CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd = CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);
 
 //MessageBox(hWnd,L"하이",TEXT("Test"),NULL);

 while(GetMessage(&Message,NULL,0,0))
 {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 switch(iMessage)
 {
 case WM_DESTROY : PostQuitMessage(0);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}


+ Recent posts