'RTFM/Winform'에 해당되는 글 5건

  1. 2009.06.21 중첩된 사용자 정의 컨트롤의 DesignMode 속성은 동작하지 않음
  2. 2009.06.18 멀티 패널 컨트롤
  3. 2009.03.17 WPF, 저수준 키보드 후킹 예제
  4. 2009.03.06 BackgroundWorker를 사용하여 로딩 클래스 구현하기
  5. 2009.03.04 RunWorkerCompleted 핸들러에 사용자 상태를 전달

중첩된 사용자 정의 컨트롤의 DesignMode 속성은 동작하지 않음

RTFM/Winform 2009. 6. 21. 09:14

윈폼의 디자인 타임을 지원하는 Component.DesignMode 라는 속성이 있습니다.

이름이 의미하는 대로 이 컴퍼넌트가 현재 디자인 타임에 있는지 여부를 알 수 있어, 특히 컨트롤이나 폼의 Load 이벤트 핸들러에서 많이 사용됩니다.

예를 들어 폼이 로드되고 나서 어떤 작업을 해야 한다면 아래와 같은 코드를 작성할 수 있습니다.

(주 : Load 이벤트의 핸들러를 작성하지 않고 OnLoad 메서드를 오버라이드 하는 이유에 대해서는 졸고를 참고하십시오.)

(주의 주 : 폼의 경우라면 Load 이벤트 보다 Shown 이벤트를 사용할 것을 추천합니다. Shown 이벤트는 Load 이벤트가 발생한 후 폼이 화면에 표시된 시점에 발생합니다. 참고로 컨트롤에는 Shown 이벤트가 없습니다.)


코드에서 보듯이 Load 이벤트 핸들러에서는 디자인 타임인지 여부를 검사할 필요가 있습니다.

왜냐면 Load 이벤트가 발생하는 시점이 폼이 로드될 때인데, 비주얼 스튜디오에서 폼을 열 때도 폼이 로드된 것이기 때문에 이 이벤트가 발생하기 때문입니다.

여기서 ‘어떤 작업’이 실제로 어떤 작업이냐에 따라서 문제가 발생할 수 있습니다.

만약에 ‘어떤 작업’이 DB에서 데이터를 로드하거나 하드 디스크의 특정 위치에 있는 파일을 읽는 것이라면, 이는 디자인 타임에서는 수행될 수 없거나 수행되지 않아야 할 작업입니다.

위 코드에서 조건문을 뺀 상태에서 디자인 타임에서 할 수 없는 작업을 하면 예외가 발생되고, 비주얼 스튜디오에서 폼을 열 수 없게 됩니다.

비주얼 스튜디오의 버그라고 포기하기 전에 혹 위와 같은 문제가 아닌지 살펴보면 어쩌면 쉽게 문제가 해결될 수도 있습니다.

(물론 비주얼 스튜디오에서 폼을 열지 못하는 원인에는 수 십, 어쩌면 수 백 가지가 있겠는데, 이러한 상황에 대한 각각의 해결법을 하나씩 익혀 가는게 바로 경험이라는 것이겠지요.)


그런데 문제는 이 DesignMode 속성이 중첩된 사용자 정의 컨트롤에서는 동작을 하지 않는다는 것입니다.

코드를 보면서 이야기해 보지요.

사용자 정의 컨트롤을 하나 만들고 그 이름을 InnerTextViewer라고 합시다.

내부에 텍스트 박스를 하나 올리고, 배경색은 빨간 색으로 지정하였습니다.

이름이 의미하듯이 이 컨트롤은 텍스트 파일을 읽어서 표시하는 일을 합니다.

컨트롤이 로드(정확하게는 이 컨트롤이 속한 폼이 로드)되면 실행 디렉토리에 있는 a.txt 파일을 읽는 코드는 다음과 같겠네요.

이제 폼을 하나 만들고 이 사용자 정의 컨트롤을 올려 봅니다.

(아, 사용자 정의 컨트롤을 작성하거나 수정하면 빌드를 하여야 반영되는 건 아시죠?)

문제 없이 올라가고 실행하면 동작도 잘 합니다.

문제는 지금 부터입니다.

새로운 사용자 정의 컨트롤을 만들고 이름을 OuterTextViewer 라고 합시다.

그리고 앞에서 만든 InnerTextViewer 컨트롤을 도구상자에서 끌어 옵니다.

이번에는 배경색은 파란색으로 지정하였습니다.

(역시 빌드를 한 후에) 이제 위 폼에서 InnerTextViewer를 지우고 OuterTextViewer를 올려봅시다.

친숙한 화면이 나타났습니다. 절대 그냥 닫지 마시고 어떤 예외인지를 찬찬히 보시기 바랍니다.

FileNotFoundException 이고 1.txt 파일이 없다는 말 같습니다.

무슨 말인지 감이 오실 겁니다.

런 타임이 아닌 디자인 타임 임에도 불구하고 위 InnerTextViewer의 코드가 실행이 된 것입니다.

그렇다면 그 말은 위 코드의 ‘if (DesignMode)’ 에서 DesignMode 값이 false 라는 말이 되겠습니다.

위 코드에다 아래와 같이 메시지 박스를 출력하는 코드를 추가하여 직접 값을 볼 수도 있습니다.

정리하자면, 사용자 정의 컨트롤에 포함된 사용자 정의 컨트롤의 DesignMode 속성은 기대한 것처럼 동작하지 않는다는 것입니다.

‘중첩된 사용자 정의 컨트롤이 사용되는 경우가 있을까’ 하고 대수롭지 않게 생각할 수도 있지만, 규모가 제법 있고 코드가 구조화된 프로젝트에서라면 필요한 경우가 제법 있습니다.


그렇다면 이 문제를 어떻게 해결하면 좋을까요?

먼저 Load 이벤트에서 디자인 타임에서 할 수 없는 작업을 빼는 방법이 있겠네요.

위 예에서라면 파일을 읽는 부분을 별도의 메서드로 만들고, 폼이 로드되었을 때 이를 수동으로 호출하도록 하는 것입니다.

하지만 사용자 정의 컨트롤이 사용된 모든 폼의 로드 시점을 추적하여야 하기 때문에, 전체적인 프로그램의 복잡도를 증가시키는 요인이 될 수 있으므로 별로 좋은 방법은 아닌 것 같습니다.


또 다른 방법은 전역 변수 개념으로 플래그를 하나 만들어서 디자인 타임에서 이를 체크하는 것입니다.

코드를 보면서 이야기 해봅시다.

아래와 같이 Program 클래스에 정적 속성을 추가하고, 이 값을 응용프로그램이 실행되기 전에 true로 설정합니다.

그리고 InnerTextViewer의 Load 이벤트 핸들러에서는 DesignMode 속성 대신 이 플래그를 검사합니다.

빌드하고 나면 이제 폼에 OuterTextViewer를 올릴 수 있습니다.



소스 파일 :

:

멀티 패널 컨트롤

RTFM/Winform 2009. 6. 18. 18:22

http://www.codeproject.com/KB/cs/multipanelcontrol.aspx

 

폼을 구성하다 보면, 여러 개의 패널을 준비하여 놓고 특정 조건에 따라서 이 중 한 개만을 보여줘야 하는 경우가 종종 있습니다.

현재까지 발표된 닷넷 프레임웍에는 (디자인 타임을 지원하며) 이러한 기능을 제공하는 컨트롤은 없습니다.

그래서 대안으로,

1. 탭 컨트롤을 이용하는데, 선택되지 않은 나머지 탭을 감추는 등을 로직이 런타임에 실행되어야 합니다.

2. 패널 컨트롤을 이용할 수도 있는데, 위와 같은 문제와 더불어, 디자인 타임에는 모든 패널을 표시할 수 밖에 없어 폼의 레이아웃이 런타임과 달라 집니다.

등의 방법을 사용할 수 있는데, 이 아티클 필자의 말처럼 아주 ugly 합니다.

 

이 아티클에서는 디자인 타임을 지원하는 멀티 패널 컨트롤을 소개합니다.

스샷을 보시면 하나의 MultiPanel 컨트롤 안에 세 개의 페이지가 추가된 것을 볼 수 있는데, 폼 디자이너에서는 각각의 페이지를 별도로 표시하고 있습니다.

 

사용법은 무척 간단합니다.

디자인 타임에서 MultiPanel 컨트롤의 스마트 태그나 Document Online 창을 이용해 적절히 페이지를 구성한 후, 코드에서는 MultiPanel.SelectedPage 속성을 읽거나 쓰면 됩니다.

 

이 자체로도 충분히 유용한 컨트롤이지만, 선택된 페이지가 아닌 모든 페이지에 접근하는 방법이 없어 소스를 약간 수정해 보겠습니다.

각각의 페이지에 접근하기 위해서 인덱서를 사용할 것인데, 총 3개의 오버로드를 제공하겠습니다.

이를 사용하는 코드는 다음과 같습니다.

 

원 제작자의 소스는 제일 위 원문 링크에서 받으시면 되고, 제가 수정한 소스는 아래 링크에서 받을실 수 있습니다.

:

WPF, 저수준 키보드 후킹 예제

RTFM/Winform 2009. 3. 17. 16:53

http://blogs.vertigo.com/personal/ralph/Blog/archive/2007/02/12/wpf-low-level-keyboard-hook-sample.aspx

 

SetWindowsHookEx Win32 API를 사용하여 저수준 키보드 후킹을 구현하는 방법입니다.

여기서 ‘저수준 후킹’이란, 키보드 이벤트 핸들러가 구현된 닷넷 애플리케이션이 활성화되지 않은 상태이더라도 키보드 이벤트를 발생시킬 수 있다는 의미가 되겠습니다.

Popup Killer 에서 단축 키를 눌러 특정 프로세스를 죽일 때 이 코드를 사용합니다.

제목에는 WPF라고 되어 있지만 윈폼 애플리케이션에도 적용이 가능한 코드입니다.

:

BackgroundWorker를 사용하여 로딩 클래스 구현하기

RTFM/Winform 2009. 3. 6. 10:15

http://www.codeproject.com/KB/cs/yourownloadingclassbw.aspx

 

백그라운드 워커 컴퍼넌트를 사용하여 사용자에게 작업이 진행 중임을 알리는 로딩 폼을 만드는 방법을 설명합니다.

 

:

RunWorkerCompleted 핸들러에 사용자 상태를 전달

RTFM/Winform 2009. 3. 4. 13:50
http://www.pluralsight.com/community/blogs/mike/archive/2005/10/24/15875.aspx

BackgroundWorker의 알려진 버그 중 한 가지는 UserState 속성이 RunWorkerCompleted 이벤트로 전달되지 않는다는 것입니다.

본 포스트에서는 이에 대한 여러 가지 해결 방법을 제시합니다.

: