예제 #1
0
        private static void GetCompositionUnderlines(IntPtr hIMC, int targetStart, int targetEnd, List <CompositionUnderline> underlines)
        {
            var clauseSize = ImeNative.ImmGetCompositionString(hIMC, ImeNative.GCS_COMPCLAUSE, null, 0);

            if (clauseSize <= 0)
            {
                return;
            }

            int clauseLength = (int)clauseSize / sizeof(Int32);

            // buffer contains 32 bytes (4 bytes) array
            var clauseData = new byte[(int)clauseSize];

            ImeNative.ImmGetCompositionString(hIMC, ImeNative.GCS_COMPCLAUSE, clauseData, clauseSize);

            var clauseLength_1 = clauseLength - 1;

            for (int i = 0; i < clauseLength_1; i++)
            {
                int from = BitConverter.ToInt32(clauseData, i * sizeof(Int32));
                int to   = BitConverter.ToInt32(clauseData, (i + 1) * sizeof(Int32));

                var  range = new Range(from, to);
                bool thick = (range.From >= targetStart && range.To <= targetEnd);

                underlines.Add(new CompositionUnderline(range, ColorUNDERLINE, ColorBKCOLOR, thick));
            }
        }
예제 #2
0
        /// <summary>
        /// Change composition range.
        /// </summary>
        /// <param name="selectionRange">The selection range.</param>
        /// <param name="characterBounds">The character bounds.</param>
        public void ChangeCompositionRange(Range selectionRange, Rect[] characterBounds)
        {
            if (!isActive)
            {
                return;
            }

            var screenInfo  = ((IRenderWebBrowser)owner).GetScreenInfo();
            var scaleFactor = screenInfo.HasValue ? screenInfo.Value.DeviceScaleFactor : 1.0f;

            //This is called on the CEF UI thread, we need to invoke back onte main UI thread to
            //access the UI controls
            owner.UiThreadRunAsync(() =>
            {
                //TODO: Getting the root window for every composition range change seems expensive,
                //we should cache the position and update it on window move.
                var parentWindow = Window.GetWindow(owner);
                if (parentWindow != null)
                {
                    //TODO: What are we calculating here exactly???
                    var point = owner.TransformToAncestor(parentWindow).Transform(new Point(0, 0));

                    var rects = new List <Rect>();

                    foreach (var item in characterBounds)
                    {
                        rects.Add(new Rect(
                                      (int)((point.X + item.X) * scaleFactor),
                                      (int)((point.Y + item.Y) * scaleFactor),
                                      (int)(item.Width * scaleFactor),
                                      (int)(item.Height * scaleFactor)));
                    }

                    compositionBounds = rects;
                    MoveImeWindow(source.Handle);
                }
            });
        }
예제 #3
0
 void IRenderWebBrowser.OnImeCompositionRangeChanged(Range selectedRange, Rect[] characterBounds)
 {
     RenderHandler?.OnImeCompositionRangeChanged(selectedRange, characterBounds);
 }
예제 #4
0
        private static void GetCompositionInfo(IntPtr hwnd, uint lParam, string text, List <CompositionUnderline> underlines, ref int compositionStart)
        {
            var hIMC = ImeNative.ImmGetContext(hwnd);

            underlines.Clear();

            int targetStart = text.Length;
            int targetEnd   = text.Length;

            if (IsParam(lParam, ImeNative.GCS_COMPATTR))
            {
                GetCompositionSelectionRange(hIMC, ref targetStart, ref targetEnd);
            }

            // Retrieve the selection range information. If CS_NOMOVECARET is specified
            // it means the cursor should not be moved and we therefore place the caret at
            // the beginning of the composition string. Otherwise we should honour the
            // GCS_CURSORPOS value if it's available.
            if (!IsParam(lParam, ImeNative.CS_NOMOVECARET) && IsParam(lParam, ImeNative.GCS_CURSORPOS))
            {
                // IMM32 does not support non-zero-width selection in a composition. So
                // always use the caret position as selection range.
                int cursor = (int)ImeNative.ImmGetCompositionString(hIMC, ImeNative.GCS_CURSORPOS, null, 0);
                compositionStart = cursor;
            }
            else
            {
                compositionStart = 0;
            }

            if (IsParam(lParam, ImeNative.GCS_COMPCLAUSE))
            {
                GetCompositionUnderlines(hIMC, targetStart, targetEnd, underlines);
            }

            if (underlines.Count == 0)
            {
                var range = new Range();

                bool thick = false;

                if (targetStart > 0)
                {
                    range = new Range(0, targetStart);
                }

                if (targetEnd > targetStart)
                {
                    range = new Range(targetStart, targetEnd);
                    thick = true;
                }

                if (targetEnd < text.Length)
                {
                    range = new Range(targetEnd, text.Length);
                }

                underlines.Add(new CompositionUnderline(range, ColorUNDERLINE, ColorBKCOLOR, thick));
            }

            ImeNative.ImmReleaseContext(hwnd, hIMC);
        }
예제 #5
0
 /// <summary>
 /// Called when the IME composition range has changed.
 /// </summary>
 /// <param name="selectedRange">is the range of characters that have been selected</param>
 /// <param name="characterBounds">is the bounds of each character in view coordinates.</param>
 public virtual void OnImeCompositionRangeChanged(Range selectedRange, Rect[] characterBounds)
 {
 }
예제 #6
0
 public void OnImeCompositionRangeChanged(CefSharp.Structs.Range selectedRange, Rect[] characterBounds)
 {
 }
예제 #7
0
        private static void GetCompositionInfo(IntPtr hwnd, uint lParam, string text, List <CompositionUnderline> underlines, ref int compositionStart)
        {
            var hIMC = ImeNative.ImmGetContext(hwnd);

            underlines.Clear();

            byte[] attributes  = null;
            int    targetStart = text.Length;
            int    targetEnd   = text.Length;

            if (IsParam(lParam, ImeNative.GCS_COMPATTR))
            {
                attributes = GetCompositionSelectionRange(hIMC, ref targetStart, ref targetEnd);
            }

            // Retrieve the selection range information. If CS_NOMOVECARET is specified
            // it means the cursor should not be moved and we therefore place the caret at
            // the beginning of the composition string. Otherwise we should honour the
            // GCS_CURSORPOS value if it's available.
            if (!IsParam(lParam, ImeNative.CS_NOMOVECARET) && IsParam(lParam, ImeNative.GCS_CURSORPOS))
            {
                // IMM32 does not support non-zero-width selection in a composition. So
                // always use the caret position as selection range.
                int cursor = (int)ImeNative.ImmGetCompositionString(hIMC, ImeNative.GCS_CURSORPOS, null, 0);
                compositionStart = cursor;
            }
            else
            {
                compositionStart = 0;
            }

            if (attributes != null &&
                // character before
                ((compositionStart > 0 && (compositionStart - 1) < attributes.Length && attributes[compositionStart - 1] == ImeNative.ATTR_INPUT)
                 ||
                 // character after
                 (compositionStart >= 0 && compositionStart < attributes.Length && attributes[compositionStart] == ImeNative.ATTR_INPUT)))
            {
                // as MS does with their ime implementation we should only use the GCS_CURSORPOS if the character
                // before or after is new input.
                // https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/windows/Documents/ImmComposition.cs,1079
            }
            else
            {
                compositionStart = text.Length;
            }

            if (IsParam(lParam, ImeNative.GCS_COMPCLAUSE))
            {
                GetCompositionUnderlines(hIMC, targetStart, targetEnd, underlines);
            }

            if (underlines.Count == 0)
            {
                var range = new Range();

                bool thick = false;

                if (targetStart > 0)
                {
                    range = new Range(0, targetStart);
                }

                if (targetEnd > targetStart)
                {
                    range = new Range(targetStart, targetEnd);
                    thick = true;
                }

                if (targetEnd < text.Length)
                {
                    range = new Range(targetEnd, text.Length);
                }

                underlines.Add(new CompositionUnderline(range, ColorUNDERLINE, ColorBKCOLOR, thick));
            }

            ImeNative.ImmReleaseContext(hwnd, hIMC);
        }