반응형

지금까지의 작업으로 Grid Control의 외적인 모습들을 개략적으로 만들어 왔다.

오늘은 Grid Control에 남아 있는 세로 스크롤바 이벤트 처리와 마우스 휠 이벤트 처리를 구현해서 Grid Control에서 정보를 Viewing하기 위한 일반적인 방법들을 구현하고자 한다.

 

저자가 작성한 소스를 본 사람들은 알겠지만 다소 엉성한 부분들이 꽤 있을 수 있다. 하나 하나의 기능을 만들어가면서 내용을 정리하고 있는 수준이다 보니 많은 부분이 깔끔하지 못할 수 있지만 나 처럼 누군가가 만들어 놓은 Grid Control을 사용만 해오다가 직접 내가 이러한 Control을 만들어 보면서 하나씩 배우고 익히는 부분이기에 더 그럴 수 있을 것이다. 

저자가 구현한 부분에 보다 좋은 아이디어나 방법이 있다면 댓글로 많은 조언과 도움을 주시길 희망하며...

 

[그림 10-1] 행 추가를 통해서 세로 스크롤바 및 마우스 휠 사용

세로 스크롤바의 경우에는 행(Row)의 맨 처음과 마지막 까지 스크롤바의 움직임에 따라 행(Row)을 이동하면서 행의 컬럼들을 보여주게 된다.

WANIGrid Control 내에서 세로스크롤바가 처음 나타났을 때의 행(Row) 개수를 파악하고 저장하기 위한 rowsCount 변수를 선언한다.

private int rowsCount = 0;  //Grid Control에서 보여지는 행의 갯수를 저장하기 위한 변수

 

WANIGrid Control의 사이즈가 변경될 때, Control 내의 표기할 수 있는 행(Row)의 개수가 변경될 수 있기에 rowsCount 변수를 초기화 하는 부분을 추가한다.

HScrollBar/VScrollBar를 초기화 하는 메소드에 rowsCount를 초기화한다.

public void InitializeScollBar()
{
    rowsCount = 0; //Control 크기가 변경되었을 경우 행(Row) 개수 초기화

    //가로 스크롤바 설정
    hScrollBar.Left = 1;
    hScrollBar.Width = Width - vScrollBar.Width - 2;
    hScrollBar.Top = Height - hScrollBar.Height - 2;
        
    //세로 스크롤바 설정
    vScrollBar.Left = Width - vScrollBar.Width - 2;
    vScrollBar.Top = topHeaderHeight + 2;
    vScrollBar.Height = Height - topHeaderHeight - hScrollBar.Height - 4;        
}

 

WANIGrid Control의 폭/높이를 기준으로 가로/세로 스크롤바를 보여줄지를 결정하는 메소드인 ReCalcScrollBar에서 rowsCount 변수에 Row개수를 설정하는 부분을 추가한다.

WANIGrid Control에서 세로 스크롤바가 나타나기 전의 Row수를 설정하는 부분을 추가해서 세로 스크롤바 또는 마우스 휠 이벤트 처리 시에 사용할 수 있도록 한다.

private void ReCalcScrollBars()
{
    if (hScrollBar == null || vScrollBar == null) return;
    //컬럼의 전체 폭
    if (grid != null && grid.GridHeaderList != null) 

        allColsWidth = grid.GridHeaderList[grid.GridHeaderList.Count() - 1].Left + grid.GridHeaderList[grid.GridHeaderList.Count() - 1].Width;

    //컬럼의 폭이 클라이언트 사이즈 폭 보다 클 경우 가로 스크롤바를 보여준다.
    if ((allColsWidth > 0) && (allColsWidth > ClientSize.Width - ysclWidth))
    {
        hScrollBar.Visible = true;
        hScrollBar.LargeChange = ((lastVisibleCol - firstVisibleCol) + 1) / 2 + 1;
        lastHScrollValue = ((lastVisibleCol - firstVisibleCol) + 1) / 2 + 1;
    }
    else
    {
        hScrollBar.Visible = false;
        grid.FirstVisibleCol = 0; //Control 크기가 바뀌면서 hScrollBar가 가려지면 Grid의 첫번째 컬럼 부터 그려지도록 처리
    }
    //로우의 높이가 클라이언트 사이즈 높이 보다 클 경우 세로 스크롤바를 보여준다.
    if (allRowsHeight > 0 && (allRowsHeight > Height - topHeaderHeight - xsclHeight))
    {
        vScrollBar.Visible = true;
        if (rowsCount == 0) rowsCount = (allRowsHeight / rowHeight) - 1; //WANIGrid Control에서 세로 스크롤바가 나타나기 전의 Row 개수 설정
        vScrollBar.Maximum = allRowsHeight;
        vScrollBar.LargeChange = rowHeight * 5;
        vScrollBar.SmallChange = rowHeight;
    }
    else
    {
        vScrollBar.Visible = false;
        grid.FirstVisibleRow = 0;
    }
}

 

세로 스크롤바를 움직였을 때 발생하는 이벤트

private void VScrollBar_Scroll(object sender, ScrollEventArgs e)
{
    firstVisibleRow = e.NewValue / rowHeight; //입력되는 세로 스크롤바의 값을 Row 위치로 변환

    if (firstVisibleRow > (allRowsHeight / rowHeight)) return;
    if (firstVisibleRow >= (allRowsHeight / rowHeight) - rowsCount)
    {
        firstVisibleRow = (allRowsHeight / rowHeight) - rowsCount;
        grid.FirstVisibleRow = firstVisibleRow;
        vScrollBar.Value = vScrollBar.Maximum;                
    }
    else
    {
        grid.FirstVisibleRow = firstVisibleRow;
        vScrollBar.Value = firstVisibleRow * rowHeight;
    }
                        
    CalcVisibleRange();
    ReCalcScrollBars();
    Invalidate();
}

 

마우스 휠 처리는 컨트롤 키를 누르고 휠을 움직였을 때와 그렇지 않고 휠만 움직였을 떄로 구분해서 처리한다.

컨트롤 키를 누른 상태에서 휠을 위/아래로 움직이면 가로 스크롤바를 움직인 효과가 나도록 했고, 마우스 휠만 위/아래로 움직였을 경우에는 세로 스크롤바를 움직인 효과가 나도록 처리했다.

마우스 휠의 경우 위로 굴리면 양수 값이 아래로 굴리면 음수 값이 나오게 된다. 

컨트롤 키를 누른 상태에서 마우스 휠을 위로 굴리면 가로 스크롤의 좌측으로, 아래로 굴리면 우측으로 움직이는 효과가 나도록 처리했다.

마우스 휠을 위로 굴리면 세로 스크롤의 위쪽으로, 아래로 굴리면 세로 스크롤의 아래쪽으로 움직인 효과가 나도록 처리했다.

private void Mouse_Wheel(object sender, MouseEventArgs e)
{
    //Control Key를 누르고 Wheel을 돌렸을 경우는 HScrollBar와 동일
    if (ModifierKeys == Keys.Control)
    {
        if ((e.Delta / 120) > 0)  //업의 경우에는 좌측으로 이동
        {
            firstVisibleCol -= 2;
            if (firstVisibleCol < 0) firstVisibleCol = 0;
            grid.FirstVisibleCol = firstVisibleCol;
            hScrollBar.Value = firstVisibleCol;
        }
        else //다운의 경우에는 우측으로 이동
        {
            firstVisibleCol += 2;
            if (firstVisibleCol >= (grid.GridHeaderList.Count - 1)) firstVisibleCol = grid.GridHeaderList.Count - 3;
            grid.FirstVisibleCol = firstVisibleCol;
            hScrollBar.Value = hScrollBar.Maximum;
        }
    }
    else //Wheel만 움직였을 경우에는 VScrollBar와 동일
    {
        if (firstVisibleRow < 0) return; 

        if ((e.Delta / 120) > 0) //업의 경우 위쪽으로 이동
        {
            firstVisibleRow -= 2;
            if (firstVisibleRow < 0)
            {
                firstVisibleRow = 0;
                grid.FirstVisibleRow = firstVisibleRow;
                vScrollBar.Value = 0;
            }
            else
            {
                grid.FirstVisibleRow = firstVisibleRow;
                vScrollBar.Value = firstVisibleRow * rowHeight;
            }
        }
        else //다운의 경우에는 아래쪽으로 이동
        {
            if (rowsCount == 0) return; // rowsCount가 0일 경우는 Row의 Height가 Control Height를 넘지 않았음
            firstVisibleRow += 2;
            if (firstVisibleRow >= (allRowsHeight / rowHeight) - rowsCount)
            {
                firstVisibleRow = (allRowsHeight / rowHeight) - rowsCount;
                grid.FirstVisibleRow = firstVisibleRow;
                vScrollBar.Value = vScrollBar.Maximum;
            }
            else
            {
                grid.FirstVisibleRow = firstVisibleRow;
                vScrollBar.Value = firstVisibleRow * rowHeight;
            }
        }
    }
    CalcVisibleRange();
    ReCalcScrollBars();
    Invalidate();
}

 

이렇게 해서 지금까지는 Grid Header를 만들고, Row를 추가하고 가로/세로 스크롤바 및 마우스 휠 이벤트 처리까지 구현을 해 보았다.

 

추가 한 행(Row)에 직접 데이터를 입력하고 보여주는 부분을 구현해 나가기에 앞서 WANIGrid Control 내에서 마우스로 클릭한 부분의 좌표를 Grid 내의 Cell 선택 영역으로 표시하기 위한 기능을 구현할 생각이다.

사용자가 WANIGrid Control 내의 Header 영역을 제외한 부분을 클릭하면 클릭 된 영역이 어느 행과 컬럼인지를 식별하기 위한 메소드를 만들어 볼 것이다.

부족하지만 Grid Control에 필요한 기능들을 고민과 학습을 통해서 하나씩 하나씩 천천히 구현해 나가볼 생각이다.

지금까지의 소스는 아래와 같다.

WANI Grid_20190721.zip
0.33MB

저자의 부족한 소스를 보고 조언 및 더 나은 방법이 있다면 기탄없이 댓글을 달아주시길 희망해 본다.

여러분들이 보내주는 의견들이 곧 WANIGrid Control의 기능을 보다 편리하고 고도화해 나갈 수 있는 방법이라 생각한다.

 

 

반응형

+ Recent posts