728x90
반응형
<Win32API>✔
================================================================
7-2-다. 컨트롤의 메시지
컨트롤은 자신에게 어떤 변화가 있을 때마다 부모 윈도우로 메시지를 보내며 이 메시지를 통지 메시지라고 부른다.
예를 들어 ->체크 박스의 경우 사용자가 마우스로 체크 박스를 클릭할 때마다 부모 윈도우로 BN_CLICKED 메시지를 보낸다.
컨트롤이 부모 윈도우로 보내는 통지 메시지와는 달리 부모 윈도우가 체크 박스의 현재 상태를 알아보거나 상태를 바꾸고자 할 때도 차일드 윈도우로 메시지를 보낸다.
부모 윈도우가 체크 박스로 보낼 수 있는 메시지에는 다음 두가지가 있다.
메시지 | 설명 |
BM_GETCHECK | 체크 박스가 현재 체크되어 있는 상태인지를 조사하며 추가정보는 없다. |
BM_SETCHECK | 체크 박스의 체크 상태를 변경하며 wParam에 변경할 체크 상태를 보내주면 된다. |
BM_GETCHECK에 의해 리턴되는 값, 또는 BM_SETCHECK에 의해 설정되는 체크 박스의 상태는 다음 세가지가 있다.
상수 | 의미 |
BST_CHECKED | 현재 체크되어 있다. |
BST_UNCHECKED | 현재 체크되어 있지 않다. |
BST_INDETERMINATE | 체크도 아니고 안체크도 아닌 상태 |
ID 0의 체크 박스가 클릭되었을 때> 를 처리하는 코드를 보자.
체크 박스가 클릭되면 BN_CLICKED 통지 메시지가 WM_COMMAND 메시지를 통해 전달되므로 WM_COMMAND 메시지에 이 코드가 작성되어 있다.
case WM_COMMAND:
switch(LOWORD(wParam)) {
case 0:
if (SendMessage(c1,BM_GETCHECK,0,0)==BST_UNCHECKED) {
SendMessage(c1,BM_SETCHECK,BST_CHECKED,0);
ELLIPSE = TRUE;
}
else {
SendMessage(c1,BM_SETCHECK,BST_UNCHECKED,0);
ELLIPSE = FALSE;
}
InvalidateRect(hWnd, NULL, TRUE);
break;
* 부모 윈도우> BM_GETCHECK 메시지를 c1체크 박스로 보내 현재 체크 박스의 상태를 조사
> 그 값이 BST_UNCHECKED (현재 체크되어 있지 않으면) BM_SETCHECKED 메시지를 다시 보내 체크 박스에 체크 표시를 명령함.
> 이때 wParam으로 체크 표시를 하라는 의미의 BST_CHECKED가 전달되었다.
> 만약 BST_UNCHECKED가 아니면, 즉 현재 체크되어 있으면 체크 표시를 해제하도록 메시지를 보낸다.
> 또한 조사된 체크 박스의 상태에 따라 ELLIPSE 변수값을 TRUE나 FALSE로 변경하도록 하며
> InvalidateRect 함수를 호출하여 WM_PAINT 메시지를 발생시키는데
> WM_PAINT 메시지에서는 ELLIPSE 변수의 값에 따라 사각형이나 타원을 그리게 된다.
> 따라서 사용자가 이 체크 박스를 클릭할 때마다 체크박스의 상태가 토글되며 화면상의 사각형/타원형이 계속 교체된다.
* 부모 윈도우와 자식 윈도우는 이런 식으로 메시지를 통해 서로의 상태를 알리거나 변경하도록 지시한다
* ID 2의 체크 박스> 는 BS_3STATE 스타일로 생성
> 되었으므로 세가지 상태를 가질 수 있으며
> 수동 체크 박스이기 때문에 ID 0의 체크 박스와 마찬가지로 BN_CLICKED 통지 메시지가 발생했을 때 체크 상태를 변경해줘야 한다.
> 반면 ID 1과 ID 3의 체크 박스는 자동 체크 박스이기 때문에 이런 코드를 작성하지 않아도 윈도우즈가 알아서 체크 박스의 상태를 변경해 준다.
> 이렇게 변경된 값은 체크 박스의 상태가 필요할 때만 BM_GETCHECK 메시지를 보내 상태를 알아 보기만 하면 되며 체크 박스값이 변경될 때마다 어떤 처리를 해 줄 필요는 없다.
> 이 예제의 경우 ID 1의 체크 박스 상태는 종료시에만 사용되므로 종료 직전에만 값을 검사하여 체크되어 있으면 메시지 박스를 출력하고 그렇지 않으면 그냥 프로그램을 종료하면 된다.
case WM_DESTROY: if (SendMessage(c2,BM_GETCHECK,0,0)==BST_CHECKED) MessageBox(hWnd,"Good bye","Check",MB_OK); PostQuitMessage(0); return 0;
> ID 0의 수동 체크 박스는 체크 상태가 변경될 때마다 ELLIPSE 변수값을 변경해 주어야 하고
> 또한 화면을 다시 그려야 하므로 자동 체크 박스 스타일은 부적당하다.
7-2-라. 라디오 버튼
* "button" 클래스에 BS_RADIOBUTTON, BS_AUTORADIOBUTTON 둘 중 하나의 스타일을 지정하면 라디오 버튼이 된다.
> 수동, 자동(윈도우즈가 체크 상태를 자동으로 변경)의 두 가지 종류
- 같은 그룹에 속한 라디오 버튼은 하나만 선택할 수 있으며 사용자에 의해 라디오 버튼이 선택되면 같은 그룹에 속한 다른 모든 라디오 버튼은 선택이 해제된다.
----------------------------------------------------------------
<게임만들기>
SelectObject(MemDC, HbmHero);
BitBlt(hdc, ixPos, iyPos, XTILE, YTILE, MemDC, 0, 0, SRCCOPY);
에서 골뱅이의 좌표값을 가지고 잇음.
맴카피를 쓰지 않는다 : 현재 히어로의 멈춰있는 @ 이 위치를 계속 로드해서 동시에 히어로의 위치를 가져와야한다
맵복사할때 memcpy를 쓰면 for문을 쓰면 복사하면서 @의 위치를 알수 잇다./예) 맵핵
- 컴퓨터는 위치를 실시간으로 계산하고 잇다. 스타 : 다 감시 해야 한다. 그래서 총인구수 제한을 둔다.
- 타이머 있으면 : 실시간오락
- 타이머 빠지면 : 퍼즐 오락
- 따라오는 몹 은 실시간으로 캐릭터의위치를 안다. 타이머를 늘리면 천천히 쫒아 오고, 줄이면 빨리 쫒아온다
* 타이머
- 테트리스의 블럭 속도
- 블럭이 도달할때마다.if문으로 각 라인이 찼는지 검사한다.
- 블럭 = *이고, 공백은 0으로 두고, 다찼으면 한줄 지움.
- 도형그리는 알고리즘만 중요하다.
- 타이머 숫자 감소.
- 랜덤함수의 시드값을 현재시간으로 하면 항상 랜덤하게 된다.
**********************
(@)길 o 1
(@)닷 o 2
(@)박스 벽 x
(@)박스 박스 x
(@)박스 길 o 3
(@)박스 닷 o 4
(@)벽 x
**********************
위 논리로 좌표.
> 전체를 다시 그리면서 일어나는 깜빡임 현상을 처리하기위해 무효화영역 을
> RECT 의 멤버 변수에 무효화 영역 의 좌표를 넣고 키입력시 처리 .
> #: 이동 불가 영역, .(dot) : 스테이지 성공, 박스 이동처리
* ucMap(실제 맵)의 #을 화면에 그림으로 그려놓았을뿐 '화면'
-> 방향키가 변하려면 지도의 @가 변해야 한다.
> 'HOME' 키 입력 처리 : 스테이지 재시작의 메시지박스호출
-> 재시작 : @위치를 찾아 다시 그린다.
> . 지점에 박스가 놓이면 : 다음 스테이지
> 마지막 스테이지까지 클리어 하면 게임종료
내일 오전 : 최적화 할것.
--------------------------------------------------------------
<소스>
#include <windows.h>
#include "smart.h"
#include "resource1.h"
HINSTANCE g_hInst;
LPSTR lpszClass = TEXT ("SMART" );
LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM );
stMsgMap MsgMap[] =
{
{ WM_PAINT , OnPaint },
{ WM_KEYDOWN, OnKeydown },
{ WM_CREATE, OnCreate },
{ WM_DESTROY, OnDestroy },
{ WM_NULL, 0 }
};
/****Mapping****/
UCHAR ucStageMap[STAGE ][YFRAME ][XFRAME + 1] =
{
{
"###############",
"# #########" ,
"# ### ########",
"# ## ##" ,
"# B ## ##" ,
"# @ ## ##" ,
"# ## ##" ,
"# . ##" ,
"##### ##" ,
"###############",
}
,
{
"###############",
"# ###" ,
"# ### . ###" ,
"# ## ##" ,
"# @ ## ##" ,
"# B ## ##" ,
"# ## ##" ,
"# ##### ##" ,
"##### ##" ,
"###############",
}
};
UCHAR ucMap[YFRAME ][XFRAME + 1];
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)WndProc;
WndClass.lpszClassName = lpszClass;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW ;
RegisterClass(&WndClass);
hWnd = CreateWindow(
lpszClass,
lpszClass,
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU ,
CW_USEDEFAULT,
CW_USEDEFAULT,
XWINSIZE,
YWINSIZE,
NULL, ( HMENU) NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
while ( GetMessage(&Message, 0, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd , UINT iMessage , WPARAM wParam , LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
stMsgMap *stpMap = MsgMap;
while( WM_NULL != ((*stpMap).uiMsg) )
{
if ( iMessage == ((*stpMap).uiMsg))
{
return (((*stpMap).fp)( hWnd, wParam, lParam));
}
++stpMap;
}
return(DefWindowProcA( hWnd, iMessage, wParam, lParam));
}
LRESULT OnDestroy(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
DeleteObject(HbmFront);
DeleteObject(HbmRear);
DeleteObject(HbmRight);
DeleteObject(HbmLeft);
DeleteObject(HbmGround);
DeleteObject(HbmRoad);
DeleteObject(HbmDot);
DeleteObject(HbmBox);
DeleteDC(MemDC);
PostQuitMessage(0);
return 0;
}
LRESULT OnCreate(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
HDC hdc;
Load_map();
hdc = GetDC( hWnd);
MemDC = CreateCompatibleDC(hdc);
HbmFront = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP1 ));
HbmLeft = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP2 ));
HbmRight = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP3 ));
HbmRear = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP4 ));
HbmGround = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP5 ));
HbmRoad = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP7 ));
HbmDot = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP8 ));
HbmBox = LoadBitmap(g_hInst, MAKEINTRESOURCE (IDB_BITMAP9 ));
ReleaseDC( hWnd, hdc);
HbmHero = HbmFront;
return 0;
}
void Load_map(void )
{
int ixCnt;
int iyCnt;
uiDotNum = 0;
uiScore = 0;
for (ixCnt = 0; ixCnt < XFRAME; ixCnt++)
{
for (iyCnt = 0; iyCnt < YFRAME; iyCnt++)
{
if ( '.' == ucStageMap[uiStage][iyCnt][ixCnt])
{
++uiDotNum;
}
if ( '@' == ucStageMap[uiStage][iyCnt][ixCnt])
{
ixPos = ixCnt;
iyPos = iyCnt;
ucMap[iyCnt][ixCnt] = ' ';
continue;
}
ucMap[iyCnt][ixCnt] = ucStageMap[uiStage][iyCnt][ixCnt];
}
}
return;
}
LRESULT OnPaint(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
int ixCnt;
int iyCnt;
hdc = BeginPaint( hWnd, &ps);
for (ixCnt = 0; ixCnt < XFRAME; ixCnt++)
{
for (iyCnt = 0; iyCnt < YFRAME; iyCnt++)
{
if ( '#' == ucMap[iyCnt][ixCnt])
{
SelectObject(MemDC, HbmGround); //벽이면 백그라운드 사용.
}
else if ( ' ' == ucMap[iyCnt][ixCnt])
{
SelectObject(MemDC, HbmRoad);
}
else if ( '.' == ucMap[iyCnt][ixCnt])
{
SelectObject(MemDC, HbmDot);
}
else if ( 'B' == ucMap[iyCnt][ixCnt])
{
SelectObject(MemDC, HbmBox);
}
BitBlt(hdc, ixCnt* XTILE, iyCnt* YTILE, XTILE, YTILE, MemDC, 0, 0, SRCCOPY);
}
}
SelectObject(MemDC, HbmHero);
BitBlt(hdc, ixPos* XTILE, iyPos* YTILE, XTILE, YTILE, MemDC, 0, 0, SRCCOPY);
EndPaint( hWnd, &ps);
wsprintf(cTitle, TEXT( "STAGE : %d KeyCount : %d" ), (uiStage + 1), uiScore);
SetWindowText(hWnd , cTitle);
return 0;
}
LRESULT OnKeydown(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
int ixCnt;
int iyCnt;
UINT uiDotCnt;
RECT stArea;
stArea.left = ixPos* XTILE;
stArea.right = (ixPos + 1)* XTILE;
stArea.top = iyPos* YTILE;
stArea.bottom = (iyPos + 1)* YTILE;
int iRet;
switch ( wParam)
{
case VK_RIGHT:
++uiScore;
HbmHero = HbmRight;
if ( ' ' == ucMap[iyPos][ixPos + 1])
{
++ixPos;
stArea.right = (ixPos + 1)* XTILE;
}
else if ( '.' == ucMap[iyPos][ixPos + 1])
{
++ixPos;
stArea.right = (ixPos + 1)* XTILE;
}
else if ( 'B' == ucMap[iyPos][ixPos + 1])
{
if ( ' ' == ucMap[iyPos][ixPos + 2])
{
ucMap[iyPos][ixPos + 2] = ucMap[iyPos][ixPos + 1];
if ( '.' != ucStageMap[uiStage][iyPos][ixPos + 1])
{
ucMap[iyPos][ixPos + 1] = ' ';
}
else
{
ucMap[iyPos][ixPos + 1] = '.';
}
++ixPos;
stArea.right = (ixPos + 2)* XTILE;
}
else if ( '.' == ucMap[iyPos][ixPos + 2])
{
ucMap[iyPos][ixPos + 2] = ucMap[iyPos][ixPos + 1];
if ( '.' != ucStageMap[uiStage][iyPos][ixPos+1])
{
ucMap[iyPos][ixPos + 1] = ' ';
}
else
{
ucMap[iyPos][ixPos + 1] = '.';
}
++ixPos;
stArea.right = (ixPos + 2)* XTILE;
}
}
break;
case VK_LEFT:
++uiScore;
HbmHero = HbmLeft;
if ( ' ' == ucMap[iyPos][ixPos - 1])
{
--ixPos;
stArea.left = ixPos* XTILE;
}
else if ( '.' == ucMap[iyPos][ixPos - 1])
{
--ixPos;
stArea.left = ixPos* XTILE;
}
else if ( 'B' == ucMap[iyPos][ixPos - 1])
{
if ( ' ' == ucMap[iyPos][ixPos - 2])
{
ucMap[iyPos][ixPos - 2] = ucMap[iyPos][ixPos - 1];
if ( '.' != ucStageMap[uiStage][iyPos][ixPos - 1])
{
ucMap[iyPos][ixPos - 1] = ' ';
}
else
{
ucMap[iyPos][ixPos - 1] = '.';
}
--ixPos;
stArea.left = (ixPos- 1)* XTILE;
}
else if ( '.' == ucMap[iyPos][ixPos - 2])
{
ucMap[iyPos][ixPos - 2] = ucMap[iyPos][ixPos - 1];
if ( '.' != ucStageMap[uiStage][iyPos][ixPos - 1])
{
ucMap[iyPos][ixPos - 1] = ' ';
}
else
{
ucMap[iyPos][ixPos - 1] = '.';
}
--ixPos;
stArea.left = (ixPos - 1)* XTILE;
}
}
break;
case VK_UP:
++uiScore;
HbmHero = HbmRear;
if ( ' ' == ucMap[iyPos-1][ixPos])
{
--iyPos;
stArea.top = iyPos* YTILE;
}
else if ( '.' == ucMap[iyPos-1][ixPos])
{
--iyPos;
stArea.top = iyPos* YTILE;
}
else if ( 'B' == ucMap[iyPos-1][ixPos])
{
if ( ' ' == ucMap[iyPos-2][ixPos])
{
ucMap[iyPos - 2][ixPos] = ucMap[iyPos - 1][ixPos];
if ( '.' != ucStageMap[uiStage][iyPos-1][ixPos])
{
ucMap[iyPos - 1][ixPos] = ' ';
}
else
{
ucMap[iyPos - 1][ixPos] = '.';
}
--iyPos;
stArea.top = (iyPos-1)* YTILE;
}
else if ( '.' == ucMap[iyPos-2][ixPos])
{
ucMap[iyPos - 2][ixPos] = ucMap[iyPos - 1][ixPos];
if ( '.' != ucStageMap[uiStage][iyPos - 1][ixPos])
{
ucMap[iyPos - 1][ixPos] = ' ';
}
else
{
ucMap[iyPos - 1][ixPos] = '.';
}
--iyPos;
stArea.top = (iyPos-1)* YTILE;
}
}
break;
case VK_DOWN:
++uiScore;
HbmHero = HbmFront;
if ( ' ' == ucMap[iyPos+1][ixPos])
{
++iyPos;
stArea.bottom = (iyPos + 1)* YTILE;
}
else if ( '.' == ucMap[iyPos+1][ixPos])
{
++iyPos;
stArea.bottom = (iyPos + 1)* YTILE;
}
else if ( 'B' == ucMap[iyPos+1][ixPos])
{
if ( ' ' == ucMap[iyPos+2][ixPos])
{
ucMap[iyPos + 2][ixPos] = ucMap[iyPos + 1][ixPos];
if ( '.' != ucStageMap[uiStage][iyPos + 1][ixPos])
{
ucMap[iyPos + 1][ixPos] = ' ';
}
else
{
ucMap[iyPos + 1][ixPos] = '.';
}
++iyPos;
stArea.bottom = (iyPos + 2)* YTILE;
}
else if ( '.' == ucMap[iyPos+2][ixPos])
{
ucMap[iyPos + 2][ixPos] = ucMap[iyPos + 1][ixPos];
if ( '.' != ucStageMap[uiStage][iyPos + 1][ixPos])
{
ucMap[iyPos + 1][ixPos] = ' ';
}
else
{
ucMap[iyPos + 1][ixPos] = '.';
}
++iyPos;
stArea.bottom = (iyPos + 2)* YTILE;
}
}
break;
case VK_HOME:
iRet = MessageBox(hWnd , TEXT ("스테이지 다시시작" ), TEXT ("명박 명박"), MB_YESNO);
if (iRet == IDYES)
{
Load_map();
uiStage = 0;
uiScore = 0;
HbmHero = HbmFront;
}
InvalidateRect( hWnd, NULL, TRUE);
return 0;
}
InvalidateRect( hWnd, &stArea, FALSE);
uiDotCnt = 0;
for (ixCnt = 0; ixCnt < XFRAME;ixCnt++)
{
for (iyCnt = 0; iyCnt < YFRAME; iyCnt++)
{
if ( 'B'== ucMap[iyCnt][ixCnt])
{
if ( '.'== ucStageMap[uiStage][iyCnt][ixCnt])
++uiDotCnt;
}
}
}
if (uiDotCnt == uiDotNum)
{
MessageBox(hWnd , TEXT ("스테이지 클리어" ), TEXT ("명박 ㅇㅋ" ), MB_OK );
++uiStage;
if (( STAGE) <= uiStage)
{
MessageBox(hWnd , TEXT ("게임종료" ), TEXT ("명박 ㅇㅋ" ), MB_OK );
SendMessage(hWnd , WM_DESTROY , wParam , lParam );
return 0;
}
Load_map();
HbmHero = HbmFront;
InvalidateRect( hWnd, NULL, TRUE);
}
return 0;
}
--------------------------------------------------------------
728x90
'코스웨어 > 15년 스마트컨트롤러' 카테고리의 다른 글
20151119 임현수 업무일지 WIN32API #6 게임 푸시푸시 구현 (4) | 2015.11.20 |
---|---|
20151119_안향진_API_6 (5) | 2015.11.20 |
20151119 / API_6-푸시푸시 끝/ 남수진 (4) | 2015.11.20 |
20151119- 강동조 개인업무일지 PushPush (5) | 2015.11.19 |
20151119 - 홍준모 (게임 만들기) 6일 차 (4) | 2015.11.19 |
20151119_박서연_일일업무일지_WinAPI(6) (4) | 2015.11.19 |
20151119 - 권오민 - WinAPI 6일차 (5) | 2015.11.19 |
20151119_주재민_API_6(작성중) (4) | 2015.11.19 |