자, 오늘은 아주 간단한 Windows API 프로그래밍 퀴즈를 하나 내겠다.
다음과 같은 창을 만들려면 어떻게 해야 할까? (닫기 X 버튼이 사용 불가)
닫기 버튼 말고 최소화 및 최대화 버튼이야 윈도우의 스타일이라는 형태로 지정 가능하다.
WS_MINIMIZE/WS_MAXIMIZE와 WS_MINIMIZEBOX/WS_MAXIMIZEBOX가 있는데, BOX가 붙은 비트는 이 창에 해당 버튼과 기능을 제공하라는 뜻이다. 그리고 BOX가 없는 비트는 이 창이 현재 실제로 최소화됐거나 최대화돼 있음을 나타낸다.
즉, 프로그램이 지정하는 속성 정보와, 사용자가 변경하는 상태 정보가 비트값만 달리하여 동일 스타일에 한데 담겨 있다. 이건 개인적으로는 좀 이상한 설계라고 생각한다. 뭐 그건 그렇고...
그런데 닫기 버튼은 이런 스타일의 형태로 존재하지 않는다.
사실, UI 디자인 상으로도 응용 프로그램은 사용자에게 뭔가 강압적인 요소를 가능한 한 만들지 않아야 하며, 모든 창은 사용자가 언제라도 닫을 수 있어야 한다. [X] 버튼이 없는 창을 접할 일은 극히 드물다. 이는 오늘날처럼 언제라도 task switch가 가능한 선점형 멀티태스킹 환경에서는 더욱 그러하다.
창에 시스템 메뉴 자체를 완전히 없애서 [X]버튼을 없애는 것 말고 저렇게 [X] 버튼을 disable만 시키는 간단한 방법은 시스템 메뉴에서 SC_CLOSE를 없애거나 disable시키는 것이다. 창의 WM_CREATE 메시지에서 이렇게 해 주면 된다.
HMENU h = ::GetSystemMenu(hWnd, FALSE);
::RemoveMenu(h, SC_CLOSE, MF_BYCOMMAND);
요렇게 해 주면 캡션에 달린 [X]버튼도 같이 영향을 받게 된다. [X]버튼뿐만 아니라 시스템 메뉴를 더블클릭해도 창이 닫히지 않는다.
그런데, 외형상 닫기 버튼을 없애는 것은 마우스를 통한 닫기 동작을 차단해 주는 반면, 키보드 Alt+F4를 차단하지는 못한다.
물론, 이런 메시지가 왔을 때 닫는 반응을 안 하도록 WM_CLOSE 메시지나 IDCANCEL을 차단하는 식으로 별도의 처리를 할 수도 있지만, 운영체제 차원에서 창을 닫으려는 시도를 원천차단하는 방법은 따로 있다.
이것은 윈도우의 스타일에 있는 게 아니라, 윈도우 클래스의 스타일에 있다.
바로 CS_NOCLOSE 되시겠다.
아무 창에나 쉽게 쓰이는 속성이 아니라고 판단되었는지 윈도우의 스타일이 아니라 클래스의 스타일로 분류되었다. 뭐, 역사적으로는 [X] 버튼 자체가 윈도 95/NT에서 처음 등장한 것이기 때문에 최소화/최대화 버튼하고는 API가 들어갈 위치가 다르기도 했고 말이다.
윈도우 클래스를 등록할 때 저 스타일을 준 윈도우는 윈도우 프로시저에서 WM_CREATE 때 시스템 메뉴 조작 같은 걸 하지 않아도 시스템 메뉴에 '닫기' 명령이 등재되지 않으며, [X] 버튼이 자동으로 흐리게 표시된다. 그리고 Alt+F4를 눌러도 자동으로 닫히지 않는다.
응용 프로그램이 직접 제공하는 '종료' 명령으로 WM_CLOSE 메시지를 날려 줘야만 닫을 수 있다. 아니면 프로세스를 강제로 죽이든가.
MDI 차일드 윈도우도 이런 스타일이 지정된 클래스에 소속된 놈으로 지정할 수 있다. 그렇기 때문에 MDI 창들 중에도 절대로 닫히지 않고 언제나 떠 있어야 하는 고정 붙박이 윈도우는 요렇게 따로 배치하는 게 가능하다.
화면을 다 차지한 채 Z-순서가 바뀌지도 않고(WS_EX_TOPMOST) 닫히지도 않는 창이 떠 있다면, 거기에다 키보드/마우스/메시지 훅만 추가해서 다른 프로그램으로 작업 전환도 되지 않게 해서 포커스를 특정 프로그램이 사실상 독점할 수도 있다. 특정 프로그램만 뜬 채로 통제를 벗어나지 않아야 하는 공공장소의 특수 목적 PC에서 돌아가는 프로그램은 이런 기능을 활용하면 만들 수 있을 듯하다.
16비트 윈도 시절에는 특정 프로그램이 시스템의 자원을 독점하기가 훨씬 더 쉬웠고 그때는 그냥 modal이 아니라 system modal이라는 기능이 버젓이 존재했다. 이 창을 닫기 전에는 아예 다른 프로그램으로 Alt+Tab 작업 전환도 안 되는 거다.
물론 이런 강압적인 기능은 32비트 이후부터는 공식적으로 삭제되었지만 이것의 영향을 받았는지 윈도 NT 계열과는 달리 9x 계열은 메시지 대화상자에도 그 잔재가 여전히 남아 있었다. 취소 버튼이 없이 '확인'만 있는 메시지 박스는 시스템 메뉴에 '닫기'가 존재하지 않았으며 [X] 버튼이 클릭 가능하지 않았다. 단, 그래도 키보드의 ESC나 Alt+F4는 동작한다.
Posted by 사무엘