.NET CF C# 调用颜色选择对话框


.NET 环境下是有ColorDialog选择框的,但是到了.NET CF下却没了,即使是.NET CF 3.5也是没有。本想自己写个ColorDialog的,这也不是什么困难的事情,可突然间又发现了ChooseColor这个函数,参考了OpenNETCF,于是自己就实现了它。实现并不难,难的主要是参数的设置和转换,不过细细看下也就明白了!

一:函数原型:

BOOL ChooseColor(LPCHOOSECOLOR lpcc);

返回值:

如果点了选择框的OK按钮,则返回值为非0. CHOOSECOLOR结构的rgbResult返回用户选择的颜色的RGB值。

如果用户取消或关闭选择框或出现错误,返回值为0

    如果想获得扩展的错误信息,可以调用CommDlgExtendedError函数,原型为:DWORD CommDlgExtendedError()

 

二:调用参数

这里需要提到ChooseColor 函数的参数CHOOSECOLOR ,原型如下:

typedef struct tagCHOOSECOLOR {
    DWORD          lStructSize;
    HWND           hwndOwner;
    HINSTANCE      hInstance;
    COLORREF       rgbResult;
    COLORREF*      lpCustColors;
    DWORD          Flags;
    LPARAM         lCustData;
    LPCCHOOKPROC   lpfnHook;
    LPCTSTR        lpTemplateName;
} CHOOSECOLOR, *LPCHOOSECOLOR;

// P/Invoke
[DllImport("commdlg.dll", EntryPoint = "ChooseColor")]
public static extern bool CreateColorDialog(CHOOSECOLOR chooseColor);


    最初在设置这些参数的时候可真是费了一番周折。在用
C++进行开发的时候,这个参数还是很好设置的,可以参考http://blog.csdn.net/wellwelcome/archive/2007/04/17/1567767.aspx,可是在.NET CF C#下转换就不是那么简单了,颇费一番周折才搞定,如下:

[StructLayout(LayoutKind.Sequential)]
public class CHOOSECOLOR
{
    private int lStructSize;
    internal IntPtr hwndOwner; // 依托窗口
    private IntPtr hInstance;
    internal int rgbResult; // 通过该值获得选择的颜色值
    internal IntPtr lpCustColors; // 用户自己定义的颜色,也就是现实在颜色框下方的两排
    internal uint Flags; // 选择框的类型
    private int lCustData;
    private IntPtr lpfnHook;
    private IntPtr lpTemplateName;
    public CHOOSECOLOR()
    {
        this.lStructSize = Marshal.SizeOf(this);
        this.hwndOwner = IntPtr.Zero;
        this.hInstance = IntPtr.Zero;
        this.rgbResult = 0xffffff;
        this.lpCustColors = IntPtr.Zero;
        this.Flags = 0;
        this.lCustData = 0;
        this.lpfnHook = IntPtr.Zero;
        this.lpTemplateName = IntPtr.Zero;
    }
}

[Flags]
public enum ColorFlags : uint
{
    AnyColor = 0x100,
    FullOpen = 2,
    PreventFullOpen = 4,
    RgbInit = 1,
    SolidColor = 0x80
}

     其实最主要只要关心四个参数hwndOwner rgbResult lpCustColors Flags。上面的代码已经做了详细解释。

   
    
这里要特别说明一按下lpCustColors参数的设置,MSDN上说要必须要给它分配一个数组大小为16DWORD(C#uint, 不过此处指定为int)静态数组,然后把该指针赋值给它。“静态”,我用红字标识了是说明它的全局固定性,因此这里就不得不提到GCHandle类型了。

以下为
MSDN上的内容:

-------------------
GCHandle:

提供从非托管内存访问托管对象的方法。

GCHandle 类与 GCHandleType 枚举结合使用以创建对应于任何托管对象的句柄。此句柄可为以下四种类型之一:WeakWeakTrackResurrectionNormal Pinned。分配了句柄以后,在非托管客户端保留唯一的引用时,可以使用 GCHandle 防止垃圾回收器回收托管对象。如果没有这样的句柄,则在该对象代表非托管客户端完成工作以前,有可能被垃圾回收器回收。

还可以使用 GCHandle 创建一个固定对象,该对象返回一个内存地址,并防止垃圾回收器在内存中移动该对象。

-------------------

    看完上面的描述相信您也就知道为什么我要提到静态和GCHandle了,也相信您也知道该怎么做了

    还有,因为GCHandle的静态全局性,所以在动态申请并且使用完该对象后一定要记得Free掉,否则那就是大罪过了。

int[] rawCustom = new int[0x10];
// 申请一段内存,提供从非托管内存访问托管对象的方法,防止垃圾回收器回收托管对象;
// 如果没有这样的句柄,则在该对象代表非托管客户端完成工作以前,有可能被垃圾回收器回收
// 这里强调静态性
GCHandle custHandle = GCHandle.Alloc(rawCustom, GCHandleType.Pinned);

// Do something

// 记得一定要释放!
custHandle.Free();

 

    上面的叙述相信已经很清楚,剩下的就只有调用了,如下:
ColorDialog.CHOOSECOLOR chsColor = new ColorDialog.CHOOSECOLOR();
// 设置依托窗口
chsColor.hwndOwner = ColorDialog.GetActiveWindow();
// 设置Dialog类型
chsColor.Flags = ColorDialog.ColorFlags.AnyColor;
// 定制的颜色值(当然您也可以通过custHandle[index] = Color.FromArgb的方式对每个对象赋值)
chsColor.lpCustColors = custHandle.AddrOfPinnedObject();
// 这里有一点要说明, 如果点击'OK',则进入if内;否则如果点击'X'则不会进入if语句内
if (ColorDialog.CreateColorDialog(chsColor))
{
    // 获得颜色值
    this.BackColor = FromWin32(chsColor.rgbResult);
    string strShow = string.Format("0x{0:X8}", chsColor.rgbResult);
    System.Diagnostics.Debug.WriteLine(strShow);

    this.Invalidate();
}

 

-------------------

好了,大功告成!看到那么熟悉的界面是不是有一点小小的开心呢? 呵呵,下面附有下载,代码里有详尽的说明,试试吧!

图示:
  






-------------------
代码下载:











 
 
 
 

--------------------------------------------------

李森 – listen
E-mail:  lisencool@gmail.com

声明:
这里集中了在WinCEWindows Mobile开发中的一些基本常识。我很乐意和大家分享,也希望大家提出意见,并给我投稿,我会第一时间替您发表并署上您的大名!

Announce:
Here collects general knowledge on WinCE and Windows mobile. I 'm very glad to share them with all friends, and also hope you can share your problems and opinions and contribute articles to me to share with others. I'll publish your articles and sign your name at the first time.

  

posted on 2009-09-10 10:29  listenlisten  阅读(3492)  评论(5编辑  收藏  举报

导航