Skip to content

Commit b08e74b

Browse files
committed
Get the real colors when copying the screen
1 parent f807c77 commit b08e74b

File tree

2 files changed

+101
-6
lines changed

2 files changed

+101
-6
lines changed

PSReadLine/ConsoleLib.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,64 @@ IntPtr templateFileWin32Handle
105105

106106
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
107107
internal static extern bool GetCurrentConsoleFontEx(IntPtr consoleOutput, bool bMaximumWindow, ref CONSOLE_FONT_INFO_EX consoleFontInfo);
108+
109+
[StructLayout(LayoutKind.Sequential)]
110+
internal struct COLORREF
111+
{
112+
internal uint ColorDWORD;
113+
114+
internal uint R
115+
{
116+
get { return ColorDWORD & 0xff; }
117+
}
118+
119+
internal uint G
120+
{
121+
get { return (ColorDWORD >> 8) & 0xff; }
122+
}
123+
124+
internal uint B
125+
{
126+
get { return (ColorDWORD >> 16) & 0xff; }
127+
}
128+
}
129+
130+
[StructLayout(LayoutKind.Sequential)]
131+
internal struct CONSOLE_SCREEN_BUFFER_INFO_EX
132+
{
133+
internal int cbSize;
134+
internal COORD dwSize;
135+
internal COORD dwCursorPosition;
136+
internal ushort wAttributes;
137+
internal SMALL_RECT srWindow;
138+
internal COORD dwMaximumWindowSize;
139+
internal ushort wPopupAttributes;
140+
internal bool bFullscreenSupported;
141+
internal COLORREF Black;
142+
internal COLORREF DarkBlue;
143+
internal COLORREF DarkGreen;
144+
internal COLORREF DarkCyan;
145+
internal COLORREF DarkRed;
146+
internal COLORREF DarkMagenta;
147+
internal COLORREF DarkYellow;
148+
internal COLORREF Gray;
149+
internal COLORREF DarkGray;
150+
internal COLORREF Blue;
151+
internal COLORREF Green;
152+
internal COLORREF Cyan;
153+
internal COLORREF Red;
154+
internal COLORREF Magenta;
155+
internal COLORREF Yellow;
156+
internal COLORREF White;
157+
}
158+
159+
[DllImport("kernel32.dll", SetLastError = true)]
160+
internal static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput,
161+
ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);
162+
163+
[DllImport("kernel32.dll", SetLastError = true)]
164+
internal static extern bool SetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput,
165+
ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);
108166
}
109167

110168
public delegate bool BreakHandler(ConsoleBreakSignal ConsoleBreakSignal);

PSReadLine/ScreenCapture.cs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Diagnostics.CodeAnalysis;
7+
using System.Runtime.InteropServices;
78
using System.Text;
89
using System.Windows.Forms;
910

@@ -163,6 +164,47 @@ public static void CaptureScreen(ConsoleKeyInfo? key = null, object arg = null)
163164
\red255\green255\blue255;
164165
";
165166

167+
private static string GetRTFColorFromColorRef(NativeMethods.COLORREF colorref)
168+
{
169+
return string.Concat("\\red", colorref.R.ToString("D"),
170+
"\\green", colorref.G.ToString("D"),
171+
"\\blue", colorref.B.ToString("D"), ";");
172+
}
173+
174+
private static string GetColorTable()
175+
{
176+
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
177+
var csbe = new NativeMethods.CONSOLE_SCREEN_BUFFER_INFO_EX
178+
{
179+
cbSize = Marshal.SizeOf(typeof(NativeMethods.CONSOLE_SCREEN_BUFFER_INFO_EX))
180+
};
181+
if (NativeMethods.GetConsoleScreenBufferInfoEx(handle, ref csbe))
182+
{
183+
return GetRTFColorFromColorRef(csbe.Black) +
184+
GetRTFColorFromColorRef(csbe.DarkBlue) +
185+
GetRTFColorFromColorRef(csbe.DarkGreen) +
186+
GetRTFColorFromColorRef(csbe.DarkCyan) +
187+
GetRTFColorFromColorRef(csbe.DarkRed) +
188+
GetRTFColorFromColorRef(csbe.DarkMagenta) +
189+
GetRTFColorFromColorRef(csbe.DarkYellow) +
190+
GetRTFColorFromColorRef(csbe.Gray) +
191+
GetRTFColorFromColorRef(csbe.DarkGray) +
192+
GetRTFColorFromColorRef(csbe.Blue) +
193+
GetRTFColorFromColorRef(csbe.Green) +
194+
GetRTFColorFromColorRef(csbe.Cyan) +
195+
GetRTFColorFromColorRef(csbe.Red) +
196+
GetRTFColorFromColorRef(csbe.Magenta) +
197+
GetRTFColorFromColorRef(csbe.Yellow) +
198+
GetRTFColorFromColorRef(csbe.White);
199+
}
200+
201+
// A bit of a hack if the above failed - assume PowerShell's color scheme if the
202+
// background color is Magenta, otherwise we assume the default scheme.
203+
return Console.BackgroundColor == ConsoleColor.DarkMagenta
204+
? PowerShellColorTable
205+
: CmdColorTable;
206+
}
207+
166208
private static void DumpScreenToClipboard(int top, int count)
167209
{
168210
var buffer = ReadBufferLines(top, count);
@@ -174,12 +216,7 @@ private static void DumpScreenToClipboard(int top, int count)
174216
var rtfBuffer = new StringBuilder();
175217
rtfBuffer.Append(@"{\rtf\ansi{\fonttbl{\f0 Consolas;}}");
176218

177-
// A bit of a hack because I don't know how to find the shortcut used to start
178-
// the current console. We assume if the background color is Magenta, then
179-
// PowerShell's color scheme is being used, otherwise we assume the default scheme.
180-
var colorTable = Console.BackgroundColor == ConsoleColor.DarkMagenta
181-
? PowerShellColorTable
182-
: CmdColorTable;
219+
var colorTable = GetColorTable();
183220
rtfBuffer.AppendFormat(@"{{\colortbl;{0}}}{1}", colorTable, Environment.NewLine);
184221
rtfBuffer.Append(@"\f0 \fs18 ");
185222

0 commit comments

Comments
 (0)