Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 806521
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T00:15:21+00:00 2026-05-15T00:15:21+00:00

After happily using open source software for many years I’ve figured it’s time to

  • 0

After happily using open source software for many years I’ve figured it’s time to give back. And since documentation is usually a weak point for many projects, plus my C# skills are not exactly in high demand in my corner of FLOSS land, I’ve figured I’ll start with tutorials, etc.

After the second tutorial for a burning tool, I already got annoyed with the routine of

  1. take screenshot
  2. highlight any important part
  3. annotate it
  4. add to website
  5. repeat

and figured I could automate that.

I guess what I’m looking for is a program that would take a screenshot of the currently open window, paint e.g. a yellow bar around the focused control (a button maybe) then pop up a little textbox for me to enter a description for the picture and finally add it all to a website/database/list/etc.

Now for my actual question: Unless anybody knows a tool that already does that, I need some starters on how to access size and position of controls on ‘foreign’ windows so that I can calculate where to paint those highlighting bars around important controls. I remember those password-unmasking tools for Windows that could reveal the content of any ******-protected textbox, but I can’t find any open examples on that.. WinAPI stuff I guess, WindowFromPoint + GetDlgItem or something like that. No idea if it’s any easier in Linux, either one will be fine though. No preference on programming language either.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T00:15:22+00:00Added an answer on May 15, 2026 at 12:15 am

    To my knowledge, what you want to do requires some P/Invoke, since .NET does not feature any API for accessing the windows of other applications.

    You could probably start by using GetForegroundWindow to get the current Window (you would need to fire that code using a global hotkey or a timer, because if you switch windows to take the screenshot, you will get your own window returned from GetForegroundWindow).

    Edit

    I got inspired by your question to do a little Sunday afternoon coding. I found out, that GetForegroundWindow will get you the foreground Window, but not a Control level. But there is another useful function, GetGUIThreadInfo, that will get you the currently focused control and some other info. We can use GetWindowInfo to get the information about the Window (which might be a control contained in a top-level window).

    Putting these things together, we can make a Window class that abstracts away all the gritty P/Invoke calls:

    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Text;
    
    namespace dr.Stackoverflow.ScreenshotTest
    {
        public class Window
        {
            private WINDOWINFO info;
            private readonly IntPtr handle;
    
            internal Window(IntPtr handle)
            {
                this.handle = handle;
            }
    
            public int Handle
            {
                get { return handle.ToInt32(); }
            }
    
            // Note - will not work on controls in other processes.
            public string Text
            {
                get
                {
                    int length = GetWindowTextLength(handle);
                    if ( length > 0 )
                    {
                        StringBuilder buffer = new StringBuilder(length);
                        if (0 < GetWindowText(handle, buffer, length))
                        {
                            return buffer.ToString();
                        }
                    }
                    return "<unknown>";
                }
            }
    
            public Rectangle WindowArea
            {
                get
                {
                    EnsureWindowInfo();
                    return info.rcWindow;
                }
            }
    
            public override string ToString()
            {
                return String.Format("{0} 0x{1}", Text, handle.ToString("x8"));
            }
    
            private unsafe void EnsureWindowInfo()
            {
                if (info.cbSize == 0)
                {
                    info.cbSize = sizeof (WINDOWINFO);
                    if ( !GetWindowInfo(handle, out info) ) 
                        throw new ApplicationException("Unable to get Window Info");
    
                }
            }
    
            public static Window GetForeground()
            {
                IntPtr handle = GetForegroundWindow();
                if (handle == IntPtr.Zero)
                    return null;
    
                return new Window(handle);
            }
    
            public unsafe static Window GetFocus()
            {
                IntPtr foreground = GetForegroundWindow();
                int procId;
                int tId = GetWindowThreadProcessId(foreground, out procId);
                if (0 != tId)
                {
                    GUITHREADINFO threadInfo = new GUITHREADINFO() {cbSize = sizeof (GUITHREADINFO)};
                    if ( GetGUIThreadInfo(tId, out threadInfo) )
                    {
                        return new Window(threadInfo.hwndFocus);
                    }
                }
                return null;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct WINDOWINFO
            {
                public int cbSize;
                public RECT rcWindow;
                public RECT rcClient;
                public int dwStyle;
                public int dwExStyle;
                public int dwWindowStatus;
                public uint cxWindowBorders;
                public uint cyWindowBorders;
                public int atomWindowType;
                public int wCreatorVersion;
            } 
    
            [StructLayout(LayoutKind.Sequential)]
            private struct GUITHREADINFO
            {
    
                public int cbSize;
                public int flags;
                public IntPtr hwndActive;
                public IntPtr hwndFocus;
                public IntPtr hwndCapture;
                public IntPtr hwndMenuOwner;
                public IntPtr hwndMoveSize;
                public IntPtr hwndCaret;
                public RECT rcCaret;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
    
                public static implicit operator Rectangle(RECT rhs)
                {
                    return new Rectangle(rhs.left, rhs.top, rhs.right - rhs.left, rhs.bottom - rhs.top);
                }
            }
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool GetWindowInfo(IntPtr hwnd, out WINDOWINFO pwi);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
            private static extern bool GetGUIThreadInfo(int threadId, out GUITHREADINFO threadInfo);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
            private static extern IntPtr GetForegroundWindow();
    
            [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            private static extern int GetWindowTextLength(IntPtr hWnd);
    
            [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
        }
    }
    

    Then we can make a sample program using it:

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Threading;
    
    namespace dr.Stackoverflow.ScreenshotTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Sleeping for 3 seconds (switch to a window of interest)");
                Thread.Sleep(3000);
    
                Window currentWindow = Window.GetForeground();
                Window focusedWindow = Window.GetFocus();       
                if ( currentWindow != null )
                {
                    Console.WriteLine("Foreground window");
                    Console.WriteLine(currentWindow.Text);
                    Console.WriteLine(currentWindow.WindowArea);
                }
                if (focusedWindow != null)
                {
                    Console.WriteLine("\tFocused window");
                    Console.WriteLine("\t{0}", focusedWindow.WindowArea);
                }
    
                if (focusedWindow !=null && currentWindow != null && focusedWindow.Handle != currentWindow.Handle)
                {
                    Console.WriteLine("\nTaking a screenshot");
                    Rectangle screenshotArea = currentWindow.WindowArea;
                    Bitmap bm = new Bitmap(currentWindow.WindowArea.Width,currentWindow.WindowArea.Height);
                    using(Graphics g = Graphics.FromImage(bm))
                    {
                        g.CopyFromScreen(screenshotArea.Left,screenshotArea.Top, 0,0, new Size(screenshotArea.Width,screenshotArea.Height));
                        Rectangle focusBox = focusedWindow.WindowArea;
                        focusBox.Offset(screenshotArea.Left * -1, screenshotArea.Top * -1);
                        focusBox.Inflate(5,5);
                        g.DrawRectangle(Pens.Red,focusBox);
                    }
                    bm.Save("D:\\screenshot.png", ImageFormat.Png);
                }
            }
        }
    }
    

    This will make a screenshot of the current foreground window with a red box highlighting the currently focused control. Please be aware that this is sample code and features minimal error-checking 🙂 When you run it, Alt-Tab to the window of interest and stay there until the program finishes.

    There are some limitations though. The most important one i discovered is that this approach won’t work in a WPF application – simply because the individual controls is not Windows, as they are in other Windows programs.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 480k
  • Answers 480k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer Let's consider the following example: CREATE TABLE your_table (some_value int,… May 16, 2026 at 6:10 am
  • Editorial Team
    Editorial Team added an answer It looks a lot like this isn't possible at all. May 16, 2026 at 6:10 am
  • Editorial Team
    Editorial Team added an answer I am offering several methods: 1. A fast method that… May 16, 2026 at 6:10 am

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.