搜索
bottom↓
回复: 6

在C#中使用GDI的简单总结

[复制链接]

出0入0汤圆

发表于 2011-7-9 16:57:22 | 显示全部楼层 |阅读模式
在C#默认支持的是GDI+库,使用GDI+库,有很丰富的函数和排版手段,可以满足大部分的要求.除非,你需要使用bitmap字体,GDI+对于字体的支持有很大限制,支持truetype字体,而对于点阵字体(栅格字体)则不再支持,但是很多字体都是这种点阵字体,这样就带来一个问题,使用不了了.而很多公司则会自己制作某些用途的字体,比如说在LED显示屏上使用,这个时候使用GDI+则不再是一个明智的选择了.此外GDI+虽然强大,但是经过测试发现效率却是低下,速度比GDI慢了不少.
但是CS的界面开发环境和编码习惯又很适合,所以比较折衷的解决方法是使用C#调用系统的gdi api函数实现编程.
首先C#环境中的color结构是AARRGGBB,而在win32的颜色结构却是AABBGGRR,所以如果不注意则会使到颜色出现偏差或者逆转.在.net环境的类库当中,在system.drawing的命名空间中有ColorTranslator.ToWin32()这个函数,来对color结构转换成win32的api使用的颜色结构.
GDI中比较重要的函数,gdi函数基本都是来之一个dll. Gdi32.dll
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("GDI32.dll")]
        public static extern bool DeleteObject(IntPtr objectHandle);


        [DllImport("gdi32.dll")]
        public static extern bool FillRgn(IntPtr hdc, IntPtr hrgn, IntPtr hbr);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect,
            int nBottomRect);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateSolidBrush(Int32 crColor);

        [DllImport("gdi32.dll")]
        public static extern int SetBkMode(IntPtr hdc, int iBkMode);
        public const int TRANSPARENT = 1;
        public const int OPAQUE = 2;

        [DllImport("gdi32.dll")]
        static extern uint SetBkColor(IntPtr hdc, int crColor);

        [DllImport("gdi32.dll")]
        static extern uint SetTextColor(IntPtr hdc, int crColor);


        [DllImport("gdi32", EntryPoint = "CreateFontW", CharSet = CharSet.Auto)]
        static extern IntPtr CreateFontW(
                    [In] Int32 nHeight,
                    [In] Int32 nWidth,
                    [In] Int32 nEscapement,
                    [In] Int32 nOrientation,
                    [In] FontWeight fnWeight,
                    [In] Boolean fdwItalic,
                    [In] Boolean fdwUnderline,
                    [In] Boolean fdwStrikeOut,
                    [In] FontCharSet fdwCharSet,
                    [In] FontPrecision fdwOutputPrecision,
                    [In] FontClipPrecision fdwClipPrecision,
                    [In] FontQuality fdwQuality,
                    [In] FontPitchAndFamily fdwPitchAndFamily,
                    [In] String lpszFace);


        [DllImport("gdi32.dll")]
        public static extern int GetTextFace(IntPtr hdc, int nCount,
           [Out] StringBuilder lpFaceName);

        public const Int32 LF_FACESIZE = 32;


        [DllImport("gdi32.dll", ExactSpelling = true)]
        public static extern bool BitBlt(
        IntPtr hdcDest,     //    目标设备的句柄   
        int nXDest,         //    目标对象的左上角的X坐标   
        int nYDest,         //    目标对象的左上角的Y坐标   
        int nWidth,         //    目标对象的矩形的宽度   
        int nHeight,        //    目标对象的矩形的长度   
        IntPtr hdcSrc,      //    源设备的句柄   
        int nXSrc,          //    源对象的左上角的X坐标   
        int nYSrc,          //    源对象的左上角的X坐标   
        TernaryRasterOperations dwRop //    光栅的操作值   
        );

        [DllImport("gdi32.dll")]
        public static extern bool StretchBlt(IntPtr hdcDest, int nXOriginDest, int nYOriginDest,
            int nWidthDest, int nHeightDest,
            IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
            TernaryRasterOperations dwRop);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetTextExtentPoint(IntPtr hdc, string lpString,
            int cbString, ref Size lpSize);

        [DllImport("Gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC lptm);


        [DllImport("gdi32.dll")]
        public static extern bool GetCharABCWidthsFloatW(IntPtr hdc, uint iFirstChar, uint iLastChar, [Out] ABCFloat[] lpABCF);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool TextOutW(IntPtr hdc, int nXStart, int nYStart,
            string lpString, int cbString);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetCharWidth32(IntPtr hdc, uint iFirstChar, uint iLastChar,
           [Out] int[] lpBuffer);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int DrawText(IntPtr hdc, string lpStr, int nCount, ref Rect lpRect, dwDTFormat wFormat);


        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern IntPtr CreateCompatibleDC(IntPtr hdc);

        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern bool DeleteDC(IntPtr hdc);

这些都是在GDI中比较常用的函数,其中SelectObject,和DeleteObject更是关键,在GDI的使用中最容易出现的问题就是内存泄漏,很多时候是因为没有正确释放资源引起的.所以需要特别小心,在GDI中释放资源使用DeleteObject这个函数来释放.
下面来实现一些具体的函数

        /// <summary>
        /// 填充特定DC的一个区域的特定颜色
        /// </summary>
        /// <param name="hdc">给定DC</param>
        /// <param name="Rect">给定区域</param>
        /// <param name="FillColor">给定颜色</param>
        public  static void FillRect(IntPtr hdc, Rectangle Rect, Color FillColor)
        {            
            IntPtr fillBrush = CreateSolidBrush(ColorTranslator.ToWin32(FillColor));
            IntPtr rectR = CreateRectRgn(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
            FillRgn(hdc, rectR, fillBrush);
            DeleteObject(rectR);
            DeleteObject(fillBrush);
        }
这个函数实现对一个区域填充一个颜色, 当中创建了画笔,创建了区域,然后最后,当然还要记得释放两者占用的资源.

创建字体函数
        public static IntPtr CreatFont(String FontName, Int32 Height, FontStyle Style)
        {
            IntPtr Result;// = IntPtr.Zero;
            FontWeight boldWeight = FontWeight.FW_NORMAL;
            Boolean Italic = false;
            Boolean Underline = false;
            Boolean Bold = false;

            if ((Style & FontStyle.Bold) != 0)
            {   
                Bold = true;
            }

            if ((Style & FontStyle.Italic) != 0)
            {
                Italic = true;
            }

            if ((Style & FontStyle.Underline) != 0)
            {
                Underline = true;
            }

            if (Bold)
            {
                boldWeight = FontWeight.FW_BOLD;
            }


            Result = CreateFontW(Height, 0, 0, 0, boldWeight, Italic, Underline, false,
                                 FontCharSet.DEFAULT_CHARSET, FontPrecision.OUT_DEFAULT_PRECIS,
                                 FontClipPrecision.CLIP_DEFAULT_PRECIS, FontQuality.DRAFT_QUALITY,
                                 FontPitchAndFamily.DEFAULT_PITCH, FontName);
            return Result;
        }
在.net中,默认的字体类,不支持点阵字体,所以要使用CreateFontW这个函数来创建自己的字体资源,其中大部分的选项都试用默认值即可.
然后就是设置画板字体,在GDI环境中,DC是带着字体的,而不像GDI+那样子是分离的,所以经常需要设置不同的字体
        public static IntPtr SetCanvasFont(IntPtr hdc, ApiFont NewFont)
        {
            IntPtr FontPtr = CreatFont(NewFont.Name, NewFont.Size, NewFont.Style);
            IntPtr OldPtr =  SelectObject(hdc, FontPtr);
            DeleteObject(OldPtr);
            return OldPtr;
        }
这个函数,将DC原来的字体资源释放掉,这样的实现会带来一个新的问题,因为一般来说都需要将DC原来的字体资源再通过selectobject函数放回去,然后将新的字体资源释放掉.所以这个函数是要小心使用的.
所以就有了第二个版本
        public static IntPtr SetCanvasFontNotDelete(IntPtr hdc, ApiFont NewFont)
        {
            IntPtr FontPtr = CreatFont(NewFont.Name, NewFont.Size, NewFont.Style);
            IntPtr OldPtr = SelectObject(hdc, FontPtr);
            return OldPtr;
        }

这样子就可以手动的释放资源,但是需要特别注意,的是一定要记得释放掉字体资源.

一般的使用画图的步骤
                IntPtr pTarget = e.Graphics.GetHdc();
                IntPtr pSource = CreateCompatibleDC(pTarget);
                IntPtr pOrig = SelectObject(pSource, drawBmp.GetHbitmap());
                GDIApi.StretchBlt(pTarget, 0, 0, this.Width, this.Height, pSource, 0, 0, drawWidth, drawHeight, TernaryRasterOperations.SRCCOPY);
                IntPtr pNew = SelectObject(pSource, pOrig);
                DeleteObject(pNew);
                DeleteDC(pSource);
                e.Graphics.ReleaseHdc(pTarget);
这样子就可以将drawBmp画到e.graphics上面了.最重要的是后面释放掉资源,否则内存的泄漏速度是很厉害的.我的软件每次重画就有7M左右的泄漏.一下子从十几M的内存上升到几百M的内存占用

        [DllImport("gdi32.dll")]
        public static extern int SetBkMode(IntPtr hdc, int iBkMode);
        public const int TRANSPARENT = 1;
        public const int OPAQUE = 2;
这个函数是设置透明度的,参数2如果为1则是透明,2则是不透明.
不透明的话,将字符串画上去的时候,会有白色的背景.一般来说设为透明.
获取字符或者字体的信息函数
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetTextExtentPoint(IntPtr hdc, string lpString,
            int cbString, ref Size lpSize);
        [DllImport("Gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC lptm);
       [DllImport("gdi32.dll")]
        public static extern bool GetCharABCWidthsFloatW(IntPtr hdc, uint iFirstChar, uint iLastChar, [Out] ABCFloat[] lpABCF);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetCharWidth32(IntPtr hdc, uint iFirstChar, uint iLastChar,
           [Out] int[] lpBuffer);
这几个函数都可以获取字体或者字符串占用的空间大小,而又各有区别.
GetTextExtentPoint可以方便的获取一个字符串,或者字符串的部分的长度,因为可以通过cbString这个长度来控制获取的范围.
GetTextMetrics则是获取一个字体的各种高度信息,包括height,ascent,descent,还包括字体能够表现的字符范围等等信息.
GetCharABCWidthsFloatW则是获取某段连续字符串的abcwidth信息,abcwidth信息在某些情况下,需要特别注意,否则斜体会排版得很难看.
GetCharWidth32获取一个连续的字符段的宽度信息, 但是根据实践,居然和GetTextExtentPoint获取的信息不大一致,暂时是少于实际占用的空间.使到计算出来的占用宽度实际上不足以容纳字符串的排版.


字符串的描绘
这是在gdi操作中非常重要的一部分,使用Gdi是因为需要使用特殊字体,而字体当然是针对字符串来使用的的.所以,这根本就是使用gdi的目的.
常用的字符串输出有来个函数
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public static extern bool TextOutW(IntPtr hdc, int nXStart, int nYStart,
            string lpString, int cbString);
     [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int DrawText(IntPtr hdc, string lpStr, int nCount, ref Rect lpRect, dwDTFormat wFormat);
TextOutW是一个比较简单的函数,适合一般的场合,只需要设置X和Y的坐标即可
DrawText,则会控制输出的空间大小,排版规则.比较适合需要精确控制的场所,又或者比如说输出阿拉伯文字的时候,要设置为右对齐.

获取系统所有的字体
由于C#不支持点阵字体,所以自然地,使用.net提供的函数,获取的安装字体列表自然是不包含点阵字体的.所以并不符合我的要求.所以还得使用系统的api函数,来获取安装字体列表.
        private Int32 EnumFontCallBack(ref ENUMLOGFONTEX lpelfe, IntPtr lpntme, int FontType, int lParam)
        {
            //Debug.WriteLine(lpelfe.elfFullName);
            if (lpelfe.elfFullName.Substring(0, 1) != "@")
            {
                if (!sysFontList.Contains(lpelfe.elfFullName))
                {
                    sysFontList.Add(lpelfe.elfFullName);
                }

            }

            return 1;
        }

            LOGFONT logfont = new LOGFONT();
            logfont.lfCharSet = FontCharSet.DEFAULT_CHARSET;
            Bitmap bmp = new Bitmap(10, 10);
            Graphics g = Graphics.FromImage(bmp);
            IntPtr hDC = g.GetHdc();
            EnumFontFamilies.EnumFontFamiliesEx(hDC, logfont, EnumFontCallBack, IntPtr.Zero, 0);
            g.ReleaseHdc(hDC);
            g.Dispose();
            bmp.Dispose();

    public class EnumFontFamilies
    {
        public const int LF_FACESIZE = 32;
        
        public delegate int EnumFontExDelegate( ref ENUMLOGFONTEX lpelfe, IntPtr lpntme, int FontType, int lParam );

        [DllImport("gdi32.dll", EntryPoint = "EnumFontFamiliesEx", CharSet = CharSet.Unicode)]
        public static extern int EnumFontFamiliesEx( IntPtr hDC, [In] LOGFONT logFont, EnumFontExDelegate enumFontExCallback,
             IntPtr lParam, uint dwFlags );

    }

其中EnumFontCallBack为回调函数,通过这个回调函数,可以获取到系统所有的字体,包括点阵的字体.



附录A:
GDI使用的结构和常量
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct ENUMLOGFONTEX
    {
        public LOGFONT elfLogFont;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string elfFullName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string elfStyle;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string elfScript;
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class LOGFONT
    {
        public int lfHeight;
        public int lfWidth;
        public int lfEscapement;
        public int lfOrientation;
        public FontWeight lfWeight;
        [MarshalAs(UnmanagedType.U1)]
        public bool lfItalic;
        [MarshalAs(UnmanagedType.U1)]
        public bool lfUnderline;
        [MarshalAs(UnmanagedType.U1)]
        public bool lfStrikeOut;
        public FontCharSet lfCharSet;
        public FontPrecision lfOutPrecision;
        public FontClipPrecision lfClipPrecision;
        public FontQuality lfQuality;
        public FontPitchAndFamily lfPitchAndFamily;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string lfFaceName;

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("LOGFONT\n");
            sb.AppendFormat("   lfHeight: {0}\n", lfHeight);
            sb.AppendFormat("   lfWidth: {0}\n", lfWidth);
            sb.AppendFormat("   lfEscapement: {0}\n", lfEscapement);
            sb.AppendFormat("   lfOrientation: {0}\n", lfOrientation);
            sb.AppendFormat("   lfWeight: {0}\n", lfWeight);
            sb.AppendFormat("   lfItalic: {0}\n", lfItalic);
            sb.AppendFormat("   lfUnderline: {0}\n", lfUnderline);
            sb.AppendFormat("   lfStrikeOut: {0}\n", lfStrikeOut);
            sb.AppendFormat("   lfCharSet: {0}\n", lfCharSet);
            sb.AppendFormat("   lfOutPrecision: {0}\n", lfOutPrecision);
            sb.AppendFormat("   lfClipPrecision: {0}\n", lfClipPrecision);
            sb.AppendFormat("   lfQuality: {0}\n", lfQuality);
            sb.AppendFormat("   lfPitchAndFamily: {0}\n", lfPitchAndFamily);
            sb.AppendFormat("   lfFaceName: {0}\n", lfFaceName);

            return sb.ToString();
        }
    }

    public enum FontWeight : int
    {
        FW_DONTCARE = 0,
        FW_THIN = 100,
        FW_EXTRALIGHT = 200,
        FW_LIGHT = 300,
        FW_NORMAL = 400,
        FW_MEDIUM = 500,
        FW_SEMIBOLD = 600,
        FW_BOLD = 700,
        FW_EXTRABOLD = 800,
        FW_HEAVY = 900,
    }
    public enum FontCharSet : byte
    {
        ANSI_CHARSET = 0,
        DEFAULT_CHARSET = 1,
        SYMBOL_CHARSET = 2,
        SHIFTJIS_CHARSET = 128,
        HANGEUL_CHARSET = 129,
        HANGUL_CHARSET = 129,
        GB2312_CHARSET = 134,
        CHINESEBIG5_CHARSET = 136,
        OEM_CHARSET = 255,
        JOHAB_CHARSET = 130,
        HEBREW_CHARSET = 177,
        ARABIC_CHARSET = 178,
        GREEK_CHARSET = 161,
        TURKISH_CHARSET = 162,
        VIETNAMESE_CHARSET = 163,
        THAI_CHARSET = 222,
        EASTEUROPE_CHARSET = 238,
        RUSSIAN_CHARSET = 204,
        MAC_CHARSET = 77,
        BALTIC_CHARSET = 186,
    }
    public enum FontPrecision : byte
    {
        OUT_DEFAULT_PRECIS = 0,
        OUT_STRING_PRECIS = 1,
        OUT_CHARACTER_PRECIS = 2,
        OUT_STROKE_PRECIS = 3,
        OUT_TT_PRECIS = 4,
        OUT_DEVICE_PRECIS = 5,
        OUT_RASTER_PRECIS = 6,
        OUT_TT_ONLY_PRECIS = 7,
        OUT_OUTLINE_PRECIS = 8,
        OUT_SCREEN_OUTLINE_PRECIS = 9,
        OUT_PS_ONLY_PRECIS = 10,
    }
    public enum FontClipPrecision : byte
    {
        CLIP_DEFAULT_PRECIS = 0,
        CLIP_CHARACTER_PRECIS = 1,
        CLIP_STROKE_PRECIS = 2,
        CLIP_MASK = 0xf,
        CLIP_LH_ANGLES = (1 << 4),
        CLIP_TT_ALWAYS = (2 << 4),
        CLIP_DFA_DISABLE = (4 << 4),
        CLIP_EMBEDDED = (8 << 4),
    }
    public enum FontQuality : byte
    {
        DEFAULT_QUALITY = 0,
        DRAFT_QUALITY = 1,
        PROOF_QUALITY = 2,
        NONANTIALIASED_QUALITY = 3,
        ANTIALIASED_QUALITY = 4,
        CLEARTYPE_QUALITY = 5,
        CLEARTYPE_NATURAL_QUALITY = 6,
    }
    [Flags]
    public enum FontPitchAndFamily : byte
    {
        DEFAULT_PITCH = 0,
        FIXED_PITCH = 1,
        VARIABLE_PITCH = 2,
        FF_DONTCARE = (0 << 4),
        FF_ROMAN = (1 << 4),
        FF_SWISS = (2 << 4),
        FF_MODERN = (3 << 4),
        FF_SCRIPT = (4 << 4),
        FF_DECORATIVE = (5 << 4),
    }

    /// <summary>
    /// Enumeration for the raster operations used in BitBlt.
    /// In C++ these are actually #define. But to use these
    /// constants with C#, a new enumeration type is defined.
    /// </summary>
    public enum TernaryRasterOperations
    {
        SRCCOPY = 0x00CC0020, /* dest = source                   */
        SRCPAINT = 0x00EE0086, /* dest = source OR dest           */
        SRCAND = 0x008800C6, /* dest = source AND dest          */
        SRCINVERT = 0x00660046, /* dest = source XOR dest          */
        SRCERASE = 0x00440328, /* dest = source AND (NOT dest )   */
        NOTSRCCOPY = 0x00330008, /* dest = (NOT source)             */
        NOTSRCERASE = 0x001100A6, /* dest = (NOT src) AND (NOT dest) */
        MERGECOPY = 0x00C000CA, /* dest = (source AND pattern)     */
        MERGEPAINT = 0x00BB0226, /* dest = (NOT source) OR dest     */
        PATCOPY = 0x00F00021, /* dest = pattern                  */
        PATPAINT = 0x00FB0A09, /* dest = DPSnoo                   */
        PATINVERT = 0x005A0049, /* dest = pattern XOR dest         */
        DSTINVERT = 0x00550009, /* dest = (NOT dest)               */
        BLACKNESS = 0x00000042, /* dest = BLACK                    */
        WHITENESS = 0x00FF0062, /* dest = WHITE                    */
    };

    [Flags]
    public enum dwDTFormat : int
    {
        DT_TOP = 0, DT_LEFT = 0x00000000, DT_CENTER = 0x00000001, DT_RIGHT = 0x00000002,
        DT_VCENTER = 0x00000004, DT_BOTTOM = 0x00000008, DT_WORDBREAK = 0x00000010, DT_SINGLELINE = 0x00000020,
        DT_EXPANDTABS = 0x00000040, DT_TABSTOP = 0x00000080, DT_NOCLIP = 0x00000100, DT_EXTERNALLEADING = 0x00000200,
        DT_CALCRECT = 0x00000400, DT_NOPREFIX = 0x00000800, DT_INTERNAL = 0x00001000
    };


    public struct Rect
    {
        public int Left, Top, Right, Bottom;
        public Rect(Rectangle r)
        {
            this.Left = r.Left;
            this.Top = r.Top;
            this.Bottom = r.Bottom;
            this.Right = r.Right;
        }
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct TEXTMETRIC
    {
        public Int32 tmHeight;
        public Int32 tmAscent;
        public Int32 tmDescent;
        public Int32 tmInternalLeading;
        public Int32 tmExternalLeading;
        public Int32 tmAveCharWidth;
        public Int32 tmMaxCharWidth;
        public Int32 tmWeight;
        public Int32 tmOverhang;
        public Int32 tmDigitizedAspectX;
        public Int32 tmDigitizedAspectY;
        public char tmFirstChar;
        public char tmLastChar;
        public char tmDefaultChar;
        public char tmBreakChar;
        public byte tmItalic;
        public byte tmUnderlined;
        public byte tmStruckOut;
        public byte tmPitchAndFamily;
        public byte tmCharSet;
    }

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2011-7-9 18:01:49 | 显示全部楼层
good ,正用上,请教一下如何用setdibits,
int SetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits,CONST BITMAPINFO *lpbmi, UINT fuColorUse);
BITMAPINFO 这个在C#里面不知道是用什么类型来代替

出0入0汤圆

 楼主| 发表于 2011-7-9 21:18:32 | 显示全部楼层
我对这个函数没用过
根据我的经验
[DllImport("gdi32.dll")]
static extern int SetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint
   cScanLines, byte [] lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse);

typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;
都是将这些结构换成C#形式的结构体就好了

typedef struct tagRGBQUAD {
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;

typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

出0入0汤圆

发表于 2011-7-11 08:47:08 | 显示全部楼层
学了C#三年多了 gdi方面一直没机会接触, 希望楼主能发个项目实例,学习起来比较直观

出0入0汤圆

发表于 2011-7-11 09:15:12 | 显示全部楼层
非常感谢!试试先

出0入0汤圆

发表于 2011-7-11 12:56:10 | 显示全部楼层
先MARK

出0入10汤圆

发表于 2022-9-28 16:47:28 | 显示全部楼层
MARK,后面学习一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 17:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表