GetGUIThreadInfo - Как точно определить положение каретки в любом приложении при выделении текста? - PullRequest
0 голосов
/ 20 мая 2011

Я использую GetGUIThreadInfo для отслеживания каретки в любом приложении Windows. Я понимаю, что это может не работать для всех приложений. Прямо сейчас я тестирую в Блокноте, WordPad и Word. Я не могу объяснить некоторые несоответствия в координатах каретки, возвращаемых GetGUIThreadInfo в разных случаях. Особенно результаты, которые я вижу, когда текст выделен, а не выделен.

Я работаю с текстом abcd. Я выбираю слева направо. Вот мои результаты ...

WordPad

abcd|  = left: 60, right: 61, top: 14, bottom: 32
abc|d| = left: 58, right: 66, top: 14, bottom: 15

Слово

abcd|  = left: 53, right: 54, top: 113, bottom: 131
abc|d| = left: 45, right: 46, top: 113, bottom: 147

При выделении текста в WordPad нижняя часть уменьшается с 32 до 15. Почему?

Когда текст выделяется в Word, правое сужается с 54 до 46. В действительности, нижняя часть увеличивается с 131 до 147. Почему?

Я также думаю, что координаты, возвращаемые для Word, всегда неверны из-за небольшого количества. Я говорю это потому, что когда я конвертирую клиентские координаты rcCaret в экранные координаты, основанные на hwndCaret, а затем показываю окно в этом месте, оно никогда не находится рядом с кареткой. Неважно, выделен текст или нет.

Может кто-нибудь объяснить мне эти результаты? И, если возможно, также дайте мне несколько советов о том, как лучше занять позицию каретки?

namespace TrackCaret
{
  class Program
  {
    static void Main(string[] args)
    {
      Timer trackCaretTimer = new Timer((TimerCallback)delegate(object data)
        {
          Win32.GUITHREADINFO guiInfo = new Win32.GUITHREADINFO();
          guiInfo.cbSize = Marshal.SizeOf(guiInfo);
          Win32.GetGUIThreadInfo(0, out guiInfo);

          string msg = string.Format("left: {0}, right: {1}, top: {2}, bottom: {3}", 
            guiInfo.rcCaret.left, guiInfo.rcCaret.right, guiInfo.rcCaret.top, guiInfo.rcCaret.bottom);
          Console.WriteLine(msg);
        }, null, 0, 5000);

      Console.ReadLine();
    }
  }

  class Win32
  {
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
      public int left;
      public int top;
      public int right;
      public int bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct GUITHREADINFO
    {
      public int cbSize;
      public uint flags;
      public IntPtr hwndActive;
      public IntPtr hwndFocus;
      public IntPtr hwndCapture;
      public IntPtr hwndMenuOwner;
      public IntPtr hwndMoveSize;
      public IntPtr hwndCaret;
      public RECT rcCaret;
    }

    [DllImport("user32.dll")]
    public static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO lpgui);
  }
}
...