본문 바로가기
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));
    }
    
    반응형

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