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(); } } }
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)); }
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); } } }