打开windows的调色板,当然是只能在windows平台上用哈。
其实就是调用comdlg32.dll中的ChooseColor方法,网上也有相关文章,但是试了都打不开,参数封送有点问题,于是自己试验出了正确的方法,记录分享一下。
这里我们直接使用宽字符版本。
先定义传入结构体,这个和c++上定义是对应的:
[StructLayout(LayoutKind.Sequential)]
public struct CHOOSECOLORW
{
public Int32 lStructSize;
public IntPtr hwndOwner;
public IntPtr hInstance;
public Int32 rgbResult;
public IntPtr lpCustColors;
public Int32 Flags;
public long lCustData;
public UIntPtr lpfnHook;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpTemplateName;
}
然后声明方法:
#if UNITY_STANDALONE || UNITY_EDITOR
[DllImport("comdlg32.dll", CharSet = CharSet.Unicode)]
private extern static bool ChooseColorW(ref CHOOSECOLORW pChoosecolor);
[DllImport("comdlg32.dll")]
private extern static int CommDlgExtendedError();
#else
private static bool ChooseColorW(ref CHOOSECOLORW pChoosecolor){return false;}
private static int CommDlgExtendedError(){return 0;}
#endif
第二个方法是用来看错误信息的,如果ChooseColorW返回false,可以调用它来看错误码,错误码含义在msdn上可以查,不要也没关系。
最后是调用打开并获取颜色:
public void OpenColorPicker()
{
CHOOSECOLORW cc = new CHOOSECOLORW();
cc.lStructSize = Marshal.SizeOf(cc);
cc.hwndOwner = IntPtr.Zero;
cc.lpCustColors = Marshal.AllocHGlobal(16 * 4);
cc.rgbResult = 0;
cc.Flags = 0x00000002 | 0x00000001;
var s = ChooseColorW(ref cc);
Marshal.FreeHGlobal(cc.lpCustColors);
if (s)
{
var a = cc.rgbResult;//获取int型颜色值 rgba由这个值组成
var color = (Color)DrawColor.Value;//这里自己定义一个Color变量后面来保存数据,我这是其它业务中的
color.b = ((a & 0xFF0000) >> 16) / 255f;
color.g = ((a & 0x00FF00) >> 8) / 255f;
color.r = ((a & 0x0000FF)) / 255f;
DrawColor.Value = color;//这里自己定义一个Color变量后面来保存数据,我这是其它业务中的
}
else
{
string msg="unknown";
switch (CommDlgExtendedError())
{
case 0x0001:
msg = "CDERR_STRUCTSIZE";
break;
default:
break;
}
Debug.LogFormat("ChooseColor error:{0}", msg);
}
}
好了,上个效果图: