Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[질문]vb에서 트레이 아이콘 만드는 방법 좀..

81 views
Skip to first unread message

서동수

unread,
Aug 14, 2001, 12:58:33 AM8/14/01
to
VB 에서 트레이 아이콘 (오른쪽 귀퉁이의 아아콘, 시작시 같이 뜨는 거 있지요?)
쉽게 만드는 방법 좀 알려 주세요.
뭔가 OCX 가 있을 것도 같은데..
도와 주십시요.


환상

unread,
Aug 15, 2001, 9:32:45 PM8/15/01
to
조금 복잡한듯 한데요...
방법을 일단은 소개하죠... ^^!

먼저 클래스 모듈을 하나 만듭니다.
아래의 소스를 붙여넣기합니다.
'-----------------------------------------------------
Option Explicit

'설명
' 클래스 모듈 전체와
'--추가코드
'mSystemTray 모듈
'
'시스템 트레이에서 일어날 이벤트를 받을 수 있도록
'이벤트 프로시저의 선언
'Private WithEvents SystemTray As SystemTray
'
'시스템 트레이 추가할 때는 다음 코드가 필요함.
''{시스템 트레이에 등록.
''앞에서 WithEvents 키워드로 선언했으므로
''New 키워드로 생성함.
''그리고 이벤트를 받을 윈도우 핸들을 인수로 넘김.
'Set SystemTray = New SystemTray
'With SystemTray
' Set .TrayIcon = Me.Icon
' .TrayHwnd = Me.hwnd
' .TrayTip = Alarm.Times
' .InTray = True
'End With
''}
'시스템 트레이에서 일어나는 이벤트를 받을 수 있도록 다음
'코드가 필요함
'Private Sub SystemTray_MouseDown(Button As Integer)
' Me.Visible = True
' SystemTray.InTray = False
'End Sub

'시스템 트레이에 아이콘이 나타나 있는 지 여부
Private mInTray As Boolean
'시스템 트레이에 마우스가 이동할 때 나타나는 ToolTip Text
Private mTrayTip As String
'서브 클래스시킬 때 필요한 컨트롤의 핸들.
Private mTrayHwnd As Long
'시스템 트레이에 나타날 아이콘
Private mTrayIcon As StdPicture
'각 핸들과 메세지에 대한 중복되지 않는 ID.
'(이 프로그램에서는 항상 0임.)
Private TrayID As Long
'}
'{트레이 시스템에 나타날 컨트롤에서 발생할 사용자 정의 이벤트
Public Event MouseMove()
Public Event MouseDown(Button As Integer)
Public Event MouseUp(Button As Integer)
Public Event MouseDblClick(Button As Integer)
'}

Private Sub Class_Initialize()
'기본 ToolTip을 지정.
TrayTip = "VB를 이용한 시스템 트레이"
End Sub

Private Sub Class_Terminate()
'{시스템 트레이에 아이콘이 있는 상태로 종료되면
' 안되므로 아이콘이 있다면 아이콘을 없앰.
If mInTray Then
Me.InTray = False
End If
'}
End Sub

'{시스템 트레이에 핸들을 제공할 컨트롤을 설정하거나 리턴함.
Public Property Let TrayHwnd(HWndToReceiveMsg As Long)
mTrayHwnd = HWndToReceiveMsg
End Property
Public Property Get TrayHwnd() As Long
TrayHwnd = mTrayHwnd
End Property
'}

'{시스템 트레이에 나타날 아이콘을 설정하거나 리턴함.
Public Property Set TrayIcon(Icon As StdPicture)
'NOTIFYICONDATA 구조체
Dim Tray As NOTIFYICONDATA
Dim Result As Long

'{Icon 변수가 Nothing이거나 아이콘이 아니면(Bmp, Cur 등) 빠져나감.
If Icon Is Nothing Then Exit Property
If Icon.Type <> vbPicTypeIcon Then Exit Property
'}

'시스템 트레이에 아이콘이 있을 때만 변경함.
If mInTray Then
'콜백 메세지를 받을 때 필요한 유일한 번호.
Tray.uID = TrayID
'메세지를 받을 핸들
Tray.hwnd = mTrayHwnd
'시스템 트레이에 나타날 아이콘
Tray.hIcon = Icon.Handle
'유효한 데이타 항목에 플래그를 설정함.
Tray.uFlags = NIF_ICON
'구조체의 크기
Tray.cbSize = Len(Tray)

'시스템 트레이에 데이터를 보냄.
Result = Shell_NotifyIcon(NIM_MODIFY, Tray)
End If

Set mTrayIcon = Icon
End Property
Public Property Get TrayIcon() As StdPicture
Set TrayIcon = mTrayIcon
End Property
'}

'{시스템 트레이 위로 마우스 포인터가 움직일 때 나타나는 ToolTip 문자열을
' 설정하거나 리턴함.
Public Property Let TrayTip(Tip As String)
Dim Tray As NOTIFYICONDATA
Dim Result As Long

If mInTray Then
Tray.uID = TrayID
Tray.hwnd = mTrayHwnd
Tray.szTip = Tip & vbNullChar
Tray.uFlags = NIF_TIP
Tray.cbSize = Len(Tray)

Result = Shell_NotifyIcon(NIM_MODIFY, Tray)
End If

mTrayTip = Tip
End Property
Public Property Get TrayTip() As String
TrayTip = mTrayTip
End Property
'}

'
Public Property Let InTray(Show As Boolean)
'컨트롤의 인스턴스에 대한 주소 포인터
Dim ClassAddr As Long
Dim msg As String

'이전과 다를 때만 변경
If (Show = mInTray) Then Exit Property


If Show Then '시스템 트레이에 아이콘을 추가한다면.
'{아이콘과 핸들은 꼭 필요하므로 없다면 빠져나감.
If mTrayIcon Is Nothing _
Or mTrayHwnd = 0 Then
msg = "TrayIcon, 또는 TrayHwnd 속성을 설정하지"
msg = msg & " 않았으므로 취소되었습니다."
MsgBox msg, vbInformation, "알립니다"
Exit Property
End If
'}

'컨트롤의 윈도우 프로시저를 서브 클래스함.
PrevWndProc = SetWindowLong(mTrayHwnd, GWL_WNDPROC, AddressOf
SubWndProc)

'컨트롤의 윈도우 구조체에의 USERDATA에 주소를 저장함.
'이것은 콜백 호출시 클래스 개체에 대한 포인터를 가져올 때 쓰임.
SetWindowLong mTrayHwnd, GWL_USERDATA, ObjPtr(Me)


AddIcon mTrayHwnd, TrayID, TrayTip, mTrayIcon
mInTray = True
Else 'Not Show Then '시스템 트레이에서 아이콘을 제거한다면
If mInTray Then '시스템 트레이에 아이콘이 있을 때만 제거하기 위함.
DeleteIcon mTrayHwnd, TrayID

'서브 클래스된 컨트롤의 윈도우 프로시저를 해제함.
SetWindowLong mTrayHwnd, GWL_WNDPROC, PrevWndProc
mInTray = False
End If
End If

End Property
Public Property Get InTray() As Boolean
InTray = mInTray
End Property

'--설명
'시스템 트레이에 아이콘을 추가함
Private Sub AddIcon(hwnd As Long, Id As Long, _
Tip As String, Icon As StdPicture)

Dim Tray As NOTIFYICONDATA
Dim Result As Long

'핸들과 콜백 메세지에 대한 유일한 ID
Tray.uID = Id
'윈도우 메세지를 받을 핸들
Tray.hwnd = hwnd

If Not (Icon Is Nothing) Then
Tray.hIcon = Icon.Handle
' Set ICON flag to validate data item
'아이콘이 변경됨을 알림.
Tray.uFlags = Tray.uFlags Or NIF_ICON
Set mTrayIcon = Icon
End If

If (Tip <> "") Then
Tray.szTip = Tip & vbNullChar
'Tip이 변경됨을 알림.(이 경우 이전의 아이콘이 변경되는
'것도 알려야 하므로 Or 연산자로 이전 변경 사항을 같이 적용)
Tray.uFlags = Tray.uFlags Or NIF_TIP
mTrayTip = Tip
End If

'사용자 정의 메세지를 설정함. SubWndProc에서 이것을 골라내게 됨
Tray.uCallbackMessage = TRAY_CALLBACK
'메세지가 변경됨을 알림.(역시 이전 변경 사항도 같이 적용함)
Tray.uFlags = Tray.uFlags Or NIF_MESSAGE
'구조체의 길이
Tray.cbSize = Len(Tray)

'변경될 데이터와 함께 시스템 트레이에 추가 메세지를 보냄.
Result = Shell_NotifyIcon(NIM_ADD, Tray)
End Sub

'--설명
'시스템 트레이에서 아이콘을 삭제함.
Private Sub DeleteIcon(hwnd As Long, Id As Long)
Dim Tray As NOTIFYICONDATA
Dim Result As Long

'핸들과 콜백 메세지에 대한 유일한 값
Tray.uID = Id
'메세지를 받을 핸들
Tray.hwnd = hwnd
'변경 사항은 없음.(삭제하니까)
Tray.uFlags = 0&
'구조체의 길이
Tray.cbSize = Len(Tray)

'데이터와 함께 삭제 메세지를 보냄.
Result = Shell_NotifyIcon(NIM_DELETE, Tray)
End Sub

'--설명
'시스템 트레이에서 발생된 이벤트를 알아내서 비베의 이벤트를 발생시키기 위함.
Friend Sub SendEvent(MouseEvent As Long, Id As Long)

'MouseEvent는 실제로 발생한 윈도우의 메세지임.
'이것을 검사해서 비베의 해당하는 컨트롤에 이벤트를 일으킴.
Select Case MouseEvent
Case WM_MOUSEMOVE
RaiseEvent MouseMove
Case WM_LBUTTONDOWN
RaiseEvent MouseDown(vbLeftButton)
Case WM_LBUTTONUP
RaiseEvent MouseUp(vbLeftButton)
Case WM_LBUTTONDBLCLK
RaiseEvent MouseDblClick(vbLeftButton)
Case WM_RBUTTONDOWN
RaiseEvent MouseDown(vbRightButton)
Case WM_RBUTTONUP
RaiseEvent MouseUp(vbRightButton)
Case WM_RBUTTONDBLCLK
RaiseEvent MouseDblClick(vbRightButton)
End Select
End Sub
'-----------------------------------------------------

그리고, 일반모듈을 하나 만듭니다.
'-----------------------------------------------------
Option Explicit

'// 프로그램 실행중 트래이를 사용하는지의 여부를 저장 //
Global vSystemTray As Boolean

'{API 함수
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA"
(ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As
Long) As Long

'특정한 윈도우에서 윈도우 구조체의 정보를 가져옴.
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA"
(ByVal hwnd As Long, ByVal nIndex As Long) As Long

'특정한 윈도우의 윈도우 구조체의 정보를 설정함.
Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Declare Function Shell_NotifyIcon Lib "shell32.dll" _
Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, _
lpData As NOTIFYICONDATA) As Long

Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (pDest As Any, pSource As Any, _
ByVal ByteLen As Long)
'}

'{SetWindowLong, GetWindowLong API 함수의 nIndex 인수에
' 쓰이는 상수. 가져오거나 설정할 정보.
Public Const GWL_USERDATA = (-21&)
Public Const GWL_WNDPROC = (-4&)
Public Const WM_USER = &H400&
'}

'NOTIFYICONDATA 구조체의 uCallbackMessage에 설정될 값.
Public Const TRAY_CALLBACK = (WM_USER + 101&)

'{Shell_NotifyIcon의 dwMessage에 쓰일 값.
Public Const NIM_ADD = &H0& '아이콘을 추가
Public Const NIM_MODIFY = &H1& '아이콘을 변경
Public Const NIM_DELETE = &H2& '아이콘을 삭제
'}
'{Shell_NotifyIcon의 uFlags에 쓰일 값.
Public Const NIF_MESSAGE = &H1& '메세지를 변경
Public Const NIF_ICON = &H2& '아이콘 모양을 변경
Public Const NIF_TIP = &H4& 'ToolTip을 변경
'}

'{윈도우 메세지 상수
Public Const WM_MOUSEMOVE = &H200&
Public Const WM_LBUTTONDOWN = &H201&
Public Const WM_LBUTTONUP = &H202&
Public Const WM_LBUTTONDBLCLK = &H203&
Public Const WM_RBUTTONDOWN = &H204&
Public Const WM_RBUTTONUP = &H205&
Public Const WM_RBUTTONDBLCLK = &H206&
'}

'{API 타입
Public Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
uID As Long
uFlags As Long
uCallbackMessage As Long
hIcon As Long
szTip As String * 64
End Type
'}

'이전 윈도우 프로시저
Public PrevWndProc As Long

'--설명
'InTray Property Let 프로시저에서 SetWindowLong API 함수를 호출함.
'이때 AddressOf 연산자를 이용해 SubWndProc 프로시저의 주소를 인수로 넘김.
'그러므로 SubWndProc 프로시저는 서브 클래스(Sub Class)가 됨.
'나중에 시스템 트레이에서 메세지를 받으면 SubWndProc 프로시저를 호출하게 됨
'SubWndProc 프로시저에서는 메세지가 TRAY_CALLBACK이라면
'SendEvent 프로시저를 호출해서 어떤 메시지를 받았는 지 알림.
'SendEvent 프로시저에서는 MouseUp, MouseDown, MouseMove,
'MouseDblClick에 해당하는 메세지일 경우 RaiseEvent 메쏘드로 이벤트를
'일으킴.

Public Function SubWndProc(ByVal hwnd As Long, _
ByVal msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

'SystemTray 클래스 변수
Dim SystemTray As SystemTray
'클래스 개체에 대한 포인터
Dim ClassAddr As Long

'운영체제에서 보내온 메세지가 TRAY_CALLBACK인 지 확인함.
'(Shell_NotifyIcon API 함수를 호출할 때 Tray.uCallbackMessage에
'TRAY_CALLBACK를 설정한 것을 기억할 것.)
Select Case msg
'사용자가 시스템 트레이에서 이벤트를 일으킨 경우.
Case TRAY_CALLBACK
'클래스 개체에 대한 포인터를 가져옴. 이것은 컨트롤이 서브클래스화될

'컨트롤의 Window 구조체의 USERDATA에 저장됨.
ClassAddr = GetWindowLong(hwnd, GWL_USERDATA)
'개체를 참조하지 않는 포인터를 클래스 개체로 복사함.
CopyMemory SystemTray, ClassAddr, 4
'윈도우에서 보내온 메세지를 전달함.
SystemTray.SendEvent lParam, wParam
'포인터를 Null로 만듦.
CopyMemory SystemTray, 0&, 4
End Select

'이전의 윈도우에게 모든 메세지를 전달함.
SubWndProc = CallWindowProc(PrevWndProc, hwnd, msg, wParam, lParam)
End Function
'-----------------------------------------------------

여기까지 만들었으면 이제 시스템 트레이에 아이콘을 넣을 준비는 끝났습니다.
참고로, 위의 소스는 모듈화된 소스이므로 수정할 부분이 따로 있지는 않으리라
봅니다.

이제 폼에서 시스템트레이의 이벤트를 만들어주어야 합니다.
폼의 일반에 아래의 이벤트를 붙여넣기 합니다.
그리고 폼이 시작시 시스템트레이 이벤트를 사용한다고 윈도우에게 알려줍니다.
'-----------------------------------------------------
Private WithEvents SystemTray As SystemTray
'-----------------------------------------------------
Private Sub Form_Load()
Set SystemTray = New SystemTray
With SystemTray
Set .TrayIcon = Me.Icon
.TrayHwnd = Me.hwnd
.TrayTip = Me.Caption
.InTray = Not Me.Visible
End With
End Sub
'-----------------------------------------------------

이제 마지막으로 시스템트레이에서의 마우스의 이벤트를 만들어줍니다.
'-----------------------------------------------------
Private Sub SystemTray_MouseUp(Button As Integer)
If Button = 1 Then
Me.Show
Me.Visible = True
' SystemTray.InTray = False
Me.WindowState = 0
End If
End Sub
'-----------------------------------------------------

그리고 Command Button을 하나 만듭니다.
'-----------------------------------------------------
Private Sub CommandButton1_Click()
Me.Visible = False
End Sub
'-----------------------------------------------------


위에서 처럼 만들어 보면 아마 시스템 트레이를 사용할 수 있도록 될겁니다.
내용은 Command Button을 클릭하면 폼이 사라지고 시스템트레이에서 마우스
좌측키
를 누르면 폼이 나타나게 됩니다.
그리고 저는 시스템트레이에서 마우스좌측키를 눌렀을때 해당폼이 나타나게
했지만
PopupMenu를 사용하시면 여러가지의 메뉴중에 선택하도록 만들수도 있겠죠...^^
그럼, 참고가 되었으면 합니다.
즐거운 하루되세요...

0 new messages