SORU
15 AĞUSTOS 2011, PAZARTESİ


Cam denetimleri oluşturma: Çözüm, çift ara belleğe alma/mükemmelleştirmek bulundu gerekiyor

I (nihayet!) işleme Windows'un bir yolunu buldu.Formları ne de herhangi bir büyük uygulama zaman herhangi bir büyük dezavantajı var gibi görünmüyor bu camı kontrol eder. Temelde yerel olarak geçersiz kılar resmi onları çizmek için nasıl açıklayan Kodlu this article esinlenerek.

Bu yaklaşım, bir bit eşlem için Denetim işlemek için kullanılan ve GDI ve Dar resim alana uygun alfa kanalı ile boya geri. Uygulama basit ama kullanılabilirlik için mükemmel olabilir, ama bu bir soru değil. Ancak sonuçlar oldukça tatmin edici

Real textbox on glass

Bu gerçekten kullanılabilir düzeltilmesi gereken 2 alan, ancak vardır.

  1. Çift ara belleğe almabu bindirme görüntü ve gerçek arasındaki titreşimi çünkü kontrol ve (kod ile kendinizi test) sık sık korkunç. SetStyles(this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true) çift tamponlu temel kontrol ayarı çalışmıyor, ama biraz deneme yanılma ile yapabiliriz sanıyorum.
  2. Bazı kontroller çalışmıyor. Aşağıdaki çalışma yapmak mümkün oldum:

    • TextBox
    • MaskedComboBox
    • ComboBox == DropDownStyle DropDownList ()
    • ListBox
    • CheckedListBox
    • Liste görünümü
    • Ağaç görünümü
    • DateTimePicker
    • MonthCalendar

    Ama bu neden olmasın, ancak iş bulamıyorum. Gerçek Dar ihtiyacım var sırasında tüm kontrol başvuran, ben kolu eğitimli tahminimce referans "giriş" (metinsel) bir parçası, muhtemelen bir çocuk. Giriş pencere kolu nasıl Winapı uzmanlardan yardıma açığız.

    • (DropDownStyle=! ComboBox DropDownList)
    • NumericUpDown
    • Denetler

Ama çift tampon tamir olurana odakkullanılabilirlik için.

İşte örnek bir kullanım:

new GlassControlRenderer(textBox1);

İşte kod:

public class GlassControlRenderer : NativeWindow
{
    private Control Control;
    private Bitmap Bitmap;
    private Graphics ControlGraphics;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case 0xF: // WM_PAINT
            case 0x85: // WM_NCPAINT
            case 0x100: // WM_KEYDOWN
            case 0x200: // WM_MOUSEMOVE
            case 0x201: // WM_LBUTTONDOWN
                this.Control.Invalidate();
                base.WndProc(ref m);
                this.CustomPaint();
                break;

            default:
                base.WndProc(ref m);
                break;
        }
    }

    public GlassControlRenderer(Control control)
    {
        this.Control = control;
        this.Bitmap = new Bitmap(this.Control.Width, this.Control.Height);
        this.ControlGraphics = Graphics.FromHwnd(this.Control.Handle);
        this.AssignHandle(this.Control.Handle);
    }

    public void CustomPaint()
    {
        this.Control.DrawToBitmap(this.Bitmap, new Rectangle(0, 0, this.Control.Width, this.Control.Height));
        this.ControlGraphics.DrawImageUnscaled(this.Bitmap, -1, -1); // -1, -1 for content controls (e.g. TextBox, ListBox)
    }
}

Çok sevindim bunu düzeltmek için olurdumbir kez ve herkes içintüm cam işleme, gerçek bir yol var .NET, WPF olmadan kontrol eder.

EDİT: çift tamponlama anti-titreşim Olası yolları/:

  • Çizgi çıkarma this.Control.Invalidate() titreşimi ortadan kaldırır, ama bir kutudaki yazmayı keser.
  • WM_SETREDRAW yaklaşım ve SuspendLayout yöntemi, hiç şans denedim:

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
    
    private const int WM_SETREDRAW = 11;
    
    public static void SuspendDrawing(Control parent)
    {
        SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
    }
    
    public static void ResumeDrawing(Control parent)
    {
        SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
        parent.Refresh();
    }
    
    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case 0xF: // WM_PAINT
            case 0x85: // WM_NCPAINT
            case 0x100: // WM_KEYDOWN
            case 0x200: // WM_MOUSEMOVE
            case 0x201: // WM_LBUTTONDOWN
                //this.Control.Parent.SuspendLayout();
                //GlassControlRenderer.SuspendDrawing(this.Control);
                //this.Control.Invalidate();
                base.WndProc(ref m);
                this.CustomPaint();
                //GlassControlRenderer.ResumeDrawing(this.Control);
                //this.Control.Parent.ResumeLayout();
                break;
    
            default:
                base.WndProc(ref m);
                break;
        }
    }
    

CEVAP
29 EYLÜL 2011, PERŞEMBE


Burada çok daha az titreyen bir sürümü, hala mükemmel olmasa bile.

public class GlassControlRenderer : NativeWindow
{
    private Control Control;
    private Bitmap Bitmap;
    private Graphics ControlGraphics;

    private object Lock = new object();

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case 0x14: // WM_ERASEBKGND
                this.CustomPaint();
                break;

            case 0x0F: // WM_PAINT
            case 0x85: // WM_NCPAINT

            case 0x100: // WM_KEYDOWN
            case 0x101: // WM_KEYUP
            case 0x102: // WM_CHAR

            case 0x200: // WM_MOUSEMOVE
            case 0x2A1: // WM_MOUSEHOVER
            case 0x201: // WM_LBUTTONDOWN
            case 0x202: // WM_LBUTTONUP
            case 0x285: // WM_IME_SELECT

            case 0x300: // WM_CUT
            case 0x301: // WM_COPY
            case 0x302: // WM_PASTE
            case 0x303: // WM_CLEAR
            case 0x304: // WM_UNDO
                base.WndProc(ref m);
                this.CustomPaint();
                break;

            default:
                base.WndProc(ref m);
                break;
        }
    }

    private Point Offset { get; set; }

    public GlassControlRenderer(Control control, int xOffset, int yOffset)
    {
        this.Offset = new Point(xOffset, yOffset);
        this.Control = control;
        this.Bitmap = new Bitmap(this.Control.Width, this.Control.Height);
        this.ControlGraphics = Graphics.FromHwnd(this.Control.Handle);
        this.AssignHandle(this.Control.Handle);
    }

    public void CustomPaint()
    {
        this.Control.DrawToBitmap(this.Bitmap, new Rectangle(0, 0, this.Control.Width, this.Control.Height));
        this.ControlGraphics.DrawImageUnscaled(this.Bitmap, this.Offset); // -1, -1 for content controls (e.g. TextBox, ListBox)
    }
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • We've moved!

    We've moved!

    7 Ocak 2008
  • Microsoft Help & Training Videos

    Microsoft He

    31 Mart 2009
  • natescamp

    natescamp

    30 NİSAN 2009