C# 获取和设置TextBox等控件的滚动条位置
张静茹2015/11/07软件综合 IP:山东
由于TextBox修改Text后会导致鼠标光标位置和滚动条的改变
C#的textbox好像又没有获取与设置滚动条位置的函数,所以找到了俩设置的API

       [DllImport("user32.dll")]
        static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
hwnd:指定控件的句柄。
nBar:指定类型的滚动条。0:水平滚动条,1:垂直滚动条。
bRedraw: 重绘标志


        [DllImport("user32.dll", EntryPoint = "GetScrollPos")]
        public static extern int GetScrollPos( int hwnd, int nBar);
hwnd:指定控件的句柄。
nBar:指定类型的滚动条。0:水平滚动条,1:垂直滚动条。
return: 滚动条位置



The following example:


            XXXXXXXXXXXXXow(GetScrollPos((int)textBox1.Handle,1).ToString());
            SetScrollPos(textBox1.Handle, 1, XXXXXXXXXXXnes.Length - 1, true);





修改TextBox的Text属性之后 恢复光标位置和滚动条位置

        private void button1_Click(object sender, EventArgs e)
        {
            int TextBoxSouSelectionStart = XXXXXXXXXXXlectionStart;//TextBoxSou光标位置    
            int TextBoxSouSelectionLength = XXXXXXXXXXXlectionLength;//TextBoxSou选中长度    
            int TextBoxSouScrollPos = GetScrollPos((int)textBox1.Handle,1);//TextBox滚动条位置


            textBox1.Text += "asdi";
            XXXXXXXXXXXcus();


            XXXXXXXXXXXlectionStart = TextBoxSouSelectionStart;
            XXXXXXXXXXXlectionLength = TextBoxSouSelectionLength;
            SetScrollPos(textBox1.Handle, 1, TextBoxSouScrollPos, true);
            SendMessage(textBox1.Handle, 0x00B6, 0,TextBoxSouScrollPos);
        }
来自:计算机科学 / 软件综合
22
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
acmilan
9年2个月前 IP:四川
796048
这个特性确实有点麻烦→_→主要原因是光标位置发生改变了。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796052
引用 acmilan:
这个特性确实有点麻烦→_→主要原因是光标位置发生改变了。
恩 mfc也这样吗?我现在用这个办法,能解决问题 但是还是会闪一下,有个文字被全选然后 取消全选的过程
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796074
引用 张静茹:
恩 mfc也这样吗?我现在用这个办法,能解决问题 但是还是会闪一下,有个文字被全选然后 取消全选的过程
可能.NET的Text属性的实现有问题,建议尝试一下不改变Text属性,而是直接调用SetWindowText或者发送WM_SETTEXT设置文本。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796078
引用 acmilan:
可能.NET的Text属性的实现有问题,建议尝试一下不改变Text属性,而是直接调用SetWindowText或者发送WM_SETTEXT设置文本。



TextBox继承自ConTrol
<code class="lang-c">// System.Windows.Forms.TextBox
public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}</code>


ConTrol的
<code class="lang-c">// System.Windows.Forms.Control
[Bindable(true), Localizable(true), DispId(-517), SRCategory("CatAppearance"), SRDescription("ControlTextDescr")]
public virtual string Text
{
    get
    {
        if (!this.CacheTextInternal)
        {
            return this.WindowText;
        }
        if (this.text != null)
        {
            return this.text;
        }
        return "";
    }
    set
    {
        if (value == null)
        {
            value = "";
        }
        if (value == this.Text)
        {
            return;
        }
        if (this.CacheTextInternal)
        {
            this.text = value;
        }
        this.WindowText = value;
        this.OnTextChanged(EventArgs.Empty);
        if (this.IsMnemonicsListenerAxSourced)
        {
            for (Control control = this; control != null; control = control.ParentInternal)
            {
                Control.ActiveXImpl activeXImpl = (Control.ActiveXImpl)control.Properties.GetObject(Control.PropActiveXImpl);
                if (activeXImpl != null)
                {
                    activeXImpl.UpdateAccelTable();
                    return;
                }
            }
        }
    }
}</code>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796081
引用 张静茹:
TextBox继承自ConTrol
// XXXXXXXXXXXXXXXXXrms.TextBox
public override string Text
{
    get
    {
        return base....
XXXXXXXlectionSet = false;
可能就是这一句出毛病的→_→
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796083
mfc的CEditView实现了查找和替换功能,mfc的完整源代码可在vc/atlmfc/src找到。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796086
引用 acmilan:
mfc的CEditView实现了查找和替换功能,mfc的完整源代码可在vc/atlmfc/src找到。
我自己声明一个类然后继承TextBox,然后自己重写Text属性set方法里写XXXXXXXse.text = value;?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796089
引用 张静茹:
我自己声明一个类然后继承TextBox,然后自己重写Text属性set方法里写XXXXXXXse.text = value;?
[s::L] 没有XXXXXXXse这种用法
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796092
引用 acmilan:
mfc的CEditView实现了查找和替换功能,mfc的完整源代码可在vc/atlmfc/src找到。

只用SetWindowText改变Text还是会自动把光标设置为0 滚动条在最上面,使用你的SetWindowText和我原来办法就完美了~~~
<code class="lang-c">        [DllImport("user32.dll", EntryPoint = "SetWindowText", CharSet = CharSet.Ansi)]
        public static extern int SetWindowText(int hwnd, string lpString);
private void button1_Click(object sender, EventArgs e)
{
    int TextBoxSouSelectionStart = textBox1.SelectionStart;//TextBoxSou光标位置    
    int TextBoxSouSelectionLength = textBox1.SelectionLength;//TextBoxSou选中长度  
    int TextBoxSouScrollPos = GetScrollPos((int)textBox1.Handle, 1);//TextBox滚动条位置 
  
    SetWindowText((int)textBox1.Handle, textBox1.Text + "\r\n" + (Convert.ToUInt32(textBox1.Lines[textBox1.Lines.Length - 1]) + 1));
    textBox1.Focus();
  
    textBox1.SelectionStart = TextBoxSouSelectionStart;
    textBox1.SelectionLength = TextBoxSouSelectionLength;
    SetScrollPos(textBox1.Handle, 1, TextBoxSouScrollPos, true);
    SendMessage(textBox1.Handle, 0x00B6, 0, TextBoxSouScrollPos);
}</code>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 修改于 9年2个月前 IP:四川
796101
引用 张静茹:
没有XXXXXXXse这种用法
c++中调用基类的基类的函数是常见语法(Control::setText)
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796108
引用 张静茹:
只用SetWindowText改变Text还是会自动把光标设置为0 滚动条在最上面,使用你的SetWindowText和我原来办法就完美了~~~
        
        public static extern int Set...
这里应该改成CharSet = XXXXXXXXXXto或CharSet.Unicode。。。不然很多字符都可能变成一堆问号
使用XXXXXXXXXXsi的话,.NET要先把string从unicode转换为ansi字符串,然后调用SetWindowTextA,然后SetWindowTextA再把ansi字符串转换成unicode调用SetWindowTextW。。。与其这样不如直接使用XXXXXXXXXXto或CharSet.Unicode,这样.NET会直接调用SetWindowTextW。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796160
引用 acmilan:
这里应该改成CharSet = XXXXXXXXXXto或CharSet.Unicode。。。不然很多字符都可能变成一堆问号
使用XXXXXXXXXXsi的话,.NET要先把string从unicode转换为ansi字符串,然后调用Set...
恩 是的
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796168
引用 acmilan:
c++中调用基类的基类的函数是常见语法(Control::setText)
这得是Control的setText方法是public吧
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796203
引用 张静茹:
这得是Control的setText方法是public吧
应该protected就行
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796235
引用 acmilan:
应该protected就行
C#的多态特性,TextBox继承TextBoxBase,它再继承Control,TextBox里的Text属性是override修饰的,继承链中的text都被他覆盖了,好像不能访问Control的Text了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796264
引用 张静茹:
C#的多态特性,TextBox继承TextBoxBase,它再继承Control,TextBox里的Text属性是override修饰的,继承链中的text都被他覆盖了,好像不能访问Control的Text了
c++中如果setText是虚函数(可以被子类重写的函数)的话,setText()是call this->vtable[n_setText],而Control::setText()则是call Control::setText。c#的base.Text应该也类似,只是可能不能随意跨级调用而已。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796317
引用 acmilan:
c++中如果setText是虚函数(可以被子类重写的函数)的话,setText()是call this->vtable,而Control::setText()则是call Control::setText。c#的base.Text应该也类似...


<code class="lang-c">typeof(Control).GetProperty("WindowText", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).
    SetValue(textBox1, "在TextBox里显示的内容");</code>

TextBox.Text直接调用TextBoxBase的Text,它再调用Control的Text,然后再给ConTrol的WindowText,这个属性声明为内部,是访问不到的,Text否是子类覆写父类的,子类根本调用不到父类的Text

我用这段代码直接用反射得到了Control的WindowText,然而还是没卵用,修改了textBox1的Text后光标和滚动条还是会动,但是不会全选了,跟直接使用SetWindowText是一样的


刚才又试了一下 这个办法对Label Button是没用的,奇怪他们的Text都是一样的呀,最后都是Control的WindowTex
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796325
引用 张静茹:
typeof(Control).GetProperty("WindowText", XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXnPublic | XXXXXXXXXXXXXXXXXXXXndingFlags.Publ...
XXXXXXXlectionSet = false;应该就是全选的作用。mfc中替换文本的做法好像就是你这么做的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年2个月前 IP:山东
796326
引用 acmilan:
XXXXXXXlectionSet = false;应该就是全选的作用。mfc中替换文本的做法好像就是你这么做的。
应该是的,XXXXXXXlectionSet = false;是在TextBox里的,跳过了TextBox确实不会全选了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan
9年2个月前 IP:四川
796330
引用 张静茹:
应该是的,XXXXXXXlectionSet = false;是在TextBox里的,跳过了TextBox确实不会全选了
→_→我不知道.net加上这一句有什么用
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年1个月前 IP:山东
799045
引用 acmilan:
→_→我不知道.net加上这一句有什么用

终于解决了,这样滚动条就不会变了
<code class="lang-c">var SelectInternal = typeof(RichTextBox).GetMethod("SelectInternal", BindingFlags.Instance | BindingFlags.NonPublic);
SelectInternal.Invoke(richTextBox1, new object[]{1000,1000,1000});//要插入的位置,三个参数 好像必须一样原型:internal virtual void SelectInternal(int start, int length, int textLen)
richTextBox1.SelectedText = "要插入的文本";</code>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
9年1个月前 IP:山东
799120
<code class="lang-c">richTextBox1.Enabled = false;
//Application.DoEvents();
richTextBox1.Rtf = richTextBox2.Rtf;
richTextBox1.Enabled = true;</code>


又发现一个办法
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
张静茹
进士 学者 机友 笔友
文章
139
回复
1869
学术分
1
2010/12/30注册,1个月23天前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}