아래 뜨는 Download 나 PC App Store는 모두의 프린터와 상관없는 광고입니다!!
특히 PC App Store는 악성 소프트웨어이니 절대 클릭하지 마세요!!
모두의 프린터는 어떠한 경우에도 본인인증, 회원가입, 카드결제를 요구하지 않습니다.
다운로드를 유도하는 애드센스 광고를 피로곰이 배포하는 프로그램들의 다운로드 링크로 착각하지 않도록 주의하시기 바랍니다. 피로곰이 배포하는 모든 프로그램은 본인인증, 회원가입, 이용료 결제 없이 무료로 사용가능합니다.
많이 찾는 글들...
  1. MS윈도 디펜더(바이러스 백신) 예외설정 방법
  2. ghostscript 실행파일 경로가 지정되어 있지 않아서 변환할 수 없습니다.
  3. PC App Store 제거 방법
  4. Ghostscript/GhostPCL 설치 안내
  5. 파일 다운로드가 차단되는 경우
  6. 내 컴퓨터의 32비트,64비트 여부 아는법
  7. 'Windows의 PC 보호' 문제
  8. 모두의 프린터 실행후 환경설정창 뜨지 않고 무반응
  9. Ghostscript PDF변환 불가. Can't load Ghostscript DLL
  10. 대법원 인터넷 등기소, 전자소송, 경매,전자공탁등 대법원계열 사이트관련
  11. 모두의 프린터 사용후 네트워크 장애가 발생하는경우. (대법원 인터넷등기소 등)
  12. 출력시 모두의 프린터가 강제종료 되는 경우.'지원하지 않는 PDF또는 가상 프린터입니다.'
  13. 오픽(OPic), 연결상태 확인 불가 프린터, 등록되지 않은 프린터(MarkAny e-PageSAFER)
  14. YBM 토익성적표 관련(정상적인 프린터로 출력을 진행하시기 바랍니다)
  15. 리포트뷰어(ReportViewer) 관련(특수목적프린터, 문서변환 프로그램을 제거해주세요)
  16. 인터넷증명발급센터 서트피아(Certpia) 관련 안내
  17. 인강사이트 관련 - 출력에 매우 오래 걸림, PDF파일 버벅거림, PDF여는데 오래걸림 등등
  18. '잘못된 프린터 데이터를 수신하였습니다.' 문제
  19. MS서피스, 삼성 갤럭시북 등 ARM기반 랩탑, '잘못된 프린터 데이터를 수신하였습니다.' 문제

Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #4

Go로 윈도 네이티브 GUI 줘 패기… 4번째 입니다.

이번엔 레이아웃에 대한 부분을 다뤄보도록 합니다.

앞서 C/C++에서 윈도 API를 가지고 GUI 어플리케이션을 만드는게 매우 비효율적인 노가다 개삽질이라는 식의 표현을 한적이 있는데요. 그 이유는 ..

API에서 모든 UI객체는 전부다 윈도입니다. 창도 윈도 버튼도 윈도 에디트 박스도 체크박스도 스크롤바도 스크롤바 안의 상하단 버튼도 죄~~다 윈도입니다. 그 말은 그 하나하나를 다 CreateWindow 를 하고 그 각 객체별로 WndProc 같은 메시지 프로시저를 한땀 한땀 다 등록을 시켜야 한단 소리죠 그래야 키보드 입력이던 마우스 클릭이던 내용을 그리고 지우고 지지고 볶고 .. 가 가능합니다.

그렇게 수 없이 많은 반복적인 코드를 생성해야 한다는 점도 문제지만 윈도 API로 GUI를 만든다는게 지랄같은 가장 큰 이유는 실제 그 프로그램이 어떤 형태로 눈에 보여질지를 직관적으로 알 수 없다는 겁니다. 각 객체를 생성하고 해당 객체들이 어느 위치에 놓일지 x, y 좌표 값을 가지고 배치를 해대야 하는데 .. 그게 어찌 보일진 실행을 해 봐야 아는것이죠.

그런이유로 과거에 API로 GUI만들때는 포토샵이든 그림판이든 뭐든간에 레이아웃 디자인을 잡고 좌표값을 뽑아 놓고 그 값을 보고 코딩을 하시던 분들도 계셨습니다. 이런식으로 SetWindowPos 같은 함수로 일일이 x,y 좌표값으로 버튼 하나 에디트박스 하나 체크박스 하나 라벨하나 하나하나 한땀 한땀 위치를 잡아 대는 짓이 매우 지랄 같고 그런 놈들의 수 많은 이벤트 처리를 비롯한 반복되는 코드들을 줄인답시고 나온게 MFC같은 놈이죠.

MFC에 들어서는 그나마 .. 윈도 API에 비해선 나아진게

이렇게 눈으로 직접 봐 가며 위치도 잡고 크기 조정도 가능한 에디터를 지원하고 이 에디터를 통해 코드 상의 변수나 함수와 직접적으로 연동시키는 등의 짓도 가능해 졌습니다. 그럼에도 불구하고 API든 MFC든 C/C++라는 언어를 기반으로 MS의 직원들이 지들 나름대론 그래도 좀 편해보고자 만든 체계여도 리눅스나 웹쪽 개발만 해오던 사람 입장으론 쉽게 개념이 이해가 되지 않기도 합죠..

여튼 사설이 너무 길어지고 있긴 합니다만 .. 여튼간에 윈도 GUI 프로그래밍은 .. 어려워요 .. 

하지만 Go라는 Managed 언어를 쓰면서 너무 어렵기만 하고 노가다만 심하다면 .. 때려쳐야지 그걸 왜 합니까..

여튼간에 Go뿐 아니라 파이썬이든 러스트든간에 MS에서 제공하는 저런 API, SDK, IDE의 혜택을 받지 못하는 경우 개발자에게 쥐어진건 오직 코드작성을 하는 방법뿐이 남지 않기 때문에 대부분의 Managed 언어에서 UI 프로그래밍을 할때 레이아웃은 툴킷이나 프레임워크 차원에서 알아서 잡아버립니다.

알아서 잡아버린다는게 뭔 소리냐면 ..

웹프론트에서 반응형 그리드를 생각 하면 이해가 빠르실텐데;; 웹프론트를 해보신 적 없는 분들은 반응형이니 그리드니 뭔 소린지 모르실테니 간단히 설명 해봅니다.

1-1. 라벨 1-2. 에디트 박스1-3. 버튼
2-1.라벨2-2. 드롭다운박스2-3. 버튼

코드를 작성하는 개발자는 그저 첫째줄에는 라벨, 에디트박스, 버튼 3개를 놓고 두번째 줄에는 라벨, 드롭다운박스, 버튼을 놓겠다고 코드만 작성하면 나머지는 전체 윈도의 크기를 기준하여 한줄에 3개의 요소가 있으니 넓이 / 3, 2줄이니 높이 / 2를 하여 알.아.서 레이아웃을 잡아 배치를 해버립니다.

물론 이 배치 기준도 가로기준이니 세로기준이니 그런걸 세세하게 나누기도 합니다만.

제가 만든 Walk 랩퍼의 경우 기본적으로 윈도 창은 세로(Vertical)을 기준으로 동작합니다.

Go
func test1() {
	mgr, _ := NewWindowMgrNoResize("레이아웃 테스트", 640, 480, GetIcon())

	mgr.Label("라벨입니다.")
	le := mgr.LineEdit(false)
	le.SetText("라인 텍스트 입력")
	mgr.CheckBox("체크박스입니다", false, func() {})
	mgr.StartForeground()
}

640*480의 윈도 창을 하나 만들고 라벨, 라인텍스트, 체크박스 3개의 UI객체를 윈도에 추가를 했습니다. 세로 기준으로 레이아웃 베치가 되기 때문에 위에서 아래로 한줄당 하나의 UI요소가 배치되고 이 놈들의 넓이는 창의 넓이와 같고 높이는 높이/3 으로 각각 배치된겁니다. 

그럼 앞서 표로 설명한거 같이 그리드 형식으로 이래저래 배치를 하려면 어찌 해야 하느냐 ..

Go
func test1() {
	mgr, _ := NewWindowMgrNoResize("레이아웃 테스트", 640, 480, GetIcon())

	mgr.HSplit()
	mgr.Label("1-1. 라벨")
	le1 := mgr.LineEdit(false)
	le1.SetText("1-2. 에디트 박스")
	mgr.PushButton("1-3. 버튼", func() {})
	mgr.EndSplit()

	mgr.HSplit()
	mgr.Label("2-1. 라벨")
	mgr.DropDownBox([]string{"1.하나", "2.둘", "3.셋"})
	mgr.PushButton("2-3. 버튼", func() {})
	mgr.EndSplit()

	mgr.StartForeground()
}

이렇게 하시면 됩니다. 1줄에 3개의 요소가 총 2줄로 전체 창의 크기에 맞춰서 알아서 레이아웃이 잡혀서 균등배치가 되었지요. 근데 이렇게 놓고보면 보기가 그닥 좋지 않습니다. 그럼 창 크기를 적당히 조절 하시면 되겠구요.

이렇게 조절 하셔도 되구요. 중요한건 창의 높이의 경우 모든 UI요소들은 최소 높이가 존재합니다. 폰트의 크기나 체크박스 같은 이미지나 여러 이유로 최소한의 높이라는게 있는데 창의 높이가 이 UI요소들의 최소 높이를 합한것보다 적은 값으로 지정된 경우에는 창의 크기를 UI 요소들의 합에 맞춰서 늘려버립니다.

예를들어

Go
func test1() {
	mgr, _ := NewWindowMgrNoResize("레이아웃 테스트", 640, 1, GetIcon()) // 창 높이 1

	mgr.HSplit()
	mgr.Label("1-1. 라벨")
	le1 := mgr.LineEdit(false)
	le1.SetText("1-2. 에디트 박스")
	mgr.PushButton("1-3. 버튼", func() {})
	mgr.EndSplit()

	mgr.HSplit()
	mgr.Label("2-1. 라벨")
	mgr.DropDownBox([]string{"1.하나", "2.둘", "3.셋"})
	mgr.PushButton("2-3. 버튼", func() {})
	mgr.EndSplit()

	mgr.StartForeground()
}

이렇게 창 높이를 1로 생성한다 해도

이렇게 라벨이나 에디트 박스 버튼들의 최소한의 높이와 Margin 값을 합한 최소값으로 창 크기를 늘려버립니다. 어찌됫건 막 짜도 창은 제대로 구성되서 보여집니다.

위의 코드를 보시면 HSplit 이라는 놈이 등장 하는데요 ..

창에 배치되는 요소들은 기본은 위에서 아래로 세로(Vertical)으로 쌓아가니까 쉽게보자면 위에서 아래로 쌓아가는거고 그 한줄 한줄에 여러 요소를 나눠서 넣고 싶으면 그 한줄을 나누는(Split) 것이지요. 

Go
func (m *WinResMgr) HSplit() *walk.Splitter 
func (m *WinResMgr) VSplit() *walk.Splitter
func (m *WinResMgr) EndSplit()

그래서 이 두 함수가 존재합니다. HSplit 는 가로로 분할 해주는거고 VSplit 은 세로로 분할 해주는 겁니다.

HSplit 이던 VSplit 이던 분할을 끝마칠때는 EndSplit을 호출하시면 됩니다.

HTML이나 XML에서 <tag></tag>와 같이 HSplit 이 호출되고 EndSplit 이 호출 되기 전까진 가로로 분할하여 UI 요소를 쌓는다는 소리고 VSplit 이 호출되고 EndSplit이 호출되는 사이에 작성된 UI요소의 코드들은 세로로 분할하여 쌓아간다는 소리입니다.

이 Split 함수는 각각의 분할 상황 내에서 중복해서 사용 가능합니다. 

Go
func test2() {
	mgr, _ := NewWindowMgrNoResize("레이아웃 테스트2", 640, 480, GetIcon())

	mgr.HSplit()

	mgr.VSplit()
	mgr.Label("HSplit 안에 Vsplit1")
	mgr.Label("HSplit 안에 Vsplit2")
	mgr.Label("HSplit 안에 Vsplit3")
	mgr.PushButton("버튼1", func() {})
	mgr.EndSplit()

	mgr.TextArea(false)

	mgr.VSplit()
	mgr.Label("HSplit 안에 Vsplit2-1")
	mgr.Label("HSplit 안에 Vsplit2-2")
	mgr.Label("HSplit 안에 Vsplit2-3")
	mgr.Label("HSplit 안에 Vsplit2-4")
	mgr.PushButton("버튼2", func() {})
	mgr.EndSplit()

	mgr.EndSplit()

	mgr.StartForeground()
}

이런식으로 말이죠 .. 

레이아웃에 대한 부분은 이정도 설명하면 된것 같으니 .. 다음 글에선 UI요소들에 대한 설명을 좀 해보도록 하겠습니다.

많이 찾는 글들...
  1. MS윈도 디펜더(바이러스 백신) 예외설정 방법
  2. ghostscript 실행파일 경로가 지정되어 있지 않아서 변환할 수 없습니다.
  3. PC App Store 제거 방법
  4. Ghostscript/GhostPCL 설치 안내
  5. 파일 다운로드가 차단되는 경우
  6. 내 컴퓨터의 32비트,64비트 여부 아는법
  7. 'Windows의 PC 보호' 문제
  8. 모두의 프린터 실행후 환경설정창 뜨지 않고 무반응
  9. Ghostscript PDF변환 불가. Can't load Ghostscript DLL
  10. 대법원 인터넷 등기소, 전자소송, 경매,전자공탁등 대법원계열 사이트관련
  11. 모두의 프린터 사용후 네트워크 장애가 발생하는경우. (대법원 인터넷등기소 등)
  12. 출력시 모두의 프린터가 강제종료 되는 경우.'지원하지 않는 PDF또는 가상 프린터입니다.'
  13. 오픽(OPic), 연결상태 확인 불가 프린터, 등록되지 않은 프린터(MarkAny e-PageSAFER)
  14. YBM 토익성적표 관련(정상적인 프린터로 출력을 진행하시기 바랍니다)
  15. 리포트뷰어(ReportViewer) 관련(특수목적프린터, 문서변환 프로그램을 제거해주세요)
  16. 인터넷증명발급센터 서트피아(Certpia) 관련 안내
  17. 인강사이트 관련 - 출력에 매우 오래 걸림, PDF파일 버벅거림, PDF여는데 오래걸림 등등
  18. '잘못된 프린터 데이터를 수신하였습니다.' 문제
  19. MS서피스, 삼성 갤럭시북 등 ARM기반 랩탑, '잘못된 프린터 데이터를 수신하였습니다.' 문제