티스토리 뷰

728x90

이미지 맵은 웹 페이지에서 큰 이미지 하나에 영역을 구분해서 마치 각 영역이 개별 버튼인 것처럼 동작하는 것을 말합니다. 이미지를 자르고 HTML로 복잡하게 구현할 필요가 없으니 홈페이지등에 자주 활용됩니다. 이와같은 이미지맵을 VB.Net으로 윈도우 폼 환경에서 구현해 보고자 합니다.



판넬(Panel) 컨트롤이나 픽처박스(PictureBox) 모두 사용할 수 있겠지만 이미지 내부의 영역을 지정하는 좌표를 보다 간편하게 얻기 위해서 판넬 컨트롤을 사용하고 배경이미지(BackgroundImage)를 등록했습니다. 사용할 수 있는 이미지는 웹에서 사용하는 *.gif, *.jpg, *.png등 대부분의 이미지 파일을 사용할 수 있으므로 영역을 표현하는 이미지맵 좌표는 포토샵이나 기타 외부 도구로 작성하셔도 됩니다.

판넬 컨트롤이 이미지맵에 적절한 이유는 판넬은 컨테이너로 다른 컨트롤을 포함하기 때문에 디자이너 화면에서도 간편하게 이미지맵 영역을 표현하는 좌표를 얻을 수 있기 때문입니다. 판넬내에 위치하여 판넬을 부모컨트롤로 하는 컨트롤들은 시작 위치가 폼의 좌상단이 아니라 판넬의 좌상단을 0,0으로 위치(Location)의 기준을 삼습니다. 그래서 판넬의 위치를 이동해도 이미지맵의 좌표에는 아무런 영향을 주지 않습니다. 

사각형 형태의 영역은 영역에 해당하는 자식 판넬을 그리고 자식 판넬의 위치(Location)와 크기(Size)값으로 영역을 표현할 수 있습니다. 위의 예제의 화살표와 같은 도형은 각 꼭지점의 위치를 위의 예제에서 자식 판넬을 꼭지점으로 이동시켜 해당 위치를 알아내는 방법으로 영역을 표현할 수 있습니다. 물론 같은 방식으로 타원이나, 원형 영역도 표현할 수 있습니다. 아래의 코드는 위의 예제에서 마우스를 클릭하면 영역을 감지하여 레이블에 영역 이름을 출력하는 예제입니다.


Public Class Form1
    Dim path As System.Drawing.Drawing2D.GraphicsPath = New System.Drawing.Drawing2D.GraphicsPath()
    Dim workpath As System.Drawing.Drawing2D.GraphicsPath = New System.Drawing.Drawing2D.GraphicsPath()
    Dim iterator As System.Drawing.Drawing2D.GraphicsPathIterator
    Dim mapnames() As String = {"Disk", "Server", "Folder", "Arrow"}

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        path.AddRectangle(New Rectangle(25, 60, 32, 34))
        path.SetMarkers()
        path.AddRectangle(New Rectangle(25, 102, 32, 34))
        path.SetMarkers()
        path.AddRectangle(New Rectangle(25, 150, 32, 34))
        path.SetMarkers()
        path.AddPolygon({New Point(102, 8), New Point(102, 99), New Point(56, 100), New Point(128, 171), _
                         New Point(189, 100), New Point(148, 100), New Point(149, 8), New Point(102, 8)})
        iterator = New System.Drawing.Drawing2D.GraphicsPathIterator(path)
    End Sub

    Private Sub Panel1_MouseClick(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseClick
        iterator.Rewind()
        For i = 0 To iterator.SubpathCount - 1
            iterator.NextMarker(workpath)
            If workpath.IsVisible(e.X, e.Y) Then
                Label1.Text = mapnames(i) & " Clicked!"
            End If
        Next
    End Sub
End Class

폼을 로드하면서 AddRectangle, AddPolygon과 같은 메소드로 영역을 표현하는 패스(Path)를 등록합니다. 패스를 등록하면서 패스 사이에 SetMarkers() 메소드로 패스를 서로 구분할 수 있도록 해줍니다. 자유 도형(Polygon)의 경우 시작점과 끝점을 일치 시켜서 반드시 닫힌 도형이 되도록 패스를 생성해야 합니다. 

마우스 클릭 이벤트를 받으면 폼 로드 시점에 등록해 놓은 패스 컬렉션을 하나씩 읽어서 마우스의 위치가 해당 패스 영역에 포함되는 지를 IsVisible() 메소드로 확인하고 추출한 패스 인덱스 값으로 영역의 이름을 레이블에 출력하는 과정으로 동작합니다.

조금 더 응용하면 마우스 이동 이벤트(MouseMove)에서 마우스의 위치로 영역을 인식한 다음 커서의 모양을 바꾸거나 툴팁을 출력하거나 영역의 경계선을 직접 그려서 표현하는 방법도 있을 수 있습니다.

728x90
댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/11   »
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
글 보관함