한글 문서를 프로그램으로 채울 때 글자를 넣는 것보다 먼저 해결해야 하는 게 "어디에 넣을 것인가"입니다. HwpCtrl(한글 웹/ActiveX 컨트롤)에서 그 위치를 잡는 메서드가 MovePos입니다. 캐럿, 즉 입력 위치를 문서 처음이나 끝, 특정 문단의 특정 글자, 표 안의 옆 칸 같은 곳으로 옮겨 줍니다. 반환값은 성공하면 true, 실패하면 false입니다.

구문

BOOL MovePos(VARIANT& moveID, VARIANT& para, VARIANT& pos)
boolean MovePos([number moveID], [number para], [number pos])

세 인자 모두 생략할 수 있습니다. moveID를 생략하면 moveCurList(1)로 처리됩니다.

광고

moveID 값

ID 값 동작
moveMain 0 루트 리스트의 특정 위치 (para, pos로 지정)
moveCurList 1 현재 리스트의 특정 위치 (para, pos로 지정)
moveTopOfFile 2 문서 시작
moveBottomOfFile 3 문서 끝
moveTopOfList 4 현재 리스트의 시작
moveBottomOfList 5 현재 리스트의 끝
moveStartOfPara 6 현재 문단의 시작
moveEndOfPara 7 현재 문단의 끝
moveStartOfWord 8 현재 단어의 시작 (현재 리스트 안에서만)
moveEndOfWord 9 현재 단어의 끝 (현재 리스트 안에서만)
moveNextPara 10 다음 문단의 시작 (현재 리스트 안에서만)
movePrevPara 11 앞 문단의 끝 (현재 리스트 안에서만)
moveNextPos 12 한 글자 뒤로 (서브 리스트를 넘나듦)
movePrevPos 13 한 글자 앞으로 (서브 리스트를 넘나듦)
moveNextPosEx 14 한 글자 뒤로 (서브 리스트를 넘나들며 머리말/꼬리말, 각주/미주, 글상자까지 포함)
movePrevPosEx 15 한 글자 앞으로 (서브 리스트를 넘나들며 머리말/꼬리말, 각주/미주, 글상자까지 포함)
moveNextChar 16 한 글자 뒤로 (현재 리스트 안에서만)
movePrevChar 17 한 글자 앞으로 (현재 리스트 안에서만)
moveNextWord 18 한 단어 뒤로 (현재 리스트 안에서만)
movePrevWord 19 한 단어 앞으로 (현재 리스트 안에서만)
moveNextLine 20 한 줄 아래로
movePrevLine 21 한 줄 위로
moveStartOfLine 22 현재 줄의 시작
moveEndOfLine 23 현재 줄의 끝
moveParentList 24 한 레벨 상위 리스트로
moveTopLevelList 25 탑레벨 리스트로
moveRootList 26 루트 리스트로
moveCurrentCaret 27 현재 캐럿 위치로 (캐럿 위치가 뷰 맨 위로 올라감, ver:0x0507013B, 0x06000105)
moveLeftOfCell 100 현재 셀의 왼쪽 셀
moveRightOfCell 101 현재 셀의 오른쪽 셀
moveUpOfCell 102 현재 셀의 위쪽 셀
moveDownOfCell 103 현재 셀의 아래쪽 셀
moveStartOfCell 104 현재 셀이 있는 행(row)의 시작
moveEndOfCell 105 현재 셀이 있는 행(row)의 끝
moveTopOfCell 106 현재 셀이 있는 열(column)의 시작
moveBottomOfCell 107 현재 셀이 있는 열(column)의 끝
moveScrPos 200 한/글 문서 화면의 screen 좌표로 위치 설정
moveScanPos 201 GetText() 실행 후의 위치로 이동

"리스트"가 뭔지 알아야 표가 읽힌다

표를 보면 "현재 리스트 안에서만", "서브 리스트를 넘나듦" 같은 말이 계속 나옵니다. 한글 문서에서 본문은 루트 리스트이고, 표의 각 셀이나 글상자, 각주, 머리말 같은 것은 그 안에 딸린 별도의 리스트(서브 리스트)로 취급됩니다. 그래서 표 셀 안에 캐럿이 있을 때 moveNextChar(16)는 셀 끝에서 더 나가지 못하고 멈추지만, moveNextPos(12)는 셀 경계를 넘어 다음 위치로 이어집니다. 머리말·각주·글상자까지 훑어야 한다면 moveNextPosEx(14)를 씁니다.

moveParentList(24)와 moveRootList(26)는 셀이나 글상자 안에서 바깥으로 빠져나올 때 씁니다. 이동한 뒤의 위치는 상위 리스트에서 그 서브 리스트를 담고 있는 컨트롤 코드(표나 글상자 자체)가 있는 자리입니다. 이미 루트 리스트에 있어서 더 올라갈 곳이 없으면 위치는 그대로인 채 반환되고, 이동할 때 선택 영역(셀렉션)은 무조건 풀립니다. 셀 내용을 다 채우고 표 다음에 이어서 글을 쓰려는데 계속 셀 안에 갇혀 있다면 이 두 값을 확인해 보면 됩니다.

para와 pos

para는 이동할 문단 번호, pos는 그 문단 안의 문자 위치입니다. 둘 다 moveMain(0)이나 moveCurList(1)일 때만 의미가 있고, 나머지 moveID에서는 무시됩니다.

예외가 moveScrPos(200)입니다. 이때 para는 문단 번호가 아니라 화면 좌표로 해석되며, 하위 워드(LOWORD)가 x, 상위 워드(HIWORD)가 y입니다. 마우스 커서의 (x, y) 좌표를 그대로 넘기면 그 지점으로 캐럿이 갑니다. moveScanPos(201)는 문서를 검색(GetText로 훑는 중)하면서 캐럿을 옮기려 할 때만 쓸 수 있습니다.

호출 예

문서 끝으로 가서 내용을 덧붙이거나, 첫 문단 처음으로 돌아가는 정도가 가장 흔한 용도입니다.

// 문서 끝으로 이동
HwpCtrl.MovePos(3);

// 루트 리스트의 첫 문단(0), 첫 글자(0)로 이동
HwpCtrl.MovePos(0, 0, 0);

상수 이름(moveBottomOfFile 등)이 스크립트에서 정의돼 있지 않은 환경이 있으니 숫자로 넘기는 편이 안전합니다. 그리고 반환값이 false인데 그냥 넘어가면 엉뚱한 위치에 글자가 들어가는 일이 생기므로, 표 안을 이동하는 반복문에서는 결과를 확인하고 멈추는 조건으로 쓰는 게 좋습니다.