代码之家  ›  专栏  ›  技术社区  ›  Mironline Naeem Bashir

组合框下拉位置

  •  2
  • Mironline Naeem Bashir  · 技术社区  · 16 年前

    我有一个最大化的表单,它有组合框控件(停靠在右上角)和500px Width

    尝试打开组合框后,列表的一半将离开屏幕。如何在窗体中强制列表显示?

    1 回复  |  直到 12 年前
        1
  •  7
  •   Max    12 年前

    棘手的问题。我找不到解决这个问题的好办法,只有一个变通办法。添加一个新类并粘贴下面显示的代码。编译。将新控件从工具箱顶部放到窗体上。

    解决办法不是很好。问题是下拉窗口将忽略移动它的尝试,直到下拉动画完成。视觉效果不是很好,你会看到窗口向下,然后跳到左边。我不知道用什么方法来拍它的头,也许其他人知道。

    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
    
    推荐文章