Skip to content

Commit c1b405f

Browse files
committed
Add Copy screenshot button
1 parent 3356c68 commit c1b405f

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/StructuredLogViewer/Controls/GraphControl.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class GraphControl
2323
private Color outgoingColor, incomingColor, border;
2424
private Brush outgoingBrush, incomingBrush;
2525

26+
public UIElement CanvasElement => grid;
27+
2628
public event Action SelectionChanged;
2729

2830
public GraphControl()

src/StructuredLogViewer/Controls/GraphHostControl.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Runtime.InteropServices;
34
using System.Windows;
45
using System.Windows.Controls;
56
using System.Windows.Input;
7+
using System.Windows.Media;
8+
using System.Windows.Media.Imaging;
69
using Microsoft.Build.Logging.StructuredLogger;
710

811
namespace StructuredLogViewer.Controls;
@@ -14,6 +17,33 @@ public GraphHostControl()
1417
Initialize();
1518
}
1619

20+
public static double DpiX;
21+
public static double DpiY;
22+
23+
static GraphHostControl()
24+
{
25+
IntPtr dc = GetDC(IntPtr.Zero);
26+
27+
if (dc != IntPtr.Zero)
28+
{
29+
const int LOGPIXELSX = 88;
30+
const int LOGPIXELSY = 90;
31+
DpiX = GetDeviceCaps(dc, LOGPIXELSX) / (double)96;
32+
DpiY = GetDeviceCaps(dc, LOGPIXELSY) / (double)96;
33+
34+
ReleaseDC(IntPtr.Zero, dc);
35+
}
36+
}
37+
38+
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
39+
internal static extern IntPtr GetDC(IntPtr hWnd);
40+
41+
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
42+
internal static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
43+
44+
[DllImport("Gdi32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
45+
internal static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
46+
1747
public event Action<string> DisplayText;
1848
public event Action<string> GoToSearch;
1949

@@ -138,6 +168,14 @@ private void Initialize()
138168
BorderThickness = new Thickness()
139169
};
140170

171+
var copyImageButton = new Button
172+
{
173+
Content = "Copy screenshot",
174+
VerticalAlignment = VerticalAlignment.Center,
175+
Margin = new Thickness(0, 0, 8, 0),
176+
BorderThickness = new Thickness()
177+
};
178+
141179
var depthCheckbox = new CheckBox
142180
{
143181
Content = "Layer by depth",
@@ -159,6 +197,11 @@ private void Initialize()
159197
Margin = new Thickness(0, 0, 8, 0)
160198
};
161199

200+
copyImageButton.Click += (s, e) =>
201+
{
202+
CopyImage();
203+
};
204+
162205
helpButton.Click += (s, e) =>
163206
{
164207
Process.Start(new ProcessStartInfo("https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/Graph") { UseShellExecute = true });
@@ -204,6 +247,7 @@ private void Initialize()
204247
toolbar.Children.Add(invertedCheckbox);
205248
toolbar.Children.Add(searchTextBox);
206249
toolbar.Children.Add(locateButton);
250+
toolbar.Children.Add(copyImageButton);
207251
toolbar.Children.Add(helpButton);
208252

209253
topToolbar.Children.Add(searchButton);
@@ -265,4 +309,20 @@ void Locate()
265309

266310
Children.Add(graphControl.Content);
267311
}
312+
313+
private void CopyImage()
314+
{
315+
var visual = graphControl.CanvasElement;
316+
317+
var renderTarget = new RenderTargetBitmap(
318+
(int)(visual.DesiredSize.Width * DpiX),
319+
(int)(visual.DesiredSize.Height * DpiY),
320+
96 * DpiX,
321+
96 * DpiY,
322+
PixelFormats.Pbgra32);
323+
324+
renderTarget.Render(visual);
325+
326+
Clipboard.SetImage(renderTarget);
327+
}
268328
}

0 commit comments

Comments
 (0)