Walter Kiess

Walter Kiess

  • NA
  • 53
  • 12.5k

Changing ColorDialog box window position

Mar 12 2012 11:57 PM
Hi All, 

I'm fairly new to C#. I am trying to set the ColorDialog's window start up position so that it shows next to the form it is being called from. Since there is no .Top or .Left property, I'm using some code I found on the web which creates a subclass (?) of the ColorDialog and hooks WM_INITDIALOG to set the Title. I modified this to add the X and Y coords for the startup position and the SetWindowPos API to set the windows position. It runs OK, except that no matter what I do, the ColorDialog always shows wherever the heck it wants to, not where I specify it should show.
I added some debugging code to allow me step through the code and see it pop up only to find that it DID show at the specified point only to be moved to the normal startup position once execution continued. 

This is the code I'm using:

    public class ColorDialogEx : ColorDialog
    {
        //This public class extends the Color Dialog to allow setting the 
        //window's title rather than just showing "Set Color".
        //Not sure exactly how it works other than it using the HookProc to
        //send a msg to the window to set the window's title. The description
        //given on-line was in German and not very explicit.
        //http://dotnet-snippets.de/dns/fenstertitel-im-colordialog-festlegen-SID562.aspx

        //Windows Message Constants
        private const Int32 WM_INITDIALOG = 0x0110;
        private const Int32 WM_SHOWWINDOW = 0x0018;
        private const Int32 WM_NEXTDLGCTL = 0x0028;
        private const Int32 WM_SETFONT = 0x0030;
        

        //uFlag Constants
        private const uint SWP_NOSIZE = 0x0001;
        private const uint SWP_SHOWWINDOW = 0x0040;
        private const uint SWP_NOZORDER = 0x0004;
        private const uint UFLAGS = SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW;

        //Windows Handle Constants
        static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
        static readonly IntPtr HWND_TOP = new IntPtr(0);
        static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

        //Module vars
        private int _x;
        private int _y;
        private string _Title;

        //WinAPI definitions
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern bool SetWindowText(IntPtr hWnd, string text);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

        //Our Overload. I added the X & Y coords, but they don't work...
        public ColorDialogEx(string Title, int X, int Y) : base()
        {
            _Title = Title;
            _x = X;
            _y = Y;
        }
        
        //Hook into Windows Messages
        protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
        {
            if (msg == WM_INITDIALOG) //Hook into Windows Message WM_INITDIALOG
            {
                SetWindowText(hWnd, _Title); //Set my own title
                bool a = SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, UFLAGS); //Executes fine, but dialogbox is Not moved
                //a = a; //using this line as a debugger breakpoint, I notice the window actually IS moved, but reverts to the wrong location when execution resumes
            }
            return base.HookProc(hWnd, msg, wparam, lparam);
        }

A colleague of mine tried a version in VB .NET and it worked fine for him, yet I can't make it work in C#. Can anyone help with this problem? Let me know if any other info is required.

Regards,
Walter

Answers (1)