C# listview 현재 크기 구하기! (feat.스크롤바?)

안녕하세요!!

인터넷을 뒤져서… 화면을 캡쳐하는걸 만들었습니다.

public static bool CaptureWindow(System.Windows.Forms.Control control, ref System.Drawing.Bitmap bitmap)
{
    Graphics g2 = Graphics.FromImage(bitmap);
    IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);
    IntPtr dc2 = g2.GetHdc();
    Point APoint = control.PointToScreen(new Point(0, 0));
    BitBlt(dc2, 0, 0, control.Width, control.Height, dc1, APoint.X, APoint.Y, 13369376);
    g2.ReleaseHdc(dc1);
    g2.Dispose();
    return true;
}
private void button4_Click(object sender, EventArgs e)
{
    Bitmap bitmap = new Bitmap(listView1.Width, listView1.Height);  //가로,세로
    MainForm.CaptureWindow(listView1, ref bitmap);
    bitmap.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\report.jpg");    //저장경로
    bitmap.Dispose();
}

이런 코드를 만들었습니다. 역시나 작동은 잘 합니다!
제가 원하는건 원래는!
창을 키우지 않고도 현재상태의! 리스트뷰의 길이와 넓이를 구해서 캡쳐를 하는건데 (캡쳐라기 보다는 사진으로 저장)
그치만… 아무리 검색해도 안나와서… 한참을 고민고민하다가 떠오른 방법이 바로!

캡쳐버튼을 누르면 현재 리스트뷰의 길이와 넓이 만큼 순간적으로 커졌다가 캡쳐를 하고 다시 원래 상태로 돌아오게 만들자 였습니다.
그럴러면 현재 리스트뷰에 있는 아이템?의 넓이와 높이를 알아야하는데… 아무리 검색해도 또 안나오더라구요… (라고 글을 쓰면서 어디선가 행의 갯수 구하기란 글을 본것같기도하고, 컬럼의 크기 구하기도 본것같음. 그렇다면 각 컬럼의 넓이를 더하면 리스트뷰의 넓이가 나오고 행의 갯수를 구하면 하나의 행의 높이 곱하기 갯수하면 되는것인가…)

그렇군요…
그 혹시 더 좋은 방법이 있다면…
제일 좋은건 역시나 첫번째인데 방법이 없을가요!
창은 작은 사이즈지만 현재 리스트뷰의 넓이와 길이에 딱 맞춰 캡쳐(아니고 사진으로 저장)하는 방법!!!
(높이가 높으면 아래는 캡쳐가 안되니ㅠㅠ)

=======
글을 쓰면서 다시 한번 깨닫네요…
한번에 단어를 만든다기 보단 자음 모음부터 차근차근 써나가야 된다는걸…

=======

int columnsWidth = listView1.Columns[0].Width + listView1.Columns[1].Width + listView1.Columns[2].Width + listView1.Columns[3].Width +
    listView1.Columns[4].Width + listView1.Columns[5].Width + listView1.Columns[6].Width + listView1.Columns[7].Width + listView1.Columns[8].Width +
    listView1.Columns[9].Width + listView1.Columns[10].Width + listView1.Columns[11].Width + listView1.Columns[12].Width + listView1.Columns[13].Width +
    listView1.Columns[14].Width + listView1.Columns[15].Width + listView1.Columns[16].Width + listView1.Columns[17].Width + listView1.Columns[18].Width +
    listView1.Columns[19].Width + listView1.Columns[20].Width + listView1.Columns[21].Width + listView1.Columns[22].Width + listView1.Columns[23].Width;

이방법말고… 뭔가 더 없을가요 한방에 구하는 방법…?

1 Like

모든 컬럼의 너비는 간단하게 Sum 함수를 사용해서 구할 수 있겠죠.
(Columns 속성은 IList<T>가 아닌 IList를 구현하므로 Cast 호출 필요)

var totalWidth = listView1.Columns.Cast<ColumnHeader>().Sum(x => x.Width);

또는 마지막 ListViewItemBounds 속성으로 높이를 포함한 전체 크기를 알 수 있습니다.

그리고 컨트롤의 DrawToBitmap 함수를 사용하면 화면 DC를 BitBlt 하는 것 보다는 화면 영역을 벗어나는 크기 등의 상황에서 더 안전하게 비트맵으로 저장할 수 있습니다.

SaveToBitmap(listView1, "Test.png");
...
private static void SaveToBitmap(ListView listView, string path)
{
    var margin = SystemInformation.Border3DSize + new Size(2, 2);

    var lastItem = listView.Items[listView.Items.Count - 1]; // listView.Items[^1];
    var totalSize = (Size)lastItem.Position + lastItem.Bounds.Size + margin;

    // Store original size
    var originalSize = listView.Size;

    listView.Size = totalSize;

    using (var bitmap = new Bitmap(totalSize.Width, totalSize.Height))
    {
        listView.DrawToBitmap(bitmap, new Rectangle(Point.Empty, totalSize));
        bitmap.Save(path);
    }

    // Revert to original size
    listView.Size = originalSize;
}

위 코드에서는 기본적으로 스크롤 바가 생기지 않는 것을 가정한 것인데 혹시 스크롤 바가 생긴다면 SaveToBitmap 함수 첫 줄의 new Size(2, 2) 부분을 적절히 조정하시면 될 것 같습니다.

2 Likes

일단 감사를 먼저 드리고 읽어보겠습니다
몇줄만 읽었는데 크… 감동이네요 감사합니다!!!

=======
일단 아직 고쳐보지는 않고 그대로 적용해서 해보니,
창의 크기는 그대로고,
캡쳐된 사진은, 눈에 보이는 창의영역과
실제 리스트뷰의 크기만큼의 빈공간을 캡쳐했더라구요.

이 소스를 토대로, 순간적으로 창의 크기를 리스트뷰의 크기만큼 늘려서
캡쳐를 하고, 다시 작아지는 소스로 어케 잘 수정을 한번 해보겠습니다!

보고 또 보고 이해하면서 열심히 배우겠습니다!!

1 Like