소연의_개발일지
article thumbnail

Tray 기능이란?

윈도우의 트레이 영역(우측 하단)에 아이콘을 등록하여 백그라운드작업의 상태를 확인하거나 간단하게 컨트롤 할 수 있다.

 

Tray 주요 함수와 속성

 

-  Shell_NotifyIcon(DWORD dwMessage, PNOTIFYICONDATA pnid )

매개변수로 속성ID NOTIFYICONDATA 구조체를 가진다.

 

-  DWORD dwMessage

속성 ID 내 용
NIM_ADD Tray영역에 등록
NIM_DELETE Tray영역에서 제거
NIM_MODIFY 상태를 수정

 

-  PNOTIFYICONDATA pnid

구조체 멤버 내 용
DWORD cbSize 구조체의 크기
HWND hWnd 해당 Tray를 소유한 핸들
UINT uID Tray ID
UINT uFlags Tray가 가지는 속성
UINT uCallbackMessage NIF_MESSAGE를 속성으로 가질 때 사용.
보낼 메시지를 설정
HICON hIcon NIF_ICON을 속성으로 가질 때 사용.
Tray에 보여줄 Icon을 설정
TCHAR szTip NIF_TIP을 속성으로 가질 때 사용.
Tray에 툴팁으로 띄울 내용을 설정

 

 

예제 프로그램: Tray 구현해보기

▶ 예제 프로그램의 구성

1. 대화상자의 x를 누르면 창이 사라지며 트레이에 등록된다. 

2. 등록된 아이콘에 커서를 올렸을 때 툴팁이 나온다.

3. 우클릭 시 메뉴가 뜨고 Open 버튼을 눌렀을 때 다이얼로그가 열린다. Close 버튼을 클릭하면 다이얼로그가 종료된다.

 

1. 필요 리소스 제작

프로젝트 우클릭 - [리소스 추가]

 

[Menu] 클릭 → [새로 만들기] 클릭

 

Menu 탭 밑에 Open 과 Close 작성해주기

 

 

트레이 속성에서 ID도 기본값에서 IDR_MENU_TRAY로 변경하였다.

 

 

2. 필요 함수 구현

 

헤더에 #define 선언

#define WM_TRAYICON_MSG WM_USER + 1

 

헤더에 트레이 객체 생성

// -- 트레이 관련
NOTIFYICONDATA  nid;		// 트레이 객체
BOOL m_bTray = FALSE;		// 트레이 생성 flag
// 트레이 관련 함수 선언
void InitTray();			// 트레이 생성
void OnExit();				// 프로그램 종료
void OnTrayPopupClose();	// 트레이 Open
void OnTrayPopupOpen();		// 트레이 Close
LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam);

 

 

cpp 파일에 함수 추가

함수 이름 함수 설명
void InitTray(); 트레이 생성
void OnExit(); 프로그램 종료
void OnTrayPopupClose(); 트레이 열기
void OnTrayPopupOpen(); 트레이 닫기
LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam); 이벤트 발생시 트레이 상태 변경

 

void InitTray();

void CTrayCppExampleDlg::InitTray()
{
	nid.cbSize = sizeof(nid);
	nid.hWnd = GetSafeHwnd();
	nid.uID = 0;
	nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
	nid.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);	//아이콘 변경 필요시 여기서 변경
	lstrcpy(nid.szTip, TEXT("View DBAgent program"));
	nid.uCallbackMessage = WM_TRAYICON_MSG;
}

 

void OnExit();

void CTrayCppExampleDlg::OnExit()
{
	Shell_NotifyIcon(NIM_DELETE, &nid); //종료시 삭제작업을 해줘야 바로 아이콘이 사라진다.

	DestroyWindow();
}

 

void OnTrayPopupClose();
void OnTrayPopupOpen();

void CTrayCppExampleDlg::OnTrayPopupClose()
{
	CString strMessage;
	strMessage.Format(_T("정말 프로그램을 종료하시겠습니까?"));
	if (AfxMessageBox(strMessage, MB_YESNO) == IDNO) {
		return;
	}

	if (m_bTray == TRUE) {
		Shell_NotifyIcon(NIM_DELETE, &nid);
		m_bTray = FALSE;
		OnExit();

	}

	//m_bExit = TRUE;
	AfxGetMainWnd()->PostMessage(WM_CLOSE);
}


void CTrayCppExampleDlg::OnTrayPopupOpen()
{
	if (m_bTray == TRUE) {
		m_bTray = FALSE;
		Shell_NotifyIcon(NIM_DELETE, &nid);
	}

	ShowWindow(SW_SHOW);
	::SetWindowPos(AfxGetMainWnd()->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}

 

 

LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam);

LRESULT CTrayCppExampleDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam)
{
	switch (lParam) 
	{
		case WM_LBUTTONDBLCLK:	// 더블클릭했을 때
			{
				ShowWindow(SW_SHOW);					// 창 띄우기
				Shell_NotifyIcon(NIM_DELETE, &nid);		// TRAY 삭제
			}
			break;
		case WM_RBUTTONUP:	// 오른쪽 마우스 클릭했을 때
			{
				SetForegroundWindow();

				CPoint ptMouse;
				::GetCursorPos(&ptMouse);

				CMenu menu;
				menu.LoadMenu(IDR_MENU_TRAY);	// 메뉴 띄우기
				CMenu *pMenu = menu.GetSubMenu(0);
				pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, AfxGetMainWnd());
			}
			break;
	}
	return TRUE;
}

 

 


 

1. 닫기 버튼 눌렀을 때 창이 사라지며 트레이에 등록하기

 

닫기 버튼 눌렀을 때는 두가지 방법으로 구현이 가능하다. 

- Onclose() 함수 사용

- OnSysCommand() 함수 사용

 

여기서 OnSysCommand()로 하는 방법을 설명한다.

MFC 대화상자 클래스를 생성하면 OnSysCommand함수가 자동으로 생성되어 있다.

여기에 닫기 버튼을 눌렀을 때 경우를 분기하여 수정한다.

void CTrayCppExampleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}

	if (nID == SC_CLOSE)
	{
		Shell_NotifyIcon(NIM_ADD, &nid);
		ShowWindow(SW_HIDE);
	}

	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

 

2. OninitDialog에 InitTray() 추가

 

3. 메세지맵에 메뉴 버튼 클릭시 트레이 Open/Close 연결해준다.

 

연결해주지 않으면 메뉴버튼 클릭시 함수가 연결되지 않음!!

ON_MESSAGE(WM_TRAYICON_MSG, OnTrayNotify)
ON_COMMAND(ID_MENU_CLOSE, &CTrayCppExampleDlg::OnTrayPopupClose)
ON_COMMAND(ID_MENU_OPEN, &CTrayCppExampleDlg::OnTrayPopupOpen)

 

실행화면

 

 

예제 코드 소스 입니다.

https://github.com/guaba98/TrayCppExample

 

GitHub - guaba98/TrayCppExample: Cpp Tray 기능 예제입니다.

Cpp Tray 기능 예제입니다. Contribute to guaba98/TrayCppExample development by creating an account on GitHub.

github.com

 

profile

소연의_개발일지

@ssoyxon

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!