- включить PuTTY;
- зайти на вкладку Window->Translations;
- вручную прописать кодировку CP866 в поле Remote character set;
- сохранить настройки по необходимости и подключиться.
И еще, де факто SSH сервером под Windows является OpenSSH.
public sealed class BufferedGraphicsManager { private static BufferedGraphicsContext bufferedGraphicsContext; public static BufferedGraphicsContext Current { get { return BufferedGraphicsManager.bufferedGraphicsContext; } } static BufferedGraphicsManager() { AppDomain.CurrentDomain.ProcessExit += new EventHandler(BufferedGraphicsManager.OnShutdown); AppDomain.CurrentDomain.DomainUnload += new EventHandler(BufferedGraphicsManager.OnShutdown); BufferedGraphicsManager.bufferedGraphicsContext = new BufferedGraphicsContext(); } private static void OnShutdown(object sender, EventArgs e) { BufferedGraphicsManager.Current.Invalidate(); } }Из этого кода видно, что хранящийся внутри BufferedGraphicsManager объект класса BufferedGraphicsContext уничтожается при выгрузке текущего AppDomain. BufferedGraphicsContext обеспечивает создание (а также уничтожение) нового экземпляра BufferedGraphics на основе объекта Graphics, предоставляя для этого единственный метод Allocate:
public BufferedGraphics Allocate(Graphics targetGraphics, Rectangle targetRectangle) { if (this.ShouldUseTempManager(targetRectangle)) return this.AllocBufferInTempManager(targetGraphics, IntPtr.Zero, targetRectangle); else return this.AllocBuffer(targetGraphics, IntPtr.Zero, targetRectangle); }Метод принимает в качестве параметра объект Graphics и область на нем, для которой нужно создать буфер. Если площадь этой области не превышает площадь MaximumBuffer (проверяется внутри метода ShouldUseTempManager*), вызывается метод AllocBuffer и возвращается полученный от него объект BufferedGraphics. Метод AllocBuffer создает внутри себя (с помощью метода CreateBuffer, описанного ниже), новый внеэкранный Graphics, оборачивает его в BufferedGraphics, сохраняет в переменную объекта buffer и возвращает её. Эта переменная используется для того, чтобы в дальнейшем при уничтожении экземпляра BufferedGraphicsContext (методом Dispose), уничтожить связанный с ним экземпляр BufferedGraphics. За создание внеэкранного (т.е. только в памяти) экземпляра Graphics отвечает метод CreateBuffer. Он с помощью нативной функции CreateDIBSection создает "аппаратно-независимый битмап" (DIB), на основе которого создает новый объект Graphics, и возвращает его в качестве результата. Если площадь переданной области превышает площадь MaximumBuffer, то вызывается метод AllocBufferInTempManager, исходный код которого приведен ниже:
private BufferedGraphics AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) { BufferedGraphicsContext bufferedGraphicsContext = (BufferedGraphicsContext) null; BufferedGraphics bufferedGraphics = (BufferedGraphics) null; try { // Создаем новый "временный" контент bufferedGraphicsContext = new BufferedGraphicsContext(); if (bufferedGraphicsContext != null) // Для чего эта проверка? всегда ДА { // Создаем в нем буферизированное полотно (graphics), которое внутри себя (переменная context) хранит // ссылку на него же bufferedGraphics = bufferedGraphicsContext.AllocBuffer(targetGraphics, targetDC, targetRectangle); // ВОТ, этот флаг указывает, что объект bufferedGraphics // при своем уничтожении должен уничтожить породившего его // bufferedGraphicsContext: bufferedGraphics.DisposeContext = true; } } finally { // В нормальной ситуации это условие не выполняется if (bufferedGraphicsContext != null && (bufferedGraphics == null || bufferedGraphics != null && !bufferedGraphics.DisposeContext)) bufferedGraphicsContext.Dispose(); } return bufferedGraphics; }Из этого кода видно, что внутри метода AllocBufferInTempManager создается новый экземпляр BufferedGraphicsContext, у которого вызывается метод AllocBuffer, а полученный от её BufferedGraphics возвращается в качестве результата. Причем, созданный временный объект BufferedGraphicsContext не уничтожается сразу же, а только при уничтожении созданного им BufferedGraphics. Для этого BufferedGraphics хранит обратную ссылку на своего создателя, а при уничтожении, если свойство DisposeContext равно true, забирает его с собой. Класс BufferedGraphics очень маленький. Его исходный код занимает чуть больше 100 строк. Он является простой оберткой над объектом Graphics, и предоставляет метод Render для копирования его на другой Graphics:
public void Render(Graphics target)Копирование осуществляется нативной функцией BitBlt. Так как же использовать ДБ в ручном режиме? Об этом очень хорошо написано здесь. * исходный код метода ShouldUseTempManager:
private bool ShouldUseTempManager(Rectangle targetBounds) { return targetBounds.Width * targetBounds.Height > this.MaximumBuffer.Width * this.MaximumBuffer.Height; }
control.DoubleBuffered = true;или
control.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);Рассмотрим что происходит с контролом, когда мы включаем для него автоматическую ДБ. Свойство DoubleBuffered, также как метод SetStyle, располагаются в классе System.Windows.Forms.Control. Заглянем в исходный этого класса. Код свойства DoubleBuffered выглядит так:
protected virtual bool DoubleBuffered { get { return this.GetStyle(ControlStyles.OptimizedDoubleBuffer); } set { if (value != this.DoubleBuffered) { if (value) this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, value); else this.SetStyle(ControlStyles.OptimizedDoubleBuffer, value); } } }Как видно из этого фрагмента кода, приведенные выше 2 способа включения ДБ ничем друг от друга не отличаются, за исключением того, что в сеттере DoubleBuffered устанавливается еще флаг ControlStyles.AllPaintingInWmPaint. Но так как этот флаг устанавливается и в конструкторе контрола*, то если вы его не сбрасывали вручную, оба этих способа имеют одинаковый эффект. Из исходного кода класса Control, так же можно увидеть что флаг ControlStyles.AllPaintingInWmPaint проверяется только внутри закрытого метода WmEraseBkgnd (а устанавливается только в конструкторе и сеттере свойства DoubleBuffered), вот его реализация:
private void WmEraseBkgnd(ref Message m) { if (this.GetStyle(ControlStyles.UserPaint)) { if (!this.GetStyle(ControlStyles.AllPaintingInWmPaint)) { IntPtr wparam = m.WParam; if (wparam == IntPtr.Zero) { m.Result = (IntPtr) 0; return; } else { NativeMethods.RECT rect = new NativeMethods.RECT(); UnsafeNativeMethods.GetClientRect(new HandleRef((object) this, this.Handle), out rect); using (PaintEventArgs e = new PaintEventArgs(wparam, Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom))) this.PaintWithErrorHandling(e, (short) 1); } } m.Result = (IntPtr) 1; } else this.DefWndProc(ref m); }Отсюда видно, что если флаг AllPaintingInWmPaint НЕ установлен, то при получении окном сообщения WM_ERASEBKGND**, происходит вызов метода PaintWithErrorHandling, с параметром layer равным 1, который в свою очередь вызывает перерисовку фона контрола, если не установлен флаг ControlStyles.Opaque***. Так же стоит рассмотреть флаг ControlStyles.UserPaint. Этот флаг указывает на то, что содержимое контрола будет отрисовываться средствами Framework.NET, а не средствами системы. Например, если вы зададите фоновую картинку для вашей формы, и сбросите флаг UserPaint, то картинка не будет отрисовываться. Вернемся теперь к ДБ. Основные действия по ДБ разворачиваются внутри метода WmPaint. Этот метод отвечает за обработку сообщения WM_PAINT, которое прилнетает когда какой-либо участок контрола нуждается в перерисовке. Метод WmPaint является закрытым и вызывается только из метода WndProc при условии, что установлен флаг ControlStyles.UserPaint:
protected virtual void WndProc(ref Message m) { switch (m.Msg) { ... case WM_PAINT: if (this.GetStyle(ControlStyles.UserPaint)) { this.WmPaint(ref m); break; } else { this.DefWndProc(ref m); break; } ... } }
private void WmPaint(ref Message m) { if (this.DoubleBuffered || this.GetStyle(ControlStyles.AllPaintingInWmPaint) && this.DoubleBufferingEnabled) { IntPtr num; // нативный хендл Graphics Rectangle rectangle; // перерисовываемый участок полотна // Инициализация num и rectangle... if (rectangle.Width > 0) { if (rectangle.Height > 0) { Rectangle clientRectangle = this.ClientRectangle; using (BufferedGraphics bufferedGraphics = BufferedGraphicsManager.Current.Allocate(num, clientRectangle)) { Graphics graphics = bufferedGraphics.Graphics; graphics.SetClip(rectangle); System.Drawing.Drawing2D.GraphicsState gstate = graphics.Save(); using (PaintEventArgs e = new PaintEventArgs(graphics, rectangle)) { this.PaintWithErrorHandling(e, (short) 1, false); graphics.Restore(gstate); this.PaintWithErrorHandling(e, (short) 2, false); bufferedGraphics.Render(); } } } } ... } else { // отрисовка без двойной буферизации... } }Как видно из приведенного выше фрагмента кода, для того чтобы графика отрисовывалась с ДБ нужно чтобы DoubleBuffered был равен true, или чтобы свойство DoubleBufferingEnabled****. Далее, всё вполне понятно из исходного кода. Как и ожидалось никаких чудес нету. Автоматическая ДБ происходит теми же средствами что и ручная.
private void PaintWithErrorHandling(PaintEventArgs e, short layer) { ... switch (layer) { case (short) 1: if (!this.GetStyle(ControlStyles.Opaque)) { this.OnPaintBackground(e); break; } else break; case (short) 2: this.OnPaint(e); break; } ... }* Фрагмент исходного кода конструктора класса Control в котором устанавливаются флаги ControlStyles:
internal Control(bool autoInstallSyncContext) { ... this.SetStyle(ControlStyles.UserPaint | ControlStyles.StandardClick | ControlStyles.Selectable | ControlStyles.StandardDoubleClick | ControlStyles.AllPaintingInWmPaint | ControlStyles.UseTextForAccessibility, true); ... }** Сообщение WM_ERASEBKGND приходит при изменении размера контрола. Фрагмент исходного кода, в котором обрабатывается сообщение WM_ERASEBKGND:
protected virtual void WndProc(ref Message m) { switch (m.Msg) { ... case WM_ERASEBKGND: this.WmEraseBkgnd(ref m); break; ... } }*** ControlStyles.Opaque – указывает .NET фреймворку что фон контрола не нужно отрисовывать. **** Закрытое свойство DoubleBufferingEnabled, имеет следующую реализацию:
bool DoubleBufferingEnabled { private get { return this.GetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer); } }Смысл этого свойства не очень понятен, так как метод WmPaint вызывается только при условии что установлен флаг ControlStyles.UserPaint, Поэтому DoubleBufferingEnabled здесь всегда будет true. А так как оно закрытое и нигде кроме WmPaint не проверяется, то для чего оно нужно?
BufferedGraphicsContext myContext = new BufferedGraphicsContext(); // использование myContext.Dispose();или
using(BufferedGraphicsContext myContext = new BufferedGraphicsContext()) { // использование }BufferedGraphicsContext имеет один метод Allocate и одно свойство MaximumBuffer.
public BufferedGraphics Allocate(Graphics targetGraphics, Rectangle targetRectangle) { if (this.ShouldUseTempManager(targetRectangle)) return this.AllocBufferInTempManager(targetGraphics, IntPtr.Zero, targetRectangle); else return this.AllocBuffer(targetGraphics, IntPtr.Zero, targetRectangle); }Внутри метода происходит проверка MaximumBuffer и targetRectangle (методом ShouldUseTempManager**). Если требуемый размер полотна превышает заданный полем MaximumBuffer , то вызывается метод AllocBufferInTempManager. Этот метод внутри себя создает новый экземпляр класса BufferedGraphicsContext, вызывает у него метод AllocBuffer и возвращает полученный от него объект класса BufferedGraphics.***
public sealed class BufferedGraphicsManager { private static BufferedGraphicsContext bufferedGraphicsContext; public static BufferedGraphicsContext Current { get { return BufferedGraphicsManager.bufferedGraphicsContext; } } static BufferedGraphicsManager() { AppDomain.CurrentDomain.ProcessExit += new EventHandler(BufferedGraphicsManager.OnShutdown); AppDomain.CurrentDomain.DomainUnload += new EventHandler(BufferedGraphicsManager.OnShutdown); // В СТАТИЧЕСКОМ КОНСТРУКТОРЕ ПРОСТО СОЗДАЕТСЯ НОВЫЙ // НОВЫЙ ОБЪЕКТ BufferedGraphicsContext BufferedGraphicsManager.bufferedGraphicsContext = new BufferedGraphicsContext(); } private BufferedGraphicsManager() { } [PrePrepareMethod] private static void OnShutdown(object sender, EventArgs e) { BufferedGraphicsManager.Current.Invalidate(); } }
private bool ShouldUseTempManager(Rectangle targetBounds) { return targetBounds.Width * targetBounds.Height > this.MaximumBuffer.Width * this.MaximumBuffer.Height; }*** При этом созданный внутри метода AllocBufferInTempManager экземпляр BufferedGraphicsContext не уничтожается, ответственность за его уничтожение ложится на пользователя получившего объект BufferedGraphics, который хранит обратную ссылку, при уничтожении которого и уничтожается породиший его объект BufferedGraphicsContext. Как это работает? Исходный код метода AllocBufferInTempManager:
private BufferedGraphics AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) { BufferedGraphicsContext bufferedGraphicsContext = (BufferedGraphicsContext) null; BufferedGraphics bufferedGraphics = (BufferedGraphics) null; try { // Создаем новый "временный" контент bufferedGraphicsContext = new BufferedGraphicsContext(); if (bufferedGraphicsContext != null) // Всегда ДА { // Создаем в нем буферизированное полотно, которое внутри себя (переменная context) хранит // ссылку на него же bufferedGraphics = bufferedGraphicsContext.AllocBuffer(targetGraphics, targetDC, targetRectangle); // ВОТ, этот флаг указывает, что объект bufferedGraphics // при своем уничтожении должен уничтожить породившего его // bufferedGraphicsContext: bufferedGraphics.DisposeContext = true; } } finally { // В нормальной ситуации это условие не выполняется if (bufferedGraphicsContext != null && (bufferedGraphics == null || bufferedGraphics != null && !bufferedGraphics.DisposeContext)) bufferedGraphicsContext.Dispose(); } return bufferedGraphics; }
Environment.Exit(0);Метод Environment.Exit(int exitCode) является аналого сишной функции exit(int code).
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String str = in.readLine();В C# ввод строки с консоли реализуется так:
Console.ReadLine();
<requestedExecutionLevel level="asInvoker" uiAccess="false" />на следующую:
<requestedExecutionLevel level="requireAdministrator" uiaccess="false" />После этого рядом с иконкой программы появится картинка щита, указывающая что запуск программы требует прав администратора.
LoadFile "C:\Program Files\PostgreSQL\9.1\bin\libpq.dll"и перезагрузить веб-сервер.