📄 consolecontrol.cs
字号:
else if(csbi.dwSize.x * csbi.dwSize.y < cols * bufferRows)
{
if(csbi.dwSize.y < bufferRows)
{
bufferRows = coordConsoleSize.y = csbi.dwSize.y;
scrollbar.Maximum = bufferRows - rows - 6;
}
Win32Interop.SetConsoleScreenBufferSize(hStdOut, coordConsoleSize);
Win32Interop.SetConsoleWindowInfo(hStdOut, true, ref srConsoleRect);
}
pScreenBuffer = new Win32Interop.CHAR_INFO[rows * cols];
}
void refreshScreenBuffer()
{
Win32Interop.COORD coordBufferSize;
Win32Interop.COORD coordStart;
Win32Interop.SMALL_RECT srRegion;
Win32Interop.CONSOLE_SCREEN_BUFFER_INFO csbi = new Win32Interop.CONSOLE_SCREEN_BUFFER_INFO();
Win32Interop.GetConsoleScreenBufferInfo(hStdOut, ref csbi);
if((csbi.srWindow.Right - csbi.srWindow.Left + 1 != cols) || (csbi.srWindow.Bottom - csbi.srWindow.Top + 1 != rows) || (csbi.dwSize.y != bufferRows))
{
resizeConsoleWindow();
}
rowOffset = csbi.srWindow.Top;
scrollbar.Value = Math.Min(scrollbar.Maximum, csbi.srWindow.Top);
coordBufferSize.x = (short)cols;
coordBufferSize.y = (short)bufferRows;
coordStart.x = 0;
coordStart.y = 0;
srRegion.Top = (short)(csbi.srWindow.Top);
srRegion.Left = 0;
srRegion.Bottom = (short)(csbi.srWindow.Top + rows - 1);
srRegion.Right = (short)(cols - 1);
Win32Interop.ReadConsoleOutput(hStdOut, pScreenBuffer, coordBufferSize, coordStart, ref srRegion);
}
protected override void OnPaint(PaintEventArgs e)
{
int t = Environment.TickCount;
refreshScreenBuffer();
Win32Interop.CONSOLE_SCREEN_BUFFER_INFO csbi = new Win32Interop.CONSOLE_SCREEN_BUFFER_INFO();
Win32Interop.GetConsoleScreenBufferInfo(hStdOut, ref csbi);
Win32Interop.CONSOLE_CURSOR_INFO cinf;
Win32Interop.GetConsoleCursorInfo(hStdOut, out cinf);
e.Graphics.FillRectangle(Brushes.Black, 0, 0, charWidth * cols, charHeight * rows);
for(int i = 0; i < rows; ++i)
{
int dwX = 0;
int dwY = i * charHeight;
int sameColor = 0;
Color lastColor = Color.Empty;
for(int j = 0; j < cols; ++j) {
int attrBG = pScreenBuffer[i * cols + j].Attributes >> 4;
Color color;
if(ColorTranslator.ToWin32(consoleColors[attrBG]) == (csbi.wAttributes >> 4))
{
// transparent
color = Color.Empty;
}
else
{
color = consoleColors[attrBG];
}
if(color == lastColor && j != cols-1)
{
sameColor++;
}
else
{
if(color != Color.Empty)
{
int x = dwX - sameColor * charWidth;
int width = (sameColor + 1) * charWidth;
Brush backgroundBrush = new SolidBrush(color);
e.Graphics.FillRectangle(backgroundBrush, x, dwY, width, charHeight);
backgroundBrush.Dispose();
}
lastColor = color;
}
dwX += charWidth;
}
}
for(int i = 0; i < rows; ++i)
{
int dwX = 0;
int dwY = i * charHeight;
for(int j = 0; j < cols; ++j)
{
string s = ((char)pScreenBuffer[i * cols + j].Character.UnicodeChar).ToString();
if(s != " ")
{
Color fontColor = consoleColors[pScreenBuffer[i * cols + j].Attributes & 0xF];
Brush fontBrush = new SolidBrush(fontColor);
e.Graphics.DrawString(s, font, fontBrush, dwX, dwY);
fontBrush.Dispose();
}
dwX += charWidth;
}
}
if(csbi.dwCursorPosition.y >= csbi.srWindow.Top && csbi.dwCursorPosition.y <= csbi.srWindow.Bottom)
{
if(cinf.bVisible)
{
csbi.dwCursorPosition.y -= csbi.srWindow.Top;
Rectangle cursorRectangle = new Rectangle(csbi.dwCursorPosition.x * charWidth,
csbi.dwCursorPosition.y * charHeight,
charWidth,
charHeight);
cursor.Draw(e.Graphics, cursorRectangle);
}
}
Brush selectionBrush = new SolidBrush(selectionColor);
e.Graphics.FillRectangle(selectionBrush, rectSelection);
selectionBrush.Dispose();
}
void drawingTimerTick(object sender, EventArgs e)
{
this.Invalidate();
}
#endregion
#region Selection handling
public void ClearSelection()
{
textSelection = TextSelection.None;
rectSelection = Rectangle.Empty;
Invalidate();
}
protected void CopySelectionToClipboard()
{
int nSelX = rectSelection.Left / charWidth;
int nSelY = rectSelection.Top / charHeight;
int nSelColumns = (rectSelection.Right - rectSelection.Left) / charWidth;
int nSelRows = (rectSelection.Bottom - rectSelection.Top) / charHeight;
if ((nSelColumns == 0) || (nSelRows == 0))
{
ClearSelection();
return;
}
StringBuilder selectedText = new StringBuilder();
for(int i = 0; i < nSelRows; ++i)
{
for (int j = 0; j < nSelColumns; ++j)
{
selectedText.Append((char)pScreenBuffer[(nSelY + i + rowOffset) * cols + nSelX + j].Character.UnicodeChar);
}
selectedText.Append(Environment.NewLine);
}
ClearSelection();
Clipboard.SetDataObject(selectedText.ToString());
}
protected override void OnMouseUp(MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
if(textSelection == TextSelection.Selected)
{
// if the user clicked inside the selection rectangle, copy data
if(rectSelection.Contains(e.X, e.Y))
{
CopySelectionToClipboard();
}
ClearSelection();
}
else if(textSelection == TextSelection.Selecting)
{
if((rectSelection.Left == rectSelection.Right) && (rectSelection.Top == rectSelection.Bottom))
{
textSelection = TextSelection.None;
}
else
{
textSelection = TextSelection.Selected;
}
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
int deltaX;
int deltaY;
Point point = Point.Empty;
if(e.Button == MouseButtons.Left)
{
point.X = e.X;
point.Y = e.Y;
deltaX = point.X - this.Left - mouseCursorOffset.Y;
deltaY = point.Y - this.Top - mouseCursorOffset.Y;
if (deltaX > 0 || deltaY > 0)
{
if (textSelection != TextSelection.None)
{
if (textSelection == TextSelection.Selected) return;
// selecting text for copy/paste
Point coordSel = Point.Empty;
coordSel.X = Math.Min(Math.Max(e.X, 0) / charWidth, cols - 1);
coordSel.Y = Math.Min(Math.Max(e.Y, 0) / charHeight, rows - 1);
if(coordSel.X >= coordSelOrigin.X)
{
rectSelection.X = coordSelOrigin.X * charWidth;
rectSelection.Width = (coordSel.X + 1) * charWidth - rectSelection.X;
}
else
{
rectSelection.X = coordSel.X * charWidth;
rectSelection.Width = (coordSelOrigin.X + 1) * charWidth - rectSelection.X;
}
if (coordSel.Y >= coordSelOrigin.Y)
{
rectSelection.Y = coordSelOrigin.Y * charHeight;
rectSelection.Height = (coordSel.Y + 1) * charHeight - rectSelection.Y;
}
else
{
rectSelection.Y = coordSel.Y * charHeight;
rectSelection.Height = (coordSelOrigin.Y + 1) * charHeight - rectSelection.Y;
}
Invalidate();
}
}
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
mouseCursorOffset.X -= this.Left;
mouseCursorOffset.Y -= this.Top;
if(textSelection == TextSelection.Selected)
{
return;
}
textSelection = TextSelection.Selecting;
coordSelOrigin.X = Math.Min(Math.Max(e.X, 0) / charWidth, cols - 1);
coordSelOrigin.Y = Math.Min(Math.Max(e.Y, 0) / charHeight, rows - 1);
int left = coordSelOrigin.X * charWidth;
int top = coordSelOrigin.Y * charHeight;
rectSelection = new Rectangle(left, top, 0, 0);
}
}
#endregion
#region Scrolling
private void vScrolled(object sender, ScrollEventArgs e)
{
int delta = e.NewValue - scrollbar.Value;
Win32Interop.SMALL_RECT sr;
sr.Top = (short)delta;
sr.Bottom = (short)(delta);
sr.Left = 0;
sr.Right = 0;
Win32Interop.SetConsoleWindowInfo(hStdOut, false, ref sr);
Invalidate();
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -