none
关于.net调用GDI中logFont,TextOut,GetPath等的问题 RRS feed

  • 问题

  •        

    1.上图是下面代码的输出,用GetPath函数获取的所有point的坐标都是0,这是为什么?

    2.还有logFont的lfEscapement和lfOrientation为900时为什么不能竖向输出?

    如果不用路径,直接在屏幕上输出的效果是这样的

    private void Form1_Paint(object sender, PaintEventArgs e)
            {
                LOGFONT logFont = new LOGFONT();
                logFont.lfHeight = 50;
                logFont.lfWidth = 30;
                logFont.lfEscapement =900;
                logFont.lfOrientation = 900;
                logFont.lfWeight = 30;
                logFont.lfFaceName = "Mongolian Writing";
                logFont.lfCharSet = 1;
                logFont.lfOutPrecision = 1;
                logFont.lfPitchAndFamily = 1;



                IntPtr dc = e.Graphics.GetHdc();
                Font f = Font.FromLogFont(logFont);
                IntPtr hdcFont = f.ToHfont();

                SelectObject(dc, hdcFont);
                string TextV =  "I want to print vertical text";
                SetROP2(dc, 5);
                SetBkMode(dc, 1);
                BeginPath(dc);
                TextOut(dc, 0, 0, TextV, TextV.Length);
                EndPath(dc);
                e.Graphics.ReleaseHdc();

                int nCount = GetPath(dc, null, null, 0);
                POINT[] ptPath = new POINT[nCount];
                byte[] b = new byte[nCount];

                
                string strPoints = "";
                for (int i = 0; i < nCount; i++)
                {
                    strPoints += ptPath[i].ToString();
                    strPoints += "\n";
                }
                e.Graphics.DrawString(strPoints, Font, Brushes.Black, new PointF(100.0f, 0.0f));
            }

    2012年3月13日 15:57

答案

  • 我们先解决第一个问题,就是输出为什么是0的问题。 根据MSDN 文档说明,如果GetPath的最后一个参数为0的话,返回值为 Point的个数,如果是非零的话,返回的是Point 的 所有枚举,包含着point的X和Y。如果是非零并且小于path中point的个数的话,返回为1.其它为-1,表示调用异常或失败。

    以下是英文说明: 连接参考: http://msdn.microsoft.com/zh-cn/library/dd144908(v=VS.85).aspx 

    Return value

    If the nSize parameter is nonzero, the return value is the number of points enumerated. If nSize is 0, the return value is the total number of points in the path (and GetPath writes nothing to the buffers). If nSize is nonzero and is less than the number of points in the path, the return value is 1.

    然后我修改了一些代码,输出的已经不是0了。

    供你参考:

     int nCount = GetPath(dc,null, null, 0);
                POINT[] ptPath = new POINT[nCount];
                byte[] b = new byte[nCount];
                int nc = GetPath(dc, ptPath, b, nCount);//因为不知道个数,所以我调用了2次,第一次获得个数,第二次得到枚举值。
    
                string strPoints = "";
                for (int i = 0; i < nc; i++)
                {
                    strPoints += ptPath[i].ToString();
                    strPoints += "\n";
                }

    希望对您有所帮助。

    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us

    2012年3月15日 2:32
    版主

全部回复

  • 完整代码

                            

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;


    namespace GDIText
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }



            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public class LOGFONT
            {
                public int lfHeight = 0;
                public int lfWidth = 0;
                public int lfEscapement = 0;
                public int lfOrientation = 0;
                public int lfWeight = 0;
                public byte lfItalic = 0;
                public byte lfUnderline = 0;
                public byte lfStrikeOut = 0;
                public byte lfCharSet = 0;
                public byte lfOutPrecision = 0;
                public byte lfClipPrecision = 0;
                public byte lfQuality = 0;
                public byte lfPitchAndFamily = 0;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
                public string lfFaceName = string.Empty;
            }
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int X;
                public int Y;


                public POINT(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }


                public static implicit operator System.Drawing.Point(POINT p)
                {
                    return new System.Drawing.Point(p.X, p.Y);
                }


                public static implicit operator POINT(System.Drawing.Point p)
                {
                    return new POINT(p.X, p.Y);
                }
                public override string ToString()
                {
                    //string s0
                    return "X=" +this.X.ToString() + ",Y=" + this.Y.ToString();
                }
            }
            [DllImport("gdi32.dll")]
            static public extern IntPtr CreateCompatibleDC(IntPtr hDC);
            [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
            public static extern bool BitBlt(IntPtr hdcDest, int nXDest,
             int nYDest, int nWidth, int nHeight, IntPtr hdcSrc,
             int nXSrc, int nYSrc, int dwRop);
            [DllImport("user32.dll", EntryPoint = "GetDC")]
            public static extern IntPtr GetDC(IntPtr hWnd);
            [DllImport("gdi32.dll")]
            static extern bool BeginPath(IntPtr hdc);
            [DllImport("gdi32.dll")]
            static extern bool EndPath(IntPtr hdc);
            [DllImport("gdi32.dll")]
            private static extern IntPtr SetROP2(IntPtr hdc, int fnDrawMode);
            [DllImport("gdi32.dll")]
            private static extern IntPtr SetBkMode(IntPtr hdc, int nBkMode);
            [DllImport("gdi32.dll")]
            static public extern bool DeleteObject(IntPtr hObject);
            [DllImport("gdi32.dll")]
            static public extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
            [DllImport("gdi32.dll")]
            static public extern IntPtr DeleteDC(IntPtr hDC);
            [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
            static extern bool TextOut(IntPtr hdc, int nXStart, int nYStart,
               string lpString, int cbString);
            [DllImport("gdi32.dll")]
            static extern int GetPath(IntPtr hdc, [Out] POINT[] lpPoints,
               [Out] byte[] lpTypes, int nSize);






            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                LOGFONT logFont = new LOGFONT();
                logFont.lfHeight = 20;
                logFont.lfWidth = 1;
                logFont.lfEscapement =900;
                logFont.lfOrientation = 900;
                logFont.lfWeight = 30;


                logFont.lfFaceName = "Mongolian Writing";
                logFont.lfCharSet = 1;
                logFont.lfOutPrecision = 1;
                logFont.lfPitchAndFamily = 1;

                IntPtr dc = e.Graphics.GetHdc();
                //SelectObject(dc, dcBmp);
                Font f = Font.FromLogFont(logFont);
                IntPtr hdcFont = f.ToHfont();


                SelectObject(dc, hdcFont);
                string TextV = "I want to print vertical text";
                SetROP2(dc, 5);
                SetBkMode(dc, 1);
                BeginPath(dc);
                TextOut(dc, 0, 0, TextV, TextV.Length);
                EndPath(dc);
                e.Graphics.ReleaseHdc();

                int nCount = GetPath(dc, null, null, 0);
                POINT[] ptPath = new POINT[nCount];
                byte[] b = new byte[nCount];

                string strPoints = "";
                for (int i = 0; i < nCount; i++)
                {
                    strPoints += ptPath[i].ToString();
                    strPoints += "\n";
                }

            }


            private void Form1_Load(object sender, EventArgs e)
            {


            }
        }
    }

    2012年3月14日 15:04
  •        最后少了一行输出的代码

    e.Graphics.DrawString(strPoints, Font, Brushes.Black, new PointF(100.0f, 0.0f));

    2012年3月14日 15:06
  • 我们先解决第一个问题,就是输出为什么是0的问题。 根据MSDN 文档说明,如果GetPath的最后一个参数为0的话,返回值为 Point的个数,如果是非零的话,返回的是Point 的 所有枚举,包含着point的X和Y。如果是非零并且小于path中point的个数的话,返回为1.其它为-1,表示调用异常或失败。

    以下是英文说明: 连接参考: http://msdn.microsoft.com/zh-cn/library/dd144908(v=VS.85).aspx 

    Return value

    If the nSize parameter is nonzero, the return value is the number of points enumerated. If nSize is 0, the return value is the total number of points in the path (and GetPath writes nothing to the buffers). If nSize is nonzero and is less than the number of points in the path, the return value is 1.

    然后我修改了一些代码,输出的已经不是0了。

    供你参考:

     int nCount = GetPath(dc,null, null, 0);
                POINT[] ptPath = new POINT[nCount];
                byte[] b = new byte[nCount];
                int nc = GetPath(dc, ptPath, b, nCount);//因为不知道个数,所以我调用了2次,第一次获得个数,第二次得到枚举值。
    
                string strPoints = "";
                for (int i = 0; i < nc; i++)
                {
                    strPoints += ptPath[i].ToString();
                    strPoints += "\n";
                }

    希望对您有所帮助。

    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us

    2012年3月15日 2:32
    版主
  • 就第二个问题,我发现您的另外一个post, 我们会在那里讨论这个问题:

    http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/5d3bf04d-e743-4e48-a021-4b633e203ab7/#e9748058-1307-4cb0-9437-b381545ab8f1 

    另外,根据我的经验,往往直接输出字体的话,好像是不可以翻转的。一般都是通过写画一个bitmap 或者其它图片格式的,然后再图片上处理翻转。


    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us

    2012年3月15日 3:15
    版主
  • 谢谢,我注意到忘记了第二次的GetPath调用。
    2012年3月17日 1:52