none
BITMAPINFO нарисовать прямоугольник RRS feed

  • Вопрос

  • Пытаюсь нарисовать прямоугольник в окне таким способом:

    private struct RGBQUAD
            {
                public byte rgbBlue;
                public byte rgbGreen;
                public byte rgbRed;
                public byte rgbReserved;
            }
    
    private struct BITMAPINFOHEADER
            {
                public int biSize;
                public int biWidth;
                public int biHeight;
                public short biPlanes;
                public short biBitCount;
                public int biCompression;
                public int biSizeImage;
                public int biXPelsPerMeter;
                public int biYPelsPerMeter;
                public int biClrUsed;
                public int biClrImportant;
            }
    
    private struct BITMAPINFO
            {
                public BITMAPINFOHEADER bmiHeader;
                public RGBQUAD bmiColors;
            }
    
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern bool DeleteObject(IntPtr hObject);
    
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern int ReleaseDC(IntPtr hdc, int state);
    
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern bool DeleteDC(IntPtr hdc);
    
    [DllImport("gdi32.dll")]
            private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
    
    [DllImport("gdi32.dll", ExactSpelling = true)]
            private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO pbmi, uint iUsage, int ppvBits, IntPtr hSection, uint dwOffset);
    
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern int SaveDC(IntPtr hdc);
    
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
            private static extern IntPtr GetDC(IntPtr hdc);
    
    private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
    
    private const int BI_RGB = 0;
    private const int DIB_RGB_COLORS = 0;
    private const int SRCCOPY = 0x00CC0020;
    
    public void DrawRectangle(IntPtr hwnd, Rectangle ctlrct)
            {
                 RECT rc = new RECT();
                 RECT rc2 = new RECT();
    
                 rc.left = ctlrct.Left;
                 rc.right = ctlrct.Right;
                 rc.top = ctlrct.Top;
                 rc.bottom = ctlrct.Bottom;
    
                 rc2.left = 0;
                 rc2.top = 0;
                 rc2.right = rc.right - rc.left;
                 rc2.bottom = rc.bottom - rc.top;
    
                 IntPtr destdc = GetDC(hwnd);
                 IntPtr Memdc = CreateCompatibleDC(destdc);
                 IntPtr bitmap;
                 IntPtr bitmapOld = IntPtr.Zero;
    
                 BITMAPINFO dib = new BITMAPINFO();
                 dib.bmiHeader.biHeight = -(rc.bottom - rc.top);
                 dib.bmiHeader.biWidth = rc.right - rc.left;
                 dib.bmiHeader.biPlanes = 1;
                 dib.bmiHeader.biSize = Marshal.SizeOf(typeof(BITMAPINFOHEADER));
                 dib.bmiHeader.biBitCount = 32;
                 dib.bmiHeader.biCompression = BI_RGB;
                 if (!(SaveDC(Memdc) == 0))
                    {
                        bitmap = CreateDIBSection(Memdc, ref dib, DIB_RGB_COLORS, 0, IntPtr.Zero, 0);
                        if (!(bitmap == IntPtr.Zero))
                        {
                            bitmapOld = SelectObject(Memdc, bitmap);
                            try
                            {        
                                BitBlt(destdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, Memdc, 0, 0, SRCCOPY);
                            }
                            catch (Exception e)
                            {
                                Trace.WriteLine(e.Message);
                            }
    
                            SelectObject(Memdc, bitmapOld);
                            DeleteObject(bitmap);
    
                            ReleaseDC(Memdc, -1);
                            DeleteDC(Memdc);
                        }
                  }
            }

    hwnd - это окно, в котором рисовать, ctlrct - размер прямоугольника.

    Беда в том, что рисуется чёрный прямоугольник. Как можно задать цвет для рисования (красный там или зелёный)?

    6 июля 2013 г. 19:28

Ответы

Все ответы

  • А нужно обязательно на C++ рисовать?
    Мазохизм какой-то!
  • Это не C++, а С#.

    Насчёт причин.

    Есть стеклянная форма. На ней должны быть Label, TextBox и некоторые другие элементы.

    Форма полностью стеклянная, то есть функции DwmExtendFrameIntoClientArea(this.Handle, ref marg);
    передаётся Margins с полями -1.

    В чем проблема?

    Если оставлять фоном чёрный цвет, то Label можно нарисовать с помощью функции DrawThemeTextEx, для которой и нужна эта обвязка. Другим способом у меня нарисовать нормальный текст не получилось. Но в таком случае всякий текст в других элементах становится прозрачным.

    Можно установить this.TransparencyKey в какой-нибудь другой цвет. Тогда всё прорисовывается как нужно, но DrawThemeTextEx рисует текст в чёрном прямоугольнике, который естественно не прозрачен.

    Вот и возникает вопрос, как нарисовать текст с помощью DrawThemeTextEx на прямоугольнике нужного цвета? Ну или решить проблему с отрисовкой элементов с чёрным цветом...

  • Взгляните сюда, может быть поможет -
    http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=4418
    7 июля 2013 г. 10:45
  • И всё-таки, зачем использовать GDI и pinvoke в C#?

    И хотелось бы знать, какая технология используется. По TransparencyKey полагаю, WinForms? Тогда не проще ли использовать GDI+?

    7 июля 2013 г. 13:25
  • Потому что требуется нарисовать Aero текст на стекле. И сделать это корректно получилось у меня только так.

    Используется TransparencyKey в WinForms, верно.

    Нормальный текст в облачке рисует функция DrawThemeTextEx.

    Правильный результат мы видим, если не использовать TransparecyKey. Надпись нарисована правильно,текст кнопки не читаем.

    Текст в облачке на чёрном фоне и правильно отрисованную кнопку получаем, установив TransparecyKey в серый цвет RGB(221,220,220). Если покрасить прямоугольник в серый цвет, то по идее текст должен стать нормальным.

    Я пробовал не использовать функцию CreateDIBSection и делал следующим образом:

    public void DrawTextOnGlass(IntPtr hwnd, String text, Font font, Rectangle ctlrct, int iglowSize)
            {
                if (IsGlassEnabled())
                {
                    Image img = (System.Drawing.Image)(resources.GetObject("Standard"));
    
                    RECT rc = new RECT();
                    RECT rc2 = new RECT();
    
                    rc.left = ctlrct.Left;
                    rc.right = ctlrct.Right + 2 * iglowSize;
                    rc.top = ctlrct.Top;
                    rc.bottom = ctlrct.Bottom + 2 * iglowSize;
    
                    Bitmap bmp = new Bitmap(img, rc.right - rc.left, rc.bottom - rc.top);
    
                    rc2.left = 0;
                    rc2.top = 0;
                    rc2.right = rc.right - rc.left;
                    rc2.bottom = rc.bottom - rc.top;
    
                    IntPtr destdc = GetDC(hwnd);
                    IntPtr Memdc = CreateCompatibleDC(destdc);
                    IntPtr bitmap;
                    IntPtr bitmapOld = IntPtr.Zero;
                    IntPtr logfnotOld;
    
                    int uFormat = DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX;
    
                    if (!(SaveDC(Memdc) == 0))
                    {
                        bitmap = bmp.GetHbitmap();
                        if (!(bitmap == IntPtr.Zero))
                        {
                            bitmapOld = SelectObject(Memdc, bitmap);
                            IntPtr hFont = font.ToHfont();
                            logfnotOld = SelectObject(Memdc, hFont);
                            try
                            {
                                System.Windows.Forms.VisualStyles.VisualStyleRenderer renderer = new System.Windows.Forms.VisualStyles.VisualStyleRenderer(System.Windows.Forms.VisualStyles.VisualStyleElement.Window.Caption.Active);
                                DTTOPTS dttOpts = new DTTOPTS();
                                dttOpts.dwSize = (uint)Marshal.SizeOf(typeof(DTTOPTS));
                                dttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
                                dttOpts.iGlowSize = iglowSize;
                                DrawThemeTextEx(renderer.Handle, Memdc, 0, 0, text, -1, uFormat, ref rc2, ref dttOpts);
                                BitBlt(destdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, Memdc, 0, 0, SRCCOPY);
                            }
                            catch (Exception e)
                            {
                                Trace.WriteLine(e.Message);
                            }
    
                            SelectObject(Memdc, bitmapOld);
                            SelectObject(Memdc, logfnotOld);
                            DeleteObject(bitmap);
                            DeleteObject(hFont);
    
                            ReleaseDC(Memdc, -1);
                            DeleteDC(Memdc);
                        }
                    }
                }
            }

    То есть в ресурсах у меня лежит эталонная картинка, которую я могу покрасить в любой цвет. Я её просто достаю, масштабирую под размер текста и рисую на ней, что нужно. В результате, текст отображается на большом сером облаке да ещё и вверх ногами.

    Я не спорю, может лучше использовать GDI+, но идей в этом направлении у меня нет. Может приведёте пример реализации через GDI+?

    7 июля 2013 г. 19:06
  • Здравствуйте,

    Может я и ошибаюсь, но вероянто Вам подойдет:

    CreateDIBPatternBrushPt

    По поводу GDI+: Brushes and Filled Shapes in GDI+


    Если вам помог чей-либо ответ, пожалуйста, не забывайте жать на кнопку "Предложить как ответ" или "Проголосовать за полезное сообщение"

    12 июля 2013 г. 11:04
    Модератор