Дважды буферизированный ListBox

Для вычисления расстояния между двумя точками на сфере, необходимо сделать Большое Круговое вычисление .

существует много библиотек C/C++ для помощи с проекцией карты в MapTools, если необходимо повторно спроектировать расстояния до плоской поверхности. Чтобы сделать это, Вам будет нужна строка проекции различных систем координат.

можно также найти MapWindow полезный инструмент визуализировать точки. Также как его открытый исходный код это - полезное руководство по тому, как пользоваться библиотекой proj.dll, которая, кажется, базовая библиотека проекции с открытым исходным кодом.

8
задан Julien Poulin 15 July 2009 в 19:57
поделиться

3 ответа

У меня были похожие проблемы, хотя и со списком, нарисованным владельцем. Мое решение заключалось в использовании объектов BufferedGraphics. Ваш опыт может отличаться от этого решения, если ваш список не нарисован владельцем, но, возможно, это послужит вам источником вдохновения.

Я обнаружил, что у TextRenderer были трудности с отображением в правильное место, если я не предоставил TextFormatFlags.PreserveGraphicsTranslateTransform. Альтернативой этому было использование P / Invoke для вызова BitBlt для прямого копирования пикселей между графическими контекстами. Я выбрал это как меньшее из двух зол.

/// <summary>
/// This class is a double-buffered ListBox for owner drawing.
/// The double-buffering is accomplished by creating a custom,
/// off-screen buffer during painting.
/// </summary>
public sealed class DoubleBufferedListBox : ListBox
{
    #region Method Overrides
    /// <summary>
    /// Override OnTemplateListDrawItem to supply an off-screen buffer to event
    /// handlers.
    /// </summary>
    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;

        Rectangle newBounds = new Rectangle(0, 0, e.Bounds.Width, e.Bounds.Height);
        using (BufferedGraphics bufferedGraphics = currentContext.Allocate(e.Graphics, newBounds))
        {
            DrawItemEventArgs newArgs = new DrawItemEventArgs(
                bufferedGraphics.Graphics, e.Font, newBounds, e.Index, e.State, e.ForeColor, e.BackColor);

            // Supply the real OnTemplateListDrawItem with the off-screen graphics context
            base.OnDrawItem(newArgs);

            // Wrapper around BitBlt
            GDI.CopyGraphics(e.Graphics, e.Bounds, bufferedGraphics.Graphics, new Point(0, 0));
        }
    }
    #endregion
}

Класс GDI (предложен frenchtoast ).

public static class GDI
{
    private const UInt32 SRCCOPY = 0x00CC0020;

    [DllImport("gdi32.dll", CallingConvention = CallingConvention.StdCall)]
    private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, UInt32 dwRop);

    public static void CopyGraphics(Graphics g, Rectangle bounds, Graphics bufferedGraphics, Point p)
    {
        IntPtr hdc1 = g.GetHdc();
        IntPtr hdc2 = bufferedGraphics.GetHdc();

        BitBlt(hdc1, bounds.X, bounds.Y, 
            bounds.Width, bounds.Height, hdc2, p.X, p.Y, SRCCOPY);

        g.ReleaseHdc(hdc1);
        bufferedGraphics.ReleaseHdc(hdc2);
    }
}
12
ответ дан 5 December 2019 в 12:11
поделиться

Вы можете проверить, улучшает ли дело переключение на элемент управления ListView с помощью флажков. С этим не так легко справиться (но, эй, WinForms ListBox тоже не гениальный ход), я обнаружил, что его поведение при изменении размера с DoubleBuffered = true терпимо.

В качестве альтернативы вы можете попытаться уменьшить мерцание, переопределив фоновый рисунок родительских форм - либо предоставив пустую кисть, либо переопределив WM_ERASEBKND , ничего не делая и вернув TRUE . (это нормально, если ваш элемент управления покрывает всю клиентскую область родительской формы, иначе вам понадобится более сложный метод рисования фона.

Я успешно использовал это в приложениях Win32, но я не знаю, были ли формы control добавляет часть этого '

2
ответ дан 5 December 2019 в 12:11
поделиться

Раньше это выполнялось путем отправки сообщения WM_SETREDRAW элементу управления.

const int WM_SETREDRAW = 0x0b;

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 0, (IntPtr) 0);
yourform.DefWndProc(ref m);

// do your updating or whatever else causes the flicker

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 1, (IntPtr) 0);
yourform.DefWndProc(ref m);

См. Также: Ссылка на WM_SETREDRAW в Microsoft Фиксированная ссылка

Если кто-то еще использовал сообщения Windows под .NET, пожалуйста при необходимости обновите это сообщение.

0
ответ дан 5 December 2019 в 12:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: