Windows API에서 LoadCursor는 EXE/DLL 실행 파일의 리소스로부터 마우스 포인터를 얻어 오는 함수이다. 아니면 모듈 핸들 값을 NULL로 생략하면, 시스템이 제공하는 다양한 공용 포인터를 얻을 수도 있다. 일반적인 화살표 아니면 모래시계, 텍스트 입력란용 I-beam 등등 말이다.

그런 known 포인터의 명칭은 IDC_ARROW, IDC_IBEAM, IDC_WAIT ... 등으로 10여 종이 WinUser.h에 정의돼 있다. 실제값은 그냥 32xxx대의 리소스 ID 정수이다.

그런데, 제어판의 마우스 포인터 설정에 나열되어 있는 공통 포인터 중, 유일하게 IDC_* 명칭이 전혀 부여되지 않은 포인터가 하나 있다. 바로 펜 모양의 필기 포인터이다.
MSDN 문서와 WinUser.h를 눈을 씻고 찾아 보시라. 무려 Windows 95 이래로 제어판에 버젓이 등재되어 온 표준 공통 포인터임에도 불구하고 이름이 없다. 신기하지 않은가?

사용자 삽입 이미지

사실, 이 펜이랑 xor 반전 십자가인 IDC_CROSS(정밀도 선택), 그리고 IDC_UPARROW(대체 선택)는 응용 프로그램에서 거의 볼 일이 없긴 했다. =_=;;

그래서 본인은 장난기가 발동했다.
1부터 65535까지 brute-force로 LoadCursor 요청을 해서 문서화되지 않은 마우스 포인터가 돌아오는 게 있는지 역대 Windows 운영체제별로 확인을 해 봤다.

사용자 삽입 이미지

결과는 꽤 흥미로웠다.
답부터 말하자면 펜 모양은 32631이라는 ID가 홀로 부여되어 있었다. Windows 95부터 10까지 동일하게 사용 가능하다.
'홀로'라는 말은 인접한 32630이나 32632 같은 숫자에는 포인터가 배당된 게 없다는 뜻이다.

모든 Winows에는 100부터 11x번에 완전 기본 마우스 포인터가 할당되어 있었다. 즉, Aero 포인터를 쓰고 있더라도 여기에는 완전 운영체제 기본 흑백 화살표 포인터들이 있으며, 얘들은 포인터 뒤에 입체감을 주는 그림자도 표시되지 않았다. 이건 무슨 다른 특수한 용도로 쓰이는가 보다.

그리고 IDC_HELP 다음으로 32652부터 32662 사이에 있는 11개의 포인터는.. 놀랍게도 마우스 휠을 눌러서 자동 스크롤 모드가 됐을 때 나타나는 '작은 원 + 검은 삼각형'들이었다(각 방향별로). 그것도 휠이 운영체제 차원에서 정식 지원되기 시작한 Windows 98부터 20년째 동일한 형태로 존재하고 있었다. 이건 기술적으로는 user32.dll에 존재하는 리소스이다.

그런데 이런 걸 도대체 왜 문서화하지 않았을까? Windows 98부터는 하이퍼링크용 IDC_HAND만 추가됐다고 달랑 써 놓고 입 싹 씻은 걸까..? 뭔가 단단히 속은 느낌이었다.

본인은 당장 날개셋 한글 입력기에다가 조치를 취했다.
날개셋 한글 입력기는 16년 전(2002...)에 나온 2.0 이래로 지금까지 자동 스크롤 모드용 마우스 포인터들을 내장하고 있었다. 그걸 모두 제거하고, (1) 운영체제가 비공식적으로 제공하는 이 포인터를 사용하게 했다. 그래서 파일 크기가 4~5KB 남짓 감소하는 효과를 얻었다.

(2) 그리고 최근에 추가된 필기 인식 입력 도구에서 마우스를 그리기 입력란 내부로 가져가면 포인터가 펜 모양으로 바뀌게 했다. 뭔가를 그리면 된다는 것을 강조하기 위해서이다.
결과물을 보니 만족스럽다. 이 달 초에 나온 9.61 버전에 바로 요 사항들이 반영되었다.

사용자 삽입 이미지

이것 말고 문서화되지 않은 포인터로는 32663이 있는데, 일반 화살표 포인터 옆에 모래시계 대신 의외로 CD 아이콘이 자그맣게 붙어 있다.
광학 드라이브가 백그라운드에서 뭔가 돌아가고 있을 때 표시되는 듯하며 본인도 이걸 본 기억은 있다. 하지만 정확한 표시 조건은 잘 모르겠다.

차라리 화살표 옆에 점선 사각형 내지 [+]가 붙어서 drag & drop을 나타내는 포인터가 더 자주 쓰이며, 공통 포인터로 등재됐으면 좋겠는데 얘들은 그렇지 못하다. 그냥 ole32.dll에 하드코딩된 리소스가 쓰인다. 그리고 창 전체의 크기 말고 창 내부의 splitter 구획의 폭을 조절할 때 바뀌는 포인터도 창 크기 조절용과는 다른 걸 쓰는 게 UI 디자인상으로 맞는데 그것들 역시 공통 포인터에는 없다. 그렇기 때문에 여전히 싸제 자체 내장에 의존하거나, 아니면 comctl32.dll에 하드코딩된 리소스를 슬쩍 가져오는 게 통용된다.

아무튼, 오늘은 마우스 포인터와 관련하여 새로운 사실을 알게 됐다.
그러고 보니 옛날에 16비트 시절에는 메모리 공간이 엄청나게 부족하기도 하고, GDI 핸들의 번호 영역 자체가 몇 만 남짓밖에 안 되었다. 그러니 Windows 3.1뿐만 아니라 9x에서도.. 아까 본인이 했던 것처럼 1부터 65535까지 brute-force 식으로 대입해서 시스템에 현재 존재하는 비트맵· 아이콘 따위를 몽땅 나열하고 조회하는 툴을 만드는 것도 가능했다.

오늘날 32/64비트 시대에도 DLL의 심벌 ordinal 번호와 리소스 ID 번호는 16비트 영역으로 한정돼 있다. 이 둘에서는 숫자와 문자열이 식별 용도로 모두 쓰이며, 16비트를 초과하는 큰 숫자는 문자열 포인터인 것으로 간주되게 의미가 예약돼 있기 때문이다.

Posted by 사무엘

2018/12/21 08:33 2018/12/21 08:33
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1567

1. WNDCLASS와 HCURSOR

GUI 환경에서 키보드로 글자 입력을 받기 위해 캐럿(caret, 혹은 cursor)이라는 깜빡이는 세로줄이 나타난다면, 마우스의 입력을 받기 위해서는 마우스 포인터라는 게 떠 있다. 키보드 문자 입력과 마우스는 상호 배타적인 관계이다 보니, 문자 입력이 시작되면 마우스 포인터는 화면을 가리지 말라고 쏙 사라지곤 한다. 그 반면, 키보드 단축키와 마우스는 전혀 배타적이지 않고 상호 보완적이므로 이 경우는 마우스 포인터가 사라질 필요가 없다. 간단히 말해 스타를 하는 경우를 생각하면 된다.

Windows 운영체제 내부에서 생성되는 모든 창(window)들은 마우스 포인터가 자기 영역을 지날 때 어떤 모양의 포인터를 표시할지를 자유롭게 지정할 수 있다. 가장 static하고 간단한 방법으로는 윈도우 클래스를 등록할 때 WNDCLASS의 hCursor 멤버에다가 지정해 주면 된다.

HCURSOR라는 타입은 마우스 포인터의 모양을 나타내는 자료구조의 포인터이다. 마우스 포인터는 아이콘(HICON)과 거의 동급으로 취급되며, 아이콘에다가 중심 위치(hot spot) 정보만이 추가되었을 뿐이다. 화살표 그림의 경우 화살표가 가리키는 뾰족한 지점이 바로 hot spot의 위치가 되는 것이다.

그리고 그 아이콘이라는 것은 개념적으로 AND 연산용 비트맵(마스크)과 XOR 연산용 비트맵(그리기)이 추가된 정사각형 비트맵(HBITMAP) 쌍이다.
마우스 포인터 자체를 프로그램 코드를 통해 동적으로 생성하고자 한다면 이런 관계에 대해서도 이해할 필요가 있다. 이런 구조 덕분에 배경색을 반전시키는 마우스 포인터도 만들 수 있다. 또한, Windows에서 아이콘과 마우스 포인터가 매우 유사하게 취급된다는 것은 GetIconInfo 함수나 ICONINFO 구조체의 스펙을 보면 금방 수긍할 수 있다.

색깔 중에 system color가 있고 DC 오브젝트들(브러시· 펜 따위) 중에도 stock object가 있으며, 클립보드 포맷 중에 표준 포맷(CF_TEXT ...)이 있는 것처럼.. 마우스 포인터 중에도 용도가 고정되었고 운영체제 차원에서 모양을 공통으로 관리하는 것이 몇 종류 있다. 이런 공용 포인터의 예로는 일반 화살표, 모래시계, 입력란용 I-beam 등 우리에게 친숙한 것이 있으며, 이들은 제어판을 통해 그 모양을 바꿀 수 있다. 응용 프로그램에서는 LoadCursor(NULL, IDC_*)를 호출해서 이들의 HCURSOR 값을 얻을 수 있으며 이를 응당 클래스 등록 시에 사용하면 된다.

그래픽 에디터라든가 게임 급으로 정말 아주 튀는 GUI를 제공하는 프로그램을 만드는 게 아니라면, 공용 포인터 말고 다른 독자적인 포인터를 쓸 일은 잘 없을 것이다. 하지만 튀지 않는 일반 업무용 프로그램에서도 custom 포인터가 필요한 경우가 가끔은 있다.

  • 워드 프로세서의 경우, IDC_IBEAM의 변형이 필요할 때가 있다. 이탤릭체 글자에서는 포인터의 모양도 살짝 기울어지며, 세로쓰기 모드에서는 포인터의 모양 역시 90도 돌아간다.
  • drag & drop 상태를 표시하기 위해, 화살표 밑에 사각형 테두리와 [+] 마크가 붙은 포인터가 필요할 때가 있다. 이것도 의외로 공용 포인터에는 존재하지 않으며, ole32.dll 내부에 있는 비공식 리소스를 몰래 뽑아 와서 쓰는 경우가 많다.
  • 먼 옛날, IDC_HAND가 존재하지 않던 Windows 95/NT4에서는 winhlp32.exe의 내부에 있는 손가락 링크 모양 비공식 리소스를 몰래 뽑아 와서 하이퍼링크를 구현할 때 쓰기도 했다.

LoadCursor는 원래 모듈(EXE/DLL)의 리소스로부터 마우스 포인터 그림을 추출하는 함수이다.
CreateCursor 함수는 HBITMAP을 받는 게 아니라 쌩짜 AND/XOR 비트맵 배열만을 입력받아서 포인터를 생성해 주는데, 그 말인즉슨 얘는 애초에 모노크롬 포인터밖에 못 만든다는 뜻이다. 컬러를 지원하지 않는다.

그러고 보니 마우스 포인터는 마치 GIF처럼 애니메이션 가능한 버전도 생겨서 단순 아이콘과 차별화가 이뤄지긴 했다. ico 파일에는 크기와 화질이 다른 여러 아이콘들이 있을 수 있다면, ani에는 동일 아이콘의 여러 프레임이 들어갈 수 있게 된 것이다. 교집합인 정보가 있지만 서로 완전히 호환되지는 않는 미묘한 관계가 됐다.

2. WM_SETCURSOR와 SetCursor 함수

윈도우 클래스를 등록할 때 hCursor 멤버에다가 NULL을 지정하면 그 윈도우는 마우스 포인터가 기본적인 화살표로 지정된다거나, 아니면 말 그대로 아무것도 없는 올투명 이미지가 지정되어서 포인터가 사라진다거나 하지 않는다.
어찌 되는가 하면, 이 윈도우 영역으로 들어오기 직전에 유지되었던 마우스 포인터가 변경 없이 그대로 유지된다..! 마치 C언어에서 초기화되지 않은 변수처럼 undefined 상태가 되는 것이다.

이런 동작을 원하는 프로그래머나 기대하는 사용자는 전무할 것이다. 그러므로 클래스 차원에서 지정된 기본 포인터가 없는 윈도우는 자신의 윈도우 프로시저 내부에서 매번 실시간으로 마우스 포인터를 지정해 줘야 한다. 어떻게? WM_SETCURSOR라는 메시지가 왔을 때 SetCursor라는 함수를 호출해서 하면 된다.
아니 사실은 클래스 포인터가 이미 지정돼 있는 창이라도 필요하다면 이렇게 마우스 포인터를 실행 중에 얼마든지 변경할 수 있다. 동일한 웹브라우저 창이라도 포인터가 링크 위를 가리키고 있을 때는 조건부로 손가락 모양으로 바뀌어야 할 테니까 말이다.

윈도우 안에서 마우스 포인터가 움직이면 WM_MOUSEMOVE만 오는 게 아니라 그 전에 WM_SETCURSOR부터 날아온다. 그에 반해 SetCursor는 굳이 WM_SETCURSOR 메시지 타이밍이 아니어도 아무 때나 언제든지 호출 가능하다. 이 함수 자체는 지금 포인터가 나 자신이(스레드 단위) 생성한 윈도우에만 있으면 위치 불문하고 포인터 모양을 즉시 바꿔 준다. WM_PAINT 타이밍 때에만 사용 가능한 BeginPaint/EndPaint처럼 특정 메시지에 매여 있는 게 아니라는 뜻이다.

그럼 왜 굳이 WM_SETCURSOR라는 메시지가 따로 있는 것일까? 그 이유는 저렇게 일상적으로 마우스 포인터가 움직였을 때 빼고는 얘는 WM_MOUSEMOVE와는 설계 철학과 생성 조건이 매우 다르기 때문이다.

  • 윈도우가 disable됐을 때는 그 윈도우로 마우스가 움직이더라도 통상적인 WM_MOUSEMOVE가 오지 않는다. 그러나 이때에도 WM_SETCURSOR는 전달하는 상황 정보(hit-test code)만 달라진 채 언제나 온다.
  • hit-test code가 같이 온다는 점에서 유추할 수 있듯, WM_SETCURSOR는 클라이언트와 논클라이언트를 가리지 않고 온다. 그에 반해 WM_MOUSEMOVE는 클라이언트 영역 전용이고 WM_NCMOUSEMOVE가 따로 있다.
  • 마우스가 capture된 뒤부터는 마우스가 움직이면 반대로 WM_MOUSEMOVE만 오지 WM_SETCURSOR는 오지 않는다. 마우스의 포커스가 포인터 위치와 무관하게 이 윈도우에 집중되었기 때문에 포인터의 모양도 잠시 고정된다.
  • 그리고 결정적으로.. WM_MOUSEMOVE는 지금 화면을 대면하고 있는 최하위 child 윈도우에 직통으로 전달되는 반면, WM_SETCURSOR는 최상위 parent 윈도우에 먼저 전달되어서 얘들이 처리를 포기/거부했을 때에만 child로 내려간다.

마지막 항목이 중요하다. 이런 메커니즘의 차이로 인해 두 메시지는 서로 호환성이 전혀 없으며 별도의 메시지로 분리되어야만 한다. 이 메시지가 그냥 이 시점에서 표시할 HCURSOR 값만 곱게 얻는 게 목적이라면 WM_SETCURSOR 메시지는 SET이 아니라 GET이라는 동사가 붙어서 WM_GETCURSOR, WM_QUERYCURSOR처럼 명명됐을 수도 있다. 대화상자의 WM_GETDLGCODE 메시지처럼 그냥 return (LRESULT)LoadCursor(...)의 형태.
그런데 그게 아니기 때문에 자기가 직접 마우스 포인터를 재지정할 의향이 있다면 WM_SETCURSOR가 올 때마다 SetCursor를 수동으로 매번 호출도 해야 하고, 그러면서 리턴값도 0이 아닌 값으로 되돌려야 한다. 특히 DefWindowProc를 호출해서는 안 된다.

DefWindowProc가 WM_SETCURSOR 때 하는 일 중에는 논클라이언트 영역에서 포인터를 화살표 내지 창의 크기 조절 손잡이 모양으로 바꾸는 것이 포함돼 있다.
하지만 클라이언트 영역에서 DefWindowProc은 "난 마우스 포인터 모양을 자체적으로 처리할 의향이 없으니, (1) 내 부모 윈도우에서 이의 없으면 (2) 최종 처리를 내 자식 윈도우에 맡기겠소"라는 의미가 된다. Def..없이 return 0은 (2)만을 담당한다.

참고로, SetCursor(NULL)을 하면 클래스 WNDCLASS::hCursor = NULL과는 달리 비로소 마우스 포인터가 화면에서 사라진다. 이것은 HideCursor / ShowCursor 함수와 비슷한 효과를 낸다. 이들 함수는 포인터의 레퍼런스 카운터를 1 증가나 감소시켜서 카운터가 양수이면 포인터를 계속 표시시키고, 그렇지 않으면 계속 감추고 있는다. 캐럿을 표시하거나 감추는 ShowCaret / HideCaret과 비슷한 원리로 동작한다.
그에 반해 SetCursor(NULL)은 효과가 일시적이므로 해당 윈도우가 WM_SETCURSOR에서 계속해서 SetCursor(NULL)을 해 줘야만 포인터가 없는 상태가 유지된다.

사소한 사항이다만, WM_MOUSEMOVE는 메시지 큐에 post 형태로 전해지는 반면, WM_SETCURSOR는 리턴값을 꼼꼼히 확인해야 하기 때문에 언제나 sent된다는 차이도 있다. 마우스 메시지 훅킹 같은 걸 한다면 요런 차이가 민감하게 와 닿을 것이다.

3. 대기 상태 표현하기

프로그램이 파일을 읽고 쓰고 복잡한 계산을 시작해서 대략 0.n초 정도 짤막하게 사용자의 응답(더 정확히는 운영체제 메시지)에 반응을 하지 않게 됐다면, 이에 대해 가장 간단하게 피드백을 주는 방법은 SetCursor(LoadCursor(NULL, IDC_WAIT))를 해서 마우스 포인터를 그 악명 높은 모래시계 모양으로 바꾸는 것이다.

물론 처리가 끝났다면 포인터 모양을 원상복구 해야 한다. 이것은 SetCursor의 리턴값을 보관하고 있다가 도로 전달하는 것으로 쉽게 구현 가능하며, 이렇게 시작과 끝을 생성자와 소멸자에다 넣어서 간단한 C++ 클래스를 구현할 수도 있다. MFC에 있는 CWaitCursor가 그 예이다.
모래시계로 변해 있던 동안 마우스 포인터가 조금이라도 다른 곳으로 이동했거나, 위치가 안 바뀌었더라도 그 사이에 포인터 아래의 윈도우가 바뀌었다면.. 프로그램이 의식을 회복(?)했을 때 WM_MOUSEMOVE와 그에 상응하는 WM_SETCURSOR도 오기 때문에 포인터 모양이 자동으로 갱신되긴 한다. 그러나 그런 외부적인 변화가 전혀 없었더라도 포인터 모양이 원상복귀 되어야 하니까 말이다.

마우스 포인터의 움직임은 일종의 하드웨어 인터럽트 형태로 발생하며, 응용 프로그램이 WM_SETCURSOR 메시지에 응답하지 않고 있더라도 포인터가 움직인 것에 대한 반응은 해야 한다. 그렇기 때문에 프로그램이 처리를 열심히 하고 있는 동안에는 좀 전에 지정된 모래시계 모양이 유지된다. 물론, 포인터가 정상적으로 응답 중인 다른 프로그램 창 위에 놓여 있으면 거기 모양으로 바뀌며, 한 프로그램이 수 초 이상 너무 오랫동안 응답을 안 하고 있으면 그건 그것대로 문제가 된다. 내 프로그램 창이 고스트 윈도우로 바뀌는 일은 없어야 한다.

시간이 굉장히 오래 걸리는 작업을 한다면 프로그램의 디자인 형태가 바뀐다. 작업은 백그라운드 스레드에다 담당시키고 프로그램은 현재 진행 상황을 출력하면서 UI 메시지 반응도 평소처럼 한다. progress 컨트롤이 장착된 대화상자가 이 역할을 하며, 사실 Windows Vista부터는 task dialog로 이걸 간단하게 띄울 수도 있게 됐다.
동영상 인코더처럼 input 데이터를 직접 생성하고 작성하는 기능은 없고, 이미 있는 데이터를 변환하는 일이 전부인 프로그램이라면 별도의 대화상자 없이 자기 main frame window 자체가 통째로 진행 상황을 표시하는 용도로 쓰이기도 한다. <날개셋> 변환기도 이런 형태의 프로그램이다.

이를 좀 더 일반화해서 생각하면 이렇다. 어떤 윈도우가 하는 역할이 자신과 별개이고 독립적인 타 작업의 진행 상황을 관찰하면서 표시하는 게 전부라면, 보통은 그 윈도우 내부의 마우스 포인터를 굳이 별도로 모래시계 모양으로 바꾸지 않는다. 설치 프로그램들이 그 예이다. 다만, Windows Installer 엔진의 경우 본격적으로 설치/제거를 수행하는 마법사가 뜨기 전에 준비 작업을 하느라 자그마한 대화상자가 떴을 때는 마우스 포인터를 거기로 가져가면 모래시계로 바뀐다.

사용자 삽입 이미지

요런 게 대화상자 윈도우에서 WM_SETCURSOR를 처리함으로써 구현 가능하다. 이 메시지는 부모-자식 top-to-bottom 형태로 내려가기 때문에, 부모에서 메시지를 가로채 버리면 자식 윈도우의 의도와 상관없이 마우스 포인터를 모래시계 모양으로 바꿀 수 있다. 밑에 지금 무슨 윈도우가 있는지 핸들도 wParam으로 친절하게 전달된다. 여기서 SetCursor 호출만 하고 리턴값으로 nonzero를 지정하지 않으면, 대화상자 배경들만 포인터가 바뀌고 버튼 같은 각종 컨트롤들은 바뀌지 않게 된다. (위의 스크린샷처럼)

이와 대조적으로, 키보드 메시지는 포커스를 잡고 있는 최하위 윈도우에 직통으로 전달되니(bottm-to-top), 그 위에서 공통 단축키 같은 걸 처리하려면 message loop 차원에서의 pre-processing이 필요한 것이다.

<날개셋> 변환기의 경우 변환하는 파일이 적으면 스레드 없이 그냥 비응답 상태로 빠진 채로 변환을 수행한다. 그러나 수십 개, 수MB 이상 분량 파일을 요청하면 대화상자의 모든 컨트롤들을 disable시키고 progress 컨트롤을 출력하고, 대화상자 내부의 마우스 포인터를 모래시계로 바꾼 뒤 변환을 수행한다. 이때는 어차피 대화상자의 다른 기능들을 전혀 사용할 수 없고 ESC나 [X]를 눌러 중간 취소만 가능하기 때문이다.

그리고 하나 더 생각할 만한 상황은.. 딴 작업이 아니라 대화상자 자기 내부에다 출력할 데이터들을 준비하고 초기화하는 작업이 시간이 좀 오래 걸릴 때이다. <날개셋> 한글 입력기 제어판의 대화상자에도 그런 경우가 몇 가지 있다.
이때는 문제의 콤보나 리스트박스가 빈 채로 먼저 대화상자를 출력한 뒤, 스레드를 만들고 마우스 포인터를 IDC_WAIT가 아니라 IDC_APPSTARTING 모양으로 바꿨다. 대화상자가 출력은 됐지만 아직 초기화가 덜 돼서 백그라운드에서 작업 중임을 이렇게 나타낸다.

요렇게 백그라운드의 스레드 작업이 끝난 뒤에는 마우스 포인터를 어떻게 원상복구 할지가 문제가 된다.
아까처럼 스레드 없던 시절에는 작업하던 사이에 포인터 위치가 바뀌었으면 WM_SETCURSOR와 WM_MOUSEMOVE가 자동으로 생겼다. 그러나 지금은 그렇지 않다. 작업이 수행되던 중에 포인터 이동에 대한 처리는 이미 다 이뤄졌기 때문이다.

마우스 포인터의 이동 없이 아래의 창에다가 WM_SETCURSOR를 인위적으로 생성해서 포인터 모양을 원래 것으로 갱신할 수 있어야 하는데.. 이것만 어떻게 하는지 잘 모르겠다.
일단 본인이 사용하는 방법은 GetCursorPos로 현재 포인터 위치를 얻은 뒤, 그거 그대로 SetCursorPos를 하는 것이다. 위치가 바뀐 게 없음에도 불구하고 이렇게 하면 WM_SETCURSOR와 WM_MOUSEMOVE가 생성되기는 하는 것 같더라.
이 정도면 Windows 프로그래밍에서 마우스 포인터 제어와 관련해서 어지간한 문제는 다 다룬 것 같다.

Posted by 사무엘

2017/02/06 08:35 2017/02/06 08:35
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1324

Under the hood

예나 지금이나 생긴 것, 하는 일은 비슷한데 내부 메카니즘은 상당히 달라진 물건은 어떤 게 있을까?

※ 헬리콥터

회전익 항공기는 뱅글뱅글 돌아가는 로터의 영향을 받아 동체까지 반대 방향으로 돌게 된다. 그래서 이 현상을 상쇄하기 위해서 탠덤 형 헬리콥터는 동체가 길쭉하고 서로 반대 방향으로(시계/반시계) 도는 동일 크기의 로터가 앞뒤로 달려 있다. 철도 차량으로 치면 전후동력형 동차와 비슷한 형태. 그리고 동축 반전 로터형은 그 로터를 위아래 높이만 다르게 하여 동일 위치에 포개 놓았다. 양방향으로 도는 로터 두 개를 모두 배치함으로써 동체의 회전을 방지했다는 점이 공통점이다.

그러나 동축 반전 로터는 만들기가 더 어렵고 고속 주행의 효율이 떨어진다는 점 때문에 오늘날 대부분의 헬리콥터는 꼬리날개(테일 로터)를 수직 방향으로 따로 다는 방식을 쓰고 있다. 뭐, 테일 로터 방식도 문제가 없는 건 아니어서 동체를 뜨게 하는 데 전혀 도움을 주지 않는 잉여 로터에다가 엔진의 출력이 쓸데없이 낭비된다는 점, 그리고 테일 로터는 사람이 끼여서 죽거나 다칠 가능성이 굉장히 높다는 점이 지적되곤 한다만...
어쨌든 요지는, 옛날에는 꼬리날개의 기능을 다른 형태로 구현한 헬리콥터도 있었다는 것이다.

※ 마우스

구슬을 굴리던 방식에서 광학 레이저로 위치를 탐지하는 방식으로 완전히 바뀌었다. 사실은, 볼마우스가 바닥 매체에 관계없이 동작 가능하고 가끔은 사람이 일부러 트랙볼처럼 아래의 볼을 직접 굴려서 포인터를 움직일 수도 있어서 심리적으로는 무척 편하다. 그러나 볼에 먼지와 이물질이 껴서 주기적으로 청소가 필요하다는 건 답이 없는 문제이다. 청소를 안 해 주면 동작이 금세 뻑뻑해지고, 포인터가 잘 안 움직이고...;; 불편하다. 청소 때문에 볼은 필연적으로 분리가 무척 용이한 구조로 만들어질 수밖에 없고, 그래서 공공 PC에서 마우스의 볼은 자주 분실되기도 했다.

오늘날, 아래에 볼이 달려 있지 않은 요즘 마우스를 보면 본인은 옛날 생각이 난다. 초창기의 광마우스는 반드시 바닥에다 마우스 패드를 깔고 써야 했고 가끔 마우스 포인터가 오작동으로 움직이는 등 단점도 있었으나, 요즘은 많이 개선되었다.

※ 아날로그 시계

생긴 건 1부터 12까지 일정 간격으로 새겨진 원판에 시침과 분침(, 그리고 초침)이 놓인 구조는 예나 지금이나 똑같다. 하지만 옛날의 시계는 태엽과 톱니바퀴로 돌아가는 구조이던 것이 오늘날의 시계는 반도체를 이용한 전자식 쿼츠 시계로 다 바뀌었다. 예전에 글로 쓴 적이 있듯이, 둘은 구조가 완전히 다르다. 쿼츠 시계는 단순히 전기 에너지로 기계식 시계를 돌리는 시계가 아니다.

※ 모니터

21세기엔 컴퓨터 모니터든 텔레비전이든, 크고 아름답고 둥글기까지 하던 브라운관이 디스플레이 장비에서 완전히 퇴출되었다. 그 타이밍이 플로피 디스크나 카세트 테이프의 퇴출과도 시기적으로 비슷한 것 같다.
컴퓨터의 두뇌인 집적 회로가 더욱 작고 정밀해진 것만큼이나 디스플레이 장비의 소형화도 스마트폰 같은 작은 컴퓨터의 출현을 가능하게 했다. 고작 단색, 혹은 청색이 표현 안 되던 저해상도 화면도 이젠 안녕이다.

액정 모니터는 전기 적게 먹고 전자파 안 나오고, 작고 가볍다. 물론, 단점도 없지는 않아서 특히 초창기엔 비슷한 크기와 성능의 브라운관 모니터보다 상당히 비싸고, refresh rate 및 최대 해상도가 떨어지고 색감이 좀 시원찮으며, 설계 해상도 외의 해상도에서는 픽셀이 번지고 불량 화소 같은 문제가 있었다만.. 오늘날은 역시 상당수 개선되었다.

그래, 그러고 보니 옛날 브라운관 모니터는 다양한 해상도에서도 픽셀이 번지는 일이 없었다. 그리고 모니터를 처음 켰을 때는 무슨 형광등처럼 화면이 표시되는 데 딜레이가 길며 그것도 서서히 fade in이 됐었다. 이런 장면 역시 액정 화면에서는 볼 일이 없어져 있다.

※ 철도 차량

잘 알다시피, 옛날의 그 크고 아름답던 증기 기관차가 디젤로 바뀌고, 나중에는 최종 완전체인 전기 동력차로 바뀌었다.
그리고 똑같이 전동차도 처음에는 원시적인 저항· 쵸퍼 제어이던 것이 오늘날은 만렙인 VVVF 기반 제어로 바뀌었다.
심지어 VVVF 내부에서도 서열이 있어서, 처음에 GTO 소자이던 것이 더 조용하고 효율 좋은 IGBT 소자 기반으로 바뀌었다.
전기 철도는 힘 좋고(탁월한 가감속력) 조용하고 공해 물질이 배출되지 않으며 동력비 조절이 유연하다는 압도적인 장점으로 인해 철도의 주류로 자리잡았다. 특히 전기 없이는 고속철이나 지하철이 등장할 수 없었을 것이다.

※ 프린터

한 20년 전의 컴퓨터 입문 서적을 보면 프린터의 메카니즘으로는 도트, 열전사, 잉크젯, 레이저 4종류가 있다. 그 중 오늘날까지 살아남은 건 역시 잉크젯과 레이저. 그렇게도 비싸던 레이저 프린터가 이렇게까지 싸져서 가정용으로 보급된 건 정말 놀라운 일이 아닐 수 없다. 잉크젯은 프린터 값이 잉크 카트리지 값보다 더 싼 기형적인 물건이 됐고..

마치 오늘날 286, 386 급-_- CPU는 키오스크나 우주선-_-, 임베디드용으로나 제한적으로 쓰이듯, 도트와 열전사는 영수증이나 각종 토큰 같은 걸 찍는 용도로 물러났다. 그나마 도트는 진짜 완전히 사라진 듯하고, 요즘 기계는 영수증도 열전사 방식으로, 언뜻 보기에 레이저 프린터가 돌아가는 것처럼 조용히 쓰윽~ 인쇄하는 것 같다.

Posted by 사무엘

2011/08/11 08:28 2011/08/11 08:28
, , , ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/553

컴퓨터가 글자가 아닌 그림을 처리하기에는 능력이 한참 부족하던 시절에, 벌써부터 포인팅 장비라는 개념이 있는 게 사용자 인터페이스 차원에서 좋겠다는 생각을 한 선구자가 있었다. 그게 한 196~70년대의 일이다.
포인팅 장비는 2차원 평면에서의 속도감 내지 곡률을 표현할 수 있기 때문에, 컴퓨터에서 키보드와는 또 다른 영역을 개척한 중요한 입력 장치이다.

마우스: x, y 축의 재빠른 이동과 클릭을 지원하는 대표적인 포인팅 장비. 옛날에는 버튼이 3개였으나 요즘은 2버튼으로 통일되었고, 대신 휠이 달려 나온다. 또한 볼 마우스이던 것도 다 광 마우스로 대체. 3버튼이나 트리플 클릭이 없는 것은 인간이 심리적으로 3회 이상의 동일 동작 반복을 싫어한다는 증거가 될 수도 있다. 마우스를 쓰는 프로게이머는 있어도 트랙볼이나 터치패드를 쓰는 변-_-태는 없다. 하지만 인체공학적으로 잘 만들어지지 못한 마우스를 오래 사용할 경우 사용자의 손목에 굉장한 무리를 주므로 주의 필요.

트랙볼: 볼 마우스의 볼을 직접 굴리는 방식으로, 마우스와 기능면에서는 동일하다. 마우스의 쾌적한 이동성은 다소 희생했지만, (1) 좁은 공간에서 사용 가능하고 (2) 손가락만 까딱이면 되지 손목 전체를 움직일 필요가 없어서 피로감이 덜하다는 장점이 있다. 그래서 노트북에 전통적으로 트랙볼 류의 포인팅 장비가 탑재되는 경향이 있었다.
트랙볼은 x, y뿐만 아니라 마우스로는 가능하지 않은 z축 이동을 이론적으로 표현할 수 있다. (볼 자체를 좌우로 굴리기!!) 나름 3차원 장비라는 뜻. z축을 휠로 사용해도 될 것 같은데.

터치패드: 역시 노트북용 마우스 대체 장비로 손가락을 마우스처럼 이동한다. 트랙볼의 장점을 어느 정도 가지면서 이동의 편의성이 트랙볼보다 낫지만 여전히 마우스보다는 못하며, 이동 중에 클릭이나 휠 조작을 동시에 하기가 어렵다는 단점이 있다. 터치패드에 영 적응을 못 해서 늘 마우스를 지참하는 노트북 사용자도 있으나, 본인은 터치패드로 스타도 할 정도로 이놈을 아주 능숙하게 다룬다. 노트북 사용 10+년 경력.

IBM 노트북에만 있는 거시기: 이름이 뭔지 모르겠다. 트랙볼보다도 더욱 홀쭉한 bar를 한 손가락으로 어루만지고 있으면, 손가락이 닿은 지점에 따라 마우스 포인터가 직선 내지 매끄러운 곡선 궤적을 그리면서 이동한다. 공간 활용성은 최적이고 어떻게 만들었는지 정말 신기하기 그지없는 물건이긴 하나, 이동성은 그리 좋지 못하다고 봐야겠다.

아울러, 마우스를 제외한 다른 대체 포인팅 장비들은 휠을 굴리는 것까지는 표현하는 방법이 있는 반면, ‘휠을 누르는’ 동작은 표현하지 못하는 경우가 많다. 보통 휠을 누르면 동그란 앵커가 포인팅 지점에 나타나면서 문서를 위나 아래로 자동으로 스크롤하는 모드가 된다. ^^;;

터치스크린: 이건 마우스와는 성격이 약간 다른 장비이기 때문에 마우스의 대체품이 되지는 못한다. 말 그대로 화면을 터치할 수 있는데 여러 곳의 동시 터치가 가능하고 장비에 따라서는 터치하는 압력을 표현할 수 있다. 그래서 여러 손가락을 동시에 써서 그림을 그리거나 문자를 입력하거나, 건반악기의 화음 표현까지도 가능하다.

다만, 터치스크린은 딱히 스타일러스 펜을 사용하지 않는다면 좌표의 정밀도가 크게 떨어지며, 마우스로 치면 늘 click이나 drag만 존재하지 포인터를 움직이기만 하는 hovering을 표현할 수 없다는 게 문제이다. 즉, UI 요소에 대해서 ‘이게 뭐지?’ 하는 tooltip을 구현하기 어렵다. 또한 좌클릭/우클릭 구분도 할 수 없기 때문에 마우스와는 근본적으로 다른 방식의 UI 설계가 필요하다.

태블릿: 옛날에 본인이 어렸을 때는 디지타이저라고 배웠던 것 같다. 웹툰 작가 같은 그래픽 디자이너에게 필수인 물건이다. 모니터가 아니라 종이처럼 생긴 납작한 물건 위에다가 펜으로 그린다. 그래픽용으로 쓰는 물건인 만큼 압력을 표현할 수 있다.

※ 덧붙이는 말

1. 도스 시절에는 마우스를 모뎀과 같은 COM port에다 꽂았다. 추억의 mouse.com 프로그램. 무슨 인터럽트 서비스를 호출해 주면 하드웨어? 차원에서 아주 자그마한 마우스 포인터가 나타났었다. 그런데 마우스 포인터를 유지하는 게 도스 시절엔 꽤 부담스러운 일이었다. 화면을 고칠 때마다 포인터를 숨기고 다시 그려 줘야 했기 때문이다. 안 그러면 화면에 잔상이 남음.

1990년대 중반에 그래픽 카드의 성능이 발달하면서 윈도우 3.1 시절부터 flicker-free 포인터가 나타나기 시작했다. 하드웨어 차원에서 마우스 포인터의 모양을 입체적으로 보존해 준다는 뜻이다. 그것도 처음에는 시스템 기본 포인터라든가 monochrome(단색) 포인터만 지원되던 것이 2000년대부터 아무 포인터에 대해서도 OK가 되기 시작한 것이다.
윈도우 2000은 안전 모드로 부팅해서 허접한 일반 VGA 16컬러 모드에서 구동될 때도 마우스 포인터가 flicker-free가 보장되는 게 인상적이었다. 9x는 그렇지 않기 때문에.

2. 초창기에 마우스를 지원하던 프로그램은 마우스 포인터라는 게 없었고, 위· 아래로 마우스를 움직이면 선택 막대가 움직이는... 오늘날로서는 아주 기괴한 인터페이스를 제공하기도 했다.

3. 그나저나 마우스 휠이라는 건 1997년 무렵에 MS가 적극적으로 홍보하면서 널리 퍼졌다. WM_MOUSEWHEEL이라는 메시지가 운영체제 차원에서 추가된 것은 윈도우 98부터이다.
그때는 나중에 휠이 연속적이고 부드러운 rolling도 표현 가능할 것을 염두에 두고 메시지의 스펙을 설계했지만 지금 휠이 실제로 그런 방향으로 바뀐 것 같지는 않다.

일반적으로 마우스 휠 메시지는 다른 마우스 메시지와는 달리, 마우스 포인터가 가리키고 있는 윈도우가 아니라 현재 키보드 포커스를 받고 있는 윈도우로 날아간다. 그래서 원래 휠 메시지는 마우스 포인터가 어디 있든지 관계없이 받을 수 있는데 예외가 있다. 웹브라우저 창에서 굴리는 휠은 키보드 포커스도 있고 포인터 역시 그 창에 있어야 인식된다. 한 브라우저 창 안에 여러 프레임이라든가 심지어 글자 입력란처럼 여러 윈도우가 존재할 수 있기 때문에 그렇게 디자인된 것 같다.

4. 옛날 컴퓨터에는 컴퓨터의 동작 전체를 멈출 수 있는 pause 키가 존재했다. 그리고 컴퓨터가 동작 중일 때 키를 자꾸 눌러서, 처리되지 못한 키 버퍼가 꽉 차면 컴퓨터 차원에서 ‘삑삑’ 경고 beep음이 났다. 이거 기억하는 분 계시는가?

이 경고음을 마지막으로 들은 게 언제인지 기억도 안 난다. 하긴, 윈도우 9x의 BSOD도 아련한 추억이 돼 간다. 그 시절엔 그만큼 컴퓨터도, 운영체제의 구조도 단순했으며 컴퓨터의 전체 자원을 특정 프로그램이 순식간에 전부 장악하는 게 가능했다. 일부 게임을 실행하면 하드웨어를 이상하게 제어해서 pause 키가 안 먹히고 ctrl+alt+del도 안 먹히고, 심지어 caps/num lock 같은 키의 램프의 toggle도 안 되게 바뀌기도 했다.
지금은? 그렇게 한 프로그램에게 덥석 줘 버리기에는 컴퓨터의 성능과 자원이 너무 커졌고, 또 그걸 과거 컴퓨터와의 하위 호환성까지 최대한 유지하면서 제공하느라 구조가 더욱 복잡하기 짝이 없게 돼 있다.

Posted by 사무엘

2010/11/11 13:51 2010/11/11 13:51
, , , , ,
Response
A trackback , 10 Comments
RSS :
http://moogi.new21.org/tc/rss/response/409


블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/04   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        

Site Stats

Total hits:
2674296
Today:
988
Yesterday:
1540