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; }
private void InitDialog(IntPtr hWnd) { m_hWnd = hWnd; var hParent = hWnd.GetParent().AssumeNonZero(); hParent.SetWindowSubclass(m_openFileSubClassDelegate, 0, 0); //disable and hide the filter combo box var hFilterCombo = hParent.GetDlgItem(InteropUtil.ID_FilterCombo).AssumeNonZero(); hFilterCombo.EnableWindow(false); hParent.SendMessage(InteropUtil.CDM_HIDECONTROL, InteropUtil.ID_FilterCombo, 0); hParent.SendMessage(InteropUtil.CDM_HIDECONTROL, InteropUtil.ID_FilterLabel, 0); //update the file name label var hFileNameLabel = hParent.GetDlgItem(InteropUtil.ID_FileNameLabel).AssumeNonZero(); if (FileNameLabel != "") { hFileNameLabel.SendMessageString(InteropUtil.WM_SETTEXT, 0, FileNameLabel); } //find the button controls in the parent var hOkButton = hParent.GetDlgItem(InteropUtil.IDOK).AssumeNonZero(); var hCancelButton = hParent.GetDlgItem(InteropUtil.IDCANCEL).AssumeNonZero(); //We don't want the accelerator keys for the ok and cancel buttons to work, because //they are not shown on the dialog. However, we still want the buttons enabled //so that "esc" and "enter" have the behavior they used to. So, we just //clear out their text instead. hOkButton.SetWindowTextW(""); hCancelButton.SetWindowTextW(""); //find our button controls var hSelectButton = hWnd.GetDlgItem(InteropUtil.ID_SELECT).AssumeNonZero(); var hCustomCancelButton = hWnd.GetDlgItem(InteropUtil.ID_CUSTOM_CANCEL).AssumeNonZero(); //copy the font from the parent's buttons hSelectButton.LoadFontFrom(hOkButton); hCustomCancelButton.LoadFontFrom(hCancelButton); var cancelLoc = hCancelButton.GetWindowPlacement(); //hide the ok and cancel buttons hParent.SendMessage(InteropUtil.CDM_HIDECONTROL, InteropUtil.IDOK, 0); hParent.SendMessage(InteropUtil.CDM_HIDECONTROL, InteropUtil.IDCANCEL, 0); //expand the file name combo to take up the space left by the OK and cancel buttons. var hFileName = hParent.GetDlgItem(InteropUtil.ID_FileNameCombo).AssumeNonZero(); var fileNameLoc = hFileName.GetWindowPlacement(); fileNameLoc.Right = hOkButton.GetWindowPlacement().Right; hFileName.SetWindowPlacement(ref fileNameLoc); var parentLoc = hParent.GetWindowPlacement(); //subtract the height of the missing cancel button parentLoc.Bottom -= (cancelLoc.Bottom - cancelLoc.Top); hParent.SetWindowPlacement(ref parentLoc); //move the select and custom cancel buttons to the right hand side of the window: var selectLoc = hSelectButton.GetWindowPlacement(); var customCancelLoc = hCustomCancelButton.GetWindowPlacement(); m_cancelWidth = customCancelLoc.Right - customCancelLoc.Left; m_selectWidth = selectLoc.Right - selectLoc.Left; m_buttonGap = customCancelLoc.Left - selectLoc.Right; var ctrlLoc = hWnd.GetWindowPlacement(); ctrlLoc.Right = fileNameLoc.Right; //ResizeCustomControl(hWnd, fileNameLoc.Right, hCustomCancelButton, hSelectButton); ResizeCustomControl(hWnd); }
private void ResizeCustomControl(IntPtr hWnd) { if (hWnd == m_hWnd) { var hSelectButton = hWnd.AssumeNonZero().GetDlgItem(InteropUtil.ID_SELECT).AssumeNonZero(); var hOkButton = hWnd.AssumeNonZero().GetDlgItem(InteropUtil.ID_CUSTOM_CANCEL).AssumeNonZero(); var hParent = hWnd.GetParent().AssumeNonZero(); var fileName = hParent.GetDlgItem(InteropUtil.ID_FileNameCombo).AssumeNonZero(); /*var right = fileName.GetWindowPlacement().Right; var top = hSelectButton.GetWindowPlacement().Top;*/ var rect = new InteropUtil.RECT(); var selectRect = hSelectButton.GetWindowPlacement(); rect.top = selectRect.Top; rect.bottom = selectRect.Bottom; rect.right = fileName.GetWindowPlacement().Right; rect.left = rect.right - (m_cancelWidth + m_buttonGap + m_selectWidth); ResizeCustomControl(hWnd, rect, hOkButton, hSelectButton); } }
protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lparam) { switch (unchecked((uint)msg)) { case InteropUtil.WM_INITDIALOG: { InitDialog(hWnd); break; } case InteropUtil.WM_NOTIFY: { var notifyData = (InteropUtil.OFNOTIFY)Marshal.PtrToStructure(lparam, typeof(InteropUtil.OFNOTIFY)); var results = ProcessNotifyMessage(hWnd, notifyData); if (results != 0) { hWnd.SetWindowLongW(InteropUtil.DWL_MSGRESULT, results); return (IntPtr)results; } break; } case InteropUtil.WM_SIZE: { ResizeCustomControl(hWnd); break; } case InteropUtil.WM_COMMAND: { unchecked { var hParent = hWnd.GetParent().AssumeNonZero(); var code = HIGH((uint)wParam); var id = LOW((uint)wParam); if (code == InteropUtil.BN_CLICKED) { switch (id) { case InteropUtil.ID_CUSTOM_CANCEL: { //The user clicked our custom cancel button. Close the dialog. hParent.SendMessage(InteropUtil.WM_CLOSE, 0, 0); break; } case InteropUtil.ID_SELECT: { var hFileName = hParent.GetDlgItem(InteropUtil.ID_FileNameCombo); var currentText = (hFileName.GetWindowTextW() ?? "").Trim(); if (currentText == "" && !String.IsNullOrEmpty(m_currentFolder)) { //there's not text in the box, so the user must want to select the current folder. m_useCurrentDir = true; hParent.SendMessage(InteropUtil.WM_CLOSE, 0, 0); break; } else if (System.IO.Path.IsPathRooted(currentText)) { if (Directory.Exists(currentText)) { //the contents of the text box are a rooted path, that points to an existing directory. //we interpret that to mean that the user wants to select that directory. m_useCurrentDir = true; m_currentFolder = currentText; hParent.SendMessage(InteropUtil.WM_CLOSE, 0, 0); break; } } else if (!String.IsNullOrEmpty(m_currentFolder) && currentText != "") { var combined = System.IO.Path.Combine(m_currentFolder, currentText); if (Directory.Exists(combined)) { //the contents of the text box are a relative path, that points to a //an existing directory. We interpret the users intent to mean that they wanted //to select the existing path. m_useCurrentDir = true; m_currentFolder = combined; hParent.SendMessage(InteropUtil.WM_CLOSE, 0, 0); break; } } //The user has not selected an existing folder. //So we translate a click of our "Select" button into the OK button and forward the request to the //open file dialog. hParent.SendMessage ( InteropUtil.WM_COMMAND, (InteropUtil.BN_CLICKED << 16) | InteropUtil.IDOK, unchecked((uint)hParent.GetDlgItem(InteropUtil.IDOK)) ); break; } } } } break; } } return base.HookProc(hWnd, msg, wParam, lparam); }