[英]ComboBox Dropdown Position
我有一个最大化的表单,它具有 500px Width
组合框控件(停靠在右上角)
尝试打开组合框后,列表的一半出现在屏幕外。 如何强制在表单中显示列表?
棘手的问题。 我找不到一个好的解决方法,只是一个解决方法。 添加一个新类并粘贴如下所示的代码。 编译。 将新控件从工具箱顶部拖放到表单上。
解决方法不是很好。 问题是下拉窗口将忽略移动它的尝试,直到下拉动画完成。 视觉效果不是很好,你会看到窗口下拉,然后跳到左边。 我不知道有其他方法可以把它拍在头上,也许其他人知道。
C#版本:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class MyComboBox : ComboBox {
protected override void OnDropDown(EventArgs e) {
// Is dropdown off the right side of the screen?
Point pos = this.PointToScreen(this.Location);
Screen scr = Screen.FromPoint(pos);
if (scr.WorkingArea.Right < pos.X + this.DropDownWidth) {
this.BeginInvoke(new Action(() => {
// Retrieve handle to dropdown list
COMBOBOXINFO info = new COMBOBOXINFO();
info.cbSize = Marshal.SizeOf(info);
SendMessageCb(this.Handle, 0x164, IntPtr.Zero, out info);
// Move the dropdown window
RECT rc;
GetWindowRect(info.hwndList, out rc);
int x = scr.WorkingArea.Right - (rc.Right - rc.Left);
SetWindowPos(info.hwndList, IntPtr.Zero, x, rc.Top, 0, 0, 5);
}));
}
base.OnDropDown(e);
}
// P/Invoke declarations
private struct COMBOBOXINFO {
public Int32 cbSize;
public RECT rcItem, rcButton;
public int buttonState;
public IntPtr hwndCombo, hwndEdit, hwndList;
}
private struct RECT {
public int Left, Top, Right, Bottom;
}
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
private static extern IntPtr SendMessageCb(IntPtr hWnd, int msg, IntPtr wp, out COMBOBOXINFO lp);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr after, int x, int y, int cx, int cy, int flags);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
}
VB.Net 版本:
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class MyComboBox
Inherits ComboBox
'P/Invoke declarations
Private Structure COMBOBOXINFO
Public cbSize As Int32
Public rcItem As RECT
Public rcButton As RECT
Public buttonState As Integer
Public hwndCombo As IntPtr
Public hwndEdit As IntPtr
Public hwndList As IntPtr
End Structure
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
<DllImport("user32.dll", EntryPoint:="SendMessageW", CharSet:=CharSet.Unicode)>
Private Shared Function SendMessageCb(hWnd As IntPtr, msg As Integer, wp As IntPtr, ByRef lp As COMBOBOXINFO) As IntPtr
End Function
<DllImport("user32.dll")>
Private Shared Function SetWindowPos(hWnd As IntPtr, after As IntPtr, x As Integer, y As Integer, cx As Integer, cy As Integer, flags As Integer) As Boolean
End Function
<DllImport("user32.dll")>
Private Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As RECT) As Boolean
End Function
Protected Overrides Sub OnDropDown(e As EventArgs)
' Is dropdown off the right side of the screen?
Dim pos As Point = Me.PointToScreen(Me.Location)
Dim scr As Screen = Screen.FromPoint(pos)
If (scr.WorkingArea.Right < pos.X + Me.DropDownWidth) Then
Me.BeginInvoke(New Action(Sub()
'Retrieve handle to dropdown list
Dim info As COMBOBOXINFO = New COMBOBOXINFO()
info.cbSize = Marshal.SizeOf(info)
SendMessageCb(Me.Handle, &H164, IntPtr.Zero, info)
'Move the dropdown window
Dim rc As RECT
GetWindowRect(info.hwndList, rc)
Dim x As Integer = scr.WorkingArea.Right - (rc.Right - rc.Left)
SetWindowPos(info.hwndList, IntPtr.Zero, x, rc.Top, 0, 0, 5)
End Sub))
End If
MyBase.OnDropDown(e)
End Sub
End Class
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.