Skip to content

Instantly share code, notes, and snippets.

@fushnisoft
Last active September 16, 2015 20:50
Show Gist options
  • Save fushnisoft/6a8c0e21fb395bdbc3b1 to your computer and use it in GitHub Desktop.
Save fushnisoft/6a8c0e21fb395bdbc3b1 to your computer and use it in GitHub Desktop.
A quick and dirty way to attach "DebugView++.exe" to a window handle. The code makes a whole bunch of assumptions and has a lot of ugliness but it is so far serving my purpose so be nice :D
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace Fushnisoft.Utils
{
internal class EmbeddedDebugView
{
private static IntPtr _dbgViewWin = IntPtr.Zero;
private static BackgroundWorker _bw = new BackgroundWorker();
private static IntPtr _handle = IntPtr.Zero;
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, Int32 wParam, Int32 lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
// Constant values were found in the "windows.h" header file.
private const int WM_ACTIVATEAPP = 0x001C,
GWL_STYLE = -16,
WM_CLOSE = 0x10;
public static class WindowStyles
{
public static readonly Int32
WS_BORDER = 0x00800000,
WS_CAPTION = 0x00C00000,
WS_CHILD = 0x40000000,
WS_CHILDWINDOW = 0x40000000,
WS_CLIPCHILDREN = 0x02000000,
WS_CLIPSIBLINGS = 0x04000000,
WS_DISABLED = 0x08000000,
WS_DLGFRAME = 0x00400000,
WS_GROUP = 0x00020000,
WS_HSCROLL = 0x00100000,
WS_ICONIC = 0x20000000,
WS_MAXIMIZE = 0x01000000,
WS_MAXIMIZEBOX = 0x00010000,
WS_MINIMIZE = 0x20000000,
WS_MINIMIZEBOX = 0x00020000,
WS_OVERLAPPED = 0x00000000,
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
WS_POPUP = unchecked((int)0x80000000),
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
WS_SIZEBOX = 0x00040000,
WS_SYSMENU = 0x00080000,
WS_TABSTOP = 0x00010000,
WS_THICKFRAME = 0x00040000,
WS_TILED = 0x00000000,
WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
WS_VISIBLE = 0x10000000,
WS_VSCROLL = 0x00200000;
}
internal static void Resize()
{
if (_dbgViewWin != IntPtr.Zero && _handle != IntPtr.Zero)
{
RECT rect = new RECT();
GetWindowRect(_handle, out rect);
MoveWindow(_dbgViewWin, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);
InvalidateRect(_handle, IntPtr.Zero, true);
}
}
internal static void Init(int handle)
{
_handle = new IntPtr(handle);
_bw.DoWork += new DoWorkEventHandler(bw_DoWork);
_bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
_bw.RunWorkerAsync();
}
private static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result != null)
{
_dbgViewWin = (IntPtr)e.Result;
SetParent(_dbgViewWin, _handle);
// Remove border and whatnot
SetWindowLong(_dbgViewWin, GWL_STYLE, WindowStyles.WS_VISIBLE);
// Move the window to overlay it on this window
RECT rect = new RECT();
GetWindowRect(_handle, out rect);
MoveWindow(_dbgViewWin, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);
}
}
private static void bw_DoWork(object sender, DoWorkEventArgs e)
{
string debugViewPath = "DebugView++.exe";
if (debugViewPath != "" && File.Exists(debugViewPath) == true)
{
Process p = null;
Process[] processes = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(debugViewPath));
if (processes.Length > 0)
{
p = processes[0];
if (p.MainWindowHandle == IntPtr.Zero)
{
p.Kill();
p = null;
}
}
if (p == null)
{
p = Process.Start(debugViewPath, "/f");
}
p.WaitForInputIdle();
e.Result = p.MainWindowHandle;
}
}
internal static void Destroy()
{
// Stop the application
if (_dbgViewWin != IntPtr.Zero)
{
// Post a close message
PostMessage(_dbgViewWin, WM_CLOSE, 0, 0);
// Delay for it to get the message
System.Threading.Thread.Sleep(1000);
// Clear internal handle
_dbgViewWin = IntPtr.Zero;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment