매크로를 돌리다 보면 "처리가 끝났습니다" 정도의 안내를 띄우고 싶은데, MsgBox는 사용자가 확인 버튼을 누를 때까지 코드가 멈춰 버립니다. 퇴근 전에 걸어 둔 일괄 작업이 중간 안내창 하나 때문에 밤새 멈춰 있는 걸 보면 허탈하죠. 이럴 때 몇 초 보여 주고 알아서 사라지는 메시지 상자가 있으면 좋은데, MsgBox 함수의 인자만으로는 이게 안 됩니다. VB/VBA에 이를 대신할 내장 함수도 따로 없습니다.

참고로 기본 MsgBox는 이렇게 씁니다. 실행하면 [확인] 버튼 하나짜리 모달 창이 뜨고, 누를 때까지 다음 줄로 넘어가지 않습니다.

광고
Sub Sample ()
    MsgBox "LOTIONY"
End Sub

WScript.Shell의 Popup 메서드

해법은 윈도우 스크립팅 호스트(WSH)를 빌려 쓰는 것입니다. WScript.Shell 개체의 Popup 메서드는 MsgBox와 거의 같은 창을 띄우면서 대기 시간을 초 단위로 받을 수 있습니다. 윈도우에 기본으로 들어 있어서 따로 참조를 추가할 필요도 없습니다.

Sub test()
    Dim WSH As Object
    Set WSH = CreateObject("WScript.Shell")
    WSH.Popup "5 초 후 자동으로 닫습니다", 5, "Title", vbInformation
    Set WSH = Nothing
End Sub

형식은 WSH.Popup (strText, [nSecondsToWait], [strTitle], [nType])이고, 첫 번째 인자만 필수입니다.

매개변수 의미
strText 메시지 상자에 표시할 문자열 (필수)
nSecondsToWait 자동으로 닫힐 때까지 기다릴 시간(초) (선택)
strTitle 메시지 상자 제목 (선택)
nType 버튼과 아이콘 종류 (선택)

시간을 지정했더라도 그 전에 사용자가 버튼을 누르면 바로 닫힙니다. 대기 시간을 생략하거나 0으로 주면 일반 MsgBox처럼 누를 때까지 기다립니다.

버튼·아이콘 값과 반환값은 MsgBox와 같다

nType에는 MsgBox에서 쓰던 상수를 그대로 넣으면 됩니다. 버튼 값과 아이콘 값을 더해서 함께 지정할 수 있어요. 예를 들어 vbYesNo + vbQuestion이면 질문 아이콘이 붙은 [예]/[아니오] 창이 됩니다.

값 VBA 상수 의미
0 vbOKOnly [확인] 버튼
1 vbOKCancel [확인], [취소] 버튼
2 vbAbortRetryIgnore [중지], [다시 시도], [무시] 버튼
3 vbYesNoCancel [예], [아니오], [취소] 버튼
4 vbYesNo [예], [아니오] 버튼
5 vbRetryCancel [다시 시도], [취소] 버튼
16 vbCritical 오류(X) 아이콘
32 vbQuestion 물음표 아이콘
48 vbExclamation 경고(!) 아이콘
64 vbInformation 정보(i) 아이콘

어떤 버튼을 눌렀는지도 MsgBox와 같은 값으로 돌아옵니다.

값 VBA 상수 클릭된 버튼
1 vbOK [확인]
2 vbCancel [취소]
3 vbAbort [중지]
4 vbRetry [다시 시도]
5 vbIgnore [무시]
6 vbYes [예]
7 vbNo [아니오]

여기에 하나가 더 있습니다. 아무도 누르지 않아서 시간이 다 되어 닫힌 경우에는 -1이 반환됩니다. 이걸 이용하면 "10초 안에 [아니오]를 누르지 않으면 계속 진행" 같은 흐름을 만들 수 있습니다. 반환값을 받아서 vbNo일 때만 중단하고, vbYes나 -1이면 진행하는 식이죠. 무인으로 돌아가는 작업에 확인 단계를 넣을 때 꽤 쓸모가 있습니다.

VB.NET에서 쓸 때

VB.NET에서도 같은 COM 개체를 늦은 바인딩으로 불러 쓸 수 있습니다. 개체를 Object로 받으니 파일 위쪽 Option Strict가 On이면 컴파일 오류가 나므로 해당 파일만 Off로 두세요.

Dim WSH As Object = CreateObject("WScript.Shell")
Dim ret = WSH.Popup("5 초 후 자동으로 닫습니다", 5, "Title", MsgBoxStyle.Information)
WSH = Nothing

한 가지 주의할 점은, 실행 환경에 따라 대기 시간을 줘도 창이 닫히지 않는다는 이야기가 종종 나온다는 겁니다. 배포할 PC에서 한 번은 꼭 시간이 지나 닫히는지 확인해 보세요. 확실하게 제어해야 한다면 VB.NET에서는 타이머가 달린 작은 폼을 직접 만들어 띄우는 편이 결국 속 편합니다.