본문 바로가기
프로그래밍/C++

[VC++] 트레이 아이콘 프로그램 코딩 방법

by 건우아빠유리남편 2011. 1. 3.
반응형


개인적으로 트레이에 관한 내용을 정리할 일이 있어서 강좌로 올려봅니다...
아직 트레이를 안써보신 분들께 조금이나마 도움이 됐으면 합니다.

1. 트레이 통지와 관련된 함수와 파라미터

BOOL WINAPI Shell_NontifyIcon(DWORD dwMessage, PNOTIFYICONDATA pnid);

dwMessage
    - NIM_ADD : 트레이에 새로운 아이콘 추가
    - NIM_DELETE : 트레이 영역의 아이콘 제거
    - NIM_MODIFY : 트레이 영역에 있는 아이콘 수정


typedef struct _NOTIFYICONDATA
{
    DWORD    cbSize;
    HWND    hWnd;
    UINT    uID;
    UINT    uFlags;
    UINT    uCallbackMessage;
    HICON    hIcon;
    char    szTip[64];
} NOTIFYICONDATA, *PNOTIFYICONDATA;

    - cbSize : 구조체의 크기
    
    - hWnd : 윈도우 핸들
    
    - uID : 아이콘 식별자, 호출한 애플리케이션의 아이콘을 다른것과 구ㅕㄹ해서
            식별할수 있게 해주는 사용자 정의값

    - uFlags : NIF_MESSAGE  : uCallbackMessage 사용
           NIF_ICON    : hIcon 사용
           NIF_TIP    : szTip 사용

    - uCallbackMessage : 아이콘이 hWnd윈도우와 통신하기 위해서 사용할 메시지 ID.
                 메시지는 WM_APP의 오프셋으로 선언되는 사용자 정의 메시지이다.
    
    - hIcon : 화면에 그릴 아이콘의 핸들.

    - szTip : 아이콘의 툴팁을 위한 텍스트.

2. 트레이에 아이콘 추가

    NOTIFYICONDATA    nid;

    // 구조체 초기화
    ZeroMemory(&nid, sizeof nid);

    // 구조체 설정
    nid.cbSize = sizeof nid;
    nid.hWnd = hWnd;
    nid.uID = ICON_ID;
    nid.uFlags = NIF_TIP | NIF_ICON | NIF_MESSAGE;
    nid.uCallbackMessage = WM_MESSAGE;
    nid.hIcon = hSmallIcon;
    lstrcpy(nid.szTip, "Sample");

    // 트레이 영역에 추가
    Shell_NotifyIcon(NIM_ADD, &nid);

3. 트레이 아이콘 제거
    - 제거시에는 hWnd와 uID멤버만 셋팅하면 된다.

    NOTIFYICONDATA    nid;

    ZeroMemory(&nid, sizeof nid);

    nid.cbSize = sizeof nid;
    nid.hWnd = hWnd;
    nid.uID = ICON_ID;

    Shell_NotifyIcon(NIM_DELETE, &nid);

4. 트레이로 부터의 메시지 수신
    - 마우스와 관련된 메시지만 통지한다.
    
    wParam : 등록시에 설정한 ID(nid.uID).
    lParam : 메시지 종류 (WM_LBUTTONUP, ...).

    ex)
        case WM_MESSAGE:
            if(wParam == ICON_ID)
            {
                switch(lParam)
                {
                    case WM_RBUTTONUP:
                        // 처리
                        break;
                }
            }

            break;

5. Context메뉴
    - 일반적으로 트레이에서 오른쪽 버튼을 누르면 context 메뉴를 화면에 표시한다.
    아래는 그러한 일을 하는 코드의 일부이다.

    POINT pt;
    GetCursorPos(&pt);

    SetForegroundWindow(hWnd);
    TrackPopupMenu(menu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL);
    SetForegroundWindow(hWnd);

    - 주의할 점은 TrackPopupMenu를 사이에 두고 SetForegroundWindow를 꼭 호출해
    주어야 한다는 점이다. 만약 호출하지 않으면 메뉴가 사라지지 않는다.

6. For MFC.
    - 아래는 MFC에서 일반적으로 하게 되는 트레이 작업 영역에 추가 및 삭제를 위한 코드의
    일부이다.

    6.1 추가
    #define WM_TRAYNOTIFY WM_APP + 1

    NOTIFYICONDATA    nid;

    ::ZeroMemory(&nid, sizeof nid);

    nid.cbSize        = sizeof nid;
    nid.hIcon        = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    nid.hWnd        = this->m_hWnd;
    nid.uID            = IDR_MAINFRAME;
    nid.uFlags        = NIF_TIP | NIF_ICON | NIF_MESSAGE;
    nid.uCallbackMessage    = WM_TRAYNOTIFY;
    
    lstrcpy(nid.szTip, "Test");

    ::Shell_NotifyIcon(NIM_ADD, &nid);

    6.2 제거
    NOTIFYICONDATA    nid;

    ::ZeroMemory(&nid, sizeof nid);

    nid.cbSize    = sizeof nid;
    nid.uID        = IDR_MAINFRAME;
    nid.hWnd    = this->m_hWnd;

    ::Shell_NotifyIcon(NIM_DELETE, &nid);

    6.3 메시지 처리
    ON_MESSAGE(WM_TRAYNOTIFY, OnTrayNotify)

    LONG TestDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam)
    {
        CMenu    menu, *pTrayMenu;
        CPoint    pt;

        if(wParam == IDR_MAINFRAME)
        {
            switch(lParam)
            {
            case WM_RBUTTONUP:
                menu.LoadMenu(IDR_TRAYMENU);
                pTrayMenu = menu.GetSubMenu(0);

                ::GetCursorPos(&pt);

                SetForegroundWindow();
                pTrayMenu->TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, this, NULL);
                SetForegroundWindow();

                pTrayMenu->DestroyMenu();
                menu.DestroyMenu();
                break;

            case WM_LBUTTONDBLCLK:
                if(!IsWindowVisible())
                    ShowWindow(SW_SHOW);

                SetForegroundWindow();
                break;
            }
        }

        return 0;
    }
반응형

댓글