Можно ли определить левый список со списком (т.Е. полосу прокрутки слева) в приложении winforms?

#c# #.net #.net-3.5 #combobox

#c# #.net #.net-3.5 #поле со списком

Вопрос:

У меня есть приложение WinForms, которое используется на планшетных ПК с сенсорными экранами. Приложение разработано с использованием Visual Studio 2008 и использовало версию 3.5 .Net framework. У меня был запрос от клиента-левши поместить полосу прокрутки выпадающих списков в левую часть выпадающей области, а не справа, но я не уверен, как это сделать, или если это вообще возможно сделать. Кто-нибудь делал это раньше или знает, как это можно сделать?

Ответ №1:

Здесь есть решение, использующее вызовы Win32 API для изменения списка со списком: http://www.codeguru.com/csharp/csharp/cs_controls/custom/print.php/c15261

Примерно на полпути вниз, под заголовком «Выравнивание объектов ComoBox».

В конце страницы также есть ссылка на некоторый пример кода.


Пример — Левая полоса прокрутки и текст слева

 using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ComboBoxMod
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmMain());
        }
    }

    public partial class frmMain : Form
    {
        private ComboBoxMod.ComboBox cbTest; //this is the modified combo box
        private System.Windows.Forms.Button btnToggleAlign;
        private System.ComponentModel.IContainer components = null;

        public frmMain()
        {
            this.cbTest = new ComboBoxMod.ComboBox();
            this.btnToggleAlign = new Button();

            InitialiseComponent();

            for (int i = 0; i < 50; i  )
            {
                cbTest.Items.Add(i);
            }
        }

        void btnToggleAlign_Click(object sender, EventArgs e)
        {
            if (this.cbTest.ScrollAlignment == ComboBox.Alignment.Right) //If Right Aligned
            {
                this.cbTest.ScrollAlignment = ComboBox.Alignment.Left; //Set To Left
            }
            else
            {
                this.cbTest.ScrollAlignment = ComboBox.Alignment.Right; //Set To Right
            }
        }

        private void InitialiseComponent()
        {
            this.SuspendLayout();

            this.cbTest.FormattingEnabled = true;
            this.cbTest.Location = new System.Drawing.Point(12, 12);
            this.cbTest.Name = "cbTest";
            this.cbTest.Size = new System.Drawing.Size(180, 21);
            this.cbTest.TabIndex = 0;

            this.btnToggleAlign.Location = new System.Drawing.Point(12, 42);
            this.btnToggleAlign.Name = "btnScrollAlign";
            this.btnToggleAlign.Size = new System.Drawing.Size(180, 23);
            this.btnToggleAlign.TabIndex = 0;
            this.btnToggleAlign.Text = "Toggle Scrollbar Alignment";
            this.btnToggleAlign.UseVisualStyleBackColor = true;
            this.btnToggleAlign.Click  = new EventHandler(btnToggleAlign_Click);

            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(200, 75);

            this.Controls.Add(this.cbTest);
            this.Controls.Add(this.btnToggleAlign);

            this.Name = "frmMain";
            this.Text = "frmMain";
            this.ResumeLayout(false);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing amp;amp; (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
    }

    public class ComboBox : System.Windows.Forms.ComboBox //Inherits ComboBox
    {
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int GetWindowLong(IntPtr hwnd, int nIndex); //Retrieve Info About Specified Window

        [DllImport("user32")]
        public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong); //Change An Attribute Of Specified Window

        [DllImport("user32.dll")]
        public static extern int GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi); //Retrieve Info About Specified Combo Box


        [StructLayout(LayoutKind.Sequential)]
        public struct COMBOBOXINFO //Contains ComboBox Status Info
        {
            public Int32 cbSize;
            public RECT rcItem;
            public RECT rcButton;
            public ComboBoxButtonState caState;
            public IntPtr hwndCombo;
            public IntPtr hwndEdit;
            public IntPtr hwndList;
        }


        [StructLayout(LayoutKind.Sequential)] //Describes Width, Height, And Location Of A Rectangle
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        public enum ComboBoxButtonState //Determines Current State Of ComboBox
        {
            STATE_SYSTEM_NONE = 0,
            STATE_SYSTEM_INVISIBLE = 0x00008000,
            STATE_SYSTEM_PRESSED = 0x00000008
        }

        /// <summary> 
        /// Alignment Enum For Left amp; Right
        /// </summary> 
        public enum Alignment
        {
            Left = 0,
            Right = 1
        }

        /// <summary> 
        /// Align ScrollBar 
        /// </summary> 
        public Alignment ScrollAlignment
        {
            get
            {
                return Scroll; //Get Value
            }
            set
            {
                if (Scroll == value) //If Not Valid Value
                    return;

                Scroll = value; //Set Value
                AlignScrollbar(); //Call AlignScroll Method
            }
        }

        private const int GWL_EXSTYLE = -20; //ComboBox Style
        private const int WS_EX_RIGHT = 4096; //Right Align Text 
        private const int WS_EX_LEFTSCROLLBAR = 16384; //Left ScrollBar
        private const int WS_EX_RIGHTSCROLLBAR = 128; //Right ScrollBar

        private IntPtr handle; //Handle Of ComboBox
        private Alignment Scroll; //Alignment Options For ScrollBar


        public ComboBox()
        {
            handle = CASGetHandle(this); //Get Handle Of ComboBox
            Scroll = Alignment.Right; //default alignment
        }

        /// <summary>
        /// Retrieves ComboBox Handle
        /// </summary>
        /// <param name="CASCombo"></param>
        /// <returns></returns>
        public IntPtr CASGetHandle(ComboBox CASCombo)
        {

            COMBOBOXINFO CASCBI = new COMBOBOXINFO(); //New ComboBox Settings Object
            CASCBI.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(CASCBI); //Call In Correct Size
            GetComboBoxInfo(CASCombo.Handle, ref CASCBI); //Obtain Handle
            return CASCBI.hwndList; //Return Handle
        }

        /// <summary>
        /// Align The ComboBox ScrollBar
        /// </summary>
        private void AlignScrollbar()
        {
            if (handle != IntPtr.Zero) //If Valid Handle
            {
                int style = GetWindowLong(handle, GWL_EXSTYLE); //Get ComboBox Style
                switch (Scroll)
                {
                    case Alignment.Left:
                        style = WS_EX_LEFTSCROLLBAR; //Align ScrollBare To The Left
                        break;
                    case Alignment.Right:
                        style =  WS_EX_RIGHTSCROLLBAR; //Align ScrollBare To The Right
                        break;
                }
                SetWindowLong(handle, GWL_EXSTYLE, style); //Apply On ComboBox
            }
        }
    }
}
  

Комментарии:

1. Спасибо, Кайл. Спасибо, что приложили усилия для публикации рабочего примера; Я действительно ценю это! Он отлично работает и делает именно то, что я хочу! Спасибо. 🙂

Ответ №2:

в элементе управления выпадающим списком есть свойство right to left, просто установите для него значение true

Комментарии:

1. Согласно документу MSDN 3.5, RightToLeft влияет на текст , а не на положение полосы прокрутки: msdn.microsoft.com/en-us/library /…

2. Я как бы беру это обратно. Ссылка с этой страницы такова: msdn.microsoft.com/en-us/library /. … Я полагаю, что OP по-прежнему хочет, чтобы текст был выровнен по левому краю… (Я могу удалить это понижение, если вы нажмете / измените свой ответ)

3. хорошо, в этой 2-й ссылке написана выровненная по правому краю полоса прокрутки, но я вижу следующее: img403.imageshack.us/img403/5251/rtlk.png

4. кстати, возник вопрос о возможности, а не о гениальности (если ему нужно иметь выровненный по левому краю текст или выровненную по левому краю полосу прокрутки)… итак, мой ответ хорош, потому что, что? это возможно

5. Согласен, это действительно. Как указано выше, я с удовольствием удалю downvote, если вы измените свой ответ (не могу удалить downvote до обновления ответа)

Ответ №3:

Это невозможно сделать в WinForms. Хотя вы можете придумать свое собственное решение управления, представляющее требуемую структуру.