我碰到两个麻烦:
1.先建个Console Application,定义了数据结构后
        public struct MSGBOXPARAMS
        {
            public uint cbSize;
            public IntPtr hwndOwner;
            public IntPtr hInstance;
            public string lpszText;
            public string lpszCaption;
            public uint dwStyle;
            public string lpszIcon;
            public int dwContextHelpId;
            public string  lpfnMsgBoxCallback;
            public uint dwLanguageId;
        };
 MSGBOXPARAMS MsgBp = new MSGBOXPARAMS();
 MsgBp.cbSize = (uint)sizeof(MSGBOXPARAMS);//因为没赋初值所以sizeof出错,其他语言怎么就行了.若有初值这个后也可能改变初值啊!
2.MsgBp.lpszIcon//指像Icon资源的指针,这个指针是string类型,我还是不会玩.

解决方案 »

  1.   

    第一个问题是你能用sizeof能获取MSGBOXPARAMS大小?不可能吧
    cbSize的大小是为以后扩展用的 public struct HelpInfo
        {
        }
        public delegate void MsgboxCallback(HelpInfo helpInfo);    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
        public struct MsgboxParams
        {
            public  int cbSize;
            public  IntPtr hwndOwner;
            public  IntPtr hInstance;
            public  string text;
            public  string caption;
            public  int style;
            public  string icon;
            public  int helpId;
            public  IntPtr callback;
            public  int languageId;
        }
        class Program
        {
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern int MessageBoxIndirect(ref MsgboxParams param);        [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr LoadIcon(IntPtr hInstance, string iconName);        static void Main(string[] args)
            {
                MsgboxParams mp=new MsgboxParams();
               
                mp.hwndOwner = IntPtr.Zero;
                mp.hInstance = IntPtr.Zero;
                mp.text = "ok";
                mp.caption = "ti xing";
                mp.style = 0;
                mp.icon = "32512";
                mp.helpId = 0;
                mp.callback = IntPtr.Zero;
                mp.languageId = 0;
                mp.cbSize = Marshal.SizeOf(mp);            MessageBoxIndirect(ref mp);
            }
        }
      

  2.   

    因为你的结构里面有不能确定的长度类型,string.所以你这时是没有办法直接使用sizeof的,其他语言可以那是因为指定了string的长度,一般是char,例如C++。
      

  3.   

    对第一个问题的标准答案是:
    MsgBp.cbSize = Marshal.Sizeof(MsgBp);
      

  4.   

    忘记说前提了:前提是你的这个MsgParams结构必须Marshal正确哦,如果不正确的话不会导致调用Marshal.SizeOf的失败,但你的这个函数仍然无法调用。
      

  5.   

    HOHO,尝试成功弹出了窗口。至于其它参数的调整,则需要另外再慢慢来了,图标似乎是对程序资源的一个名称引用。应用程序往往会有一个这样的资源表,需要添加资源,编译进程序,然后使用。不过有些麻烦,以后再尝试。
    这个是相关的类:using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;namespace HWin32
    {
        public static class User
        {        [StructLayout(LayoutKind.Sequential)]
            public struct HELPINFO
            {
                public uint cbSize;
                public int iContextType;
                public int iCtrlId;
                public IntPtr hItemHandle;
                public IntPtr dwContextId;
                public HPoint MousePos;
            }
            [StructLayout(LayoutKind.Sequential)]
            public struct MSGBOXPARAMS
            {
                public uint cbSize;
                public IntPtr hwndOwner;
                public IntPtr hInstance;
                public String lpszText;
                public String lpszCaption;
                public uint dwStyle;
                public IntPtr lpszIcon;
                public IntPtr dwContextHelpId;
                public MsgBoxCallback lpfnMsgBoxCallback;
                public uint dwLanguageId;
            }        public delegate void MsgBoxCallback(HELPINFO lpHelpInfo);
            [DllImport("User32.dll")]
            public static extern int MessageBoxIndirect([In] ref MSGBOXPARAMS lpMsgBoxParams);
        }
    }这里是调用代码:            User.MSGBOXPARAMS mp = new User.MSGBOXPARAMS();
                mp.cbSize = (uint)Marshal.SizeOf(mp);
                mp.lpszText = "what?";
                mp.lpszCaption = "nonono";            User.MessageBoxIndirect(ref mp);
    OK.
      

  6.   

      真厉害!不过mp.icon = "32512";在C++的winuser.h中定义为IDI_APPLICATION:32512这样的东西.应该是在wingdi.h中定义了IDI_APPLICATION是什么样的图标.
      在C#中,ICON位置一片空白.
      

  7.   

    lpfnMsgBoxCallback我在书上看到lp是指针的意思,lp--->在C#不是对应String吗?
            public delegate void MsgBoxCallback(HELPINFO lpHelpInfo);这样也行啊?
    我的结构是
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct MSGBOXPARAMS
            {
                public uint cbSize;
                public IntPtr hwndOwner;
                public IntPtr hInstance;
                public string lpszText;
                public string lpszCaption;
                public uint dwStyle;
                public string lpszIcon;
                public int dwContextHelpId;
                public string  lpfnMsgBoxCallback;
                public uint dwLanguageId;
            };
      

  8.   

    lp:long point,长指针。可以指向进程地址空间的任何地方。
    lpsz一般是指字符串。sz的意思可能是指string Zero吧?这点我不太确定,隐约记得在哪里看到过,是说以\0结尾的字符串。
      

  9.   

    C++我不太熟悉,在我能够理解的范围内它的方法是:定义资源的名称(IDI_APPLICATION)、编号(32512),在你需要用到时资源的地方使用这两个大部分都可以得到你所需要的资源句柄,实际也就是资源的指针。这个搞起来似乎有些麻烦。
      

  10.   

    我用一个kakaxi.ico制作了一个资源文件.
    ResourceManager rm = new ResourceManager("API版MessageBox.myIconRes", Assembly.GetExecutingAssembly());MsgBp.lpszIcon = (Image)rm.GetObject("Pake");现在的问题就是这个指针--->图片
    怎么办啊?
      

  11.   

    我用一个kakaxi.ico制作了一个资源文件.
    ResourceManager rm = new ResourceManager("API版MessageBox.myIconRes", Assembly.GetExecutingAssembly());MsgBp.lpszIcon = (Image)rm.GetObject("Pake");现在的问题就是这个指针--->图片
    怎么办啊?
      

  12.   

    似乎无法使用这种方法取得资源。我没有找到合适的方法,在.NET程序的进程空间中,甚至没有Windows系统默认的图标资源存在。
    比如有一种方法:
    LoadIcon(hInstance,strIconName);
    这个方法如果第一个参数为NULL,后一个参数为系统定义的一个图标名称,比如:IDI_ERR,应该返回那个熟悉的错误图标的句柄。
    这个函数在其它VC++的程序中都可以正常运行,但在.NET的程序中执行是地总是返回了0。如果要使用,我目前能够想得到的办法是:
    1:使用其它API把Win32的资源文件模块加载到进程中,取得这个模块的句柄。
    2:用1得到的句柄和资源名称调用LoadIcon返回一个IntPtr。
    3:用这个IntPtr调用msg。不过我觉得这个方法纯属多余,为什么要这样使用呢?
    MessageBox.Show().就完成了所有的工作。为啥要这么麻烦。
      

  13.   

    再帮我一把我全贴出来一起研究下.using System;
    using System.Runtime.InteropServices;//API要用的
    using System.Resources;//使用资源文件要用的
    using System.Reflection;//Assembly类装这里面
    using System.Drawing;namespace API版MessageBox
    {
        class Program
        {       
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct MSGBOXPARAMS
            {
                public uint cbSize;
                public IntPtr hwndOwner;
                public IntPtr hInstance;
                public string lpszText;  //匈牙利命名法lpsz==long point string Zero
                public string lpszCaption;
                public uint dwStyle;
                public Icon lpszIcon;
                public int dwContextHelpId;
                public string  lpfnMsgBoxCallback;
                public uint dwLanguageId;
            };
           
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
            internal static extern void MessageBoxIndirect(ref MSGBOXPARAMS MsgBp);//自己设定参数
            internal const int MB_YESNO = 0x00000004;
            internal const int MB_USERICON = 0x00000080;
            static int Main()
            {
                ResourceManager rm = new ResourceManager("API版MessageBox.myIconRes", Assembly.GetExecutingAssembly());
                MSGBOXPARAMS MsgBp = new MSGBOXPARAMS();
                MsgBp.hInstance = IntPtr.Zero;//不能直接写0(int 不能转化为IntPtr),更不能写null
                MsgBp.hwndOwner = IntPtr.Zero;
                MsgBp.lpszText = "一定要成功啊MessageBoxIndirect我的ICON";
                MsgBp.lpszCaption = "Hi";
                MsgBp.dwStyle = MB_USERICON | MB_YESNO;
                MsgBp.lpszIcon =(Icon)rm.GetObject("Pake");
                MsgBp.dwContextHelpId = 0;
                MsgBp.lpfnMsgBoxCallback = null;
                MsgBp.dwLanguageId = SUBLANG_ENGLISH_US;
                MsgBp.cbSize = (uint)Marshal.SizeOf(MsgBp);
                MessageBoxIndirect(ref MsgBp);
                return 0;
            }
        }
    }问题一:MsgBp.lpszIcon =(Icon)rm.GetObject("Pake");查API函数手册上lpszIcon是个指向资源文件Icon的指针,而我记得API指针应该对应C#里的string,但是string怎么能做ICON用呢?
    问题二:还是那行报错Unable to cast object of type 'System.Drawing.Bitmap' to type 'System.Drawing.Icon.执行后ICON根本就没有显示.还有就是我把ICON改成Image能运行但是执行后ICON根本就没有显示制作资源文件也有点麻烦.我找了张KaKaxi.icousing System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Resources;namespace 把忍犬帕克做成资源文件
    {
        class Program
        {
            static void Main(string[] args)
            {//把KaKaxi.ico先拖入该.\Bin\Debug\下运行会生成一个资源文件
                ResourceWriter rw = new ResourceWriter("myIconRes.resources");//将资源文件存入PaKe.resources文件中
                Image Img = Image.FromFile("KaKaxi.ico");
               rw.AddResource("Pake",Img);             
               rw.Generate(); //以系统默认的format保存所有的资源
                rw.Close();
            }
        }
    }问题三:本来我想把这行Image Img = Image.FromFile("KaKaxi.ico");改成Icon myIcon=Icon.From(****);//可是Icon只有From句柄没有FromFile.所以上面用(Icon)会报错,我左右为难啊?
      

  14.   


        public struct HelpInfo
        {
        }
        public delegate void MsgboxCallback(HelpInfo helpInfo);    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct MsgboxParams
        {
            public int cbSize;
            public IntPtr hwndOwner;
            public IntPtr hInstance;
            public string text;
            public string caption;
            public int style;
            public IntPtr icon;
            public int helpId;
            public MsgboxCallback callback;
            public int languageId;
        }
        class Program
        {
            [DllImport("user32.dll", CharSet = CharSet.Ansi)]
            public static extern int MessageBoxIndirect(ref MsgboxParams param);        [DllImport("user32.dll", CharSet = CharSet.Ansi)]
            public static extern IntPtr LoadIcon(IntPtr hInstance, string iconName);        static void Main(string[] args)
            {
                MsgboxParams mp = new MsgboxParams();
                mp.hwndOwner = IntPtr.Zero;
                mp.hInstance = IntPtr.Zero;
                mp.text = "ok";
                mp.caption = "ti xing";
                mp.style = (int)0x00000080L;
                mp.icon = (IntPtr)32512;
                mp.helpId = 0;
                mp.callback = null;
                mp.languageId = 0;
                mp.cbSize = Marshal.SizeOf(mp);
                MessageBoxIndirect(ref mp);
            }
        }这样的话就可以用系统定义的图标了
      

  15.   

    你的方法在我看来应该都没意义。
    问题一:MsgBp.lpszIcon =(Icon)rm.GetObject("Pake");查API函数手册上lpszIcon是个指向资源文件Icon的指针,而我记得API指针应该对应C#里的string,但是string怎么能做ICON用呢? 
    1:指针怎么可能对应string?严格的说指针只能用IntPtr.但是在C#中指针是没有任何意义的(你除了显示出这个指针的实际整数值、传递给其它的非托管函数之外,但这不在C#的托管代码中执行)没有意义。你之所以认为string=指针是因为在C/C++中字符串是字符数组,往往是用指针(char *)表示的,所以你就这样觉得。
    在这个所谓的Icon的指针,应该是指向内在中某个表示Icon的内存块的指针(也有可能是指向一个handle,其中包含了指向最终Icon数据的指针),而绝不是什么string.
    问题二:还是那行报错Unable to cast object of type 'System.Drawing.Bitmap' to type 'System.Drawing.Icon.执行后ICON根本就没有显示.还有就是我把ICON改成Image能运行但是执行后ICON根本就没有显示 
    没错,因为你传递的东西根本就是两码事,一个是托管资源,一个是非托管的。即使你传递过去又有什么意义?
    问题三:本来我想把这行Image Img = Image.FromFile("KaKaxi.ico");改成Icon myIcon=Icon.From(****);//可是Icon只有From句柄没有FromFile.所以上面用(Icon)会报错,我左右为难啊?这个方法也和上面的一样在。我查找过了,问题的关键我在上面的帖子就说过了,就是这个非托管的图标指针在C#中无法取得。在C#中可以调用LoadLibrary这个API函数,但这个函数的第一个参数我不知道应该如何取得。
      

  16.   


    你说的很对 MspBp.lpszIcon 是个句柄并且
    托管创建的ICON 的技术 Icon icon=new Icon("myfileICon");
    icon.Handle 获取句柄
    但是我们传进去后 不会得到显示
    因为 我们的hInstance 没法设置
      

  17.   

    icon是资源ID!也可以是资源名称。要用ID,强制类型转化成lpctstr就可以了。
    hinstance是包含此资源的实例。
    MessageBoxIndirect从hinstance中加载icon,参见LoadIcon。
    如果要使用系统图标,就把hinstance设为0.