private static void IMEControl_GetCompExtEvent(refRECT rect) { ITextBox textBox_ = Game1.keyboardDispatcher.Subscriber as ITextBox; TextBox textBox = Game1.keyboardDispatcher.Subscriber as TextBox; if (textBox == null) { return; } Vector2 vector2 = textBox.Font.MeasureString(comp.text); if (textBox_ != null) { Acp acp = textBox_.GetSelection(); RECT CompExt = textBox_.GetTextExt(new Acp(0, acp.Start)); rect.left = CompExt.right; rect.top = CompExt.top; } else if (textBox != null)//without ITextBox interface { int strLen = textBox is ChatTextBox ? (int)(textBox as ChatTextBox).currentWidth : (int)textBox.Font.MeasureString(textBox.Text).X; int xOffset = textBox.X + strLen + (textBox is ChatTextBox ? 12 : 16); //if without textbox, we can only insert at end rect.left = xOffset; rect.top = textBox.Y + (textBox is ChatTextBox ? 12 : 8); } rect.right = rect.left + (int)vector2.X; rect.bottom = rect.top + 32; }
public void Draw(SpriteBatch spriteBatch) { //cache text, in case change by ime string compStr = text; int curSel = Math.Min(compStr.Length, caret); ITextBox textBox_ = Game1.keyboardDispatcher.Subscriber as ITextBox; TextBox textBox = Game1.keyboardDispatcher.Subscriber as TextBox; if (compStr.Length > 0 && textBox != null) { bool isTextBox = !(textBox is ChatTextBox); int xOffset = isTextBox ? TextBox_xOffset : ChatTextBox_xOffset; int yOffset = isTextBox ? TextBox_yOffset : ChatTextBox_yOffset; Vector2 DrawOrigin = new Vector2(textBox.X + xOffset, textBox.Y + yOffset); if (textBox_ != null) { int acpStart = textBox_.GetSelection().Start; DrawOrigin.X = textBox_.GetTextExt(new Acp(acpStart, acpStart)).left; } else if (isTextBox) { DrawOrigin.X += textBox.Font.MeasureString(textBox.Text).X; } else { DrawOrigin.X += (textBox as ChatTextBox).currentWidth; } //devide the compstr by compsel string left = compStr.Substring(0, curSel); string right = compStr.Substring(curSel, compStr.Length - curSel); //measure len Vector2 vec_left = textBox.Font.MeasureString(left); Vector2 vec_right = textBox.Font.MeasureString(right); //Draw background Texture2D Rect = new Texture2D(Game1.game1.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); Color[] colors = new Color[1]; Rect.GetData(colors); colors[0] = Color.White; Rect.SetData(colors); spriteBatch.Draw(Rect, new Rectangle( (int)DrawOrigin.X, (int)DrawOrigin.Y, (int)(vec_left.X + vec_right.X + 10),//plus 10 to make the bounding box a bit larger, or the caret may not visable 32), Color.White); DrawOrigin.X += 4;//make items in the white background //Draw left part spriteBatch.DrawString(textBox.Font, left, new Vector2(DrawOrigin.X, DrawOrigin.Y), Color.Black); DrawOrigin.X += vec_left.X; //Draw caret bool caretVisible = DateTime.UtcNow.Millisecond % 1000 >= 500; if (caretVisible) { spriteBatch.Draw(Game1.staminaRect, new Rectangle((int)DrawOrigin.X, (int)DrawOrigin.Y, 2, 32), Color.Black); } DrawOrigin.X += 2;//caret width 2 //Draw right part spriteBatch.DrawString(textBox.Font, right, new Vector2(DrawOrigin.X, (int)DrawOrigin.Y), Color.Black); } }
private static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { IntPtr returnCode = KeyboardInput.CallWindowProc(KeyboardInput.prevWndProc, hWnd, msg, wParam, lParam);; switch (msg) { case WM_GETDLGCODE: returnCode = (IntPtr)DLGC_WANTALLKEYS; break; case WM_CHAR: CharEntered?.Invoke(null, new CharacterEventArgs((char)wParam, (int)lParam)); break; case WM_KEYDOWN: KeyDown?.Invoke(null, new KeyEventArgs((Keys)wParam)); break; case WM_KEYUP: KeyUp?.Invoke(null, new KeyEventArgs((Keys)wParam)); break; case WM_LBUTTONDOWN: MouseSelection.left = (int)lParam & 0xffff; MouseSelection.top = (int)lParam >> 16; MouseSelection.right = MouseSelection.left; MouseSelection.bottom = MouseSelection.top; if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; Acp acp = textBox.GetAcpByRange(MouseSelection); if (acp.Start >= 0) { textBox.SetSelection(acp.Start, acp.End); Console.WriteLine("ACPStart:{0},ACPEnd:{1}", acp.Start, acp.End); Console.WriteLine("MouseDown:Left:{0},TOP:{1}RIGHT:{2}BOTTOM:{3}", MouseSelection.left, MouseSelection.top, MouseSelection.right, MouseSelection.bottom); Selecting = true; } } break; case WM_MOUSEMOVE: MouseSelection.right = (int)lParam & 0xffff; MouseSelection.bottom = (int)lParam >> 16; if (Selecting && Game1.keyboardDispatcher.Subscriber is ITextBox) { RECT range = new RECT(); range.left = Math.Min(MouseSelection.left, MouseSelection.right); range.top = Math.Max(MouseSelection.top, MouseSelection.bottom); range.right = Math.Max(MouseSelection.left, MouseSelection.right); range.bottom = Math.Min(MouseSelection.top, MouseSelection.bottom); ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; Acp acp = textBox.GetAcpByRange(range); if (acp.Start >= 0) { textBox.SetSelection(acp.Start, acp.End); textBox.SetSelState(MouseSelection.left > MouseSelection.right ? SelState.SEL_AE_END : SelState.SEL_AE_START); Console.WriteLine("ACPStart:{0},ACPEnd:{1}", acp.Start, acp.End); Console.WriteLine("MouseMove:Left:{0},TOP:{1}RIGHT:{2}BOTTOM:{3}", MouseSelection.left, MouseSelection.top, MouseSelection.right, MouseSelection.bottom); } } //handle IsMouseVisable returnCode = KeyboardInput.CallWindowProc(KeyboardInput.prevWndProc, hWnd, msg, wParam, lParam); break; case WM_LBUTTONUP: Selecting = false; break; #if TSF case EM_GETSEL: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; Acp acp = textBox.GetSelection(); Marshal.WriteInt32(wParam, acp.Start); Marshal.WriteInt32(lParam, acp.End); } break; case EM_SETSEL: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; textBox.SetSelection((int)wParam, (int)lParam); } break; case EM_REPLACESEL: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; textBox.ReplaceSelection(Marshal.PtrToStringAuto(lParam)); } break; case TF_GETSELSTATE: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; returnCode = (IntPtr)textBox.GetSelState(); } break; case TF_GETTEXT: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; var text = textBox.GetText(); Marshal.Copy(text.ToCharArray(), 0, wParam, Math.Min(text.Length, (int)lParam)); } break; case TF_GETTEXTLENGTH: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; returnCode = (IntPtr)textBox.GetTextLength(); } break; case TF_GETTEXTEXT: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; Acp acp = (Acp)Marshal.PtrToStructure(lParam, typeof(Acp)); RECT rect = textBox.GetTextExt(acp); MapWindowPoints(Game1.game1.Window.Handle, (IntPtr)0, ref rect, 2); //to screen coord Marshal.StructureToPtr(rect, wParam, false); //text ext returnCode = (IntPtr)0; //if the rect clipped } break; case TF_QUERYINSERT: if (Game1.keyboardDispatcher.Subscriber is ITextBox) { ITextBox textBox = Game1.keyboardDispatcher.Subscriber as ITextBox; Acp acp = (Acp)Marshal.PtrToStructure(wParam, typeof(Acp)); textBox.QueryInsert(acp, (uint)lParam); Marshal.StructureToPtr(acp, wParam, false); } break; case WM_KILLFOCUS: Game1.tsf.TerminateComposition(); break; #endif default: break; } return(returnCode); }