Skip to content

Commit 19b2fc3

Browse files
committed
Issues #19 Support of screenshots for windows with hardware accelerated rendering
1 parent 8c0a5b1 commit 19b2fc3

File tree

11 files changed

+312
-33
lines changed

11 files changed

+312
-33
lines changed

SmartContextMenu/Forms/MainForm.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,12 @@ private void MenuItemClick(Window window, Settings.MenuItem menuItem)
499499
case MenuItemName.SaveScreenshot:
500500
{
501501
var manager = new LanguageManager(_settings.LanguageName);
502-
var bitmap = WindowUtils.PrintWindow(window.Handle);
502+
var result = WindowUtils.PrintWindow(window.Handle, out var bitmap);
503+
if (!result || !WindowUtils.IsCorrectScreenshot(window.Handle, bitmap))
504+
{
505+
WindowUtils.CaptureWindow(window.Handle, false, out bitmap);
506+
}
507+
503508
var dialog = new SaveFileDialog
504509
{
505510
OverwritePrompt = true,
@@ -531,7 +536,12 @@ private void MenuItemClick(Window window, Settings.MenuItem menuItem)
531536

532537
case MenuItemName.CopyScreenshot:
533538
{
534-
var bitmap = WindowUtils.PrintWindow(window.Handle);
539+
var result = WindowUtils.PrintWindow(window.Handle, out var bitmap);
540+
if (!result || !WindowUtils.IsCorrectScreenshot(window.Handle, bitmap))
541+
{
542+
WindowUtils.CaptureWindow(window.Handle, false, out bitmap);
543+
}
544+
535545
Clipboard.SetImage(bitmap);
536546
}
537547
break;

SmartContextMenu/Native/Constants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,10 @@ static class Constants
143143
public const uint EVENT_SYSTEM_FOREGROUND = 3;
144144
public const uint EVENT_OBJECT_DESTROY = 0x8001;
145145
public const int OBJID_WINDOW = 0;
146+
147+
public const int CURSOR_SHOWING = 0x00000001;
148+
149+
public const int DI_COMPAT = 0x0004;
150+
public const int DI_NORMAL = 0x0003;
146151
}
147152
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
3+
namespace SmartContextMenu.Native.Enums
4+
{
5+
[Flags]
6+
public enum CopyPixelOperations
7+
{
8+
NoMirrorBitmap = -2147483648,
9+
10+
/// <summary>dest = BLACK, 0x00000042</summary>
11+
Blackness = 66,
12+
13+
///<summary>dest = (NOT src) AND (NOT dest), 0x001100A6</summary>
14+
NotSourceErase = 1114278,
15+
16+
///<summary>dest = (NOT source), 0x00330008</summary>
17+
NotSourceCopy = 3342344,
18+
19+
///<summary>dest = source AND (NOT dest), 0x00440328</summary>
20+
SourceErase = 4457256,
21+
22+
/// <summary>dest = (NOT dest), 0x00550009</summary>
23+
DestinationInvert = 5570569,
24+
25+
/// <summary>dest = pattern XOR dest, 0x005A0049</summary>
26+
PatInvert = 5898313,
27+
28+
///<summary>dest = source XOR dest, 0x00660046</summary>
29+
SourceInvert = 6684742,
30+
31+
///<summary>dest = source AND dest, 0x008800C6</summary>
32+
SourceAnd = 8913094,
33+
34+
/// <summary>dest = (NOT source) OR dest, 0x00BB0226</summary>
35+
MergePaint = 12255782,
36+
37+
///<summary>dest = (source AND pattern), 0x00C000CA</summary>
38+
MergeCopy = 12583114,
39+
40+
///<summary>dest = source, 0x00CC0020</summary>
41+
SourceCopy = 13369376,
42+
43+
/// <summary>dest = source OR dest, 0x00EE0086</summary>
44+
SourcePaint = 15597702,
45+
46+
/// <summary>dest = pattern, 0x00F00021</summary>
47+
PatCopy = 15728673,
48+
49+
/// <summary>dest = DPSnoo, 0x00FB0A09</summary>
50+
PatPaint = 16452105,
51+
52+
/// <summary>dest = WHITE, 0x00FF0062</summary>
53+
Whiteness = 16711778,
54+
55+
/// <summary>
56+
/// Capture window as seen on screen. This includes layered windows
57+
/// such as WPF windows with AllowsTransparency="true", 0x40000000
58+
/// </summary>
59+
CaptureBlt = 1073741824,
60+
}
61+
}

SmartContextMenu/Native/Gdi32.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using SmartContextMenu.Native.Enums;
4+
5+
namespace SmartContextMenu.Native
6+
{
7+
static class Gdi32
8+
{
9+
[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", SetLastError = true)]
10+
public static extern IntPtr CreateCompatibleDC([In] IntPtr hdc);
11+
12+
[DllImport("gdi32.dll", EntryPoint = "SelectObject")]
13+
public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);
14+
15+
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
16+
[return: MarshalAs(UnmanagedType.Bool)]
17+
public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, CopyPixelOperations dwRop);
18+
19+
[DllImport("gdi32.dll", EntryPoint = "StretchBlt", SetLastError = true)]
20+
[return: MarshalAs(UnmanagedType.Bool)]
21+
public static extern bool StretchBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidthDest, int nHeightDest, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int nWidthSource, int nHeightSource, CopyPixelOperations dwRop);
22+
23+
[DllImport("gdi32.dll")]
24+
public static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref IntPtr pbmi, uint pila, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
25+
26+
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
27+
public static extern bool DeleteDC([In] IntPtr hdc);
28+
29+
[DllImport("gdi32.dll")]
30+
public static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
31+
32+
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
33+
[return: MarshalAs(UnmanagedType.Bool)]
34+
public static extern bool DeleteObject([In] IntPtr hObject);
35+
36+
[DllImport("gdi32.dll")]
37+
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
38+
39+
[DllImport("gdi32.dll")]
40+
internal static extern int GetDeviceCaps(IntPtr hdc, int capindex);
41+
42+
[DllImport("gdi32.dll")]
43+
internal static extern bool PatBlt(IntPtr hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, uint dwRop);
44+
}
45+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace SmartContextMenu.Native.Structs
5+
{
6+
[StructLayout(LayoutKind.Sequential)]
7+
struct CURSORINFO
8+
{
9+
public Int32 cbSize;
10+
public Int32 flags;
11+
public IntPtr hCursor;
12+
public POINTAPI ptScreenPos;
13+
}
14+
15+
[StructLayout(LayoutKind.Sequential)]
16+
struct POINTAPI
17+
{
18+
public int x;
19+
public int y;
20+
}
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace SmartContextMenu.Native.Structs
5+
{
6+
[StructLayout(LayoutKind.Sequential)]
7+
struct ICONINFO
8+
{
9+
public bool fIcon;
10+
public Int32 xHotspot;
11+
public Int32 yHotspot;
12+
public IntPtr hbmMask;
13+
public IntPtr hbmColor;
14+
}
15+
}

SmartContextMenu/Native/User32.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,27 @@ static class User32
9595
[DllImport("user32.dll")]
9696
public static extern IntPtr GetDesktopWindow();
9797

98+
[DllImport("user32.dll")]
99+
public static extern IntPtr GetWindowDC(IntPtr ptr);
100+
101+
[DllImport("user32.dll")]
102+
public static extern IntPtr GetDC(IntPtr hWnd);
103+
104+
[DllImport("user32.dll")]
105+
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
106+
107+
[DllImport("user32.dll")]
108+
public static extern bool GetCursorInfo(out CURSORINFO pci);
109+
110+
[DllImport("user32.dll")]
111+
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
112+
113+
[DllImport("user32.dll")]
114+
public static extern bool DrawIconEx(IntPtr hdc, int xLeft, int yTop, IntPtr hIcon, int cxWidth, int cyHeight, int istepIfAniCur, IntPtr hbrFlickerFreeDraw, int diFlags);
115+
116+
[DllImport("user32.dll")]
117+
public static extern bool DestroyIcon(IntPtr hIcon);
118+
98119
[DllImport("user32.dll")]
99120
[return: MarshalAs(UnmanagedType.Bool)]
100121
public static extern bool SetWindowPos(IntPtr handle, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

SmartContextMenu/Program.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,12 @@ static ICollection<Window> ProcessCommandLine(CommandLineParser сommandLinePars
385385
// Copy Screenshot
386386
if (сommandLineParser.HasToggle("copyscreenshot"))
387387
{
388-
var bitmap = WindowUtils.PrintWindow(window.Handle);
388+
var result = WindowUtils.PrintWindow(window.Handle, out var bitmap);
389+
if (!result || !WindowUtils.IsCorrectScreenshot(window.Handle, bitmap))
390+
{
391+
WindowUtils.CaptureWindow(window.Handle, false, out bitmap);
392+
}
393+
389394
Clipboard.SetImage(bitmap);
390395
}
391396

@@ -399,7 +404,12 @@ static ICollection<Window> ProcessCommandLine(CommandLineParser сommandLinePars
399404
//Save Screenshot
400405
if (сommandLineParser.HasToggle("s") || сommandLineParser.HasToggle("savescreenshot"))
401406
{
402-
var bitmap = WindowUtils.PrintWindow(window.Handle);
407+
var result = WindowUtils.PrintWindow(window.Handle, out var bitmap);
408+
if (!result || !WindowUtils.IsCorrectScreenshot(window.Handle, bitmap))
409+
{
410+
WindowUtils.CaptureWindow(window.Handle, false, out bitmap);
411+
}
412+
403413
var dialog = new SaveFileDialog
404414
{
405415
OverwritePrompt = true,

SmartContextMenu/SmartContextMenu.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
<Compile Include="Native\Constants.cs" />
165165
<Compile Include="Native\Dwmapi.cs" />
166166
<Compile Include="Native\Enums\AccentState.cs" />
167+
<Compile Include="Native\Enums\CopyPixelOperations.cs" />
167168
<Compile Include="Native\Enums\DpiAwarenessContext.cs" />
168169
<Compile Include="Native\Enums\DwmBB.cs" />
169170
<Compile Include="Native\Enums\LayeredWindow.cs" />
@@ -175,13 +176,16 @@
175176
<Compile Include="Native\Enums\ThreadAccess.cs" />
176177
<Compile Include="Native\Enums\WindowCompositionAttribute.cs" />
177178
<Compile Include="Native\Enums\WindowShowStyle.cs" />
179+
<Compile Include="Native\Gdi32.cs" />
178180
<Compile Include="Native\Kernel32.cs" />
179181
<Compile Include="Native\Ntdll.cs" />
180182
<Compile Include="Native\SHCore.cs" />
181183
<Compile Include="Native\Structs\AccentPolicy.cs" />
182184
<Compile Include="Native\Structs\ConsoleScreenBufferInfo.cs" />
183185
<Compile Include="Native\Structs\Coord.cs" />
186+
<Compile Include="Native\Structs\CURSORINFO.cs" />
184187
<Compile Include="Native\Structs\DwmBlurBehind.cs" />
188+
<Compile Include="Native\Structs\ICONINFO.cs" />
185189
<Compile Include="Native\Structs\KeyboardLLHookStruct.cs" />
186190
<Compile Include="Native\Structs\MonitorInfo.cs" />
187191
<Compile Include="Native\Structs\MouseLLHookStruct.cs" />

0 commit comments

Comments
 (0)