트레이아이콘과 풍선알림
▶ 트레이아이콘
Windows 운영체제에서는 트레이 아이콘이라는 것이 있습니다.
작업표시줄의 우측 하단을 통해서 살펴볼 수 있습니다. 누구나 쉽게 접할 수 있을 것입니다.
트레이아이콘을 응용하여서 메뉴, 알림, 툴팁 등 을 이용하여서 사용자에게 여러 편의성을 제공할 수 있다는 점이 큰 장점입니다.
▲ win10 트레이아이콘 목록
▲ win7 트레이아이콘 목록
익숙하게 보던 것들입니다. 그리고 아이콘을 우측 클릭하면 발생하는것을 트레이 메뉴라고 합니다.
다른 프로그램들을 보게되면 트레이아이콘을 실시간으로 모양이 바뀌면서 재미난 모습을 보여주는 것들도 있습니다. 오늘은 그렇게 까지 응용하지는 않고 핵심 부분만 볼 것입니다.
▲ ToolTip 옵션
▲ 트레이 메뉴
추가적으로 트레이 메뉴의 기능들입니다. 트레이아이콘에 마우스를 올렸을 경우 발생하는 ToolTip이 있고, 우클릭을 했을 경우 발생되는 트레이 메뉴 기능이 있습니다. 트레이 메뉴 기능은 트레이 메뉴에서 지원하는 부분은 아니므로 추가 해야합니다.
▶ 풍선알림
트레이아이콘에서 좀더 추가하여서 알림을 띄워주는 부분이 있습니다. 예를들어, 백신프로그램에서 "검사를 완료했습니다" 혹은 다운로드 프로그램에서 "다운로드가 완료되었습니다" 풍선 메세지를 발생합니다.
그 알림을 풍선알림이라고 합니다.
▲ Win7 풍선알림
Window7의 경우에는 이렇게 생겨먹었습니다. 그 말인 즉슨 다른 버전은 다르다는 것이겠죠? 네
▲ Win10 알림
Window10의 환경에서 알림은 이렇게 발생된답니다. 그래서 이것을 풍선알림이라고 해야하는지 고민이 되었습니다. 그래서 단순히 알림이라고 생각됩니다.
아래에서 관련하여서 정리도 할겸 해서 사용하는 부분을 작성해보겠습니다.
코드작성
▲ 다이얼로그
기능은 간단하게 Tray Add 버튼을 클릭하면 트레이아이콘이 생성되면서 Dialog는 사라집니다.
핵심 코드를 먼저 소개하겠습니다.
▣ Tray Add 버튼 클릭시
/// TrayBalloon/TrayBalloonDlg.cpp
#define WM_TRAY_NOTIFYICACTION WM_APP+10
enum {
TRAY_BALLOON = 0
};
///Tray Add 버튼 클릭시 이벤트 함수
// 트레이아이콘 생성
void CTrayBalloonDlg::OnBnClickedTrayAdd()
{
NOTIFYICONDATA nid;
ZeroMemory(&nid, sizeof(nid));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.uID = 0; // 트레이 구조체 아이디.
nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
nid.hWnd = m_hWnd;
nid.hIcon = AfxGetApp()->LoadIconW(IDR_MAINFRAME);
nid.uCallbackMessage = WM_TRAY_NOTIFYICACTION;
lstrcpy(nid.szTip, _T("트레이아이콘 이랍니다."));
::Shell_NotifyIcon(NIM_ADD, &nid);
SetTimer(TRAY_BALLOON, 1000 * 60, NULL);
AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); // 다이얼로그는 숨는다.
}
NOTIFYICONDATA 구조체가 트레이아이콘의 핵심이 된다. 자세한부분은 아래링크를 따라가면된다.
https://msdn.microsoft.com/en-us/library/ms910625.aspx
nid.uFlags
NIF_ICON : hicon 사용.
NIF_MESSAGE : uCallbackMessage 사용.
NIF_TIP : szTip 사용.
NIF_INFO : 알림 사용
Shell_NotifyIcon 함수는 3가지 용도로 사용된다.
Shell_NotifyIcon(NIM_ADD, &nid) - 트레이 추가
Shell_NotifyIcon(NIM_MODIFY, &nid) - 트레이 변경
Shell_NotifyIcon(NIM_DELETE, &nid) - 트레이 삭제
///nid.uCallbackMessage = WM_TRAY_NOTIFYICACTION 콜백함수
LRESULT CTrayBalloonDlg::OnTaryNotifyAction(WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_RBUTTONDOWN:
{
CPoint ptMouse;
::GetCursorPos(&ptMouse);
CMenu menu;
menu.LoadMenu(IDR_TRAYMENU);
CMenu *pMenu = menu.GetSubMenu(0); //활성화 할 메뉴 지정
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, AfxGetMainWnd());
}
break;
case WM_LBUTTONDBLCLK:
{
NOTIFYICONDATA nid;
ZeroMemory(&nid, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.uID = 0;
nid.hWnd = GetSafeHwnd();
BOOL bRet = ::Shell_NotifyIcon(NIM_DELETE, &nid); //트레이아이콘 제거
if (!bRet)
{
::AfxMessageBox(_T("트레이아이콘 제거실패"));
return -1;
}
AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //윈도우 활성화
KillTimer(TRAY_BALLOON);
}
break;
}
return 1;
}
콜백함수의 기능
WM_RBUTTONDOWN (우측클릭)했을 경우에 트레이 메뉴를 발생시켜주는 부분
WM_LBUTTONDBCLK (더블클릭) 했을경우 트레이아이콘 제거하고 다이얼로그를 다시 보여준다.
////SetTimer(TRAY_BALLOON, 1000*60, NULL) 타이머함수
void CTrayBalloonDlg::OnTimer(UINT_PTR nIDEvent)
{
int nID = nIDEvent;
switch (nID)
{
case TRAY_BALLOON:
{
NOTIFYICONDATA nid;
ZeroMemory(&nid, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.dwInfoFlags = NIIF_WARNING; // 풍선 알림아이콘 종류
nid.uFlags = NIF_MESSAGE | NIF_INFO | NIF_ICON;
nid.uTimeout = 3000;
nid.hWnd = AfxGetApp()->m_pMainWnd->m_hWnd;
nid.uCallbackMessage = WM_TRAY_NOTIFYICACTION;
nid.hIcon = AfxGetApp()->LoadIconW(IDR_MAINFRAME);
lstrcpy(nid.szInfo, m_pTrayText);
lstrcpy(nid.szInfoTitle, m_pTrayTitle);
::Shell_NotifyIcon(NIM_MODIFY, &nid);
}
break;
}
CDialogEx::OnTimer(nIDEvent);
}
타이머가 1000*60 밀리세컨드 ( 1분 ) 단위로 돌고있다.
1분마다 풍선 알림을 발생시킨다.
nid.dwInfoFlags 몇 가지만 살펴보겠습니다.
NIIF_WARNING - 경고 알림을 띄운다.
NIIF_NONE - 아이콘이 없는 알림을 띄운다.
NIIF_ERROR - 에러 아이콘의 알림을 띄운다.
::Shell_NotifyIcon(NIM_MODIFY, &nid)
기존에 NIM_ADD 된 것을 수정하는 것이기 때문에 NIM_MODIFY를 사용합니다.
///알림의 Title, Text
BOOL CTrayBalloonDlg::OnInitDialog()
{
...
...
...
lstrcpy(m_pTrayTitle, _T("Tray Icon Title"));
lstrcpy(m_pTrayText, _T("안녕하세요 트레이아이콘 풍선 문구입니다. \n풍선문구가 잘 나타납니다. 다행이에요"));
}
알림에 발생되는 Title 과 Text는 저의 경우에는 OnInitDialog() 함수에서 미리 지정하였습니다.
///메시지관련 처리
BEGIN_MESSAGE_MAP(CTrayBalloonDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_TRAY_ADD, &CTrayBalloonDlg::OnBnClickedTrayAdd)
ON_BN_CLICKED(IDC_TRAY_BALLON, &CTrayBalloonDlg::OnBnClickedTrayBallon)
ON_WM_DESTROY()
ON_MESSAGE(WM_TRAY_NOTIFYICACTION, OnTaryNotifyAction)
ON_COMMAND(ID_TRAYMENU_EXIT, OnTrayMenuExit)
ON_COMMAND(ID_TRAYMENU_DIALOG_OPEN, OnTrayMenuDialogOpen)
ON_WM_TIMER()
END_MESSAGE_MAP()
메시지 관련하여서는 조금 많이 추가 되어있지만 크게 대단한부분은 없습니다.
ON_BN_CLICKED - 버튼 클릭 이벤트처리
ON_MESSAGE(WM_TRAY_NOTIRYICATION, OnTrayNorifyAction) - 트레이 아이콘 추가시 콜백 함수
ON_COMMAND - 트레이 메뉴 이벤트 처리하기 위해서 사용됨
크게 설명이 필요 없을 것 같네요.
▣ Balloon 버튼 클릭시
void CTrayBalloonDlg::OnBnClickedTrayBallon()
{
NOTIFYICONDATA nid;
ZeroMemory(&nid, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.uID = 0;
nid.uFlags = NIF_MESSAGE | NIF_INFO | NIF_ICON;
nid.hWnd = m_hWnd;
nid.hIcon = AfxGetApp()->LoadIconW(IDR_MAINFRAME);
nid.uCallbackMessage = WM_TRAY_NOTIFYICACTION;
nid.dwInfoFlags = NIIF_ERROR; // 풍선 알림아이콘
lstrcpy(nid.szInfo, m_pTrayText);
lstrcpy(nid.szInfoTitle, m_pTrayTitle);
::Shell_NotifyIcon(NIM_ADD, &nid);
}
깊은 에러처리나 예외처리는 딱히 하지 않았습니다. 소스코드가 필요하시다면 따로 올려두겠습니다.
아래에 실행 파일 첨부해두었습니다.
바이러스 의심되시면 바이러스 토탈 이용해보세요.
https://www.virustotal.com/ko/
https://www.microsoft.com/ko-kr/download/details.aspx?id=48145
혹여나 mfc140u.dll 이 없어 실행이 안된다는 문구가 있다면 Visual Studio Visual C++ 재배포 가능 패키지를 다운받아 설치하면 됩니다.
감사합니다.
'훈, IT 공부 > C,C++,MFC' 카테고리의 다른 글
C++, Gdiplus 사용하여 png 생성하기 (0) | 2018.09.09 |
---|---|
[MFC]CreateFont (0) | 2018.08.31 |
[궁금점]winApi WriteFile 함수의 동작 (0) | 2018.06.02 |
궁금점, 파일을 읽을때 NULL 문자를 읽을까? (0) | 2018.05.31 |
[MFC] WM_MOUSEHOVER, WM_MOUSELEAVE 메시지 이용방법 (0) | 2018.05.07 |
댓글