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
'개발공부 > C++' 카테고리의 다른 글
[C++ MFC] 창 최소화/최대화/작업표시줄로 내리기 (0) | 2024.08.05 |
---|---|
[C++] csv 파일 쓰기 (0) | 2024.07.22 |
[C++ MFC] 다이얼로그 배경색 변경 (0) | 2024.04.16 |
[C++] 템플릿 공부하기 (0) | 2024.04.09 |
[C++] 하위 폴더 자동 생성 코드 (0) | 2024.01.16 |