Using ChooseColor through interop
-
Okay. I'm sure I'm missing something really simple, but I am thus far unable to get ChooseColor (exported from comdlg32.dll) to work. Before anyone suggests it, I know there's a ColorDialog control available. Using it is not an option, however, since the app I'm working on is for .Net CF. When calling the ChooseColor method, the runtime returns a really useful System.NotSupportedException. My code looks like the following:
//...DATA structure and method import public struct CHOOSECOLOR { public int Flags; public IntPtr hInstance; public IntPtr hwndOwner; public IntPtr lCustData; public IntPtr lpCustColors; public IntPtr lpfnHook; public string lpTemplateName; public int lStructSize; public int rgbResult; } [DllImport("comdlg32.dll")] internal static extern bool ChooseColor(ref CHOOSECOLOR pChooseColor); //...Method calling ChooseColor public void ShowColorDialog(Form parent) { if(parent != null) { CHOOSECOLOR color = new CHOOSECOLOR(); color.lStructSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CHOOSECOLOR)); color.hwndOwner = FindWindow(null, parent.Text); bool result = ChooseColor(ref color); } }
Any help is much appreciated.The most exciting phrase to hear in science, the one that heralds the most discoveries, is not 'Eureka!' ('I found it!') but 'That's funny...’
-
Okay. I'm sure I'm missing something really simple, but I am thus far unable to get ChooseColor (exported from comdlg32.dll) to work. Before anyone suggests it, I know there's a ColorDialog control available. Using it is not an option, however, since the app I'm working on is for .Net CF. When calling the ChooseColor method, the runtime returns a really useful System.NotSupportedException. My code looks like the following:
//...DATA structure and method import public struct CHOOSECOLOR { public int Flags; public IntPtr hInstance; public IntPtr hwndOwner; public IntPtr lCustData; public IntPtr lpCustColors; public IntPtr lpfnHook; public string lpTemplateName; public int lStructSize; public int rgbResult; } [DllImport("comdlg32.dll")] internal static extern bool ChooseColor(ref CHOOSECOLOR pChooseColor); //...Method calling ChooseColor public void ShowColorDialog(Form parent) { if(parent != null) { CHOOSECOLOR color = new CHOOSECOLOR(); color.lStructSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CHOOSECOLOR)); color.hwndOwner = FindWindow(null, parent.Text); bool result = ChooseColor(ref color); } }
Any help is much appreciated.The most exciting phrase to hear in science, the one that heralds the most discoveries, is not 'Eureka!' ('I found it!') but 'That's funny...’
The .NET CF Interop marshaler is a bit quirky. So here is the code that will do exactly what you want. Notice the use of LocalAlloc and LocalFree
[StructLayoutAttribute(LayoutKind.Sequential)] private class CHOOSECOLOR: IDisposable { private int lStructSize; internal IntPtr hwndOwner; private IntPtr hInstance; internal int rgbResult; internal IntPtr lpCustColors; internal uint Flags; private int lCustData = 0; private IntPtr lpfnHook; private IntPtr lpTemplateName; public CHOOSECOLOR() { lStructSize = Marshal.SizeOf(this); hwndOwner = IntPtr.Zero; hInstance = IntPtr.Zero; rgbResult = 16777215; lpCustColors = LocalAlloc(64, 64); Flags = 0; lCustData = 0; lpfnHook = IntPtr.Zero; lpTemplateName = IntPtr.Zero; } public virtual void Dispose() { LocalFree(lpCustColors); } } [DllImport("coredll.dll")] private static extern IntPtr LocalAlloc(int flags, int size); [DllImport("coredll.dll")] private static extern int LocalFree(IntPtr addr); [DllImport("comdlg.dll")] private static extern int ChooseColor(CHOOSECOLOR pChooseColor); [DllImport("comdlg.dll")] private static extern int CommDlgExtendedError(); private void ShowChooseColor(object sender, System.EventArgs e) { CHOOSECOLOR color = new CHOOSECOLOR(); int result = ChooseColor(color); if (result == 0) { MessageBox.Show("CommDlgExtendedError = " + CommDlgExtendedError().ToString()); } }
-
The .NET CF Interop marshaler is a bit quirky. So here is the code that will do exactly what you want. Notice the use of LocalAlloc and LocalFree
[StructLayoutAttribute(LayoutKind.Sequential)] private class CHOOSECOLOR: IDisposable { private int lStructSize; internal IntPtr hwndOwner; private IntPtr hInstance; internal int rgbResult; internal IntPtr lpCustColors; internal uint Flags; private int lCustData = 0; private IntPtr lpfnHook; private IntPtr lpTemplateName; public CHOOSECOLOR() { lStructSize = Marshal.SizeOf(this); hwndOwner = IntPtr.Zero; hInstance = IntPtr.Zero; rgbResult = 16777215; lpCustColors = LocalAlloc(64, 64); Flags = 0; lCustData = 0; lpfnHook = IntPtr.Zero; lpTemplateName = IntPtr.Zero; } public virtual void Dispose() { LocalFree(lpCustColors); } } [DllImport("coredll.dll")] private static extern IntPtr LocalAlloc(int flags, int size); [DllImport("coredll.dll")] private static extern int LocalFree(IntPtr addr); [DllImport("comdlg.dll")] private static extern int ChooseColor(CHOOSECOLOR pChooseColor); [DllImport("comdlg.dll")] private static extern int CommDlgExtendedError(); private void ShowChooseColor(object sender, System.EventArgs e) { CHOOSECOLOR color = new CHOOSECOLOR(); int result = ChooseColor(color); if (result == 0) { MessageBox.Show("CommDlgExtendedError = " + CommDlgExtendedError().ToString()); } }
Thanks a lot! I was starting to think about adding the mem allocation calls - there are murmurings about them in one or two places, but I wasn't able to find anything concrete until your posting. Is it just me, or does CE's usage of the API seem a little like alchemy? There seems to be very very little in the way of example on line. Perhaps there are some useful books out there... I don't come from a C(++) background, so I'm at a little bit of a disadvantage from the outset with structure conversion / API implementation, but in this case I think I had it right, and other "quirkiness" caused problems (my desktop example worked great). One note: The import for the common dialog library should read "commdlg.dll" - two "m"s. Thank you again. Jared
The most exciting phrase to hear in science, the one that heralds the most discoveries, is not 'Eureka!' ('I found it!') but 'That's funny...’