블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday


richTextBox에 클립보드로부터 붙이기를 할 때 rtf 포맷으로 붙이기가 될 때가 있다. 그런데, 지금 하려는

작업이 plain text를 붙여야만 하는 경우여서 구글링해봤으나.. 결국은 속임수를 쓰기로...
방법은 richTextBox에서 Ctrl+V 키보드 이벤트를 가로채서 클립보드의 텍스트만 집어넣는 것이다. 간단?

ㅋㅋ 코드는 다음과 같다.


private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
    if ((e.KeyCode == Keys.V) && (e.Modifiers == Keys.Control))
    {
        e.Handled = true;
        richTextBox1.SelectedText = Clipboard.GetText();
    }
}

출처 : 모름 -ㅅ-;;

반응형
Posted by blueasa
, |

치킨 명소

Etc / 2010. 9. 9. 14:26


반응형
Posted by blueasa
, |




내용추가 (2010.9.4)
[3]-6번은 미국에만 해당되고 국내는 해당 안된다고 합니다. 
원글 내용 수정했습니다. 

아이폰4를 받고 최초로 동기화하기 전에 반드시 확인해야 할 것들, 
동기화하는 동안에 체크할 것들, 동기화하고 나서 체크할 것들을 
일목요연하게 정리해 놓은 글이 있어서 옯겨봤습니다. 

몇가지를 제외하고는 아이폰 3GS 사용자라면 이미 아는 팁들일 수도 있겠지만 
막상 아이폰4를 받으면 체크 리스트를 만들지 않는 한  
빠짐없이 확인하기가 힘들 것 같아서 미리 정리해 봤어요. 

이 팁은 TUAW에서 가져왔어요. 
대략의 내용만 옮겼으니 좀 더 자세히 보고 싶으신 분은 원문 링크 
를 참조하시구요.  



[1] 아이튠스 동기화 전에 체크할 것들

1. 표면 유리와 연결 부위.
유리에 스크래치는 없는지, 갈라진 틈은 없는지, 
느슨하게 연결된 부위는 없는지, 
앞/뒷면 유리와 스테인레스 부분이 평행을 이루는지 확인.  
틈새가 있으면 내부에 먼지가 유입되는 것은 물론, 
실수로 떨어뜨리는 경우 치명적인 손상을 가져올 수 있습니다.  
틈새가 벌어진 부분은 육안으로 식별하기가 힘들기 때문에 
아주 밝은 불빛 아래서 확대경으로 구석구석 살피는 것이 좋습니다. 


2. 홈버튼/슬립버튼
아이폰을 동기화하기 전 반드시 테스트해야 하는 것들 중 하나.  
너무 느슨하거나 너무 빡빡한지, 
힘을 줘서 눌려야 작동한다면 문제가 있는겁니다.

3. 진동 스위치
진동 스위치가 잘 밀어지는지, 진동이 즉각 적용되는지 확인합니다. 



[2] 아이튠스 동기화 하는 동안 체크할 것들

1. 케이블 접속 불량 여부
케이블을 PC에 연결했을 때 아이튠스에 아이폰이 뜨는지, 충전이 되는지 확인합니다. 
케이블 접속 불량인 경우 컴퓨터와 동기화되지 않거나 충전이 되지 않습니다. 


2. 플래시 메모리
아이폰의 플래시 메모리 칩이 오염된 경우 아이튠스 동기화시 에러가 뜰 수 있어요. 
먼지를 털어낸다던가 컴퓨터 USB 드라이브를 다른 곳에 꽂는 등 
여러가지 시도를 했음에도 불구하고 동기화가 안되다면 
아이폰 플래시 메모리에 문제점이 있는지 의심해 봐야 합니다.
메모리 불량 여부를 테스트하는 가장 간단한 방법은 
처음 동기화할 때 가능한 많은 동영상이나 음악을 넣어보는 것입니다. 
32GB 아이폰4라면 동기화하는데 보통 1-2시간 걸리는 것이 정상입니다.



[3] 동기화 하고 나서 체크할 것들

1. 볼륨 버튼 
볼륨 버튼이 제대로 작동하는지 확인해 봅니다. 


2. 이어폰 잭
아이폰에 딸려온 번들 이어폰을 꽂았을 때 흔들림이 없이 딱 맞는지 확인합니다.  
이어폰으로 음악을 들어보고, 잘 들리지 않는 경우 다른 이어폰으로 테스트해서 
이어폰 문제인지 이어폰 잭 접속부위 문제인지를 확인해 봅니다. 
플레이, 중지, 앞뒤 트랙 넘어가기, 볼륨 등 모든 기능을 확인해 봅니다. 


3. 카메라
사진 몇장을 찍어서 셔터가 잘 열리고 닫히는지 확인해 봅니다. 
아이폰의 "tap to focus" 기능을 테스트해 봅니다.  
거리와 조명의 차이를 두고. 배경을 밝게 하거나. 
화면에서 탭을 했을 때 포커스/밝기가 조절되는지 확인해 봅니다.   
사진찍을 때 스크린 왼쪽 윗부분을 탭해서 
LED 플래시가 작동하는지 테스트 해봅니다.  
동영상을 촬영해 보고, 촬영한 동영상을 플레이할 때 사운드가 들리는지 확인.
찍은 사진에 왜곡이나 문제점이 없는지 확인해 봅니다.  


4. 액셀로메터
아이폰을 가로/세로 로 놓았을 때 화면이 바뀌는지 확인. 
메모 어플로 키보드가 가로세로 모드로 잘 작동하는지 확인
입력 후 흔들면 입력을 취소하겠느냐고 묻는 창이 뜨는지 확인


5. 안테나
3G가 되는 곳에서 신호가 자동으로 잡히는지 확인합니다.   
사파리를 열어서 웹페이지 접속이 잘 되는지 확인해 봅니다. 
속도 차이는 있겠지만, 3G를 사용하는 경우 
페이지가 뜰때까지 몇분씩 기다려야 한다면 안테나를 의심해 봐야 합니다. 


6. EDGE/GPR (요 부분은 미국에만 해당된다고 해요. 국내 사용자는 패스~)
3G 신호가 잡히는 경우, 설정 - 일반 - 네트워크로 가서 
3G사용을 꺼주면 아이폰은 몇초만에 EDGE/GPRS 모드로 변환됩니다. 
사파리로 웹페이지에 접속해 보고 지나치게 속도가 느린지 확인해 봅니다. 
--> 

7. GPS
지도 어플을 열고 왼쪽 아래 화살표 버튼을 눌러서 
현재 위치가 파란색 원으로 표시되는지 확인해 봅니다. 
전파가 약한 지역에 있지 않는 한 현재 위치가 잡힐겁니다. 
아이폰 4의 GPS 안테나는 3GS보다 훨씬 정확하고 강력하기 때문에 
3G의 경우 실내에서 위치를 잡지 못하는 경우가 있지만 
아이폰4는 실내에서도 현재 위치를 잘 잡아줍니다. 
따라서 현재 위치가 잘 표시되어야 정상입니다. 
만일 못잡는다면 실외에서 테스트해 봅니다. 
실외에서도 못잡는다면 문제가 있는 것으로 봐야 합니다. 


8. 블루투스
설정 - 일반 - 네트워크 - 인터넷 테터링 On - 블루투스 활성화
주변의 블루투스 기기를 테스트해 봅니다. 


9. 와이파이
아이폰의 와이파이 옵션을 On 시켜놓은 상태에서 
아이폰이 주변의 모든 무선 네트워크 기기를 인식하는지 확인해 봅니다. 


10. 터치 스크린
아이폰 터치스크린에 데드 스팟이 없는지 확인.
노트 어플이나 사파리 등 텍스트 입력이 가능한 어플을 실행시키고 
"The quick brown fox jumps over the lazy dog" 을 
가로모드, 세로모드(홈 버튼이 왼쪽, 오른쪽으로 가게 놓고)로 입력해 봅니다. 
사진 어플을 실행시켜 사진을 열어 확대해보고, 화면 전체 보기 모드로 놓고 
화면을 손으로 밀어서 사진이 제대로 움직이는지 확인해 봅니다. 


11. LCD
플래시라이트 어플을 받아서 확인해 봅니다. 
백라이트는 설정 - 밝기 조절 - 슬라이더를 좌우로 움직여서 확인해 봅니다.


12. 라이트 센서
어두운 곳에서 설정 - 밝기 메뉴로 제대로 작동하는지 확인해 봅니다. 
밝기 자동 조절 옵션을 켠 상태에서 주변을 어둡게 헤서 밝기가 자동으로 조절되는지 확인해 봅니다.  


13. CPU/GPU
아이폰 4의 프로세서와 그래픽 하드웨어는 
3D 게임에서 뛰어난 성능을 발휘합니다. 
그래픽이 왜곡되거나 겹쳐 보이면 GPU에 문제점이 있는 것입니다. 
 지나치게 뜨거워지거나 버벅거리면 CPU 문제점을 의심해봐야 합니다. 
고화질 무비기 아이폰4에서 잘 보이는지도 확인해 봅니다.


14. 자기 탐지기 
나침반 어플을 실행시켜 우측 하단 버튼을 눌러서 
진북/좌북 변환이 가능한지 확인해 봅니다. 
8가지 위치로 변경해도 신호를 잡지 못하면 문제가 있는 것입니다. 


15. 자이로스코프
아이폰4에는  기본으로 제공되는 자이로스코프 어플이 없습니다. 
무료 어플 Gyroscope를 다운받아서 테스트해 봅니다. 
이 어플을 사용하면 아이폰4의 자이로스코프가 작동하는지 즉각 알 수 있습니다. 



16. 통화 테스트

1) 마이크로폰
스피커폰 모드와 정상 모드에서 통화 테스트를 해봅니다. 
전화를 걸어서 잘 들리는지 확인해 봅니다. 
아이폰4로 통화랄 때 들리지 않는다는 경우도 있었습니다. 
아이폰 4의 마이크로폰 문제점 때문인지, 
노이즈 제거 기능이 지나치게 민감해서 그런 것인지는
아직 확인되지 않은 것 같습니다. 

2) 스피커
이어폰 스피커와 아이폰 하단 스피커가 잘 들리는지, 사운드의 왜곡이 없는지 획인해 봅니다.

3) 근접 센서
아이폰 4 터치 스크린은 아이폰을 귀에 대면 꺼지고, 귀를 떼면 다시 켜져야 정상입니다. 
아이폰 4의 근접 센서가 통화하는 동안 제멋대로 활성회되고 
뺨을 대면 꺼진다는 보고도 있었지만 
이것은 하드웨어 문제점이라기 보다는 iOS 소프트웨어 문제점으로 보입니다.  
만일 센서가 전혀 작동되지 않는다면 하드웨어 문제점으로 보는 것이 좋습니다. 


17. 배터리
배터리에 문제점이 없는지 확인하는 방법은 여러가지가 있지만 
가장 널리 사용되는 방법은 배터리가 완전 소진될 때까지 동영상을 돌리는 것입니다. 
애플에 의하면 동영상 배터리가 완전 소진될 때까지 드는 시간은 약 10시간이라고 합니다. 
하지만 결과의 차이는 항상 존재하기 때문에 
디폴트 화면 밝기에서 완충된 아이폰으로 동영상을 돌려서
배터리가 완전 소진되는데 7시간 정도 걸리면 정상으로 볼 수 있습니다.


위의 모든 테스트는 아이폰4 하드웨어에 전혀 해를 주거나 영향을 주지 않는다고 합니다. 
저는 진리의 화이트를 기다리느라 이번 예판은 눈물을 머금고 참여하지 않았지만.. ㅠㅠ
언제 마음이 변할지 모르겠어서.. 열심히 준비하고 있답니다. ^^

아이폰 4가 손에 들어오면 꼼꼼하게 체크해봐야겠습니다. ^^
반응형
Posted by blueasa
, |

Cecil Lew

네트워크 관리 및 워크플로 처리 같은 대부분의 응용 프로그램 유형에는 다이어그램 작성 인터페이스가 필요합니다. 그러나 Windows 응용 프로그램에서 Visio와 같은 다이어그램 작성 인터페이스를 개발하기는 좀처럼 쉬운 일이 아닙니다. 이 기사에서는 Cecil Lew가 UserControl 및 몇 가지 단순한 클래스를 기반으로 하여 간단한 다이어그램 작성 도구를 빌드하는 방법을 소개합니다.

응용 프로그램에서 다이어그램 작성 기능이 필요한 경우에는 어떻게 하시겠습니까? 이 경우 다음과 같은 네 가지 방법이 있습니다. 즉, 1) 타사 라이브러리를 구입하거나 2) Netron 등의 공개 소스 라이브러리를 사용하거나(확장도 가능함) 3) 응용 프로그램을 Visio와 통합하거나 4) 새 도구를 처음부터 빌드하는 것입니다.

1번이 가장 쉽겠지만 타사 지원에 의존해야 하므로 위험도도 가장 높습니다. 2번도 괜찮은 방법 같지만, 개인적으로 이 방법을 사용해 봤는데 솔직히 25,000줄의 코드로 이루어진 다른 사람이 작성한 라이브러리를 확장하는 것은 쉬운 일이 아닙니다. 3번은 Microsoft Office 커뮤니티에서 많은 지원을 받을 수 있으므로 쉽게 수행할 수 있습니다. 그러나 이 경우 응용 프로그램을 통합하려면 대상 컴퓨터에 올바른 버전의 Visio가 설치되어 있어야 한다는 단점이 있습니다. 여기까지 읽으셨다면 제가 개인적으로 4번을 선호한다는 사실을 눈치채셨을 것입니다. Windows Form 및 GDI+에서는 확대/축소, 변환 및 회전 같은 그리기 및 2D 변환에 뛰어난 기능을 제공합니다.

이 기사에서는 이를 검증하기 위해 개발한 간단한 다이어그램 작성 응용 프로그램에 대해 설명합니다. 먼저 클래스 디자인을 중점적으로 설명한 다음 보다 중요한 기능을 자세히 설명합니다. 이 기사에서 설명하는 응용 프로그램은 C# 및 Windows Form을 사용하여 작성되었습니다. 그림 1은 이 응용 프로그램을 보여 줍니다.

그림 1

왼쪽에는 BlockControl 또는 Connector를 오른쪽의 그리기 영역으로 끌어서 놓을 수 있는 도구 상자가 있습니다. 그리고 컨트롤의 텍스트를 두 번 클릭하여 수정할 수 있습니다. 마지막으로 Connector 핸들을 끌어 BlockControl 주위의 핸들 중 하나에 부착할 수 있습니다.

물론 이 응용 프로그램에서 유용한 기능을 많이 제공하는 것은 아닙니다. 그러나 이 응용 프로그램을 통해 다이어그램 작성 프레임워크의 기초가 되는 상속, 컴퍼지션 및 다양한 C# 구문을 사용하는 방법에 대한 기본 개념을 파악할 수 있습니다.

클래스 디자인
DiagramLib 클래스 라이브러리에는 8개의 클래스가 포함됩니다. 표 1에서는 이러한 클래스 및 해당 용도를 나열합니다.

표 1. DiagramLib 라이브러리의 8개 클래스

클래스 목적
Draggable 이 프로젝트에서 발생하는 대부분의 문제는 개체 이동 및 크기 조정과 관련된 것입니다. 이 일반 Draggable UserControl은 마우스 끌기 동작과 위치 변경을 캡처하기 위한 것입니다.
LabelBox 마우스를 두 번 클릭하면 편집 모드로 전환되는 Label 형식 컨트롤입니다. BlockControl 및 Connector 개체가 사용합니다.
ResizeHandle 크기 조정 작업을 처리하는 BlockControl 주위의 작은 사각형입니다.
ConnectorHandle BlockControl 개체 끌기 및 이 개체에 부착하는 작업을 처리하는 Connector 개체 끝점의 작은 사각형입니다.
DiagramControl BlockControl 및 Connector가 상속을 받는 간단한 클래스입니다. "ID" 등의 일반적인 특성을 제공합니다.
BlockControl 텍스트 입력, 이동 및 크기 조정을 위한 주 다이어그램 작성 컨트롤로, Connector 개체와 연결됩니다.
Connector BlockControl 개체를 선 및 화살표와 연결하는 컨트롤입니다.
DrawingBoard BlockControl 및 Connector 개체를 배치하기 위한 화이트보드입니다.

그림 2그림 3에서는 DiagramLib의 클래스 계층 구조 및 이러한 클래스의 구성/연결을 확인할 수 있습니다. 또한 그림 4에서는 보다 뚜렷하게 다양한 클래스 간의 관계를 이해할 수 있습니다.

그림 2

그림 3

그림 4

Connector를 처리하는 방식에는 두 가지가 있습니다. 첫 번째는 다른 다이어그램 작성 컨트롤과 동일하게 취급하는 것입니다. 즉, Connector를 끌거나 크기를 조정할 수 있습니다. 그러나 보다 중요한 것은 Connector를 다른 화면 개체에 연결하지 않아도 된다는 것입니다. Visio에서는 이 방식을 사용합니다. 두 번째 방식을 사용하는 경우 Connector의 양 끝을 항상 무엇인가에 부착해야 합니다. 그러므로 Connector의 끝점이 아무 것에도 부착되지 않은 상태로 둘 수는 없습니다. Netron에서는 이 방식을 사용합니다. 개인적으로는 첫 번째 방식이 두 번째보다 직관적이라고 생각합니다. 그러므로 이 기사의 디자인은 Visio의 방식을 따릅니다.

다음 섹션에서는 클래스 및 여러 클래스를 함께 사용하는 방법에 대해 자세히 설명합니다.

끌기
Draggable 클래스는 UserControl에서 상속되지만 이 클래스에는 시각적인 구성 요소가 없습니다. 이 클래스는 MouseDown 이벤트 다음에 MouseMove 이벤트와 LocationChanged 이벤트가 뒤따르도록 정의되어 있는 마우스 끌기 동작을 처리합니다. 즉, 화면에서 클래스가 실제로 "끌기"되는 것이 아니라 사용자 정의 이벤트인 DraggableMouseMove, DraggableMouseStop 및 DraggableLocationChanged가 발생하는 것입니다. 이 Draggable 개체의 컨테이너가 실제 이동 또는 크기 조정을 수행합니다. 목록 1에는 Draggable 클래스의 세 가지 마우스 이벤트 처리기인 OnMouseDown, OnMouseUp 및 OnMouseMove가 있습니다.

목록 1. Draggable 클래스의 마우스 처리 루틴
 public event MouseEventHandler DraggableMouseMove; public event MouseEventHandler DraggableMouseStop; protected virtual void OnDraggableMouseStop( MouseEventArgs e) { if (DraggableMouseStop != null) { // 대리자를 호출합니다. DraggableMouseStop(this, e); } } protected virtual void OnDraggableMouseMove( MouseEventArgs e) { if (DraggableMouseMove != null) { // 대리자를 호출합니다. DraggableMouseMove(this, e); } } protected virtual void OnMouseDown(Object o, MouseEventArgs e) { IsMouseDown = true; initX = e.X; initY = e.Y; } protected virtual void OnMouseUp(Object o, MouseEventArgs e) { if (IsMouseDown) { MouseEventArgs evt = new MouseEventArgs( e.Button, e.Clicks, e.X - initX, e.Y - initY, e.Delta); OnDraggableMouseStop(evt); } IsMouseDown = false; } protected virtual void OnMouseMove(object o, MouseEventArgs e) { if (IsMouseDown) { // Delta 값(이동한 거리)만 필요합니다. // e.X는 커서의 상대 위치입니다. MouseEventArgs evt = new MouseEventArgs( e.Button, e.Clicks, e.X - initX, e.Y - initY, e.Delta); OnDraggableMouseMove(evt); } }(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.) 

Draggable 클래스에서는 이벤트 처리기를 제공하는 반면 LabelBox 및 ResizeHandle 클래스에서는 시각적 요소 및 이벤트 처리기 간의 링크를 제공합니다. 예를 들어 ResizeHandle에는 마우스 이벤트를 캡처하고 Draggable 마우스 이벤트 처리기에 작업을 위임하는 Label 컨트롤(lblHandle)이 있습니다.

public ResizeHandle() { ... lblHandle.MouseDown += new MouseEventHandler( base.OnMouseDown); lblHandle.MouseUp += new MouseEventHandler( base.OnMouseUp); lblHandle.MouseMove += new MouseEventHandler( base.OnMouseMove); this.LocationChanged += new EventHandler( base.OnLocationChanged); ... } 

앞서 Draggable 클래스에서 컨트롤의 실제 이동을 처리하지 않음을 언급했습니다. 이는 ResizeHandle 또는 LabelBox도 마찬가지입니다. 이러한 클래스는 DraggableMouseMove 이벤트를 상향 전파하여 부모 BlockControl 개체 또는 Connector 개체가 해당 작업을 처리하도록 합니다.

그림 5는 사용자가 ConnectorHandle을 끌면 클래스가 상호 작용하는 방법을 보여 주는 실제 시나리오 다이어그램입니다.

그림 5

부착 및 부착 해제 프로세스(1부): 부착
Connector의 ConnectorHandle을 BlockControl의 ResizeHandle과 아주 가까운 위치로 끌면 부착이 수행됩니다. 반대로 ConnectorHandle을 연결된 BlockControl에서 비교적 먼 위치로 끌면 연결 부착이 해제됩니다. 이 메커니즘을 설명하려면 BlockControl, Connector 및 ConnectorHandle의 구조를 자세히 살펴봐야 합니다.

BlockControl의 중앙에는 LabelBox가 있고 그 주위에는 8개의 ResizeHandle 개체가 있습니다. ResizeHandle 개체에는 그림 6과 같이 0에서 7까지의 인덱스가 지정되어 있습니다.

그림 6

나중에 살펴보겠지만 ConnectorHandle은 BlockControl에 부착되면 이 번호를 기록하기 때문에, ResizeHandle의 인덱스에는 중요한 의미가 있습니다.

Connector에는 각각 반대쪽 끝에 ConnectorHandle 개체가 두 개 있습니다(그림 7 참조).

그림 7

화면에서 ConnectorHandle을 끌면 모든 기존 BlockControl이 호출되어 해당 ResizeHandle 개체 중 ConnectorHandle에 부착될 수 있을 만큼 가까운 위치에 있는 개체가 있는지 확인합니다. BlockControl의 FindHandle 메서드(목록 2 참조)가 특정 지점으로부터 거리를 계산하여 해당 지점이 충분히 가까운 경우에는 ResizeHandle 인덱스를 반환합니다.

목록 2. BlockControl의 FindHandle 메서드
public int FindHandle(Point p) { const int GLUE_DISTANCE = 20; // 길이 20px int x = this.handles[HD_NW].Left; int y = this.handles[HD_NW].Top; int index = 0; double minDist = double.MaxValue; double dist = 0; for (int i = 0; i < NUM_HANDLE; i++) { ResizeHandle hd = this.handles[i]; dist = Math.Sqrt(Math.Pow(hd.Left - p.X, 2) + Math.Pow(hd.Top - p.Y, 2)); if (dist < minDist) { index = i; minDist = dist; } } if (minDist < GLUE_DISTANCE) { return index; } else { return -1; } } 

그림 8에는 BlockControl이 하나만 있지만 실제로 프로그램에서는 화면의 모든 BlockControl 개체를 호출합니다.

그림 8

BlockControl 개체 중 하나에서 유효한 ResizeHandle 인덱스를 반환하는 경우, 이는 Connector가 해당 BlockControl에 즉시 연결되어야 함을 의미합니다. 그러면 ConnectorHandle 위치가 갑자기 변경되어 맞추기 및 붙이기 형식으로 이동합니다.

ConnectorHandle은 ResizeHandle에서 상속되며 BlockControl에 부착되거나 BlockControl에서 부착이 해제되는 기능이 추가됩니다. ConnectorHandle은 BlockControl에 부착되면 BlockControl 이동을 따르며, 그로 인해 부모 Connector 개체의 크기와 모양을 변경합니다. ConnectorHandle은 부착된 BlockControl 및 ResizeHandle을 기억함으로써 이 작업을 수행합니다.

public class ConnectorHandle: ResizeHandle { private BlockControl connectedBlock; private int blockHandleIndex; ... 

부착 및 부착 해제 프로세스(2부): 부착 후 이동
Connector 및 BlockControl이 서로 부착된 후에 BlockControl의 해당 부분을 끌거나 크기를 조정하면 Connector의 크기도 자동으로 조정됩니다. 이는 ResizeHandle에서 LocationChanged 이벤트를 부모 BlockControl로 전송하면 부모 BlockControl은 연결된 모든 Connector가 해당 ConnectorHandle의 위치를 변경하도록 지시하기 때문입니다(그림 9 참조).

그림 9

부착 및 부착 해제 프로세스(3부): 부착 해제
연결된 BlockControl에서 ConnectorHandle을 끌거나 LabelBox 개체를 끌어 중앙에서 다른 위치로 이동하면 부착 해제가 수행됩니다. 이 작업은 끈 위치가 임계값에 도달할 때까지 마우스 이동을 무시함으로써 수행됩니다.

// ConnectorHandle 클래스 protected override void OnMouseMove(Object o, MouseEventArgs e) { if (this.connectedBlock == null) { base.OnMouseMove(o, e); } else { if (ShouldBreakBinding(e)) { connectedBlock.RemoveConnectorHandle( this, blockHandleIndex); connectedBlock = null; base.OnMouseMove(o, e); } } } private Boolean ShouldBreakBinding(MouseEventArgs e) { return (Math.Sqrt(Math.Pow(e.X,2) + Math.Pow(e.Y, 2)) > 20); } 

Connector의 LabelBox 개체를 끌어서 이동해도 역시 양 끝의 연결이 끊어집니다.

// Connector 클래스 private void Label_DraggableMouseMove(Object o, MouseEventArgs e) { // 핸들 중 하나가 Block 컨트롤에 연결되어 있는 경우 // 저항이 필요합니다. if (handles[0].ConnectedBlockControl != null || handles[1].ConnectedBlockControl != null) { double dist = Math.Sqrt(Math.Pow(e.X, 2) + Math.Pow(e.Y, 2)); if (dist <= 20) return; } ... } 

그림
이 섹션에서는 화면에서 컨트롤을 그리는 방법에 대해 자세히 다룹니다. 일부 컨트롤은 Windows Label로 구성되는 ResizeHandle 같은 Windows 기본 요소만으로 이루어져 있습니다. 그리고 GDI+ 라이브러리를 사용하여 화면 업데이트를 수행하는 컨트롤도 있습니다. 여기서는 GDI+ 관련 컨트롤에 대해 주로 설명합니다.

LabelBox 클래스 LabelBox는 개체의 텍스트 설명을 보여 주는 직사각형 상자입니다(그림 4 참조). BlockControl 및 Connector 클래스는 모두 이 클래스를 사용합니다. 이 클래스를 두 번 클릭하면 텍스트 상자가 표시되어 사용자가 내용을 편집할 수 있습니다. 이름에서 짐작되듯이 이 클래스에는 Label 컨트롤이 포함되어 있다고 생각될 수 있습니다. 그리고 이전 버전까지는 실제로 그랬습니다. 그러나 Label 컨트롤은 새로 고침 속도가 매우 느립니다. 화면에서 함께 움직이는 Label 컨트롤이 5개 이상인 경우에는 속도가 너무 느려서 이상하게 보이기도 합니다. 그러므로 이 LabelBox 버전의 경우에는 GDI+ 호출을 통해 직사각형과 텍스트를 다시 그리도록 했습니다.

// LabelBox 클래스 private void LabelBox_Paint(Object o, PaintEventArgs e) { €| e.Graphics.FillRectangle(backgroundBrush, 0, 0, this.Width, this.Height); e.Graphics.DrawRectangle(textPen, 0, 0, this.Width - 1, this.Height - 1); e.Graphics.DrawString(text, txtEdit.Font, textBrush, 2, 2); } 
Connector DrawingBoard 개체는 화면을 새로 고쳐야 할 때 Connector 개체의 Paint 메서드를 호출합니다. ConnectionStyleEnum 속성이 이 클래스에서 설정할 수 있는 스타일을 지정합니다. 이 값과 각 값을 설정했을 때의 효과가 그림 10에 나와 있습니다.

그림 10

LeftRight 및 UpDown 스타일의 경우 정적 다차원 배열을 사용하여 화살표 회전 각도를 결정합니다.

// Connector 클래스 private static int[,] degrees = new int[4,2]; static Connector() { // 화살촉을 그리기 위한 각도 매트릭스를 초기화합니다. // updown, 핸들 1 위에 핸들 0 degrees[Convert.ToInt16(ConnectorStyleEnum.UpDown), Convert.ToInt16(true)] = 0; // updown, 핸들 1 아래 핸들 0 degrees[Convert.ToInt16(ConnectorStyleEnum.UpDown), Convert.ToInt16(false)] = 180; // leftright, 핸들 1 왼쪽에 핸들 0 degrees[Convert.ToInt16(ConnectorStyleEnum.LeftRight), Convert.ToInt16(true)] = -90; // leftright, 핸들 1 오른쪽에 핸들 0 degrees[Convert.ToInt16(ConnectorStyleEnum.LeftRight), Convert.ToInt16(false)] = 90; } 

정적 생성자가 배열 각도를 초기화합니다. 클래스의 정적 생성자는 응용 프로그램 수명 동안 단 한 번만 호출됩니다. 생성자가 트리거되는 때는 클래스의 첫 번째 인스턴스를 만든 때나 정적 멤버가 처음으로 참조되는 때입니다. 화살표의 회전 각도를 확인하려면 치수를 채우면 됩니다.

// Connector 클래스 private void DrawHandlesArrows(Graphics g) { double h0Deg = 0; double h1Deg = 0; switch (connStyle) { case ConnectorStyleEnum.LeftRight: h0Deg = degrees[(int) connStyle, Convert.ToInt16(handles[0].Left < handles[1].Left)]; break; €| } 

화살촉 좌표가 일련의 점으로 기록됩니다. 그림 11그림 12에는 이러한 점이 각각 좌표축 및 화면 좌표로 표시되어 있습니다.

그림 11

그림 12

선 끝에 올바른 각도로 화살촉을 그리려면 세 가지 변환 작업을 수행해야 합니다.

  • 변환 - 화살촉이 중앙(0, 0)에서 약간 벗어나도록 이동합니다. 이 작업은 화살촉이 ConnectorHandle과 같은 영역에 있지 않도록 하기 위해 수행합니다.

  • 회전 - 선 경사도를 기준으로 정확한 각도를 계산합니다.

  • 변환 - 화살촉을 선 끝으로 이동합니다.

다음 코드 세그먼트에서는 화살촉 생성 및 그림 13에 나와 있는 3단계 변환 과정을 설명합니다.

double grad = (float) (handles[1].Top - handles[0].Top) / (float) (handles[1].Left - handles[0].Left); double deg = Math.Atan(grad) * (180 / Math.PI); €| Point[] p = new Point[] { new Point(0, 0), new Point(5, 7), new Point(0, 5), new Point(-5, 7), new Point(0, 0)}; path.AddLines(p); Matrix m = new Matrix(); m.Translate(x, y); // 직선 끝 m.Rotate((float) deg); m.Translate(0, 5); path.Transform(m); 

그림 13

결론
이 기사에서 소개한 8가지 클래스에는 기본적인 기능만이 포함되지만, 이를 기반으로 하여 보다 수준 높은 프레임워크를 만들 수 있습니다. 즉시 사용할 수 있는 라이브러리가 필요한 경우에는 http://netron.sourceforge.net/ (영문)의 공개 소스 Netron 그래프 라이브러리를 확인해 보십시오.

다운로드 단추를 클릭하면 코드(506LEW.ZIP)를 다운로드할 수 있습니다.

Visual Studio .NET Developer 및 Pinnacle Publishing에 대한 자세한 내용을 보려면 해당 웹 사이트인 http://www.pinpub.com/(영문 사이트)을 방문하십시오.

참고: 이 사이트는 Microsoft Corporation 웹 사이트가 아니므로 Microsoft는 그 내용에 책임을 지지 않습니다.

이 기사는 Visual Studio .NET Developer 2005년 6월호를 바탕으로 다시 쓰여진 것입니다. Copyright 2005, by Pinnacle Publishing, Inc., unless otherwise noted. All rights are reserved. Visual Studio .NET Developer는 Pinnacle Publishing, Inc에서 독립적으로 제작한 발행물입니다. 이 기사의 어떤 부분도 Pinnacle Publishing, Inc.의 사전 동의 없이는 어떤 형식으로도(중요한 기사나 논평에서 간략하게 인용하는 경우는 제외함) 사용하거나 복제할 수 없습니다. Pinnacle Publishing, Inc.에 연락하려면 1-800-788-1900으로 전화 주십시오.


 
출처 : http://www.xdotnet.com/xdotnet/board/BoardRead.aspx?F_Code=11&B_Code=1010&B_Index=1280&B_Page=0
반응형
Posted by blueasa
, |

KeyDown이벤트시에 한글 입력은 무조건 229(?)만 나오기 때문에 어떤 글자를 쳤는지는 알 수가 없지요.

 

그래서 한글 입력은 윈도우 메시지를 가로채서 알아냅니다.

 

먼저 윈도우 메시지를 가로채는 방법은 크게 두가지정도를 생각해 볼 수 있겠는데요,

WndProc 메서드를 오버라이드 하는 방법과 IMessageFilter를 구현해서 가로채는 방법이 있겠습니다.

 

인터넷에 찾아보니 WndProc메서드 오버라이드 하는 방법이 나와있는데 전 이 방법으로는 메시지를 가로챌 수 없더군요..

(왜 안되는지 아시는 분은 답글 남겨 주시기 바랍니다..)

음.. 코딩 환경따라 다른지 모르겠습니다.

참고로 제 환경은 Windows XP Pro 이고 .NET FramWork 1.1 Ver 1.1.4322 환경입니다..

 

 

아무튼.. 메시지 필터를 이용해서 메시지를 가로채기 위해서는

윈폼에서 Application.AddMessageFilter(구현한 필터 클래스) 호출하여 가로채는데

다음과 같은 순서로 하면 되겠습니다.

 

1. 메시지를 가로채서 어떻게 처리할 것인지를 구현한다.

즉 IMessageFilter 클래스를 구현하는것을 의미합니다.

 

구체적으로 이런식으로 구현하면 되겠습니다.

 

    public class MyMessageFilter: IMessageFilter

        {

            #region IMessageFilter 멤버

     

            public const int WM_KEYFIRST = 0x100;

            public const int WM_KEYDOWN = 0x100;

            public const int WM_KEYUP = 0x101;

            public const int WM_CHAR = 0x102;

            public const int WM_IME_STARTCOMPOSITION = 0x10D;

            public const int WM_IME_COMPOSITION = 0x10F;

            public const int WM_IME_ENDCOMPOSITION = 0x10E;

            public const int WM_IME_SETCONTEXT = 0x281;

            public const int WM_IME_NOTIFY = 0x282;

            public const int WM_IME_CONTROL = 0x283;

            public const int WM_IME_COMPOSITIONFULL = 0x284;

            public const int WM_IME_SELECT = 0x285;

            public const int WM_IME_CHAR = 0x286;

            public const int WM_IME_KEYDOWN = 0x290;

            public const int WM_IME_KEYUP = 0x291;

            public const int WM_IME_REPORT = 0x0280;

            public const int WM_IME_REQUEST = 0x0288;

            

            public bool PreFilterMessage(ref Message m)

            {

                // TODO:  MyMessageFilter.PreFilterMessage 구현을 추가합니다.

                Form1 fm = (Form1)Form.ActiveForm;

                

                switch(m.Msg)

                {

                    case WM_IME_STARTCOMPOSITION:

                        fm.WriteLine("한글 조합 시작.." + "\t" + m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

     

                    case WM_IME_COMPOSITION:

                        fm.WriteLine("한글 입력 중.." + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

     

                    case WM_IME_ENDCOMPOSITION:

                        fm.WriteLine("한글 조합 완료.." + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

     

                    case WM_IME_SETCONTEXT:

                        fm.WriteLine("WM_IME_SETCONTEXT" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_NOTIFY:

                        fm.WriteLine("WM_IME_NOTIFY" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_CONTROL:

                        fm.WriteLine("WM_IME_CONTROL" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_COMPOSITIONFULL:

                        fm.WriteLine("WM_IME_COMPOSITIONFULL" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_SELECT:

                        fm.WriteLine("WM_IME_SELECT" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_CHAR:

                        fm.WriteLine("WM_IME_CHAR" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_KEYDOWN:

                        fm.WriteLine("WM_IME_KEYDOWN" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_KEYUP:

                        fm.WriteLine("WM_IME_KEYUP" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_REPORT:

                        fm.WriteLine("WM_IME_REPORT" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    case WM_IME_REQUEST:

                        fm.WriteLine("WM_IME_REQUEST" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

     

                    case WM_KEYDOWN:

                        fm.WriteLine("WM_KEYDOWN" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    /*

                    case WM_KEYUP:

                        fm.WriteLine("WM_KEYUP" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                    */

                    case WM_CHAR:

                        fm.WriteLine("WM_CHAR" + "\t"+ m.WParam.ToString() + "\t" + m.LParam.ToString());

                        break;

                }

                

                return false;

            }

     

            #endregion

        }//end of class

 

 

2. 윈폼 클래스에서 구현한 필터 클래스를 선언합니다.

 

private MyMessageFilter mmf = new MyMessageFilter();

 

 

 

3. AddMessageFilter()로 메시지 필터를 윈폼클래스에 등록합니다.

 

Application.AddMessageFilter(mmf);

 

폼 생성자 메서드에서 등록하면 되겠네요..

 

 

참.. 제 소스에서는

윈폼 클래스에 다음과 같은 메서드를 추가했었죠..

 

        public void WriteLine(string str)

        {

            this.textBox1.Text += str + "\r\n";

        }

 

이로서 한글을 입력할때 어떤 메시지가 어떻게 발생하는 지 대충 알 수 있으리라고 생각됩니다.

출처 : Devpia


출처 : http://www.xdotnet.com/xdotnet/board/BoardRead.aspx?F_Code=14&B_Code=1052&B_Index=1294&B_Page=0

반응형
Posted by blueasa
, |

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace QEControls
{
/// <summary>
/// Summary description for FlickerFreeRichEditTextBox.
/// </summary>
public class FlickerFreeRichEditTextBox : RichTextBox
{

// #define WM_PAINT 0x000F

const short WM_PAINT = 0x00f;
const short WM_IME_NOTIFY = 0x0282;
const int IME_CMODE_NATIVE = 0x1;
//const short IMN_SETCONVERSIONMODE = 0x06;
private IntPtr IMN_SETCONVERSIONMODE = new IntPtr(0x06);

public FlickerFreeRichEditTextBox()
{
//
// TODO: Add constructor logic here
//
//SetStyle(ControlStyles.AllPaintingInWmPaint, true);
//SetStyle(ControlStyles.DoubleBuffer , true);
//SetStyle(ControlStyles.UserPaint , true);
_Paint = true;
this.ScrollBars = RichTextBoxScrollBars.Both;
}

[DllImport ("imm32.dll", CharSet=CharSet.Auto)]
public static extern int ImmGetContext (int hWnd);

[DllImport ("imm32.dll", CharSet=CharSet.Auto)]
public static extern int ImmReleaseContext (int hWnd, int hImc);

[DllImport ("imm32.dll", CharSet=CharSet.Auto)]
public static extern int ImmGetConversionStatus (int hImc, out int
fdwConversion, out int fdwSentence);

private bool _isHangulMode = false;
public bool IsHangulMode
{
get { return _isHangulMode; }
}

public bool _Paint = true;
public bool IsPainting
{
get
{
return _Paint;
}
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_PAINT)
{
if (_Paint)
base.WndProc(ref m);
else
m.Result = IntPtr.Zero;
}
else if ( m.Msg == WM_IME_NOTIFY )
{
if ( m.WParam == IMN_SETCONVERSIONMODE )
{
int hImc, dwConversion = 0, dwSentense = 0;
hImc = ImmGetContext(this.Handle.ToInt32());
ImmGetConversionStatus(hImc, out dwConversion, out dwSentense);
if ( (dwConversion & IME_CMODE_NATIVE) == 1 )
{ // 한글모드
//System.Diagnostics.Trace.WriteLine("한글모드");
_isHangulMode = true;
}
else
{
//System.Diagnostics.Trace.WriteLine("English Mode");
_isHangulMode = false;
}
ImmReleaseContext(this.Handle.ToInt32(), hImc);
}
}
else
{
base.WndProc (ref m);
}
}

public void BeginUpdate()
{
_Paint = false;
}

public void EndUpdate()
{
_Paint = true;
}
}
}

출처 : http://www.ms-news.net/f2235/iso-8859-1-b-cmljahrlehrcb3i-oscw-mfrimh6ua7a1ltptnku-5396626.html
반응형
Posted by blueasa
, |

한영 변환키 누름 상태는 윈도 메세지에서 WM_IME_NOTIFY 로 확인하는 방법과

WM_KEYUP 이나 WM_KEYDOWN 에서 wParam 에 VK_PROCESSKEY 가

들어오는것으로 확인 할 수 있다.

다만 키를 한번만 누르더라도 WM_IME_NOTIFY 로는 메세지가 여러개가 오는데,

그 중 wParam 이 IMN_SETCONVERSIONMODE 로 한번 오며 이것으로 채크하면 되겠다.

이 중 VK_PROCESSKEY 을 확인하는 방법으로 해 놓았었는데, 이것이 일부 노트북에서

동작하지 않는 것을 발견했다.

2개의 노트북에서 그런 현상이 발견되었으며 그 중 한대를 디버깅 해보았다.

한영키를 누를시 메세지에서 WM_KEYUP 이나 WM_KEYDOWN 은 넘어 오지 않고

WM_IME_NOTIFY 만 넘어오는 것이다.

이런 현상을 놓고 보았을때 WM_IME_NOTIFY 로 확인하는것이 맞겠다.
반응형

'Programming > Win32API' 카테고리의 다른 글

GetAsyncKeyState() 함수와 GetKeyState() 함수의 차이  (0) 2012.06.25
윈도우 투명  (0) 2011.10.30
Keyboard 입력 받기  (0) 2010.09.03
IME 영문만 입력가능하게 하기  (0) 2010.09.03
IME  (0) 2010.09.02
Posted by blueasa
, |

속성 -> 링커 -> 최적화 -> 참조 -> 참조하지 않는 데이터 제거

옵션이 켜있다면 말그대로 참조하지 않는 함수도 제거되는데, 만약 아무곳에서도 참조되지 않는 함수에 브레이크 포인트를 걸어놓는다면 디버깅시 비활성화 된다.

때문에 브레이크 포인트가 비활성화 된다면 이것도 염두에 두어야 한다
안그럼 삽질..
반응형
Posted by blueasa
, |

보통 '옵션->디버깅->일반->소스 파일이 원래 버전과 정확하게 일치해야 함' 이 옵션을 제거하면 되는데 그렇게도 되지 않을때가 종종 있다.
1.70 [서명 없는 UTF-8 인코딩 자동 검색] 옵션이 꺼져 있는 Visual Studio 편집기에서 소스 파일에 가비지 값이 보이는 경우가 있을 수 있습니다.
Visual Studio 에서, [도구]->[옵션]->[텍스트 편집기]->[일반]의 [서명 없는 UTF-8 인코딩 자동 검색] 옵션이 기본으로 꺼져 있습니다. [서명 없는 UTF-8 인코딩 자동 검색] 옵션이 꺼져있는 컴퓨터에서는 서명 없는 UTF-8 형식의 파일을 기본 코드 페이지로 열는 경우가 있기 때문에, 편집기에서 가비지가 보일 수 있습니다.

이 문제를 해결하려면

1. [도구]->[옵션]->[텍스트 편집기]->[일반]을 선택한 후 [서명 없는 UTF-8 인코딩 자동 검색] 옵션을 켜십시오. 이 후에도 이 문제가 발생하지 않습니다. 참고. [서명 없는 UTF-8 인코딩 자동 검색] 옵션을 켤 경우, UTF-8 영역과 한국어 (ks_c_5601-1987) 영역에 중복되어 있는 문자들만 파일에 포함되어 있을 경우 서명 없는 UTF-8 파일을 한국어 파일로 잘못 인식하여 가비지가 발생할 수 있습니다.
2. 혹은 해당 파일을 [다른 이름으로 저장]-> [인코딩하여 저장]을 선택하여 서명 있는 UTF-8 파일 형식으로 바꿀 수 있습니다.
내 경우엔 1번 방법으로는 해결되지 않았고 2번으로 해결이 됐었다.
아래 링크를 가보면 여러가지 이슈들이 많다

Microsoft Visual Studio 2005 사용 시 발생하는 문제

반응형
Posted by blueasa
, |

Hello :)

I'm working on a bit of a 2D engine and want it to work with the IME.  Now, normally with a desktop app you don't need any particularly special IME support for an IME to work with your app, you can just start typing in a text box and voila, asian characters (for the most part).  What's actually happening when you're typing asian characters is the IME is drawing windows above your application's window that contains these characters, as I understand it.  In a fullscreen game without typical input widgets, the IME has no idea where to display these windows, and even if it knew where to display those widgets, they wouldn't show up in your fullscreen app.  This means you need to read and send information to the IME directly and take any information you get from it and duplicate what it would've done by itself had you been making a regular desktop app (meaning, draw your own character candidate display, composition display, etc)

My
 2D engine thus far is in .NET 2.0 C# Managed DX.  In the August 2006 SDK, the VC++ DX utility classes contain an example textbox class that contains IME support.  The Managed DX utility classes do not contain any IME support example.  Most of the information I've found by researching around is only for desktop apps that want to extend their support for IMEs beyond the default, rather than support for fullscreen apps.


First I'll lay out what information I've found to be useful in this endeavor:

MSDN: Using an Input Method Editor in a Game (this helps to explain the VC++ DX textbox IME example)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Using_an_Input_Method_Editor_in_a_Game.asp

MSDN: Input Method Editor Function Reference
http://msdn.microsoft.com/library/en-us/intl/ime_038z.asp

Header file containing actual enumeration values I didn't find anywhere else
http://www.rpi.edu/dept/cis/software/yesterday/g77-mingw32/include/imm.h

August 2006 SDK C++ DXUT class containing textbox with IME support
C:\Program Files\Microsoft DirectX SDK (August 2006)\Samples\C++\DXUT\Optional\DXUTgui.cpp

Some IME Reference Stuff
http://www.osronline.com/ddkx/appendix/imeimes2_35ph.htm
http://www.osronline.com/ddkx/appendix/imeimes_0h2s.htm

Misc IME Related C# Code
http://www.koders.com/csharp/fidEB8980C0605213D81D1D8364B00F09538F1DF83D.aspx
http://tsuge.astgate.biz/witchgarden/?C%23+Tips%2FWitchPaper%A4%C7%BC%C2%C1%F5%A4%B7%A4%BFIME%C0%A9%B8%E6
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=7712&forum=7

.NET Win32 API Reference Stuff (since you need to use external functions in imm32.dll and user32.dll)
http://www.dotnetwire.com/frame_redirect.asp?newsid=5368
http://www.pinvoke.net/
http://custom.programming-in.net/


So, that's where I'm coming from.  Here's where I'm at.  If you are familiar with the IME language bar, the floating toolbar allows you to select which input language you'd like to use at the moment, along with the input mode.  This input language and other details that you select are context sensitive and will only be used for the window/thread you set them in.  So if you open up Notepad.exe and switch to Japanese input, you'll have Japanese input available in Notepad, but if you switch to another Notepad.exe that you happened to have open, you'll still be in English language mode (until you set it to Japanese also).

Now, if you click somewhere on an app that isn't a textbox, so you have no text entry area selected while you're in Japanese input mode, you'll notice all of the icons on the IME language bar go disabled, naturally, because you can't input anything, so it won't bother trying to handle any input or send any characters.  The second you select a text entry area, bam, those icons become available again.

When I run my 2D engine in windowed mode and watch the IME language bar, I can use the ALT+SHIFT hotkey to switch language modes and receive that window message via WndProc, allowing me to spew text in my engine that says what the current input language is set to, but all of the language bar icons are disabled.  This is common sense and is expected.

The problem is, so far I have had no luck in getting the IME to recognize the input context and accept my commands to it to switch the ConversionStatus or even to begin it's composition string for me to detect. I'm not sure if I have to tell it to start a composition string and then it notifies the window back that it's starting, or if I just wait, but it won't bother starting any composition string until it's even in the right conversion mode (I imagine).

So now, I will refer to an area of the MSDN: Using an Input Method Editor in a Game (link above) article that has been stuck in my head.

"A full-screen application must properly handle the following IME-related messages:

"
I am handling WM_INPUTLANGCHANGE(via the .NET built in OnInputLanguageChange) and WM_IME_SETCONTEXT.  The other messages I won't receive until the IME is ready to do something, and so far I haven't gotten the IME to be ready to actually do anything :). I am sure there's more I need to do than just get these basic messages and respond to them, because it doesn't seem to be doing much.  If anyone knows anyone who might be able to point me in the right direction, it would be magically delicious.


For now, here is some of the code.  I have created a namespace called External that has a class called IME in it.  So IME.Something is referring to stuff in this class.  I have all of the dll imports and struct values contained in it.

// Incoming Window Message Events
protected override void WndProc(ref Message m) {
   switch ((IME.Message)m.Msg) {
      case IME.Message.WM_IME_SETCONTEXT:
         IME.imcHandle = IME.ImmGetContext(this.Handle);
         USER32.SendMessage(IME.imcHandle, m.Msg, m.WParam, IntPtr.Zero);
         IME.ImmReleaseContext(this.Handle, IME.imcHandle);
         break;
   }

   base.WndProc(ref m);
}

// OnInputLanguageChanged Event
protected override void OnInputLanguageChanged(InputLanguageChangedEventArgs e) {

   // Get IMC Handle
   IME.imcHandle = IME.ImmGetContext(this.Handle);

   // Get language and layout details
  
keys.languageFullName = e.InputLanguage.Culture.EnglishName;
   keys.languageShortName = e.InputLanguage.Culture.TwoLetterISOLanguageName;
   keys.layoutID = e.InputLanguage.Culture.KeyboardLayoutId;

   // Get current Conversion and Sentence Modes into IME.current*
  
IME.ImmGetConversionStatus(IME.imcHandle,ref IME.currentConversionMode,ref IME.currentSentenceMode);

   if (IME.currentConversionMode == 0 && keys.languageShortName == "ja") {
      IME.currentConversionMode = (int) IME.ConversionMode.IME_CMODE_NATIVE;
      IME.currentSentenceMode = (int) IME.SentenceMode.IME_SMODE_AUTOMATIC;

      IME.ImmSetConversionStatus(IME.imcHandle,(int)IME.ConversionMode.IME_CMODE_NATIVE | (int) IME.ConversionMode.IME_CMODE_FULLSHAPE, (int)IME.SentenceMode.IME_SMODE_AUTOMATIC);

   }

   if (IME.currentConversionMode != 0 && keys.languageShortName == "en") {
      IME.currentConversionMode = 0;
      IME.currentSentenceMode = (int) IME.SentenceMode.IME_SMODE_NONE;

      IME.ImmSetConversionStatus(IME.imcHandle, (int) IME.ConversionMode.IME_CMODE_ALPHANUMERIC, (int) IME.SentenceMode.IME_SMODE_NONE);

   }

   // Release IMC Handle
   IME.ImmReleaseContext(this.Handle, IME.imcHandle);

   base.OnInputLanguageChanged(e);

}


Of course that is only a very small portion of code that will be necessary for this whole thing to work when it's complete.  I'll also restate, I do not expect this code to do what I'm after, I'm looking for info on what to do next in order to achieve the desired result.  I've tried a couple things, but if anyone has done this before or has further insight, it would sure speed things up.  I imagine it's something very simple.

-Crache


출처 : http://social.msdn.microsoft.com/forums/en-US/gametechnologiesdirectx101/thread/32e53d65-4f99-4e47-9207-7254a96af33e/

반응형
Posted by blueasa
, |