سؤال

هل من الممكن أن ownerdraw كامل رأس العمود قسم من listview?(بما في ذلك المنطقة على يمين رؤوس الأعمدة)?ListView في طريقة العرض تفاصيل.

الجواب هنا يشير إلى أن المساحة المتبقية يمكن استخلاصها جنبا إلى جنب مع آخر رأس العمود: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

ولكن لا يبدو أن العمل في كل شيء ويوجه خارج منطقة رأس.

الحل المقترح هو بناء على الرسم خارج مرت حدود:

if (e.ColumnIndex == 3) //last column index
{
    Rectangle rc = new Rectangle(e.Bounds.Right, //Right instead of Left - offsets the rectangle
            e.Bounds.Top, 
            e.Bounds.Width, 
            e.Bounds.Height);

    e.Graphics.FillRectangle(Brushes.Red, rc);
}

على ClipBounds الملكية المتاحة الرسومات سبيل المثال يشير إلى مساحة غير منضم (من الأرقام السلبية إلى إيجابية كبيرة).ولكن لا شيء يتم رسمها خارج columnheader منطقة من العمود الأخير.

هل لدى أحدكم حل لهذا ؟

هل كانت مفيدة؟

المحلول

أنا متفاجئ من قبل جيفري تان الجواب في هذا المنصب.الحل لا يمكن العمل منذ رمز يحاول رسم خارج رأس السيطرة على منطقة العميل.على hDC تستخدم في رسم مخصص (وبالتالي صاحب الرسم) هو منطقة العميل من التحكم و لذلك لا يمكن استخدام الطلاء في غير منطقة العميل.المنطقة إلى يمين اليمين معظم عمود في رأس التحكم في غير منطقة العميل.لذلك تحتاج حلا مختلفا.

الحلول الممكنة

  1. مرحبا التكنولوجيا و فعالة جزئيا

يمكنك تمكين الرسم خارج منطقة العميل باستخدام GetDC() WinAPI الاتصال:

[System.Runtime.InteropServices.DllImport("user32")]
private static extern IntPtr GetDC(IntPtr hwnd);
[System.Runtime.InteropServices.DllImport("user32")]
private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);

public static IntPtr GetHeaderControl(ListView list) {
    const int LVM_GETHEADER = 0x1000 + 31;
    return SendMessage(list.Handle, LVM_GETHEADER, 0, 0);
}

في العمود رسم معالج الحدث, سوف تحتاج إلى شيء مثل هذا:

if (e.ColumnIndex == 3) //last column index
{
  ListView lv = e.Header.ListView;
  IntPtr headerControl = NativeMethods.GetHeaderControl(lv);
  IntPtr hdc = GetDC(headerControl);
  Graphics g = Graphics.FromHdc(hdc);

  // Do your extra drawing here
  Rectangle rc = new Rectangle(e.Bounds.Right, //Right instead of Left - offsets the rectangle
            e.Bounds.Top, 
            e.Bounds.Width, 
            e.Bounds.Height);

    e.Graphics.FillRectangle(Brushes.Red, rc);

  g.Dispose();
  ReleaseDC(headerControl, hdc);
}

ولكن المشكلة مع ذلك هو أنه منذ الرسم الخاص بك هو خارج منطقة العميل ، يقوم نظام ويندوز لا تعرف دائما عندما ينبغي أن يكون استخلاصها.لذلك سوف تختفي في بعض الأحيان ، ومن ثم يكون رسم ويندوز عندما يعتقد رأس احتياجات إعادة طلاء.

  1. التكنولوجيا منخفضة ولكن القبيح

إضافة إضافية فارغة في عمود التحكم الخاصة بك ، مالك استدراجه لا تبدو ومع ذلك تريد جعلها واسعة جدا و إيقاف التمرير الأفقي (اختياري).

أعرف أن هذا أمر فظيع ، ولكن كنت تبحث عن اقتراحات :)

  1. الأكثر فعالية ، ولكن لا يزال غير مثالي

استخدام ObjectListView.هذا المجمع حول .صافي ListView يسمح لك لإضافة تراكب إلى القائمة الخاصة بك -- تراكب يمكن رسم أي مكان في ListView ، بما في ذلك الرأس.[الإعلان:أنا كاتب ObjectListView ، ولكن ما زلت أعتقد أنه أفضل حل]

public class HeaderOverlay : AbstractOverlay
{
    public override void Draw(ObjectListView olv, Graphics g, Rectangle r) {
        if (olv.View != System.Windows.Forms.View.Details)
            return;

        Point sides = NativeMethods.GetColumnSides(olv, olv.Columns.Count-1);
        if (sides.X == -1)
            return;

        RectangleF headerBounds = new RectangleF(sides.Y, 0, r.Right - sides.Y, 20);
        g.FillRectangle(Brushes.Red, headerBounds);
        StringFormat sf = new StringFormat();
        sf.Alignment = StringAlignment.Center;
        sf.LineAlignment = StringAlignment.Center;
        g.DrawString("In non-client area!", new Font("Tahoma", 9), Brushes.Black, headerBounds, sf);
    }
}

وهذا يعطي هذا:alt text

[القراءة على هذا الجواب ، وأعتقد أن هذا هو مثال على محاولة من الصعب جدا :) آمل أن تجد شيئا هنا مفيدة.]

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top