. <Shift> 클릭

<Shift> 클릭은 멀리 떨어져 있는 두 지점을 선택하고자 할 때 사용하는 명령이다. 선택을 하고자 하는 시작 지점에 캐럿을 두고 선택 끝 점으로 스크롤한 후 <Shift> 클릭하면 캐럿 위치에서 클릭한 곳까지 선택된다. 선택영역이 길어 한 화면에 보이지 않으면 마우스를 드래그해서 선택하기가 어렵고 키보드로도 선택할 수 없으므로 이 액션은 반드시 지원해야 한다.

예를 들어 12쪽에서 88쪽까지의 내용을 복사하고 싶다고 해보자. 12쪽에서 클릭한 후 쭉 스크롤해서 88쪽까지 내려가야 하는데 쭉이 아니라 아마 쭈우우우욱 한참 내려가야 할 것이다. 부지런히 내려가고 있는 중에 마우스를 놓치기라도 하면 정말 짜증난다. 키보드로 <Shift+PgDn>을 계속 눌러도 되지만 역시 불편하기는 마찬가지다. <Shift> 클릭은 일단 시작 지점에 캐럿을 두고 스크롤바를 사용하여 빠르게 이동한 후 끝 점을 지정할 수 있기 때문에 긴 문서를 선택할 때 아주 유용하다.

동작의 정의가 간단하기 때문에 코드도 간단하다. 캐럿이 있는 지점을 SelStart에 대입하고 클릭한 지점을 SelEnd에 대입한 후 화면을 다시 그려주기만 하면 된다. 모든 일은 마우스 왼쪽 버튼을 클릭할 때 일어나므로 OnLButtonDown 함수에만 코드를 작성한다.

 

void OnLButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)

{

     int toff;

    BOOL bShift, bControl;

 

    bShift=((GetKeyState(VK_SHIFT) & 0x8000) != 0);

    bControl=((GetKeyState(VK_CONTROL) & 0x8000) != 0);

 

     if (fDoubleClick) {

          ....

     }

 

    if (bShift) {

        toff=GetOffFromXY(x+xPos,y+yPos);

        ExpandSelection(off,toff);

        off=toff;

    } else {

          ClearSelection();

          off=GetOffFromXY(x+xPos,y+yPos);

          SelStart=SelEnd=off;

    }

 

     SetCapture(hWnd);

     bCapture=TRUE;

     SetCaret();

}

 

<Shift>키와 <Ctrl>키의 상태를 사용할 것이므로 OnKey 함수에서와 마찬가지로 bShift, bControl 변수에 키보드 상태를 미리 조사해두었다. keyFlags 인수로도 키보드 상태가 전달되기는 하지만 일관성을 위해 GetKeyState 함수로 따로 조사하였다. 클릭한 위치의 오프셋을 toff에 조사한 후 off를 시작점으로 toff를 끝점으로 하여 ExpandSelection 함수를 호출하면 된다. 이 함수는 선택영역이 없으면 off~toff까지 새로 선택영역을 만들어 주고 기존의 선택영역이 있으며 SelStart는 그대로 두고 SelEnd toff까지 확장하므로 <Shift> 클릭의 동작과 아주 잘 어울린다.

이때 주의할 것은 <Shift> 클릭은 더블클릭과는 달리 이 처리만으로 끝나는 것이 아니라 계속 드래그를 할 수 있어야 한다는 점이다. <Shift> 클릭으로 일단 범위를 선택한 후 계속 드래그 하면 선택영역은 마우스를 따라 확장되어야 한다. 그래서 bShift 처리 후 곧바로 리턴하지 않고 커서를 캡처하여 OnMouseMove에서 선택영역을 계속 확장할 수 있도록 하였다.