'input'에 해당되는 글 12건

  1. 2010.07.20 WinApi WM_SIZE
  2. 2010.07.19 WinApi 생성과 종료, 작업영역
posted by nsakura 2010. 7. 20. 01:31

방금전 포스트를 보면 자동으로 윈도우 크기를 구해서 창 가운데에 글씨를 출력하는 프로그램인데

약간 문제가있다.

사용자가 창의 크기를 바꾸거나하면

글씨는 그대로 처음에 있던 곳에 있다 이게 무슨 말이냐면.

창이커지면 커진대로 중앙을 찾아야하는데 그런게 안된다는것이다.

그럼 어떻게하면 사용자가 윈도우창의 크기를 바꿔도 출력은 항상가운데 뜨게 할것인가?

이것 역시 윈도에서 지원하고 그 메세지는  WM_SIZE 이다.

WM_SIZE의 플래그 값은

 SIZE_MAXHIDE   다른 윈도우가 최대화 되어 이 윈도우가 가려졌다
 SIZE_IMIZED   최대화 되었다
 SIZE_MAXSHOW   다른 윈도우가 원래 크기로 복구되어 이 윈도우가 드러났다
 SIZE_MINIMIZED   최소화 되었다
 SIZE_RESTORED   크기가 변경되었다.


그래서 문제가 있던 이전 코드를

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass=TEXT("GFP NSAKURA OUTPUT");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){

 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=lpszClass;
 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,nShowCmd);

 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;
  TCHAR str[20];
 int score=80;
 static RECT rt;

 switch(iMessage){
  case WM_SIZE:
   GetClientRect(hWnd,&rt); 
   InvalidateRect(hWnd,&rt,TRUE);
   return 0;
  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
  case WM_PAINT:
   hdc=BeginPaint(hWnd,&ps);
   wsprintf(str,TEXT("너 점수 %d"),score);
   TextOut(hdc,rt.right/2,rt.bottom/2,str,lstrlen(str));
   EndPaint(hWnd,&ps);
   return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

이렇게 바꾸어주면 해결이 된다.

이 방법 말고.

  case WM_SIZE:
   rt.right=LOWORD(lParam);
   rt.bottom=HIWORD(lParam);
   InvalidateRect(hWnd,&rt,TRUE);
   return 0;

이런 방법도 있다.

그리고 마지막 한가지 방법이 더있는데 WM_PAINT에서도 가능하지만

이 방법은 효율성의 문제가 있기때문에 설명하지 않겠다.

그 외에도

WM_MOVE라는 메세지가 있는데.

이건 단순 윈도우의 위치가 변경되었을때 보내지는 메세지인데.

뭐 그렇게 많이 쓰지도 않을것 같아 굳이 해보지는 않겠다.

이로서 입력도 끝이 났다.

'Computer > Win API' 카테고리의 다른 글

WinApi 리소스 [아이콘][커서]  (2) 2010.07.20
WinApi 리소스 [메뉴]  (0) 2010.07.20
WinApi 생성과 종료, 작업영역  (0) 2010.07.19
WinApi 타이머 확장 2  (0) 2010.07.19
WinApi 타이머 확장  (1) 2010.07.19
posted by nsakura 2010. 7. 19. 19:31
생성과 종료

WndProc함수 스위치 문을보면.

WM_CREATE , WM_DESTROY 메세지가 있는데.

간단하게 크레딧에서는 윈도우가 생성될때 전달되는 메세지이고 디스트로이는 종료될때 전달되는 메세제지인데.

크레딧에는 주로 초기화와 할당을

디스토리이는 자원을 반납을 주로 한다.

예를들어 동적 메모리를 할당을 한다고 치자. 1MB

TCHAR *mem;

이하 생략

switch(iMessage){
case WM_CREATE:
 mem=(TCHAR*)malloc(1048576);
 return 0;
case WM_DESTROT:
 free(mem);
 return 0;

이런식으로 되겠다.

두번째 방법은

WinMain에서 할당과 반납을 할수있는데.


이하생략

mem=(TCHAR*)malloc(1048576);
while(GetMessage(&Message,NULL,0,0)){
이하 생략
}
free(mem)으로 해도 된다.

차이점이 있는데

상위에 방법은 CREATE메세지가 전달이 되기전에는 동적 메모리 할당이 되지 않는다.

라는 차이점이 있다.

엄밀히 따져들어가면 그렇게 동일하다고 볼수있다.

그런데 인풋을 하고있는데 왜 이런 설명을 하고있는가 의문을 품지 않은가?

간단하다 윈도우의 상황 변화시에 보내지는 메세지들도 응용 프로그램 입장으로 보면 입력이라고 할수 있기 때문이다.

작업영역

책에 이래 저래 설명이 되어있었는데 다 버려버리고.

하나의 그림을 설명하겠다.



표시된 곳 안쪽이 작업 영역 그외는 비작업 영영역이라고 한다.

비작업영역은 프로그래밍 대상이 아니고 운영체제가 알아서 관리한다.

즉 프로그래밍의 대상이 되는것은

작업영역인 것이다.

프로그램밍을 하다보면

작업 영역이 어느정도인이 알 필요성이 생길 때가 있는 이 때 쓰는 함수가

GetClientRect이다.

함수의 원형을 보면.

BOOL GetClientRect(HWND hWnd,LPRECT lpRect);

첫번째 인자는 크기를 구하고자하는 윈도우.

두번째 인자는 크기를 저장할 RECT 구조체를 말한다

만일 중앙의 위치를 계산하고자 할때.

static RECT rt;


이하 생략

GetClientRect(hWnd,&rt);

하면 윈도우 창의 크기가 구해지며.

중앙을 알아내기 윈해서는

rt.right/2

rt.bottom/2

이렇게 하면 화면의 중앙을 알수있다.

코드가 없어서 알아보기 힘들다 하는 당신들을 위해 준비했습니다.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass=TEXT("GFP NSAKURA OUTPUT");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){

 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=lpszClass;
 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,nShowCmd);

 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;
  TCHAR str[20];
 int score=80;
 static RECT rt;

 switch(iMessage){
  case WM_CREATE:
   GetClientRect(hWnd,&rt); 
   return 0;
  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
  case WM_PAINT:
   hdc=BeginPaint(hWnd,&ps);
   wsprintf(str,TEXT("너 점수 %d"),score);
   TextOut(hdc,rt.right/2,rt.bottom/2,str,lstrlen(str));
   EndPaint(hWnd,&ps);
   return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}


보시는바와 같이 자동으로 계산을 해준다.


 

'Computer > Win API' 카테고리의 다른 글

WinApi 리소스 [메뉴]  (0) 2010.07.20
WinApi WM_SIZE  (0) 2010.07.20
WinApi 타이머 확장 2  (0) 2010.07.19
WinApi 타이머 확장  (1) 2010.07.19
WinApi 타이머 콜백함수  (0) 2010.07.19