WPF篇(13)-ScrollViewer控件+ScrollBar滚动条+Slider滑动条

ScrollViewer控件

如果某个控件的尺寸太大,当前界面无法全部显示,则可以将这个控件包含在ScrollViewer中,因为ScrollViewer控件封装了一个水平滚动条ScrollBar和一个垂直滚动条ScrollBar,所以,ScrollViewer就是一个包含其它可视元素的可滚动区域控件。

ScrollViewer继承于ContentControl,所以它也是一个内容控件,只能在Content属性中设置一个子元素,如果要在ScrollViewer中显示多个子元素,请设置一个集合控件。

ScrollViewer 控件既响应鼠标命令,也响应键盘命令,并定义许多可用于按预设的增量滚动内容的方法。 可以使用 ScrollChanged 事件来检测 ScrollViewer 状态的变化。

属性成员

  • HorizontalScrollBarVisibility:是否隐藏水平滚动条,为true表示隐藏,此时水平方向不可滚动。
  • VerticalScrollBarVisibility:是否隐藏垂直滚动条,为true表示隐藏,此时垂直方向不可滚动。

事件成员

  • ScrollChanged:当控件的滚动位置发生变化时将触发此事件。

示例

xml 复制代码
<ScrollViewer VerticalScrollBarVisibility="Auto">
        <WrapPanel>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
                        <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
        </WrapPanel>
    </ScrollViewer>

如上所示,我们在WrapPanel中增加了许多子元素,然后在外面套了一层ScrollViewer,由于WrapPanel是自动换行显示所有子元素(图片),所以,ScrollViewer会做出相应适配,只显示垂直滚动条。

xml 复制代码
<ScrollViewer HorizontalScrollBarVisibility="Auto">
        <WrapPanel>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
                        <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
        </WrapPanel>
    </ScrollViewer>

ScrollBar滚动条

ScrollBar表示一个滚动条,该滚动条具有一个滑动 Thumb,其位置对应于一个值。它继承于RangeBase抽象基类,RangeBase基类继承于Control基类。带滚动特质的还有两个控件,也继承于RangeBase抽象基类,它们分别是ProgressBar(进度条)和Slider(滑动条)

RangeBase属性

  • LargeChange:表示给Value属性加减的最大值。默认为1。
  • SmallChange:表示给Value属性加减的最小值。默认为0.1。
  • Value:获取或设置范围控件的当前数量。默认为0。
  • Maximum:获取或设置Value属性的最大值。
  • Minimum:获取或设置Value属性的最小值。

RangeBase事件成员

ValueChanged:当前Value属性发生改变时触发的事件。

注意:ScrollBar、ProgressBar和Slider都将继承上面的属性、方面与事件成员。

ScrollBar自身属性

ScrollBar自身有两个属性,Orientation 和ViewportSize 。

  • Orientation :表示当前滚动条是水平的还是垂直的。
  • ViewportSize:获取或设置当前可见的可滚动内容的数量。默认值为0。

另外,它还有一个滚动事件Scroll可以使用。

举例

前端代码

xml 复制代码
<Grid x:Name="viewport" >
        <Grid.RowDefinitions>
            <RowDefinition Height="115"/>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Canvas>
            <StackPanel x:Name="element" Orientation="Horizontal" Canvas.Left="{Binding CanvasLeft}">
               <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
                        <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" Width="100" Height="100"/>
            </Border>
            </StackPanel>
        </Canvas>        
        <ScrollBar Grid.Row="1" Orientation="Horizontal" 
                   Maximum="{Binding Maximum}"
                   Value="{Binding X}"
                   ViewportSize="{Binding ElementName=viewport,Path=ActualWidth}"/>
        <TextBlock Grid.Row="2" Text="ScrollBar" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
    </Grid>

观察这个UI设计,在StackPanel控件中增加了多张图片,使其不能完全在Canvas中显示出来,然后在下面实例化了一根水平滚动条。注意滚动条的其中三个参数使用了绑定。

  • Maximum:表示这根滚动条的最大值。

  • Value:表示滚动条的当前值。

  • ViewportSize:表示滚动条要作用于某个控件的宽度(这里实际上指Grid的宽度)。

最后,我们将StackPanel控件的Canvas.Left依赖属性绑定到一个CanvasLeft属性。只要CanvasLeft属性的值发生改变,那么StackPanel相对于Canvas水平位置就发生改变。

那么CanvasLeft属性是怎样发生改变的呢?这一切将在后台代码中实现。

后端代码

csharp 复制代码
 /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;//将当前窗体作为ViewModel赋值给当前窗体的DataContext
            Loaded += (s, e) =>
            {
                //计算滚动条的最大值
                Maximum = element.ActualWidth - viewport.ActualWidth;
            };
        }
 
        private double maximum = 0;
        /// <summary>
        /// 滚动条的最大值
        /// </summary>
        public double Maximum
        {
            get { return maximum; }
            set { maximum = value; NotifyPropertyChanged("Maximum"); }
        }
 
        private double x = 0;
        /// <summary>
        /// 滚动条的当前值
        /// </summary>
        public double X
        {
            get { return x; }
            set { x = value; CanvasLeft = -x; NotifyPropertyChanged("X"); }
        }
 
        private double canvasLeft = 0;
        /// <summary>
        /// 相对于Canvas控件Left边距
        /// </summary>
        public double CanvasLeft
        {
            get { return canvasLeft; }
            set { canvasLeft = value; NotifyPropertyChanged("CanvasLeft"); }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        /// <summary>
        /// 属性通知方法
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

如果把下面这段代码换成Slider控件,也是可以用的:

更换前

xml 复制代码
<ScrollBar Grid.Row="1" Orientation="Horizontal" 
                   Maximum="{Binding Maximum}"
                   Value="{Binding X}"
                   ViewportSize="{Binding ElementName=viewport,Path=ActualWidth}"/>

更换后

xml 复制代码
<Slider Grid.Row="1" Maximum="{Binding Maximum}" Value="{Binding X}"/>

Slider滑动条

Slider滑动条与ScrollBar滚动条有点相似,甚至某些情况下,两者还可以互换使用。Slider也继承于RangeBase基类,其功能是提供一个可以滑动取值的控件。

属性成员

  • IsSnapToTickEnabled:Slider会有一些刻度线,如果要求Thumb移动到最近的刻度线,则可将该值设置为true。
  • AutoToolTipPrecision:获取或设置Slider的值的小数点位数。
  • AutoToolTipPlacement :获取或设置按下Thumb时是否显示提示工具。
  • Interval :获取或设置用户按下RepeatButton时执行增加减少命令的时间间隔(毫秒)。
  • Delay :获取或设置用户按下RepeatButton时延时多少毫秒后执行命令
  • IsDirectionReversed: 获取或设置增加值的方向。
  • Orientation :获取或设置Slider的方向。水平或垂直。
  • TickFrequency: 获取或设置刻度线之间的间隔。默认为1.0
  • Ticks: 获取或设置为 System.Windows.Controls.Slider 显示的刻度线的位置。
  • SelectionStart: 获取或设置 System.Windows.Controls.Slider 的指定选择内容的最大值。
  • TickPlacement: 获取或设置刻度线的位置
  • IsSelectionRangeEnabled: 获取或设置显示选择范围
  • IsMoveToPointEnabled: 如果Thumb 立即移动到鼠标单击的位置,则为true。
  • SelectionEnd :获取或设置 System.Windows.Controls.Slider 的指定选择内容的最大值。

示例

csharp 复制代码
 <Grid x:Name="viewport" >
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Canvas>
            <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Padding="3" Margin="3">
                <Image Source="pack://application:,,,/Images/R-C.jpg" 
                       Width="{Binding ElementName=slider,Path=Value}" 
                       Height="{Binding ElementName=slider,Path=Value}"/>
            </Border>
        </Canvas>
        <DockPanel Grid.Row="1">
            <TextBlock Text="滑动改变图片大小" Margin="3" FontSize="14"/>
            <Slider x:Name="slider" Minimum="50" Maximum="500" Value="50" Margin="3"/>
        </DockPanel>        
    </Grid>
相关推荐
小新同学^O^7 小时前
简单学习 --> 模型参数
学习·llm·大模型参数
cdbqss17 小时前
VB2026 菜单生成基类 BqGetMenuStrip
数据库·经验分享·学习·oracle·vb
吃好睡好便好9 小时前
创建魔方矩阵和单位矩阵
开发语言·人工智能·学习·线性代数·matlab·矩阵
星夜夏空999 小时前
STM32单片机学习(21) —— I2C通信
stm32·单片机·学习
searchforAI11 小时前
B站视频转笔记用哪个工具?2026年四款AI笔记工具对比实测
人工智能·经验分享·笔记·gpt·学习·视频总结·ai笔记
爱上好庆祝11 小时前
学习JS第十一天(JS的进阶)
前端·javascript·学习
yeiweilan12 小时前
AI应用学习
学习
吃好睡好便好12 小时前
矩阵的加减运算
开发语言·人工智能·学习·线性代数·算法·matlab·矩阵
她说彩礼65万12 小时前
WPF视觉树 逻辑树
wpf
Mister西泽12 小时前
C++ Primer Plus 第六版 编程练习题及详细答案
开发语言·c++·学习·visual studio