반응형
/*/================================================================================= 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)); }
반응형
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."