C# 组合框下拉位置

C# 组合框下拉位置,c#,winforms,combobox,drop-down-menu,position,C#,Winforms,Combobox,Drop Down Menu,Position,我有一个最大化的表单,它有一个组合框控件(停靠在右上角),宽度为500pxWidth 在尝试打开组合框后,列表的一半将退出屏幕。如何在表单中强制列表显示 棘手的问题。我找不到解决这个问题的好办法,只是一个变通办法。添加一个新类并粘贴如下所示的代码。编译。将新控件从工具箱顶部拖到窗体上 解决办法不是很好。问题是下拉窗口将忽略移动它的尝试,直到下拉动画完成。视觉效果不是很好,你会看到窗口下拉,然后跳到左边。我不知道还有什么方法可以拍它的头,也许其他人会 C#版本: using System; usi

我有一个最大化的表单,它有一个组合框控件(停靠在右上角),宽度为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);
}
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
使用系统;
使用系统图;
使用System.Windows.Forms;
使用System.Runtime.InteropServices;
公共类MyComboBox:组合框{
受保护的覆盖无效OnDropDown(事件参数e){
//下拉菜单是否在屏幕右侧?
点位置=此点到屏幕(此位置);
屏幕scr=屏幕起始点(位置);
如果(scr.WorkingArea.Right<位置X+此下拉宽度){
此.BeginInvoke(新操作(()=>{
//检索下拉列表的句柄
COMBOBOXINFO=新建ComboxInfo();
info.cbSize=Marshal.SizeOf(info);
SendMessageCb(this.Handle,0x164,IntPtr.Zero,out-info);
//移动下拉窗口
RECT-rc;
GetWindowRect(info.hwnList,out rc);
int x=scr.WorkingArea.Right-(rc.Right-rc.Left);
SetWindowPos(info.hwnlist,IntPtr.Zero,x,rc.Top,0,0,5);
}));
}
基础.降速(e);
}
//P/Invoke声明
私有结构ComboxInfo{
公共Int32 cbSize;
公共RECT rcItem,rcButton;
公共int按钮状态;
公共IntPtr hwndCombo、hwndEdit、hwndList;
}
私有结构矩形{
公共int左、上、右、下;
}
[DllImport(“user32.dll”,EntryPoint=“SendMessageW”,CharSet=CharSet.Unicode)]
专用静态外部IntPtr SendMessageCb(IntPtr hWnd、int msg、IntPtr wp、out COMBOXINFO lp);
[DllImport(“user32.dll”)]
私有静态外部bool SetWindowPos(IntPtr hWnd、IntPtr after、intx、inty、intcx、intcy、intflags);
[DllImport(“user32.dll”)]
私有静态外部bool GetWindowRect(IntPtr hWnd,out RECT rc);
}
VB.Net版本:

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);
}
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
导入系统
导入系统。绘图
导入System.Windows.Forms
导入System.Runtime.InteropServices
公共类MyComboBox
继承组合框
'P/Invoke声明
私有结构ComboxInfo
公共CBSIZEAS Int32
公共rcItem作为RECT
公共按钮为RECT
公共按钮state为整数
公共hwndCombo作为IntPtr
公共HwnEdit作为IntPtr
作为IntPtr的公共hwndList
端部结构
私有结构
公共左整数
作为整数的公共Top
作为整数的公权
公共底部为整数
端部结构
私有共享函数SendMessageCb(hWnd作为IntPtr,msg作为Integer,wp作为IntPtr,ByRef lp作为COMBOBOXINFO)作为IntPtr
端函数
私有共享函数SetWindowPos(hWnd为IntPtr,后面为IntPtr,x为整数,y为整数,cx为整数,cy为整数,标志为整数)为布尔值
端函数
私有共享函数GetWindowRect(hWnd作为IntPtr,ByRef rc作为RECT)作为布尔值
端函数
受保护的覆盖子OnDropDown(e作为事件参数)
'下拉菜单是否在屏幕右侧?
Dim pos As Point=Me.点到屏幕(Me.位置)
变光scr为屏幕=屏幕起点(位置)
如果(scr.WorkingArea.Right<位置X+Me.DropDownWidth),则
Me.BeginInvoke(新动作(Sub)()
'检索下拉列表的句柄
作为COMBOBOXINFO的尺寸信息=新ComboxInfo()
info.cbSize=Marshal.SizeOf(info)
SendMessageCb(Me.Handle,&H164,IntPtr.Zero,info)
'移动下拉窗口
Dim rc As RECT
GetWindowRect(info.hwnList,rc)
尺寸x为整数=scr.WorkingArea.Right-(rc.Right-rc.Left)
SetWindowPos(info.hwnList、IntPtr.Zero、x、rc.Top、0、0、5)
末端接头)
如果结束
MyBase.OnDropDown(e)
端接头
末级

您的解决方案对我来说效果非常好,我刚刚对其进行了编辑,添加了Vb.Net版本的源代码马克斯刚才