Click here to Skip to main content
15,031,550 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to build an universal autocomplete and now I need to show my interface on the caret position inside any application . I tried to write code for solving this but without any events and all I get is 0 0 coordinates. I want to be a simple method , I do not want to be raised by an event.

What I have tried:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        [StructLayout(LayoutKind.Sequential)]  
        public struct RECT
        {
            public uint Left;
            public uint Top;
            public uint Right;
            public uint Bottom;
        };

        [StructLayout(LayoutKind.Sequential)] 
        public struct GUITHREADINFO
        {
            public uint 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;
        };

        Point startPosition = new Point();       // Point required for ToolTip movement by Mouse
        GUITHREADINFO guiInfo;                     // To store GUI Thread Information
        Point caretPosition;                     // To store Caret Position  
        
        [DllImport("user32.dll")]
        static extern int GetWindowText(int hWnd, StringBuilder text, int count);

        
        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(int hWnd, out uint lpdwProcessId);

        
        [DllImport("user32.dll", EntryPoint = "GetGUIThreadInfo")]
        public static extern bool GetGUIThreadInfo(uint tId, out GUITHREADINFO threadInfo);

        
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        
        [DllImport("user32.dll")]
        public static extern bool ClientToScreen(IntPtr hWnd, out Point position);
       
        private void AdjustUI()
        {

            this.Left = caretPosition.X;
            this.Top = caretPosition.Y;
        }
        public void GetCaretPosition()
        {
            guiInfo = new GUITHREADINFO();
            guiInfo.cbSize = (uint)Marshal.SizeOf(guiInfo);
            GetGUIThreadInfo(0, out guiInfo);
        }
        private string GetActiveProcess()
        {
            const int nChars = 256;
            int handle = 0;
            StringBuilder Buff = new StringBuilder(nChars);
            handle = (int)GetForegroundWindow();

            if (GetWindowText(handle, Buff, nChars) > 0)
            {
                uint lpdwProcessId;
                uint dwCaretID = GetWindowThreadProcessId(handle, out lpdwProcessId);
                uint dwCurrentID = (uint)Thread.CurrentThread.ManagedThreadId;
                return Process.GetProcessById((int)lpdwProcessId).ProcessName;
            }
          
            return String.Empty;
        }
        private void EvaluateCaretPosition()
        {
            caretPosition = new Point();
            GetCaretPosition();
            caretPosition.X = (int)guiInfo.rcCaret.Left + 25;
            caretPosition.Y = (int)guiInfo.rcCaret.Bottom + 25;
            ClientToScreen(guiInfo.hwndCaret, out caretPosition);
        }
        public MainWindow()
        {
            InitializeComponent();
            while (true)
            {
                //if (GetForegroundWindow() ==MainWindow.GetForegroundWindow())
                //{
                //    return;
                //}
                string activeProcess = GetActiveProcess();
                if ((activeProcess.ToLower().Contains("explorer") | (activeProcess == string.Empty)))
                {
                    m.Visibility = Visibility.Hidden;
                }
                else
                {
                    EvaluateCaretPosition();
                    AdjustUI();
                    m.Visibility = Visibility.Visible;
                }
                MessageBox.Show("caret position {0}", caretPosition.X.ToString());
            }
        }
    }
}
Posted
Updated 22-Dec-20 2:50am

1 solution

That's not an easy thing to do in C#, as it is very low level.
There is an article on CodeProject however that shows how to do it: Processing Global Mouse and Keyboard Hooks in C#[^]
   
Comments
Member 15026969 22-Dec-20 10:24am
   
Thank you very much! I appreciate , but I have already used this.
Member 15026969 22-Dec-20 10:27am
   
The main problem to solve is getting caret coordinate from any application.
Member 15026969 22-Dec-20 12:15pm
   
I tested again this code and it is running really good. It is no problem with it. So this is the solution if anybody needs it.
BillWoodruff 22-Dec-20 21:09pm
   
Well, then, accept Rick's answer, and vote it up !

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900