본문 바로가기
핵심 API로 배우는 윈도우 프로그래밍

[windowAPI] 제4장 윈도우 각종 메뉴 구성 - 3

by 딴짓거리 2022. 10. 23.

핵심 API로 배우는 윈도우 프로그래밍 4장을 공부하고 정리한 내용입니다.

 

프로그램 실행중에 메뉴가 수정되는 상황이 있다

 

 

이렇게 메뉴창이 있다고 하자

 

프로그램을 사용할때 메뉴 버튼이 회색으로 비활성화 되어 클릭이 되지 않는 부분이 있었던 경험을 한 적이 있을 것이다.

 

사용자가 지금은 이용할 수 없게 제한할때 회색으로 비활성화를 해 놓는데

 

프로그램 실행 도중 사용자가 조건을 만족하면 비활성화 된 메뉴버튼을 다시 활성화해야 할 수도 있다.

 

 

위의 구성을 예로 들어보자

 

텍스트를 복사 붙여넣기 하는 메뉴이다.

 

텍스트를 붙여넣기 하려면 일단 복사한 텍스트가 있어야 할 것이다.

 

복사한 텍스트가 없는 상태로 붙여넣기를 하는것은 의미가 없을뿐더러 예상치 못한 결과를 초래할 수도 있다.

 

그러므로 일단 비활성화 된 상태로 프로그램이 실행되는게 좋다.

 

그 후 텍스트를 복사하면 비활성화 되었던 붙여넣기 버튼이 활성화 상태로 바뀌어야 한다.

 

이것을 구현한다.

 

먼저 복사하기 메뉴는 ID_EDITCOPY, 붙여넣기 메뉴는 ID_EDITPASTE 로 아이디를 지정해준다.

 

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	
	static HMENU		hMenu, hSubMenu;
	switch (iMsg)
	{
	case WM_CREATE:
		hMenu = GetMenu(hwnd);
		hSubMenu = GetSubMenu(hMenu, 1);
		EnableMenuItem(hSubMenu, ID_EDITCOPY, MF_GRAYED);
		EnableMenuItem(hSubMenu, ID_EDITPASTE, MF_GRAYED);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

일단 복사하기, 붙여넣기 모두 비활성화 한 상태로 프로그램이 실행된다

복사할 항목을 선택하게 되면 복사하기 버튼을 활성화 시키고

복사하기 버튼을 누르면 붙여넣기 버튼이 활성화 된다.

 

EnableMenu() 함수가 메뉴의 활성화 비활성화를 관리한다.

MF_GRAYED 매개변수는 메뉴를 비활성화 한다는 뜻이고

MF_ENABLED 로 지정해주면 메뉴를 활성화 한다.

 

double LengthPts(int x1, int y1, int x2, int y2)
{
	return(sqrt((float)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))));
}

BOOL InCircle(int x, int y, int mx, int my)
{
	if (LengthPts(x, y, mx, my) < BSIZE) return TRUE;
	else return FALSE;
}

어디서 많이 본 익숙한 함수이다.

 

화면에 원을 출력하고 그 원을 클릭하면 복사할 개체를 선택했다고 가정하기 때문에

 

원 내부를 클릭했는지 판별하는 함수를 또다시 사용하게 되었다.

 

#include <math.h>
#define BSIZE 40

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	HDC					hdc;
	PAINTSTRUCT			ps;
	static HMENU		hMenu, hSubMenu;
	int					mx, my;
	static BOOL			Select;
	static BOOL			Copy;
	static int			x, y;
	switch (iMsg)
	{
	case WM_CREATE:
		hMenu = GetMenu(hwnd);
		hSubMenu = GetSubMenu(hMenu, 1);
		Select = FALSE;
		Copy = FALSE;
		x = 300; y = 300;
		break;
	case WM_PAINT:
		EnableMenuItem(hSubMenu, ID_EDITCOPY,
			Select ? MF_ENABLED : MF_GRAYED);
		EnableMenuItem(hSubMenu, ID_EDITPASTE,
			Copy ? MF_ENABLED : MF_GRAYED);
		hdc = BeginPaint(hwnd, &ps);

		if (Select)
			Rectangle(hdc, x - BSIZE, y - BSIZE, x + BSIZE, y + BSIZE);
		Ellipse(hdc, x - BSIZE, y - BSIZE, x + BSIZE, y + BSIZE);
		EndPaint(hwnd, &ps);
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID_EDITCOPY:
			Copy = TRUE;
			InvalidateRgn(hwnd, NULL, TRUE);
			break;
		}
		break;
	case WM_LBUTTONDOWN:
		mx = LOWORD(lParam);
		my = HIWORD(lParam);
		if (InCircle(x, y, mx, my)) Select = TRUE;
		InvalidateRgn(hwnd, NULL, TRUE);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

원이 클릭되었는지 여부를 저장하는 Select 부울 변수가 있다.

복사하기 메뉴가 클릭되었는지 확인하는 Copy 부울 변수가 있다.

 

원 내부가 클릭되었으면 원 주위로 네모가 생기고 

 

Select에 true값이 저장되므로 WM_PAINT에 복사하기 버튼의 EnableMenuItem() 함수 내의 삼항연산자에서 MF_ENABLED가 선택되어 메뉴가 활성화 된다.

 

복사하기 버튼을 클릭하면 Copy에 true값이 저장되고 WM_PAINT에 붙여넣기 버튼의 EnableMenuItem() 함수 내의 삼항연산자에서 MF_ENABLED가 선택되어 붙여넣기 메뉴도 활성화 된다.

 

초기상태는 모두 비활성화
클릭을 하면 네모가 생긴다.
복사하기가 활성화
복사하기를 클릭하면 붙여넣기도 활성화

 

4장은 메뉴를 컨트롤하는것도 할 수 있구나 라는 것을 알려주는 재미있는 챕터였다.