private void ResizeCustomControl(IntPtr hWnd) { if (hWnd == m_hWnd) { IntPtr hSelectButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(InteropUtil.AssumeNonZero(hWnd), InteropUtil.ID_SELECT)); IntPtr hOkButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(InteropUtil.AssumeNonZero(hWnd), InteropUtil.ID_CUSTOM_CANCEL)); IntPtr hParent = InteropUtil.AssumeNonZero(InteropUtil.GetParent(hWnd)); IntPtr fileName = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.ID_FileNameCombo)); /*var right = fileName.GetWindowPlacement().Right; * var top = hSelectButton.GetWindowPlacement().Top;*/ var rect = new InteropUtil.RECT(); InteropUtil.WINDOWPLACEMENT selectRect = InteropUtil.GetWindowPlacement(hSelectButton); rect.top = selectRect.Top; rect.bottom = selectRect.Bottom; rect.right = InteropUtil.GetWindowPlacement(fileName).Right; rect.left = rect.right - (m_cancelWidth + m_buttonGap + m_selectWidth); ResizeCustomControl(hWnd, rect, hOkButton, hSelectButton); } }
private void ResizeCustomControl(IntPtr hWnd, InteropUtil.RECT rect, params IntPtr[] buttons) { InteropUtil.Assume(buttons != null && buttons.Length > 0); InteropUtil.AssumeNonZero(hWnd); InteropUtil.WINDOWPLACEMENT wndLoc = InteropUtil.GetWindowPlacement(hWnd); wndLoc.Right = rect.right; InteropUtil.SetWindowPlacement(hWnd, ref wndLoc); foreach (IntPtr hBtn in buttons) { int btnRight, btnWidth; m_calcPosMap[InteropUtil.GetDlgCtrlID(hBtn)](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. IntPtr hRgn = InteropUtil.CreateRectRgnIndirect(ref rect); try { if (InteropUtil.SetWindowRgn(hWnd, hRgn, true) == 0) { //setting the region failed, so we need to delete the region we created above. InteropUtil.DeleteObject(hRgn); } } catch { if (hRgn != IntPtr.Zero) { InteropUtil.DeleteObject(hRgn); } } }
private void PositionButton(IntPtr hWnd, int right, int width) { InteropUtil.AssumeNonZero(hWnd); int id = InteropUtil.GetDlgCtrlID(hWnd); //hWnd.BringWindowToTop(); InteropUtil.WINDOWPLACEMENT buttonLoc = InteropUtil.GetWindowPlacement(hWnd); buttonLoc.Right = right; buttonLoc.Left = buttonLoc.Right - width; InteropUtil.SetWindowPlacement(hWnd, ref buttonLoc); InteropUtil.InvalidateRect(hWnd, IntPtr.Zero, true); }
private void InitDialog(IntPtr hWnd) { m_hWnd = hWnd; IntPtr hParent = InteropUtil.AssumeNonZero(InteropUtil.GetParent(hWnd)); InteropUtil.SetWindowSubclass(hParent, m_openFileSubClassDelegate, 0, 0); //disable and hide the filter combo box IntPtr hFilterCombo = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.ID_FilterCombo)); InteropUtil.EnableWindow(hFilterCombo, false); InteropUtil.SendMessage(hParent, InteropUtil.CDM_HIDECONTROL, InteropUtil.ID_FilterCombo, 0); InteropUtil.SendMessage(hParent, InteropUtil.CDM_HIDECONTROL, InteropUtil.ID_FilterLabel, 0); //update the file name label IntPtr hFileNameLabel = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.ID_FileNameLabel)); if (FileNameLabel != String.Empty) { InteropUtil.SendMessageString(hFileNameLabel, InteropUtil.WM_SETTEXT, 0, FileNameLabel); } //find the button controls in the parent IntPtr hOkButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.IDOK)); IntPtr hCancelButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.IDCANCEL)); //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. InteropUtil.SetWindowTextW(hOkButton, String.Empty); InteropUtil.SetWindowTextW(hCancelButton, String.Empty); //find our button controls IntPtr hSelectButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hWnd, InteropUtil.ID_SELECT)); IntPtr hCustomCancelButton = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hWnd, InteropUtil.ID_CUSTOM_CANCEL)); if (!String.IsNullOrEmpty(SelectLabel)) { InteropUtil.SetWindowTextW(hSelectButton, SelectLabel); } if (!String.IsNullOrEmpty(CancelLabel)) { InteropUtil.SetWindowTextW(hCustomCancelButton, CancelLabel); } //copy the font from the parent's buttons InteropUtil.LoadFontFrom(hSelectButton, hOkButton); InteropUtil.LoadFontFrom(hCustomCancelButton, hCancelButton); InteropUtil.WINDOWPLACEMENT cancelLoc = InteropUtil.GetWindowPlacement(hCancelButton); //hide the ok and cancel buttons InteropUtil.SendMessage(hParent, InteropUtil.CDM_HIDECONTROL, InteropUtil.IDOK, 0); InteropUtil.SendMessage(hParent, InteropUtil.CDM_HIDECONTROL, InteropUtil.IDCANCEL, 0); //expand the file name combo to take up the space left by the OK and cancel buttons. IntPtr hFileName = InteropUtil.AssumeNonZero(InteropUtil.GetDlgItem(hParent, InteropUtil.ID_FileNameCombo)); InteropUtil.WINDOWPLACEMENT fileNameLoc = InteropUtil.GetWindowPlacement(hFileName); fileNameLoc.Right = InteropUtil.GetWindowPlacement(hOkButton).Right; InteropUtil.SetWindowPlacement(hFileName, ref fileNameLoc); InteropUtil.WINDOWPLACEMENT parentLoc = InteropUtil.GetWindowPlacement(hParent); //subtract the height of the missing cancel button parentLoc.Bottom -= (cancelLoc.Bottom - cancelLoc.Top); InteropUtil.SetWindowPlacement(hParent, ref parentLoc); //move the select and custom cancel buttons to the right hand side of the window: InteropUtil.WINDOWPLACEMENT selectLoc = InteropUtil.GetWindowPlacement(hSelectButton); InteropUtil.WINDOWPLACEMENT customCancelLoc = InteropUtil.GetWindowPlacement(hCustomCancelButton); m_cancelWidth = customCancelLoc.Right - customCancelLoc.Left; m_selectWidth = selectLoc.Right - selectLoc.Left; m_buttonGap = customCancelLoc.Left - selectLoc.Right; InteropUtil.WINDOWPLACEMENT ctrlLoc = InteropUtil.GetWindowPlacement(hWnd); ctrlLoc.Right = fileNameLoc.Right; //ResizeCustomControl(hWnd, fileNameLoc.Right, hCustomCancelButton, hSelectButton); ResizeCustomControl(hWnd); }