Skip to content

Instantly share code, notes, and snippets.

@blackholeearth
Last active April 4, 2025 11:15
Show Gist options
  • Save blackholeearth/f5f52168179e67c98a023d01693ae1a4 to your computer and use it in GitHub Desktop.
Save blackholeearth/f5f52168179e67c98a023d01693ae1a4 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Experiment_VS_Graphics_FromHwnd
{
public class Form1 : Form
{
private IContainer components = null;
private Timer timer1;
System.Diagnostics.Process visualStudio;
HashSet<IntPtr> windowHandles = new HashSet<IntPtr>();
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 5000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
public Form1()
{
InitializeComponent();
visualStudio = System.Diagnostics.Process.GetProcessesByName("devenv")[0];
EnumWindows(WindowReceiver, IntPtr.Zero); //populate windowHandles with top level windows
}
void EnumerateWindowsRecursivelyImpl(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero || !windowHandles.Add(hWnd)) return;
EnumerateWindowsRecursivelyImpl(GetWindow(hWnd, (uint)GetWindow_Cmd.GW_CHILD));
EnumerateWindowsRecursivelyImpl(GetWindow(hWnd, (uint)GetWindow_Cmd.GW_HWNDNEXT));
}
bool WindowReceiver(IntPtr hWnd, IntPtr dontCare)
{
uint pid;
GetWindowThreadProcessId(hWnd, out pid);
if (pid == (uint)visualStudio.Id)
{
windowHandles.Add(hWnd);
EnumerateWindowsRecursivelyImpl(GetWindow(hWnd, (uint)GetWindow_Cmd.GW_CHILD));
}
return true;
}
private void timer1_Tick(object sender, EventArgs e)
{
windowHandles.Clear();
EnumWindows(WindowReceiver, IntPtr.Zero); //populate windowHandles with top level windows
foreach (var window in windowHandles)
{
var gfx = Graphics.FromHwnd(window);
gfx.DrawString("Have fun!", Font, Brushes.Black, 10, 10);
gfx.Dispose();
}
}
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
@blackholeearth
Copy link
Author

blackholeearth commented Apr 4, 2025

answer taken from : https://stackoverflow.com/a/34365438/3137362


Use the System.Drawing.Graphics.FromHwnd method, passing in the HWND for the designer window.

Get the HWND by drilling down into the window handles for visual studio, via pinvoke. Perhaps use tools like Inspect to find window classes and other information that might help you identify the correct (designer) window.

I've written a C# program to get you started here. *pasted bin is Blocked - copied to gist.github*

screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment