AvalonEdit IME

Windows XP에서 AvalonEdit에서 IME가 3수준으로 보이도록 삽질중이다.

아직 테스트 중이라, 설명은 생략.

이정도면은 Windows7 보다 낳은 수준이라 생각된다.
Win7에선 2수준으로 동작하기 때문에
입력하는 글자의 크기와 폰트를 다시 정해주어야 하는데, 같은크기와 같은 폰트로 나오기때문이다.

단점은 2수준의 IME가 windows xp에서 엉뚱한곳에 나타나는데, 같이 나타난다. 메시지를 처리했다고 알려주면 될듯한다. 더 급한게 있기때문에 패스...


/*
 * SharpDevelop으로 작성되었습니다.
 * 사용자: MYHOME
 * 날짜: 2012-05-30
 * 시간: 오전 1:18
 * 
 * 이 템플리트를 변경하려면 [도구->옵션->코드 작성->표준 헤더 편집]을 이용하십시오.
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Threading;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;
using System.Diagnostics;
using System.Globalization;
 
namespace MyAvalonEditTest
{
 /// <summary>
 /// Interaction logic for Window1.xaml
 /// </summary>
 public partial class Window1 : Window
 {
  public Window1()
  {
   InitializeComponent();
            editor.TextArea.Language = System.Windows.Markup.XmlLanguage.GetLanguage("ko-kr");
            
            InitializeComponent();
 
 
            dg = new DrawingGroup();
        }
        DrawingGroup dg;
 
        HwndSource hWnd;
        
        #region DllImport
        [DllImport("Imm32.dll")]
        public static extern bool ImmGetOpenStatus(IntPtr hImc);
 
        [DllImport("user32.dll")]
        public static extern int FindWindow(string lpClassName, string lpWindowName);
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
 
        [DllImport("user32.dll")]
        public static extern int SetCursorPos(int x, int y);
 
        [DllImport("user32.dll", SetLastError = true)]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
 
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
 
        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
 
        /// <summary>
        /// IME 관련
        /// </summary>
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
 
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr ImmReleaseContext(IntPtr hWnd, IntPtr hImc);
 
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImmGetConversionStatus(IntPtr hImc, out int fdwConversion, out int fdwSentence);
 
        [DllImport("imm32.dll")]
        public static extern bool ImmSetConversionStatus(IntPtr hIMC, int fdwConversion, int fdwSentence);
 
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr ImmCreateContext();
 
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hImc);
 
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImmDestroyContext(IntPtr hImc);
 
        [DllImport("imm32.dll")]
        public static extern int ImmGetCompositionString(IntPtr himc, int dw, int lpv, int dw2);
 
        [DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
        public static extern int ImmGetCompositionStringW(IntPtr hIMC, int dwIndex, byte[] lpBuf, int dwBufLen);
 
        #endregion
        const int IME_CMODE_ALPHANUMERIC = 0x0;
        const int IME_CMODE_NATIVE = 0x1;
        const int IME_SMODE_NONE = 0x0;
            void Window_Loaded(object sender, RoutedEventArgs e)
  {
            Keyboard.Focus(editor.TextArea);
            editor.TextArea.Options.EnableImeSupport = true;
            Keyboard.Focus(editor.TextArea);
            
            hWnd = (HwndSource)PresentationSource.FromVisual(this);
            hWnd.AddHook(WndProc);
            
            Keyboard.Focus(btn);
            Keyboard.Focus(editor.TextArea);
 
            
            
  }
        public const int WM_IME_COMPOSITION = 0x10F;
        public const int WM_IME_NOTIFY = 0x0282;
 
        public const int GCS_COMPSTR = 0x0008;
 
        #region imm.h
        
        // wParam of report message WM_IME_NOTIFY
        public const int IMN_CLOSESTATUSWINDOW      = 0x0001;
        public const int IMN_OPENSTATUSWINDOW       = 0x0002;
        public const int IMN_CHANGECANDIDATE        = 0x0003;
        public const int IMN_CLOSECANDIDATE         = 0x0004;
        public const int IMN_OPENCANDIDATE          = 0x0005;
        public const int IMN_SETCONVERSIONMODE      = 0x0006;
        public const int IMN_SETSENTENCEMODE        = 0x0007;
        public const int IMN_SETOPENSTATUS          = 0x0008;
        public const int IMN_SETCANDIDATEPOS        = 0x0009;
        public const int IMN_SETCOMPOSITIONFONT     = 0x000A;
        public const int IMN_SETCOMPOSITIONWINDOW   = 0x000B;
        public const int IMN_SETSTATUSWINDOWPOS     = 0x000C;
        public const int IMN_GUIDELINE              = 0x000D;
        public const int IMN_PRIVATE = 0x000E;
        #endregion
 
 
        IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            
            switch (msg)
            {
            
                case WM_IME_NOTIFY:
                    if(wParam.ToInt32() == IMN_SETCOMPOSITIONWINDOW)
                        Console.WriteLine("WM_IME_NOTIFY w:IMN_SETCOMPOSITIONWINDOW");
                        drawText(wParam,lParam);
                    break;
 
            }
 
            //base.WndProc(hWnd,smg,wParam,lParam,handled);
 
            return IntPtr.Zero;
        }
        DrawingContext dc;
        private void drawText(IntPtr wParam, IntPtr lParam)
        {
 
            int comp = lParam.ToInt32();
 
            int intdwSize = 0;
            string text = "";
 
            IntPtr intICHwnd = IntPtr.Zero;
            TextArea textArea = this.editor.TextArea;
 
            HwndSource hwndSource = (HwndSource)PresentationSource.FromVisual(this.editor.TextArea);
            if (hwndSource == nullreturn;
             intICHwnd = ImmGetContext(hwndSource.Handle);
 
            intdwSize = ImmGetCompositionString(intICHwnd, GCS_COMPSTR, 0, 0);
            if (intdwSize != 0)
            {
 
                byte[] buffer = new byte[intdwSize];
                intdwSize = ImmGetCompositionStringW(intICHwnd, GCS_COMPSTR, buffer, intdwSize);
                text = Encoding.Unicode.GetString(buffer);
            }
 
            TextViewPosition tvp = this.editor.TextArea.Caret.Position;
            Rect textViewBounds = ImeNativeWrapper.GetBounds( textArea.TextView);//.GetBounds();
            Rect characterBounds = ImeNativeWrapper.GetCharacterBounds(textArea.TextView, textArea.Caret.Position, hwndSource);
            if (hwndSource != null)
            {
                System.Windows.Media.Matrix transformToDevice = hwndSource.CompositionTarget.TransformToDevice;
                textViewBounds.Transform(transformToDevice);
                characterBounds.Transform(transformToDevice);
            }
            
            double x = (int)Math.Max(characterBounds.Left, textViewBounds.Left);
            double y = (int)Math.Max(characterBounds.Top, textViewBounds.Top);
            double leftt = (int)textViewBounds.Left + 10;
            double top = (int)textViewBounds.Top;
            double right = (int)textViewBounds.Right;
            double bottom = (int)textViewBounds.Bottom;
 
            
            FormattedText formattedText = new FormattedText(
                text,
                CultureInfo.GetCultureInfo("ko-kr"),
                FlowDirection.LeftToRight,
                new Typeface(textArea.FontFamily.ToString()),   //여기
                textArea.FontSize,
                Brushes.Black);
            formattedText.MaxTextWidth = 300;
            formattedText.MaxTextHeight = 240;
 
            
            DrawingContext dc = dg.Open();
            
 
            dc.DrawText(formattedText,new Point(y,x));
            dc.Close();
            DrawingImage dimage;
            Image img = new Image();
            dimage = new DrawingImage(dg); ;
            img.Source = dimage;
            img.Margin = new Thickness(x,y + 3,0,0);
            if(this.mycanvas.Children.Count > 0)
                this.mycanvas.Children.RemoveAt(0);
            this.mycanvas.Children.Add(img);
 
        }
 
 
        
 }
}

댓글

이 블로그의 인기 게시물

C#에서 포인터 사용

WPF RichTextBox 와 Document의 바인딩

WPF 이미지위에 라인 그리기(WPF DrawLine on exist Image)