将控件插入到特定位置的另一个控件中?

时间:2018-09-19 22:40:09

标签: c# winforms

我正在使用获胜表格。我有两种形式:我的主要形式Form1和我制作的名为TextBlock的形式。我正在制作一个文本编辑器,您可以在其中将文本框放在页面周围,然后进行编辑(想一想)。

这是我的两种形式。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void saveToolStripMenuItem_Click(object sender, EventArgs e)
    {
        saveFileDialog.Filter = "Text File|*.txt";
        var result = saveFileDialog.ShowDialog();

        if (result == DialogResult.OK)
        {
            StreamWriter writer = new 
            StreamWriter(saveFileDialog.OpenFile());
            writer.Write(tb_Main.Text);
            writer.Dispose();
            writer.Close();
        }
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {

    }

    private void button_tb_Click(object sender, EventArgs e)
    {
        TextBlock tb_edit = new TextBlock();
        tb_edit.Text = "New Text Block";
        // tb_edit.Multiline = true;
        // tb_edit.Size = new Size(100,100);
        // tb_edit.MinimumSize = new Size(50, 50);
        tb_edit.form1 = this;

        tb_edit.TopLevel = false;
        tb_edit.btn_accepttb.BringToFront();
        tb_Main.Controls.Add(tb_edit);
        tb_edit.Show();
        tb_edit.BringToFront();

    }
}

和我的自定义表单:

 public partial class TextBlock : Form
    {
        public Form1 form1;
        public TextBlock()
        {
            InitializeComponent();
        }

        private void btn_accepttb_Click(object sender, EventArgs e)
        {
            TextBox tb_edit = new TextBox();
            tb_edit.Text = "New Text Block";
            tb_edit.Multiline = true;
            tb_edit.Size = this.Size;
            int dif = form1.tb_Main.Lines.Count()*(int)tb_edit.Font.Size;
            Point loca = new Point(this.Location.X,this.Location.Y+dif);
            tb_edit.Location = this.Location;


            form1.tb_Main.Controls.Add(tb_edit);
            tb_edit.Show();
            tb_edit.BringToFront();
            form1.tb_Main.Controls.Remove(this);
        }
    }

它的作用:它可以复制我的TextBlock,以用于放置和调整大小。当您将其放置在所需的位置以及所需的大小时,请单击该按钮,然后将其替换为该位置在该位置的常规文本框。

我要它做什么:当前它正在工作,只有一个异常。我将其添加到Form1中tb_Main的控件中(我的主文本框,它占据了整个表单),它显示了出来。它的大小正确,除非当我用文本填充tb_Main并滚动时,新的文本框保持在原位置,而其父级滚动到其后。

问题:如果我向下滚动到文档中并决定要在此处放置此文本框,如何确保将其相对于放置的文本框的滚动位置。因此,当我滚动时,它基本上保持嵌入在我放置它的页面(当我说“页面”是指我的tb_Main时)。

1 个答案:

答案 0 :(得分:1)

最好创建一个richtextbox而不是textbox。它具有textbox的所有功能以及更多功能。此示例仅对richtextbox使用{strong> 。

子类richtextbox

class MyRichTextBox : RichTextBox  {

    [DllImport( "user32.dll" )]
    private static extern bool GetScrollInfo( IntPtr hwnd, SBOrientation fnBar,
        ref SCROLLINFO lpsi );

    [StructLayout( LayoutKind.Sequential )]
    private struct SCROLLINFO {
        public uint cbSize;
        public ScrollInfoMask fMask;
        public int nMin;
        public int nMax;
        public uint nPage;
        public int nPos;
        public int nTrackPos;
    }

    private enum ScrollInfoMask : uint {
        SIF_RANGE = 0x1,
        SIF_PAGE = 0x2,
        SIF_POS = 0x4,
        SIF_DISABLENOSCROLL = 0x8,
        SIF_TRACKPOS = 0x10,
        SIF_ALL = ( SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS ),
    }

    private enum SBOrientation : int {
        SB_HORZ = 0x0,
        SB_VERT = 0x1,
    }

    private const int WM_VSCROLL = 0x115;
    private const int SB_LINEUP = 0;
    private const int SB_LINEDOWN = 1;
    private const int SB_PAGEUP = 2;
    private const int SB_PAGEDOWN = 3;
    private const int SB_THUMBPOSITION = 4;
    private const int SB_THUMBTRACK = 5;
    private const int SB_TOP = 6;
    private const int SB_BOTTOM = 7;
    private const int SB_ENDSCROLL = 8;

    private bool isThumbTrack = false;
    private TextBox childTextbox = null;
    private int scrollPos = 0;


    public MyTextBox( TextBox textbox ) { //here you pass the child textbox you want to scroll

        childTextbox = textbox;

    }

    protected override void OnVScroll( EventArgs e ) {
        if( childTextbox == null ) { base.OnVScroll( e ); return; }

        SCROLLINFO si = new SCROLLINFO();
        si.cbSize = (uint)Marshal.SizeOf( si );
        si.fMask = ScrollInfoMask.SIF_ALL;

        GetScrollInfo( this.Handle, SBOrientation.SB_VERT, ref si );

        //there is a difference when the user uses the thumb to get scroll pos.
        //When user uses the thumb we get *nTrackPos* otherwise *nPos*
        if( isThumbTrack == true ) {
            childTextbox.Location = new Point( childTextbox.Location.X, childTextbox.Location.Y - 
                                               (si.nTrackPos - scrollPos ) );

            isThumbTrack = false;
            scrollPos = si.nTrackPos;
        }
        else {
            childTextbox.Location = new Point( childTextbox.Location.X, childTextbox.Location.Y -
                                               ( si.nPos - scrollPos ) );

            scrollPos = si.nPos;
        }


        base.OnVScroll( e );
    }

    protected override void WndProc( ref Message m ) {
        int wParam;

        if(m.Msg == WM_VSCROLL ) {

            wParam = m.WParam.ToInt32();
            wParam &= 0xFFFF; //get low 16 bits of wParam

            //Check if user is using the thumb to scroll
            if( wParam == SB_THUMBTRACK ) {
                isThumbTrack = true;
            }

        }

        base.WndProc( ref m );
    }

}
相关问题