예제 #1
0
        private void ResizeCustomControl(IntPtr hWnd, InteropUtil.RECT rect, params IntPtr[] buttons)
        {
            Util.Assume(buttons != null && buttons.Length > 0);

            hWnd.AssumeNonZero();

            var wndLoc = hWnd.GetWindowPlacement();

            wndLoc.Right = rect.right;
            hWnd.SetWindowPlacement(ref wndLoc);

            foreach (var hBtn in buttons)
            {
                int btnRight, btnWidth;

                m_calcPosMap[hBtn.GetDlgCtrlID()](this, rect.right, out btnRight, out btnWidth);

                PositionButton(hBtn, btnRight, btnWidth);
            }

            //see bug # 844
            //We clip hWnd to only draw in the rectangle around our custom buttons.
            //When we supply a custom dialog template to GetOpenFileName(), it adds
            //an extra HWND to the open file dialog, and then sticks all the controls
            //in the dialog //template inside the HWND. It then resizes the control
            //to stretch from the top of the open file dialog to the bottom of the
            //window, extending the bottom of the window large enough to include the
            //additional height of the dialog template. This ends up sticking our custom
            //buttons at the bottom of the window, which is what we want.
            //
            //However, the fact that the parent window extends from the top of the open
            //file dialog was causing some painting problems on Windows XP SP 3 systems.
            //Basically, because the window was covering the predefined controls on the
            //open file dialog, they were not getting painted. This results in a blank
            //window. I tried setting an extended WS_EX_TRANSPARENT style on the dialog,
            //but that didn't help.
            //
            //So, to fix the problem I setup a window region for the synthetic HWND.
            //This clips the drawing of the window to only within the region containing
            //the custom buttons, and thus avoids the problem.
            //
            //I'm not sure why this wasn't an issue on Vista.
            var hRgn = InteropUtil.CreateRectRgnIndirect(ref rect);

            try
            {
                if (hWnd.SetWindowRgn(hRgn, true) == 0)
                {
                    //setting the region failed, so we need to delete the region we created above.
                    hRgn.DeleteObject();
                }
            }
            catch
            {
                if (hRgn != IntPtr.Zero)
                {
                    hRgn.DeleteObject();
                }
            }
        }
예제 #2
0
        private int DefViewSubClass
        (
            IntPtr hWnd,
            uint uMsg,
            IntPtr wParam,
            IntPtr lParam,
            IntPtr uIdSubclass,
            uint dwRefData
        )
        {
            if (uMsg == InteropUtil.WM_NOTIFY)
            {
                var header = (InteropUtil.NMHDR)Marshal.PtrToStructure(lParam, typeof(InteropUtil.NMHDR));
                if (header.code == InteropUtil.LVN_ITEMCHANGED && header.hwndFrom != IntPtr.Zero && header.idFrom == 1)
                {
                    var nmListView  = (InteropUtil.NMLISTVIEW)Marshal.PtrToStructure(lParam, typeof(InteropUtil.NMLISTVIEW));
                    var oldSelected = (nmListView.uOldState & InteropUtil.LVIS_SELECTED) != 0;
                    var newSelected = (nmListView.uNewState & InteropUtil.LVIS_SELECTED) != 0;
                    if (!oldSelected && newSelected)
                    {
                        if (!m_suppressSelectionChange)
                        {
                            //the item went from not selected to being selected
                            //so we want to look and see if the selected item is a folder, and if so
                            //change the text of the item box to be the item on the folder. But, before we do that
                            //we want to make sure that the box isn't currently focused.
                            var hParent    = hWnd.GetParent();
                            var hFNCombo   = hParent.GetDlgItem(InteropUtil.ID_FileNameCombo);
                            var hFNEditBox = hParent.GetDlgItem(InteropUtil.ID_FileNameTextBox);
                            var hFocus     = InteropUtil.GetFocus();

                            if
                            (
                                (hFNCombo == IntPtr.Zero || hFNCombo != hFocus) &&
                                (hFNEditBox == IntPtr.Zero || hFNEditBox != hFocus)
                            )
                            {
                                SetFileNameToSelectedItem(header.hwndFrom, hFNCombo, nmListView.iItem);
                            }
                        }
                        m_suppressSelectionChange = false;
                    }
                }
            }
            return(hWnd.DefSubclassProc(uMsg, wParam, lParam));
        }
        private int ProcessNotifyMessage(IntPtr hWnd, InteropUtil.OFNOTIFY notifyData)
        {
            switch (notifyData.hdr_code)
            {
                case InteropUtil.CDN_FOLDERCHANGE:
                {
                    var newFolder = GetTextFromCommonDialog(hWnd.GetParent().AssumeNonZero(), InteropUtil.CDM_GETFOLDERPATH);
                    if (m_currentFolder != null && newFolder != null &&  newFolder.PathContains(m_currentFolder))
                    {
                        m_suppressSelectionChange = true;
                    }
                    m_currentFolder = newFolder;
                    var fileNameCombo = hWnd.GetParent().AssumeNonZero().GetDlgItem(InteropUtil.ID_FileNameCombo).AssumeNonZero();
                    if (m_hasDirChangeFired)
                    {
                        fileNameCombo.SetWindowTextW("");
                    }
                    m_hasDirChangeFired = true;    
                    break;
                }               
                case InteropUtil.CDN_FILEOK:
                {
                    if (!AcceptFiles)
                    {
                        return 1;        
                    }
                    break;
                }
                case InteropUtil.CDN_INITDONE:
                {
                    var hParent = hWnd.GetParent();
                    var hFile = hParent.AssumeNonZero().GetDlgItem(InteropUtil.ID_FileNameCombo).AssumeNonZero();
                    hFile.SetFocus();
                    break;
                }
            }

            return 0;
        }
예제 #4
0
        protected override bool RunDialog(IntPtr hwndOwner)
        {
            Util.Assume(Marshal.SystemDefaultCharSize == 2, "The character size should be 2");

            var    nativeBuffer = Marshal.AllocCoTaskMem(InteropUtil.NumberOfFileChars * 2);
            IntPtr filterBuffer = IntPtr.Zero;

            try
            {
                var openFileName = new InteropUtil.OpenFileName();
                openFileName.Initialize();
                openFileName.hwndOwner = hwndOwner;

                var chars = new char[InteropUtil.NumberOfFileChars];

                try
                {
                    if (File.Exists(Path))
                    {
                        if (AcceptFiles)
                        {
                            var fileName = System.IO.Path.GetFileName(Path);
                            var length   = Math.Min(fileName.Length, InteropUtil.NumberOfFileChars);
                            fileName.CopyTo(0, chars, 0, length);
                            openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
                        }
                        else
                        {
                            openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
                        }
                    }
                    else if (Directory.Exists(Path))
                    {
                        openFileName.lpstrInitialDir = Path;
                    }
                    else
                    {
                        //the path does not exist.
                        //We don't just want to throw it away, however.
                        //The initial path we get is most likely provided by the user in some way.
                        //It could be what they typed into a text box before clicking a browse button,
                        //or it could be a value they had entered previously that used to be valid, but now no longer exists.
                        //In any case, we don't want to throw out the user's text. So, we find the first parent
                        //directory of Path that exists on disk.
                        //We will set the initial directory to that path, and then set the initial file to
                        //the rest of the path. The user will get an error if the click "OK"m saying that the selected path
                        //doesn't exist, but that's ok. If we didn't do this, and showed the path, if they clicked
                        //OK without making changes we would actually change the selected path, which would be bad.
                        //This way, if the users want's to change the folder, he actually has to change something.
                        string pathToShow;
                        InitializePathDNE(Path, out openFileName.lpstrInitialDir, out pathToShow);
                        pathToShow = pathToShow ?? "";
                        var length = Math.Min(pathToShow.Length, InteropUtil.NumberOfFileChars);
                        pathToShow.CopyTo(0, chars, 0, length);
                    }
                }
                catch
                {
                }

                Marshal.Copy(chars, 0, nativeBuffer, chars.Length);

                openFileName.lpstrFile = nativeBuffer;

                if (!AcceptFiles)
                {
                    var str = string.Format("Folders\0*.{0}-{1}\0\0", Guid.NewGuid().ToString("N"), Guid.NewGuid().ToString("N"));
                    filterBuffer = openFileName.lpstrFilter = Marshal.StringToCoTaskMemUni(str);
                }
                else
                {
                    openFileName.lpstrFilter = IntPtr.Zero;
                }

                openFileName.nMaxCustFilter = 0;
                openFileName.nFilterIndex   = 0;
                openFileName.nMaxFile       = InteropUtil.NumberOfFileChars;
                openFileName.nMaxFileTitle  = 0;
                openFileName.lpstrTitle     = Title;
                openFileName.lpfnHook       = m_hookDelegate;
                openFileName.templateID     = InteropUtil.IDD_CustomOpenDialog;
                openFileName.hInstance      = Marshal.GetHINSTANCE(typeof(OpenFileOrFolderDialog).Module);

                openFileName.Flags =
                    InteropUtil.OFN_DONTADDTORECENT |
                    InteropUtil.OFN_ENABLEHOOK |
                    InteropUtil.OFN_ENABLESIZING |
                    InteropUtil.OFN_NOTESTFILECREATE |
                    InteropUtil.OFN_EXPLORER |
                    InteropUtil.OFN_FILEMUSTEXIST |
                    InteropUtil.OFN_PATHMUSTEXIST |
                    InteropUtil.OFN_NODEREFERENCELINKS |
                    InteropUtil.OFN_ENABLETEMPLATE |
                    (ShowReadOnly ? 0 : InteropUtil.OFN_HIDEREADONLY);

                m_useCurrentDir = false;

                var ret = InteropUtil.GetOpenFileNameW(ref openFileName);
                //var extErrpr = InteropUtil.CommDlgExtendedError();
                //InteropUtil.CheckForWin32Error();

                if (m_useCurrentDir)
                {
                    Path = m_currentFolder;
                    return(true);
                }
                else if (ret)
                {
                    Marshal.Copy(nativeBuffer, chars, 0, chars.Length);
                    var firstZeroTerm = ((IList)chars).IndexOf('\0');
                    if (firstZeroTerm >= 0 && firstZeroTerm <= chars.Length - 1)
                    {
                        Path = new string(chars, 0, firstZeroTerm);
                    }
                }
                return(ret);
            }
            finally
            {
                Marshal.FreeCoTaskMem(nativeBuffer);
                if (filterBuffer != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(filterBuffer);
                }
            }
        }
        private void ResizeCustomControl(IntPtr hWnd, InteropUtil.RECT rect, params IntPtr[] buttons)
        {
            Util.Assume(buttons != null && buttons.Length > 0);

            hWnd.AssumeNonZero();

            var wndLoc = hWnd.GetWindowPlacement();

            wndLoc.Right = rect.right;
            hWnd.SetWindowPlacement(ref wndLoc);

            foreach (var hBtn in buttons)
            {
                int btnRight, btnWidth;

                m_calcPosMap[hBtn.GetDlgCtrlID()](this, rect.right, out btnRight, out btnWidth);

                PositionButton(hBtn, btnRight, btnWidth);
            }

            //see bug # 844
            //We clip hWnd to only draw in the rectangle around our custom buttons.
            //When we supply a custom dialog template to GetOpenFileName(), it adds 
            //an extra HWND to the open file dialog, and then sticks all the controls 
            //in the dialog //template inside the HWND. It then resizes the control 
            //to stretch from the top of the open file dialog to the bottom of the 
            //window, extending the bottom of the window large enough to include the 
            //additional height of the dialog template. This ends up sticking our custom
            //buttons at the bottom of the window, which is what we want.
            //
            //However, the fact that the parent window extends from the top of the open 
            //file dialog was causing some painting problems on Windows XP SP 3 systems. 
            //Basically, because the window was covering the predefined controls on the 
            //open file dialog, they were not getting painted. This results in a blank 
            //window. I tried setting an extended WS_EX_TRANSPARENT style on the dialog, 
            //but that didn't help.
            //
            //So, to fix the problem I setup a window region for the synthetic HWND. 
            //This clips the drawing of the window to only within the region containing
            //the custom buttons, and thus avoids the problem.
            //
            //I'm not sure why this wasn't an issue on Vista. 
            var hRgn = InteropUtil.CreateRectRgnIndirect(ref rect);
            try
            {
                if (hWnd.SetWindowRgn(hRgn, true) == 0)
                {
                    //setting the region failed, so we need to delete the region we created above.
                    hRgn.DeleteObject();
                }
            }
            catch
            {

                if (hRgn != IntPtr.Zero)
                {
                    hRgn.DeleteObject();
                }
            }
        }