/// <summary> /// フックプロシージャ /// </summary> /// <param name="nCode"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> private IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode == HCBT_ACTIVATE) { Commons.RECT rcForm = new Commons.RECT(0, 0, 0, 0); Commons.RECT rcMsgBox = new Commons.RECT(0, 0, 0, 0); GetWindowRect(this.ownerWindow.Handle, out rcForm); GetWindowRect(wParam, out rcMsgBox); // センター位置を計算する。 int x = (rcForm.Left + (rcForm.Right - rcForm.Left) / 2) - ((rcMsgBox.Right - rcMsgBox.Left) / 2); int y = (rcForm.Top + (rcForm.Bottom - rcForm.Top) / 2) - ((rcMsgBox.Bottom - rcMsgBox.Top) / 2); SetWindowPos(wParam, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); IntPtr result = CallNextHookEx(this.hHook, nCode, wParam, lParam); // フックを解除する。 UnhookWindowsHookEx(this.hHook); this.hHook = (IntPtr)0; return(result); } else { return(CallNextHookEx(this.hHook, nCode, wParam, lParam)); } }
/// <summary> /// 文字列のインデックスに対応する表示座標を取得する(調整済み) /// FIXME: 無理矢理なので .NET Framework の実装によっては破綻する可能性あり /// </summary> /// <param name="textBoxRect">EM_GETRECT で取得した RECT 構造体</param> /// <param name="index">インデックス</param> /// <returns>調整済みの表示座標</returns> public Point GetFixedPositionFromCharIndex(Commons.RECT textBoxRect, int index) { Point pointOrig = this.GetPositionFromCharIndex(index); Point result = new Point(pointOrig.X, pointOrig.Y); if (!this.Multiline) { result.Y += textBoxRect.Top; } return(result); }
private static extern bool GetWindowRect(IntPtr hWnd, out Commons.RECT lpRect);
/// <summary> /// 表示領域等を計算する(固定長のみ対応) /// FIXME: 文字末尾にタブがある場合の位置計算がおかしい /// </summary> /// <param name="graphics">Graphics</param> /// <param name="textBoxRect">テキストエリアの領域</param> /// <param name="baseFontSize">ベースとなるフォントサイズ</param> /// <returns>計算した領域情報</returns> private List <DrawDimension> CalcDrawDimensions(Graphics graphics, Commons.RECT textBoxRect, Size baseFontSize) { Size baseFontSizeHalf = TextRenderer.MeasureText(graphics, "A", this.displayFont, new Size(), this.textFormatFlags); string textBoxText = this.Text; int selectionStart = this.SelectionStart; int selectionLength = this.SelectionLength; // 描画対象の文字列インデックス範囲を得る int firstCharIndex = 0; int lastCharIndex = textBoxText.Length; if (this.Multiline) { // 最初の位置を得る int firstVisibleLine = SendMessage(this.Handle, EM_GETFIRSTVISIBLELINE, 0, 0); if (0 <= firstVisibleLine) { int firstIndex = this.GetFirstCharIndexFromLine(firstVisibleLine); if (0 <= firstIndex) { firstCharIndex = firstIndex; } } // 表示行数を得る int rows = this.ClientSize.Height / baseFontSize.Height; // 最後の位置を得る int lastIndex = this.GetFirstCharIndexFromLine(firstVisibleLine + rows); if (0 <= lastIndex) { lastCharIndex = lastIndex; } } List <DrawDimension> drawDimensionList = new List <DrawDimension>(); int columns = 0; int prevLine = this.GetLineFromCharIndex(firstCharIndex); for (int chIndex = firstCharIndex; chIndex < lastCharIndex; ++chIndex) { if (chIndex < 0 || textBoxText.Length <= chIndex) { break; } int currentLine = this.GetLineFromCharIndex(chIndex); string targetSChar = textBoxText.Substring(chIndex, 1); DrawDimension drawDimension = new DrawDimension(targetSChar); Point point = this.GetFixedPositionFromCharIndex(textBoxRect, chIndex); if (drawDimension.Type == DrawType.Emoji) { drawDimension.Area = new Rectangle(point.X, point.Y, Commons.TEXT_ICON_WIDTH, Commons.TEXT_ICON_HEIGHT); columns += 2; } else if (drawDimension.Type == DrawType.ControlChar) { drawDimension.Area = new Rectangle(point.X, point.Y, baseFontSizeHalf.Width, baseFontSizeHalf.Height); if (drawDimension.OriginalChar == '\t') { int tabColumns = 8 - (columns % 8); if (chIndex + 1 < textBoxText.Length) { Point pointNext = this.GetFixedPositionFromCharIndex(textBoxRect, chIndex + 1); drawDimension.PaddingArea = new Rectangle(point.X + baseFontSizeHalf.Width, point.Y, pointNext.X - point.X - baseFontSizeHalf.Width, baseFontSizeHalf.Height); } else { int width = baseFontSizeHalf.Width * tabColumns - baseFontSizeHalf.Width; drawDimension.PaddingArea = new Rectangle(point.X + baseFontSizeHalf.Width, point.Y, width, baseFontSizeHalf.Height); } columns += tabColumns; } else if (drawDimension.OriginalChar == '\n') { columns = 0; } else if (drawDimension.OriginalChar == '\r') { // 表示されないので columns には何もしない } } else if (drawDimension.Type == DrawType.NormalChar) { // NOTE: とりあえず固定長で考える if (StringUtils.IsHalfSizeDisplay(targetSChar)) { drawDimension.Area = new Rectangle(point.X, point.Y, baseFontSizeHalf.Width, baseFontSizeHalf.Height); columns += 1; } else { drawDimension.Area = new Rectangle(point.X, point.Y, baseFontSize.Width, baseFontSize.Height); columns += 2; } } if (selectionStart <= chIndex && chIndex < selectionStart + selectionLength) { drawDimension.Selection = true; // 前行の文字末尾がタブの場合の処理 if (prevLine != currentLine && selectionStart <= chIndex - 1 && 0 < drawDimensionList.Count) { DrawDimension prevDrawDimension = drawDimensionList[drawDimensionList.Count - 1]; if (prevDrawDimension.OriginalChar == '\t') { Rectangle area = prevDrawDimension.Area; prevDrawDimension.PaddingArea = new Rectangle(area.X + area.Width, area.Y, textBoxRect.Right - (area.X + area.Width), area.Height); } } } prevLine = currentLine; drawDimensionList.Add(drawDimension); } return(drawDimensionList); }
private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, out Commons.RECT lParam);