본문 바로가기
IT창고/API

자식윈도우 만들기/수정하기

by 창구창고 2007. 1. 22.
반응형
/*/=================================================================================
1. 버튼 , 메뉴, 스크롤 등 결국 윈도우이다
2. 자식은 부모에게 통보를 한다. WM_COMMAND(통신코드)(버튼클릭같은)
3. 부모는 자식에게 메시지를 보낸다.(형태변환같은)
4. 자식은 자신이 그려지기 전에 부모에게 컨트롤 권한을 넘긴다. (WM_CTLxxxxxxx);
5. 부모는 자식이 보내준 권한을 가지고 자식이 그려질 형태를 수정한다.
//=================================================================================*/
//자식(버튼)이 부모에게 WM_COMMAND를 보낼때 사용할 통지코드(메시지를 보내는 이유)
#define BIN_LCLICK		1
#define BIN_RCLICK		2
#define BIN_LDBCLICK	3
#define BIN_RDBCLICK	4

//부모가 자식(버튼)을 만들어 놓고 자식에게 보낼 수 있는 메시지를 설계한다.
//부모 - 자식 간의 약속
#define BM_CHANGESTYLE	WM_USER + 10
#define BM_CHANGETHICK	WM_USER + 11

#include<windows.h>


LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam);

HINSTANCE g_inst;

void Draw3dRect(HDC hdc, int x, int y, int xx, int yy, 
					BOOL down, int width )
{
	COLORREF clrMain  = RGB(192,192,192),
				clrLight = RGB(255,255,255), 
				clrDark  = RGB(128,128,128);

	HPEN hPen1, hPen2, hOldPen;
	HBRUSH hBrush, hOldBrush;     

	if(down)    
	{
		hPen2 = CreatePen(PS_SOLID,1,clrLight);
		hPen1 = CreatePen(PS_SOLID,1,clrDark);
	} 
	else 
	{
		hPen1 = CreatePen(PS_SOLID,1,clrLight);
		hPen2 = CreatePen(PS_SOLID,1,clrDark);
	}  
	hBrush =  CreateSolidBrush( clrMain );
	hOldPen = (HPEN)SelectObject(hdc, hPen1);
	hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);  

	Rectangle(hdc, x , y, xx+1, yy+1);  

	for(int i=0; i < width; i++)
	{
		SelectObject(hdc, hPen1);

		MoveToEx(hdc, xx - 1, y, 0 );
		LineTo(hdc, x, y);
		LineTo(hdc, x, yy - 1 );  

		SelectObject(hdc, hPen2);

		MoveToEx(hdc, x, yy,0);
		LineTo(hdc, xx, yy);
		LineTo(hdc, xx, y);  

		x++; y++; xx--; yy--;
	} 
	SelectObject(hdc, hOldPen);
	SelectObject(hdc, hOldBrush);

	DeleteObject(hPen1); 
	DeleteObject(hPen2); 
	DeleteObject(hBrush);
} 

int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrev,
				   LPSTR lpCmdLine,
				   int nShowCmd)
{

	ATOM atom;
	g_inst=hInstance;
	MSG Message;
	//1. 위도우 클래스 만들기 (10가지를 다 정확히 입력하지 않으면 화면이 뜨지 않는다.)
	WNDCLASS wc;		//미리정의된 10개 항목을 채우는 클래스 (WNDCLASSEX 12개 항목 10개 항목에 작은 아이콘, 구조체 크기를 포함한다.)
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground	=	(HBRUSH)GetStockObject(	WHITE_BRUSH);

	wc.hCursor		=	LoadCursor	(	0, IDC_CROSS);
	wc.hIcon		=	LoadIcon	(	0, IDI_WINLOGO	);
	wc.hInstance	=	hInstance;
	wc.lpfnWndProc	=	WndProc;
	wc.lpszClassName=	"First";
	wc.lpszMenuName	=	0;
	wc.style		=	0;

	//2. 윈도우 클래스 등록하기.
	atom = RegisterClass( & wc	);	// 등록을 하는 함수도 2가지가 있다. RegisterClass와 RegisterClassEx가 있다.

	wc.lpfnWndProc		=	ChildWndProc;
	wc.lpszClassName	=	"CHILD";
	RegisterClass( & wc	);
	//WNDCLASS로 만들었으면 RegisterClass로 등록하고 WNDCLASSEX로 만들었으면 RegisterClassEx로 등록

	//3. 등록된 클래스를 사용해서 윈도우 만들기.
	// typedef long HWND;	//	윈도우의 번호를 담을때 사용
	HWND hwnd	=	CreateWindowEx(WS_EX_RIGHT ,			// 확장 윈도우 스타일
									"First",				// 윈도우 클래스 이름
									"안녕",					// 창이름
									WS_OVERLAPPEDWINDOW,	// 기본 Window Styles : & ~ 연산으로 기존스타일 제거하기
															// WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX
									CW_USEDEFAULT,	0,	CW_USEDEFAULT,	0,	// X,Y,W,H
									0,						// 부모 윈도우 핸들( 번호 )
									0,						// 메뉴 핸들( 번호 )
									hInstance,				// 인스턴스 핸들
									0);						// 생성인자.( MDI 만들때 사용 )
	//							   

	//CreateWindowEx는 CreateWindow가 가지는 11개에 확장 윈도우 스타일 1가지 인자를 더 가져서 12가지 인자를 가진다.

	//4. 윈도우 보여주기
	ShowWindow(hwnd, nShowCmd);

	while(GetMessage(&Message,0,0,0))	//메시지 큐에 가서 메시지를 꺼내오고 가져온 메시지를 윈도우 클래스에 등록된 메세지 처리함수로 전달한다.
	{
		TranslateMessage(&Message);
		DispatchMessage(&Message);//가져온 메시지를 윈도우 클래스에 등록된 메시지 처리함수로 전달한다.
	}

	return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	static HWND hChild;
	switch(iMessage){

		//자식이 자신을 그리기 전에 보내는 메시지 - 부모에게 ㅈ색을 변경할 기회를 준다. ※중요
	case WM_CTLCOLORBTN:
		{
			HDC hdc = (HDC)wParam;
			HWND h	= (HWND)lParam;

			if(hChild	==	h)//자식이 2개 이상이라면 내가 원하는 자식인지 확인
			{
				SetTextColor(hdc,RGB(200,0,200));
			}
		}
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0 ;
	case WM_CREATE:
		hChild = CreateWindowEx(0 ,			// 확장 윈도우 스타일
			"CHILD",				// 윈도우 클래스 이름
			"자식",					// 창이름
			WS_CHILD | WS_VISIBLE  | WS_BORDER ,	// 기본 Window Styles : & ~ 연산으로 기존스타일 제거하기
			// WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX
			0,	0,	100,	100,	// X,Y,W,H
			hwnd,						// 부모 윈도우 핸들( 번호 )
			(HMENU)1,						// 메뉴 핸들( 번호 )
			g_inst,				// 인스턴스 핸들
			0);	// 생성인자.( MDI 만들때 사용 )
		
		return 0;
	case WM_COMMAND:
		switch( LOWORD(wParam))	//자식 ID
		{
		case 1:
			if(HIWORD(wParam)	==	BIN_LCLICK)	// 통지코드 조사
			{
				MessageBox(hwnd,"Click!!","",MB_OK);
			}
			break;
		}
		return 0 ;
	case WM_LBUTTONDOWN:
		{
			static int n= 2;
			++n;
			
			//자식에게 메시지를 보내서 두께를 변경하게 한다.
			//wParam : 변경할 두께 , lParam : Not Use;
			SendMessage(hChild,BM_CHANGETHICK,n,0);
		}
		return 0;
	}
	//꺼내온 메시지를 처리하지 않은경우 -> 바드시 아래 함수를 처리한다.
	return(DefWindowProc(hwnd,iMessage,wParam,lParam));
}

LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	static BOOL lDown	=	FALSE;
	static int nThick	=	2;
	switch(iMessage){
	case WM_LBUTTONDOWN:
		lDown = TRUE;	InvalidateRect(hwnd,0,FALSE);
		SetCapture(hwnd);
		return 0 ;
	case BM_CHANGETHICK:
		{
			nThick = (int)wParam;		//wParam에 두께를 보내기로 약속
			InvalidateRect(hwnd,0,FALSE);
		}
		return 0;
	case WM_LBUTTONUP:
		{
			if(GetCapture()	==	hwnd)
			{
				ReleaseCapture();
				lDown = FALSE;
				InvalidateRect(hwnd,0,FALSE);
			}
			//===================================================
			//자식이 눌렸음을 부모에게 알려준다.
			HWND hParent	=	GetParent(hwnd);
			UINT id			=	GetDlgCtrlID(hwnd);
			
			SendMessage(hParent,	WM_COMMAND,
				MAKELONG(id,BIN_LCLICK),
				(LPARAM)hwnd);
		}
		return 0 ;

	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);
			//자식은 hdc를 얻고 자신을 그리기 전에 부모에게 hdc 를 전달한다.
			// 부모가 자식의 색상을 변경할 권한을 주기 위해서 
			// 이런 용도로 미리 만들어진 메시지가 WM_CTLCOLORxxx이다.

			//wParam 에는 hdc를 lParam에는 자신의 핸들을 넣어 준다.
			HWND hParent	=	GetParent(hwnd);

			SendMessage(hParent, WM_CTLCOLORBTN,(WPARAM)hdc,(LPARAM)hwnd);


			RECT rc;
			GetClientRect(hwnd, &rc);
			Draw3dRect(hdc, 0,0,rc.right, rc.bottom,lDown, nThick);

			char s[256];

			GetWindowText(hwnd, s, 256);
			SetBkMode(hdc, TRANSPARENT);

			if(lDown == TRUE)
			{
				OffsetRect(&rc,nThick,nThick);
			}

			DrawText(hdc,s,-1,&rc,DT_SINGLELINE | DT_CENTER | DT_VCENTER );

			EndPaint(hwnd, &ps);
		}
		return 0;
	}
	//꺼내온 메시지를 처리하지 않은경우 -> 바드시 아래 함수를 처리한다.
	return(DefWindowProc(hwnd,iMessage,wParam,lParam));
}
반응형

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."