wpf 学习3

1.播放音乐

 xaml:
//音量进度条
<Slider x:Name="VolumeSlider" Tag="false" Style="{DynamicResource SliderStyle1}" Margin="10,5,0,0" Width="80" HorizontalAlignment="Right"
     Minimum="0" Maximum="1" ValueChanged="VolumeSlider_ValueChanged"/>

cs:
  MediaPlayer mediaPlayer = new MediaPlayer();
  private void PlayMusic(object sender, RoutedEventArgs e)
  {
      string musicPath = "";

      try
      {
          mediaPlayer.Open(new Uri(musicPath));
          mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
          mediaPlayer.Play();
          PausedTextbock.Text = "暂停播放";
          PausedBtn.Click += new RoutedEventHandler(PausedMusic);
      }
      catch (Exception ex)
      {
          MessageBox.Show(ex.Message);
      }
  }
  #region 暂停播放
  private void PausedMusic(object sender, RoutedEventArgs e)
  {
      Button btn = sender as Button;
      if (PausedTextbock.Text.ToString() == "暂停播放")
      {
          mediaPlayer.Pause();
          PausedTextbock.Text = "继续播放";
          PausedBtn.Click -= new RoutedEventHandler(PausedMusic);
          PausedBtn.Click += new RoutedEventHandler(ContinueMusic);
      }

  }
  #endregion
  #region 继续播放
  private void ContinueMusic(object sender, RoutedEventArgs e)
  {
      Button btn = sender as Button;
      if (PausedTextbock.Text.ToString() == "继续播放")
      {
          mediaPlayer.Play();
          PausedTextbock.Text = "暂停播放";
          PausedBtn.Click -= new RoutedEventHandler(ContinueMusic);
          PausedBtn.Click += new RoutedEventHandler(PausedMusic);
      }
  }
  #endregion

   //循环播放
  private void MediaPlayer_MediaEnded(object sender, EventArgs e)
  {
      // MediaElement需要先停止播放才能再开始播放,
      // 否则会停在最后一帧不动
      mediaPlayer.Stop();
      mediaPlayer.Play();
  }
  #region 调整音量
  private void VolumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  {
      mediaPlayer.Volume = (double)VolumeSlider.Value;
      if (VolumeSlider.Tag.ToString() == "true")
      {
          Settings.Default.结束背景音乐音量 = (double)VolumeSlider.Value;
          Settings.Default.Save();
      }
  }
  #endregion

2.开启扩展屏

 1.获取电脑的dpi百分比

根据不同电脑的设置,会有不用的dpi,

电脑分辨率是1920x1080,但页面占满全屏的长,宽是1036x816,这个dpi百分比就是它们的比值

 双屏步骤:
1.主页面“开始双屏”,菜单不显示在第二屏,待机页面出现在第二屏上,(不论主界面的嵌入的是哪个界面)
按钮文字变为“关闭双屏”,点击后关闭双屏

2.开始双屏后,主界面和第二屏都有界面,比如说签到,扩展屏上肯定是有签到页面的,那电脑上还要显示签到页面,(需要显示在第二屏的页面都要写两个,一个显示在电脑上,有按钮操作,另一个是在第二屏上显示,无一些按钮,只显示,但有倒计时)


#region 获取DPI百分比
 public static class ScreenManager
 {
     /// <summary>
     /// 获取DPI百分比
     /// </summary>
     /// <param name="window"></param>
     /// <returns></returns>
     public static double GetDpiRatio(Window window)
     {
         var currentGraphics = Graphics.FromHwnd(new WindowInteropHelper(window).Handle);
         return currentGraphics.DpiX / 96;
     }

     public static double GetDpiRatio()
     {
         return GetDpiRatio(System.Windows.Application.Current.MainWindow);
     }

     public static double GetScreenHeight()
     {
         return SystemParameters.PrimaryScreenHeight * GetDpiRatio();
     }

     public static double GetScreenActualHeight()
     {
         return SystemParameters.PrimaryScreenHeight;
     }

     public static double GetScreenWidth()
     {
         return SystemParameters.PrimaryScreenWidth * GetDpiRatio();
     }

     public static double GetScreenActualWidth()
     {
         return SystemParameters.PrimaryScreenWidth;
     }
 }
 #endregion

2.获取连接的屏

//获取连接的屏的数组
public static System.Windows.Forms.Screen[] screen = System.Windows.Forms.Screen.AllScreens;

 public static void Screen2(Window _window)
 {
     Window window = _window as Window;
     double bili = ScreenManager.GetDpiRatio(window);
     if (window!=null)
     {
        try
          {
             window.Top = 0;   
             window.Left = screen[1].WorkingArea.Left / bili; 
             window.WindowStartupLocation = WindowStartupLocation.Manual;
             window.Width = screen[1].WorkingArea.Width / bili;
             window.Height = screen[1].WorkingArea.Height / bili;
              window.Show();
           }
           catch (Exception ex)
            {
             MessageBox.Show(ex.Message);
            }
     }
 }

//WorkingArea为工作区域

3.弱引用并判断窗口是否打开

子窗口里:
public static WeakReference<MainWindow> mainwindow;

  public HYJM(MainWindow mainWindow)
  {
    InitializeComponent();
    mainwindow = new WeakReference<MainWindow>(mainWindow);
  }

 if (mainwindow.TryGetTarget(out MainWindow target))
 {
   //在这里就可以调用mainwindow里的方法了
     target.mainWindow_Display();
 }

主窗口:
new HYJM(this).show();

4.事务

 OleDbConnection conn = App.GetDbConnection();
 //开启事务
 OleDbTransaction oleDbTransaction = conn.BeginTransaction();
 OleDbCommand cmd = conn.CreateCommand();
 cmd.Transaction = oleDbTransaction;

try
{
    string sql1 = "update biaojue set 序号=" + xuhao2 + " where ID=" + ID1 + "";
    string sql2 = "update biaojue set 序号=" + xuhao1 + " where ID=" + ID2 + "";
    cmd.CommandText = sql1;
    int a = cmd.ExecuteNonQuery();
    cmd.CommandText = sql2;
    int b = cmd.ExecuteNonQuery();
    if (a == 1 && b == 1)
    {
        oleDbTransaction.Commit();
        OleDbDataAdapter adapter = new OleDbDataAdapter();
        adapter.SelectCommand = new OleDbCommand("select a.*,b.表决时间 from biaojue as a left join zhuti as b on a.会议名称=b.会议名称 where a.会议名称='" + comboboxValue + "' order by a.序号", conn);
        DataTable dtfill = new DataTable();
        adapter.Fill(dtfill);
        dt = dtfill;
        datagrid.ItemsSource = App.Fenye(dt, 1, onePageCount).DefaultView;
    }
    else
    {
        oleDbTransaction.Rollback();
    }
}
catch (Exception ex)
{
    oleDbTransaction.Rollback();
    MessageBox.Show(ex.Message);
}
finally
{
    App.CloseDbConnection(conn);
}

5.路由事件,冒泡事件,隧道事件

原文:WPF的路由事件、冒泡事件、隧道事件(预览事件) - 卖雨伞的小男孩 - 博客园 (cnblogs.com)

 1.什么是路由事件

WPF中的事件为路由事件,所谓路由事件,MSDN定义如下:

    功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。

    实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理。

 但这两类定义都比较抽象,我们来看更具体的定义:

<Border Height="50" Width="250" BorderBrush="Gray" BorderThickness="1" >
            <StackPanel Background="LightGray" Orientation="Horizontal" MouseUp="StackPanel_MouseUp">
                <TextBlock Name="YesTB" Width="50"  MouseUp="YesTB_MouseUp" Background="Blue" >Yes</TextBlock>
            </StackPanel>
        </Border>

 在这个例子中,事件的事件路由为:

TextBlock -->StackPanel-->Border —>...

2:中断事件路由      所有的路由事件都共享一个公共的事件数据基类 RoutedEventArgs。 RoutedEventArgs 定义了一个采用布尔值的 Handled 属性。 Handled 属性的目的在于,允许路由中的任何事件处理程序通过将 Handled 的值设置为 true 来将路由事件标记为“已处理”。

private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("Panel");
        }

        private void YesTB_MouseUp(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("button");
            e.Handled = true;
        }

    在上面的例子中,将不再触发StackPanel_MouseUp事件。

3:自定义路由事件

      如下面的示例所示,首先使用 RegisterRoutedEvent 方法注册一个 RoutedEvent。按照约定,RoutedEvent 静态字段名称应当以后缀 Event 结束。在本示例中,事件的名称是 Tap,事件的路由策略是 Bubble。在注册调用之后,可以为该事件提供添加和移除公共语言运行时 (CLR) 事件访问器。

      请注意,尽管该事件在本特定示例中是通过 OnTap 虚方法引发的,但您引发事件的方式或者事件响应更改的方式取决于您的需要。

      还要注意,本示例主要实现 Button 的一整个子类;该子类是作为单独的程序集构建的,之后将在单独的可扩展应用程序标记语言 (XAML) 页上实例化为一个自定义类。这是为了说明这样一个概念:创建子类的控件可以插入到由其他控件组成的树中,在这种情况下,这些控件上的自定义事件具有与任何固有的 Windows Presentation Foundation (WPF) 元素完全相同的事件路由功能。

public class MyButtonSimple: Button
{
    // Create a custom routed event by first registering a RoutedEventID
    // This event uses the bubbling routing strategy
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
        "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

    // Provide CLR accessors for the event
    public event RoutedEventHandler Tap
    {
            add { AddHandler(TapEvent, value); } 
            remove { RemoveHandler(TapEvent, value); }
    }

    // This method raises the Tap event
    void RaiseTapEvent()
    {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MyButtonSimple.TapEvent);
            RaiseEvent(newEventArgs);
    }
    // For demonstration purposes we raise the event when the MyButtonSimple is clicked
    protected override void OnClick()
    {
        RaiseTapEvent();
    }

}
<Window  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"
    x:Class="SDKSample.RoutedEventCustomApp"

    >
    <Window.Resources>
      <Style TargetType="{x:Type custom:MyButtonSimple}">
        <Setter Property="Height" Value="20"/>
        <Setter Property="Width" Value="250"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Background" Value="#808080"/>
      </Style>
    </Window.Resources>
    <StackPanel Background="LightGray">
        <custom:MyButtonSimple Name="mybtnsimple" Tap="TapHandler">Click to see Tap custom event work</custom:MyButtonSimple>
    </StackPanel>
</Window>

4:为什么需要自定义路由事件

      一直到目前看来,我们都不太需要自定义的路由事件。但是,在我们创建自定义控制的时候,创建一些和业务相关的路由事件,就显得很有必要。

      如,创建一个在线考试中的题型展示控件,可以为该控件设计一个自定义事件,为“提交”。这样一来,这个题型控件不仅仅只有一些通用事件,还可以看上去更“业务”。

5:什么是冒泡事件和预览事件(隧道事件)

 路由事件实际上分两类:冒泡事件和预览事件(隧道事件)。上文中的例子就是冒泡事件。

     冒泡事件是WPF路由事件中最为常见,它表示事件从源元素扩散(传播)到可视树,直到它被处理或到达根元素。这样您就可以针对源元素的上方层级对象处理事件。例如,您可向嵌入的 Grid 元素附加一个 Button.Click 处理程序,而不是直接将其附加到按钮本身。气泡事件有指示其操作的名称(例如,MouseDown)。

     隧道事件采用另一种方式,从根元素开始,向下遍历元素树,直到被处理或到达事件的源元素。这样上游元素就可以在事件到达源元素之前先行截取并进行处理。根据命名惯例,隧道事件带有前缀 Preview(例如 PreviewMouseDown)。

     在本文一开始的例子中,如果我们将MouseUP,改为PreviewMouseUP,效果会如何呢。

区别:

     冒泡事件:在YesTB上点击,首先弹出“button”,再弹出“panel”。

     预览事件(隧道事件)事件:在YesTB上点击,首先弹出“panel”,再弹出“button”。

     看到了这点区别,那么我们加入e.Handled=true的时机也要不同。首先,

     冒泡事件例子中:e.Handled=true加在YesTB_PreviewMouseUp中,加入后,点击YesTB,将只弹出“button”。

     预览事件(隧道事件)例子中:e.Handled=true家在StackPanel_PreviewMouseUp中,加入后,点击YesTB,将只弹出“panel”。

由此可得出:

若是在根元素或是上层元素里有preview事件,则在下层元素里的点击事件有时会点击没反应,因为隧道事件是从根元素向下遍历会先到达preview事件,并被截取。 

 6.获取控件相对于窗口的绝对位置

 
            获得textbox相对于窗口的绝对位置 窗口左上角为(0d,0d)
            System.Windows.Point position = c.PointToScreen(new Point(0d, -50d));

            if (position.X < 0 || position.Y < 0)
            {
                MessageBox.Show("1");
            }
            if(position.X+c.Width>this.Width|| position.Y + c.Height > this.Height)
            {
                MessageBox.Show("2");
            }
            var dp = pos - _ZWmouseDownPosition;       

7.拖动控件到屏幕边缘,就不可再拖动

用的是相对于窗口的绝对位置

使用canvas定位

  //鼠标是否按下
   bool _BTisMouseDown = false;
 //鼠标按下的位置
  System.Windows.Point _BTmouseDownPosition;

 double BTaaa = 0;
 double BTbbb = 0;
 private void BTTextbox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
 {
    
     var c = sender as TextBox;
     _BTisMouseDown = true;
     _BTmouseDownPosition = e.GetPosition(this);
    //获得控件的canvas
     BTaaa = Canvas.GetLeft(c);
     BTbbb = Canvas.GetTop(c);

     //_BTmouseDownMargin = c.Margin;
     c.CaptureMouse();
 }
 //鼠标移动触发拖动
 private void BTTextbox_PreviewMouseMove(object sender, MouseEventArgs e)
 {
     if (_BTisMouseDown)
     {
         var c = sender as TextBox;
         var pos = e.GetPosition(this);
         var dp = pos - _BTmouseDownPosition;

         //dp为鼠标在x,y轴上移动了多少
         double aa = BTaaa+dp.X;
         double bb = BTbbb+dp.Y;
         if (aa < 0)   //控件移到左边缘
         {
             aa = 0;
         }
         if (aa + c.Width > this.Width)  //控件移到右边缘
         {
             aa = this.Width - c.Width;
         }

         if (bb < 0)
         {
             bb = 0;
         }
         if (bb > this.Height - c.Height)
         {
             bb = this.Height - c.Height;
         }

         Canvas.SetLeft(c, aa);
         Canvas.SetTop(c, bb);
         
         //c.Margin = new Thickness(_BTmouseDownMargin.Left + dp.X, _BTmouseDownMargin.Top + dp.Y, _BTmouseDownMargin.Right - dp.X, _BTmouseDownMargin.Bottom - dp.Y);
     }
 }
 //鼠标弹起屏蔽消息
 private void BTTextbox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
 {
     var c = sender as TextBox;
     _BTisMouseDown = false;
     c.ReleaseMouseCapture();
 }

8.打印

参考:

用WPF实现打印及打印预览 - guogangj - 博客园 (cnblogs.com)

WPF 打印实例 - Gnie - 博客园 (cnblogs.com)

1.单个页面打印

 cs:
打印datagrid里的数据,datagrid是name名称

private void Print(object sender, RoutedEventArgs e)
 {
     PrintDialog printDialog = new PrintDialog();
     if (printDialog.ShowDialog() == true)
     {
         printDialog.PrintVisual(datagrid, "结果统计");
     }
 }

2.多个页面打印

可参考:WPF打印Xaml页面 多页打印 XpsDocumentViewer_wpf 打印-CSDN博客

没实际实现,不知道可以不

9.导入txt

   #region 导入议题(txt)
   private void DaoRu_Click(object sender, RoutedEventArgs e)
   {
       OpenFileDialog openFile = new OpenFileDialog();
       openFile.Filter = "文本文件(*.txt)|*.txt|(*.rtf)|*.rtf";
       if (openFile.ShowDialog() == true)
       {
           Encoding encoding = GetTextFileEncodingType(openFile.FileName);
           using (StreamReader sr = new StreamReader(openFile.FileName, encoding))
           {
               string temp;
               Regex regex = new Regex(@"\d*\.");   //正则表达式判断是否是以数字加点(例如:1.开头的)
               string start = "false";
               string yiti = "";
               string descrip = "";
             
               try
               {
                   while ((temp = sr.ReadLine()) != null)
                   {
                      //temp就是读取的一行数据

                      // System.Text.RegularExpressions.Match match = regex.Match(temp);
                       //if (match.Success) 
                      // {
                         //  if (start == "true")
                         //  {
                               descrip = "";
                             //  yiti = "";
                          // }
                           //yiti = regex.Replace(temp, "");
                           //count++;
                      // }
                      // else
                      // {
                        //   descrip += temp;
                      // }
                      // start = "true";
                   }
                   //if (start == "true")
                  // {
                      // InsertYiTi(yiti, descrip, conn, successCount, HYName);
                  // }

               }
               catch (Exception ex)
               {
                   MessageBox.Show(ex.Message);
               }
               finally
               {
                   MessageBox.Show("匹配到" + count + "条数据,导入成功" + count + "条");
               }
           }
       }
   }

   #region 获取编码方式
   /// <summary>
   /// 获取文本文件的字符编码类型
   /// </summary>
   /// <param name="fileName"></param>
   /// <returns></returns>
   static Encoding GetTextFileEncodingType(string fileName)
   {
       Encoding encoding = Encoding.Default;
       FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
       BinaryReader binaryReader = new BinaryReader(fileStream, encoding);
       byte[] buffer = binaryReader.ReadBytes((int)fileStream.Length);
       binaryReader.Close();
       fileStream.Close();
       if (buffer.Length >= 3 && buffer[0] == 239 && buffer[1] == 187 && buffer[2] == 191)
       {
           encoding = Encoding.UTF8;
       }
       else if (buffer.Length >= 3 && buffer[0] == 254 && buffer[1] == 255 && buffer[2] == 0)
       {
           encoding = Encoding.BigEndianUnicode;
       }
       else if (buffer.Length >= 3 && buffer[0] == 255 && buffer[1] == 254 && buffer[2] == 65)
       {
           encoding = Encoding.Unicode;
       }
       else if (IsUTF8Bytes(buffer))
       {
           encoding = Encoding.UTF8;
       }
       return encoding;
   }

   /// <summary>
   /// 判断是否是不带 BOM 的 UTF8 格式
   /// BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码。
   /// </summary>
   /// <param name="data"></param>
   /// <returns></returns>
   private static bool IsUTF8Bytes(byte[] data)
   {
       int charByteCounter = 1; //计算当前正分析的字符应还有的字节数 
       byte curByte; //当前分析的字节. 
       for (int i = 0; i < data.Length; i++)
       {
           curByte = data[i];
           if (charByteCounter == 1)
           {
               if (curByte >= 0x80)
               {
                   //判断当前 
                   while (((curByte <<= 1) & 0x80) != 0)
                   {
                       charByteCounter++;
                   }
                   //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
                   if (charByteCounter == 1 || charByteCounter > 6)
                   {
                       return false;
                   }
               }
           }
           else
           {
               //若是UTF-8 此时第一位必须为1 
               if ((curByte & 0xC0) != 0x80)
               {
                   return false;
               }
               charByteCounter--;
           }
       }
       if (charByteCounter > 1)
       {
           throw new Exception("非预期的byte格式");
       }
       return true;
   }
   #endregion
   #endregion

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值