簡體   English   中英

組合框下拉位置

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM