Develope/MFC2013. 1. 14. 18:40

오늘 작업 내용 중에 기본 기능으로 구현 한 다이얼로그 트레이 동작 기능을 정리 해보려 한다.


실행하는 다이얼로그 기반의 응용 프로그램을 Tray에 등록하고,


시스템 메뉴의 최소화, 혹은 X 버튼 클릭 시 종료가 아닌, 트레이로 상주하도록 구현해 보았다.




일단 기본적으로 짚고 넘어가자.


1. 시스템 메뉴란? 


  일반적으로 사용하는 Window의 프로그램 창의 오른쪽 상단에 있는 그것.


 


<시스템 메뉴>


2. Tray Icon 이란?


  MS 윈도우 계통의 작업 표시줄의 하단 우측편에에 작은 아이콘으로 등록어 기능을 수행하는 그룹을 말한다.

 




  < 트레이 아이콘 >




각설하고, 


일단 내가 했던 작업 방식으로 진행해보도록 하겠음.


1. 트레이에 사용 될 메뉴 리소스 작성

 

 - 일단, 트레이 우클릭 시 표시 될 메뉴 리소스를 먼저 작성한다.

 

 




<필요한 메뉴 리소스를 추가한다>

2. 메뉴에 대한 이벤트를 추가한다.

 


<메뉴 리소스 추가 및 서브 메뉴 추가>


<각 서브메뉴에 이벤트 처리기 추가>



3. 헤더 및 cpp 파일에 메뉴 이벤트에 대한 동작을 구현한다.

// 트레이 메뉴 중 정보 창 호출
void CXXXDlg::OnTraymenuAbout()
{
	CAboutDlg* pDlg = new CAboutDlg;
	pDlg->DoModal();
	delete pDlg;
}

// 트레이 메뉴 중 다이얼로그 복원
void CXXXDlg::OnTraymenuOpen()
{
        SetRestoreDialog(); <- 이건 나중에 구현 후 추가해 준다.
}

// 종료시 호출
void CXXXDlg::OnDestroy()
{
	CDialog::OnDestroy();
}

기본형으로 정보창만 호출하도록 기본 구현 하였다.

트레이 구현 시 추가로 더 작업하기 위해 나중에 다시 작업한다.


4. 커맨드에 대한 이벤트 처리 추가

 

<다이얼로그 속성의 메시지 버튼에서 메시지 이벤트를 추가해준다>




































위와 같이 이벤트 추가 후, 오버라이드 된 함수를 구현해준다.


 // 트레이 메뉴 중 정보 창 호출
void CXXXDlg::OnTraymenuAbout()
{
	CAboutDlg* pDlg = new CAboutDlg;
	pDlg->DoModal();
	delete pDlg;
}

// 트레이 메뉴 중 다이얼로그 복원
void CXXXDlg::OnTraymenuOpen()
{
        SetRestoreDialog(); <- 이건 나중에 구현 후 추가해 준다.
}

// 종료시 호출
void CXXXDlg::OnDestroy()
{
	CDialog::OnDestroy();
}

WM_SIZE 메시지는 다이얼로그의 사이즈가 변경 되었을 경우 호출되는 내부 메시지 함수다.

이것을 virtual 로 상속받아 오버라이드 하여 사용한다.

오버라이드의 개념을 모르겠다면... 그것부터 확실히 숙지하고 작업 하도록 하자.


5. 트레이 동작 함수 추가

private:
	void SetMinimizeToTray();
	void SetRestoreDialog();
	LRESULT OnTrayIconClick(WPARAM wParam, LPARAM lParam);	// 트레이 아이콘 클릭 메세시 처리 Callback 함수


SetMinimizeToTray() : 다이얼로그를 트레이로 보내는 함수

SetRestoreDialog() : 트레이에 있던 정보를 삭제 후 다이얼로그를 보여주는 함수

OnTrayIconClick() : 트레이 아이콘 클릭 시 수행 될 콜백 함수

#define TRAY_NOTIFY (WM_APP + 100) // 트레이 설정 함수 void CXXXDlg::SetMinimizeToTray() { NOTIFYICONDATA nId; ShowWindow(SW_SHOWMINIMIZED); PostMessage(WM_SHOWWINDOW, FALSE, SW_OTHERUNZOOM); nId.cbSize         = sizeof(NOTIFYICONDATA); nId.hWnd = this->m_hWnd; nId.uID         = 0; Shell_NotifyIcon(NIM_DELETE, &nId); nId.cbSize         = sizeof(NOTIFYICONDATA); nId.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); nId.hWnd = this->m_hWnd; CString str; GetWindowText(str); _tcscpy_s(nId.szTip, str.GetBuffer(str.GetLength()+1)); str.ReleaseBuffer(); nId.uID = 0; nId.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nId.uCallbackMessage = TRAY_NOTIFY; Shell_NotifyIcon(NIM_ADD, &nId); } // 윈도우 다이얼로그 복원 함수 void CXXXDlg::SetRestoreDialog() { NOTIFYICONDATA nId; nId.cbSize = sizeof(NOTIFYICONDATA); nId.hWnd = this->m_hWnd; nId.uID = 0; Shell_NotifyIcon(NIM_DELETE, &nId); ShowWindow(SW_RESTORE); SetForegroundWindow(); }

PostMessage() 를 통해 트레이의 메세지를 추가해 준다.


BEGIN_MESSAGE_MAP(CXXXDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_SIZE()
	ON_MESSAGE(TRAY_NOTIFY, OnTrayIconClick)
	ON_COMMAND(ID_TRAYMENU_ABOUT, &CXXXDlg::OnTraymenuAbout)
	ON_COMMAND(ID_TRAYMENU_OPEN, &CXXXDlg::OnTraymenuOpen)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDOK, &CXXXDlg::OnBnClickedOk)
END_MESSAGE_MAP()

메세지 맵에 위에서 등록 한 메세지를 등록해준다.

 // Tray Icon 클릭 시 처리하는 콜백 함수
LRESULT CINESRemoteDMServerDlg::OnTrayIconClick(WPARAM wParam, LPARAM lParam)
{
	switch(lParam)
	{
	case WM_LBUTTONDBLCLK:		// 왼쪽 버튼 더블 클릭의 경우 다이얼로그 복원
		{
			SetRestoreDialog();
			break;
		}
	case WM_RBUTTONDOWN:		// 오른쪽 버튼 클릭의 경우 메뉴 호출
		{
			CPoint ptMouse;
			::GetCursorPos(&ptMouse);

			CMenu	Menu;
			Menu.LoadMenu(IDR_TRAY_MENU);
			CMenu*	pMenu = Menu.GetSubMenu(0);
			pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, AfxGetMainWnd());
						
			break;
		}
	}

	return 0;
}

앞서 선언되었던 트레이 아이콘 클릭 시 호출되는 콜백함수를 구현해준다.




결론적으로 간단히 정리하자면,


시스템 메뉴 최소화 클릭 시 ON_WM_SIZE 메세지를 통하여 트레이 아이콘을 생성하여 등록하고,

현재의 다이얼로그는 숨김상태로 바꾼다.

트레이 좌, 우 클릭 시 해당하는 메시지를 호출하여 다이얼로그를 다시 보이게 하고 트레이에 등록된 정보를 없애거나,

아니면 메뉴를 호출하여 해당하는 동작을 수행하도록 한다.


조금만 응용하면, OnCommand() 메시지 처리 함수에서 시스템 메뉴의 X 버튼을 클릭 하였을 경우에도 트레이로 동작하도록

수행할 수 있다.


Posted by AsCarion