WPF 基础控件之托盘

 WPF 基础控件之托盘

控件名:NotifyIcon

作者: WPFDevelopersOrg  - 吴锋|驚鏵

原文链接:    https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022

  • 项目使用 MIT 开源许可协议。

  • 新建NotifyIcon自定义控件继承自FrameworkElement

  • 创建托盘程序主要借助与 Win32API[1]:

    • 注册窗体对象RegisterClassEx

    • 注册消息获取对应消息标识Id RegisterWindowMessage

    • 创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)CreateWindowEx

  • 以下2点需要注意:

    • 托盘控件的ContextMenu菜单MenuItem 在使用binding时无效,是因为DataContext没有带过去,需要重新赋值一次。

    • 托盘控件发送ShowBalloonTip消息通知时候需新建Shell_NotifyIcon

  • Nuget 最新[2]Install-Package WPFDevelopers 1.0.9.1-preview

8209a681c196e903927c377d1d2fa9d2.png

1) NotifyIcon.cs 代码如下:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using WPFDevelopers.Controls.Runtimes;
using WPFDevelopers.Controls.Runtimes.Interop;
using WPFDevelopers.Controls.Runtimes.Shell32;
using WPFDevelopers.Controls.Runtimes.User32;namespace WPFDevelopers.Controls
{public class NotifyIcon : FrameworkElement, IDisposable{private static NotifyIcon NotifyIconCache;public static readonly DependencyProperty ContextContentProperty = DependencyProperty.Register("ContextContent", typeof(object), typeof(NotifyIcon), new PropertyMetadata(default));public static readonly DependencyProperty IconProperty =DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NotifyIcon),new PropertyMetadata(default, OnIconPropertyChanged));public static readonly DependencyProperty TitleProperty =DependencyProperty.Register("Title", typeof(string), typeof(NotifyIcon),new PropertyMetadata(default, OnTitlePropertyChanged));public static readonly RoutedEvent ClickEvent =EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,typeof(RoutedEventHandler), typeof(NotifyIcon));public static readonly RoutedEvent MouseDoubleClickEvent =EventManager.RegisterRoutedEvent("MouseDoubleClick", RoutingStrategy.Bubble,typeof(RoutedEventHandler), typeof(NotifyIcon));private static bool s_Loaded = false;private static NotifyIcon s_NotifyIcon;//这是窗口名称private readonly string _TrayWndClassName;//这个是窗口消息名称private readonly string _TrayWndMessage;//这个是窗口消息回调(窗口消息都需要在此捕获)private readonly WndProc _TrayWndProc;private Popup _contextContent;private bool _doubleClick;//图标句柄private IntPtr _hIcon = IntPtr.Zero;private ImageSource _icon;private IntPtr _iconHandle;private int _IsShowIn;//托盘对象private NOTIFYICONDATA _NOTIFYICONDATA;//这个是传递给托盘的鼠标消息idprivate int _TrayMouseMessage;//窗口句柄private IntPtr _TrayWindowHandle = IntPtr.Zero;//通过注册窗口消息可以获取唯一标识Idprivate int _WmTrayWindowMessage;private bool disposedValue;public NotifyIcon(){_TrayWndClassName = $"WPFDevelopers_{Guid.NewGuid()}";_TrayWndProc = WndProc_CallBack;_TrayWndMessage = "TrayWndMessageName";_TrayMouseMessage = (int)WM.USER + 1024;Start();if (Application.Current != null){//Application.Current.MainWindow.Closed += (s, e) => Dispose();Application.Current.Exit += (s, e) => Dispose();}NotifyIconCache = this;}static NotifyIcon(){DataContextProperty.OverrideMetadata(typeof(NotifyIcon), new FrameworkPropertyMetadata(DataContextPropertyChanged));ContextMenuProperty.OverrideMetadata(typeof(NotifyIcon), new FrameworkPropertyMetadata(ContextMenuPropertyChanged));}private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) =>((NotifyIcon)d).OnDataContextPropertyChanged(e);private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e){UpdateDataContext(_contextContent, e.OldValue, e.NewValue);UpdateDataContext(ContextMenu, e.OldValue, e.NewValue);}private void UpdateDataContext(FrameworkElement target, object oldValue, object newValue){if (target == null || BindingOperations.GetBindingExpression(target, DataContextProperty) != null) return;if (ReferenceEquals(this, target.DataContext) || Equals(oldValue, target.DataContext)){target.DataContext = newValue ?? this;}}private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var ctl = (NotifyIcon)d;ctl.OnContextMenuPropertyChanged(e);}private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e) =>UpdateDataContext((ContextMenu)e.NewValue, null, DataContext);public object ContextContent{get => GetValue(ContextContentProperty);set => SetValue(ContextContentProperty, value);}public ImageSource Icon{get => (ImageSource)GetValue(IconProperty);set => SetValue(IconProperty, value);}public string Title{get => (string)GetValue(TitleProperty);set => SetValue(TitleProperty, value);}public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (d is NotifyIcon trayService)trayService.ChangeTitle(e.NewValue?.ToString());}private static void OnIconPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (d is NotifyIcon trayService){var notifyIcon = (NotifyIcon)d;notifyIcon._icon = (ImageSource)e.NewValue;trayService.ChangeIcon();}}public event RoutedEventHandler Click{add => AddHandler(ClickEvent, value);remove => RemoveHandler(ClickEvent, value);}public event RoutedEventHandler MouseDoubleClick{add => AddHandler(MouseDoubleClickEvent, value);remove => RemoveHandler(MouseDoubleClickEvent, value);}private static void Current_Exit(object sender, ExitEventArgs e){s_NotifyIcon?.Dispose();s_NotifyIcon = default;}public bool Start(){RegisterClass(_TrayWndClassName, _TrayWndProc, _TrayWndMessage);LoadNotifyIconData(string.Empty);Show();return true;}public bool Stop(){//销毁窗体if (_TrayWindowHandle != IntPtr.Zero)if (User32Interop.IsWindow(_TrayWindowHandle))User32Interop.DestroyWindow(_TrayWindowHandle);//反注册窗口类if (!string.IsNullOrWhiteSpace(_TrayWndClassName))User32Interop.UnregisterClassName(_TrayWndClassName, Kernel32Interop.GetModuleHandle(default));//销毁Iconif (_hIcon != IntPtr.Zero)User32Interop.DestroyIcon(_hIcon);Hide();return true;}/// <summary>///     注册并创建窗口对象/// </summary>/// <param name="className">窗口名称</param>/// <param name="messageName">窗口消息名称</param>/// <returns></returns>private bool RegisterClass(string className, WndProc wndproccallback, string messageName){var wndClass = new WNDCLASSEX{cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)),style = 0,lpfnWndProc = wndproccallback,cbClsExtra = 0,cbWndExtra = 0,hInstance = IntPtr.Zero,hCursor = IntPtr.Zero,hbrBackground = IntPtr.Zero,lpszMenuName = string.Empty,lpszClassName = className};//注册窗体对象User32Interop.RegisterClassEx(ref wndClass);//注册消息获取对应消息标识id_WmTrayWindowMessage = User32Interop.RegisterWindowMessage(messageName);//创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)_TrayWindowHandle = User32Interop.CreateWindowEx(0, className, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero,IntPtr.Zero, IntPtr.Zero);return true;}/// <summary>///     创建托盘对象/// </summary>/// <param name="icon">图标路径,可以修改托盘图标(本质上是可以接受用户传入一个图片对象,然后将图片转成Icon,但是算了这个有点复杂)</param>/// <param name="title">托盘的tooltip</param>/// <returns></returns>private bool LoadNotifyIconData(string title){lock (this){_NOTIFYICONDATA = NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);if (_TrayMouseMessage != 0)_NOTIFYICONDATA.uCallbackMessage = (uint)_TrayMouseMessage;else_TrayMouseMessage = (int)_NOTIFYICONDATA.uCallbackMessage;if (_iconHandle == IntPtr.Zero){var processPath = Kernel32Interop.GetModuleFileName(new HandleRef());if (!string.IsNullOrWhiteSpace(processPath)){var index = IntPtr.Zero;var hIcon = Shell32Interop.ExtractAssociatedIcon(IntPtr.Zero, processPath, ref index);_NOTIFYICONDATA.hIcon = hIcon;_hIcon = hIcon;}}if (!string.IsNullOrWhiteSpace(title))_NOTIFYICONDATA.szTip = title;}return true;}private bool Show(){var command = NotifyCommand.NIM_Add;if (Thread.VolatileRead(ref _IsShowIn) == 1)command = NotifyCommand.NIM_Modify;elseThread.VolatileWrite(ref _IsShowIn, 1);lock (this){return Shell32Interop.Shell_NotifyIcon(command, ref _NOTIFYICONDATA);}}internal static int AlignToBytes(double original, int nBytesCount){var nBitsCount = 8 << (nBytesCount - 1);return ((int)Math.Ceiling(original) + (nBitsCount - 1)) / nBitsCount * nBitsCount;}private static byte[] GenerateMaskArray(int width, int height, byte[] colorArray){var nCount = width * height;var bytesPerScanLine = AlignToBytes(width, 2) / 8;var bitsMask = new byte[bytesPerScanLine * height];for (var i = 0; i < nCount; i++){var hPos = i % width;var vPos = i / width;var byteIndex = hPos / 8;var offsetBit = (byte)(0x80 >> (hPos % 8));if (colorArray[i * 4 + 3] == 0x00)bitsMask[byteIndex + bytesPerScanLine * vPos] |= offsetBit;elsebitsMask[byteIndex + bytesPerScanLine * vPos] &= (byte)~offsetBit;if (hPos == width - 1 && width == 8) bitsMask[1 + bytesPerScanLine * vPos] = 0xff;}return bitsMask;}private byte[] BitmapImageToByteArray(BitmapImage bmp){byte[] bytearray = null;try{var smarket = bmp.StreamSource;if (smarket != null && smarket.Length > 0){//设置当前位置smarket.Position = 0;using (var br = new BinaryReader(smarket)){bytearray = br.ReadBytes((int)smarket.Length);}}}catch (Exception ex){}return bytearray;}private byte[] ConvertBitmapSourceToBitmapImage(BitmapSource bitmapSource){byte[] imgByte = default;if (!(bitmapSource is BitmapImage bitmapImage)){bitmapImage = new BitmapImage();var encoder = new BmpBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(bitmapSource));using (var memoryStream = new MemoryStream()){encoder.Save(memoryStream);memoryStream.Position = 0;bitmapImage.BeginInit();bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.StreamSource = memoryStream;bitmapImage.EndInit();imgByte = BitmapImageToByteArray(bitmapImage);}}return imgByte;}internal static IconHandle CreateIconCursor(byte[] xor, int width, int height, int xHotspot,int yHotspot, bool isIcon){var bits = IntPtr.Zero;BitmapHandle colorBitmap = null;var bi = new BITMAPINFO(width, -height, 32){bmiHeader_biCompression = 0};colorBitmap = Gdi32Interop.CreateDIBSection(new HandleRef(null, IntPtr.Zero), ref bi, 0, ref bits, null, 0);if (colorBitmap.IsInvalid || bits == IntPtr.Zero) return IconHandle.GetInvalidIcon();Marshal.Copy(xor, 0, bits, xor.Length);var maskArray = GenerateMaskArray(width, height, xor);var maskBitmap = Gdi32Interop.CreateBitmap(width, height, 1, 1, maskArray);if (maskBitmap.IsInvalid) return IconHandle.GetInvalidIcon();var iconInfo = new Gdi32Interop.ICONINFO{fIcon = isIcon,xHotspot = xHotspot,yHotspot = yHotspot,hbmMask = maskBitmap,hbmColor = colorBitmap};return User32Interop.CreateIconIndirect(iconInfo);}private bool ChangeIcon(){var bitmapFrame = _icon as BitmapFrame;if (bitmapFrame != null && bitmapFrame.Decoder != null)if (bitmapFrame.Decoder is IconBitmapDecoder){//var iconBitmapDecoder = new Rect(0, 0, _icon.Width, _icon.Height);//var dv = new DrawingVisual();//var dc = dv.RenderOpen();//dc.DrawImage(_icon, iconBitmapDecoder);//dc.Close();//var bmp = new RenderTargetBitmap((int)_icon.Width, (int)_icon.Height, 96, 96,//    PixelFormats.Pbgra32);//bmp.Render(dv);//BitmapSource bitmapSource = bmp;//if (bitmapSource.Format != PixelFormats.Bgra32 && bitmapSource.Format != PixelFormats.Pbgra32)//    bitmapSource = new FormatConvertedBitmap(bitmapSource, PixelFormats.Bgra32, null, 0.0);var w = bitmapFrame.PixelWidth;var h = bitmapFrame.PixelHeight;var bpp = bitmapFrame.Format.BitsPerPixel;var stride = (bpp * w + 31) / 32 * 4;var sizeCopyPixels = stride * h;var xor = new byte[sizeCopyPixels];bitmapFrame.CopyPixels(xor, stride, 0);var iconHandle = CreateIconCursor(xor, w, h, 0, 0, true);_iconHandle = iconHandle.CriticalGetHandle();}if (Thread.VolatileRead(ref _IsShowIn) != 1)return false;if (_hIcon != IntPtr.Zero){User32Interop.DestroyIcon(_hIcon);_hIcon = IntPtr.Zero;}lock (this){if (_iconHandle != IntPtr.Zero){var hIcon = _iconHandle;_NOTIFYICONDATA.hIcon = hIcon;_hIcon = hIcon;}else{_NOTIFYICONDATA.hIcon = IntPtr.Zero;}return Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify, ref _NOTIFYICONDATA);}}private bool ChangeTitle(string title){if (Thread.VolatileRead(ref _IsShowIn) != 1)return false;lock (this){_NOTIFYICONDATA.szTip = title;return Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify, ref _NOTIFYICONDATA);}}public static void ShowBalloonTip(string title, string content, NotifyIconInfoType infoType){if (NotifyIconCache != null)NotifyIconCache.ShowBalloonTips(title, content, infoType);}public void ShowBalloonTips(string title, string content, NotifyIconInfoType infoType){if (Thread.VolatileRead(ref _IsShowIn) != 1)return;var _ShowNOTIFYICONDATA = NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);_ShowNOTIFYICONDATA.uFlags = NIFFlags.NIF_INFO;_ShowNOTIFYICONDATA.szInfoTitle = title ?? string.Empty;_ShowNOTIFYICONDATA.szInfo = content ?? string.Empty;switch (infoType){case NotifyIconInfoType.Info:_ShowNOTIFYICONDATA.dwInfoFlags = NIIFFlags.NIIF_INFO;break;case NotifyIconInfoType.Warning:_ShowNOTIFYICONDATA.dwInfoFlags = NIIFFlags.NIIF_WARNING;break;case NotifyIconInfoType.Error:_ShowNOTIFYICONDATA.dwInfoFlags = NIIFFlags.NIIF_ERROR;break;case NotifyIconInfoType.None:_ShowNOTIFYICONDATA.dwInfoFlags = NIIFFlags.NIIF_NONE;break;}Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify, ref _ShowNOTIFYICONDATA);}private bool Hide(){var isShow = Thread.VolatileRead(ref _IsShowIn);if (isShow != 1)return true;Thread.VolatileWrite(ref _IsShowIn, 0);lock (this){return Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Delete, ref _NOTIFYICONDATA);}}private IntPtr WndProc_CallBack(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam){//这是窗口相关的消息if ((int)msg == _WmTrayWindowMessage){}else if ((int)msg == _TrayMouseMessage) //这是托盘上鼠标相关的消息{switch ((WM)(long)lParam){case WM.LBUTTONDOWN:break;case WM.LBUTTONUP:WMMouseUp(MouseButton.Left);break;case WM.LBUTTONDBLCLK:WMMouseDown(MouseButton.Left, 2);break;case WM.RBUTTONDOWN:break;case WM.RBUTTONUP:OpenMenu();break;case WM.MOUSEMOVE:break;case WM.MOUSEWHEEL:break;}}else if (msg == WM.COMMAND){}return User32Interop.DefWindowProc(hwnd, msg, wParam, lParam);}private void WMMouseUp(MouseButton button){if (!_doubleClick && button == MouseButton.Left)RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice,Environment.TickCount, button){RoutedEvent = ClickEvent});_doubleClick = false;}private void WMMouseDown(MouseButton button, int clicks){if (clicks == 2){RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice,Environment.TickCount, button){RoutedEvent = MouseDoubleClickEvent});_doubleClick = true;}}private void OpenMenu(){if (ContextContent != null){_contextContent = new Popup{Placement = PlacementMode.Mouse,AllowsTransparency = true,StaysOpen = false,UseLayoutRounding = true,SnapsToDevicePixels = true};_contextContent.Child = new ContentControl{Content = ContextContent};UpdateDataContext(_contextContent, null, DataContext);_contextContent.IsOpen = true;User32Interop.SetForegroundWindow(_contextContent.Child.GetHandle());}else if (ContextMenu != null){if (ContextMenu.Items.Count == 0) return;ContextMenu.InvalidateProperty(StyleProperty);foreach (var item in ContextMenu.Items)if (item is MenuItem menuItem){menuItem.InvalidateProperty(StyleProperty);}else{var container = ContextMenu.ItemContainerGenerator.ContainerFromItem(item) as MenuItem;container?.InvalidateProperty(StyleProperty);}ContextMenu.Placement = PlacementMode.Mouse;ContextMenu.IsOpen = true;User32Interop.SetForegroundWindow(ContextMenu.GetHandle());}}protected virtual void Dispose(bool disposing){if (!disposedValue){if (disposing)Stop();disposedValue = true;}}}public enum NotifyIconInfoType{/// <summary>///     No Icon./// </summary>None,/// <summary>///     A Information Icon./// </summary>Info,/// <summary>///     A Warning Icon./// </summary>Warning,/// <summary>///     A Error Icon./// </summary>Error}
}

2) NotifyIconExample.xaml 代码如下:

  • ContextMenu 使用如下:

<wpfdev:NotifyIcon Title="WPF开发者"><wpfdev:NotifyIcon.ContextMenu><ContextMenu><MenuItem Header="托盘消息" Click="SendMessage_Click"/><MenuItem Header="退出" Click="Quit_Click"/></ContextMenu></wpfdev:NotifyIcon.ContextMenu></wpfdev:NotifyIcon>
  • ContextContent 使用如下:

<wpfdev:NotifyIcon Title="WPF开发者"><wpfdev:NotifyIcon.ContextContent><Border CornerRadius="3" Margin="10" Background="{DynamicResource BackgroundSolidColorBrush}" Effect="{StaticResource NormalShadowDepth}"><StackPanel VerticalAlignment="Center" Margin="16"><Rectangle Width="100" Height="100"><Rectangle.Fill><ImageBrush ImageSource="pack://application:,,,/Logo.ico"/></Rectangle.Fill></Rectangle><StackPanel Margin="0,16,0,0" HorizontalAlignment="Center" Orientation="Horizontal"><Button MinWidth="100" Content="关于" Style="{DynamicResource PrimaryButton}" Command="{Binding GithubCommand}" /><Button Margin="16,0,0,0" MinWidth="100" Content="退出" Click="Quit_Click"/></StackPanel></StackPanel></Border></wpfdev:NotifyIcon.ContextContent></wpfdev:NotifyIcon>

3) NotifyIconExample.cs 代码如下:

  • ContextMenu 使用如下:

private void Quit_Click(object sender, RoutedEventArgs e){Application.Current.Shutdown();}private void SendMessage_Click(object sender, RoutedEventArgs e){NotifyIcon.ShowBalloonTip("Message", " Welcome to WPFDevelopers.Minimal ", NotifyIconInfoType.None);}
  • ContextContent 使用如下:

private void Quit_Click(object sender, RoutedEventArgs e){Application.Current.Shutdown();}private void SendMessage_Click(object sender, RoutedEventArgs e){NotifyIcon.ShowBalloonTip("Message", " Welcome to WPFDevelopers.Minimal ", NotifyIconInfoType.None);}

 鸣谢 - 吴锋

d37bbee4574ca70d7907e9dd31c7f493.gif

Github|NotifyIcon[3]
码云|NotifyIcon[4]

参考资料

[1]

Win32API: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw

[2]

Nuget : https://www.nuget.org/packages/WPFDevelopers/

[3]

Github|NotifyIcon: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/MainWindow.xaml

[4]

码云|NotifyIcon: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/MainWindow.xaml

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 匿名 异常_JAVA类(内部类、匿名内部类、异常、自定义异常)

内部类package AA;public class类 {int de123;StringBuffer deenewStringBuffer();public class成员内部类{public voidff() {System.out.println("这是成员内部类方法");}}/*1.可以访问外部类所有的成员&#xff0c;包括被声明为私有(private)的&#xff1b;2.可以使…

ASP.NET 多环境下配置文件web.config的灵活配置---转

注意&#xff1a;本功能在.Net Core中已经不可用&#xff0c;暂时需手动修改web.config中的信息&#xff0c;或者将其设置在appsettings.XXX.json中&#xff0c;然后再使用web.config中的环境变量来制定使用的具体appsettings文件。 转自&#xff1a;https://www.cnblogs.com/h…

Uranium UI Kit

Uranium UI Kit控件名&#xff1a;Uranium UI Ki作者&#xff1a;enisn原文链接&#xff1a; https://github.com/enisn/UraniumUI项目使用 Apache-2.0 开源许可协议。Uranium 是用于 .NET MAUI 的免费和开源 UI 工具包。它提供了一组控件和实用程序来构建现代应用程序。它建…

《Java多线程编程核心技术》读后感(十五)

线程的状态 线程对象在不同的运行时期有不同的状态&#xff0c;状态信息就存在与State枚举类中。 验证New,Runnable&#xff0c;Terminated new:线程实例化后还从未执行start()方法时的状态 runnable&#xff1a;线程进入运行的状态 terminated&#xff1a;线程被销毁时的状态 …

队列(queue)

队列(queue)和栈一样支持push和pop两个操作。但与栈不同的是,pop两个操作。但与栈的不同的是&#xff0c;pop完成的不是取出最顶端的元素&#xff0c;而是最底端的元素。也就是说最初放入的元素能够最先被取出&#xff08;这种行为被叫做FIFO:First In First Out&#xff0c;即…

一题多解,ASP.NET Core应用启动初始化的N种方案[上篇]

ASP.NET Core应用本质上就是一个由中间件构成的管道&#xff0c;承载系统将应用承载于一个托管进程中运行起来&#xff0c;其核心任务就是将这个管道构建起来。在ASP.NET Core的发展历史上先后出现了三种应用承载的编程方式&#xff0c;而且后一种编程模式都提供了针对之前编程…

WPF 简单模仿 VSCode 界面布局

WPF 简单模仿 VSCode 界面布局本文经原作者授权以原创方式二次分享&#xff0c;欢迎转载、分享。WPF 简单模仿 VSCode 界面布局作者&#xff1a;弈虎-吕女士会翻墙原文链接&#xff1a; https://github.com/Chen-Lin-Zhao-Wei/WPFLikeVSCode分享一篇群友这几天自己写的 WPF 简…

compare()方法+使用compare方法

compare()方法 compare(lob1,lob2,amount,offset_1,offset_2) 1用于比较2个lob存储的数据&#xff0c;比较的方式是从指定偏移量开始&#xff0c;对指定数量的字符或者字节进行比较。 2如果比较内容相同&#xff0c;返回0&#xff0c;否则返回-1或1. 3如果参数设置有误或不合…

linux 下 mysql默认表_linux环境下mysql默认是区分表名大小写的

在linux环境下&#xff0c;mysql默认表明是区分大小写的&#xff0c;我们可以查看全局变量发现:mysql> show variables like lower%;-------------------------------| Variable_name | Value |-------------------------------| lower_case_file_system | OFF || lower_cas…

两将军问题和TCP三次握手

两将军问题&#xff0c;又被称为两将军悖论、两军问题&#xff0c; 是一个经典的计算机思想实验。首先&#xff0c; 为避免混淆&#xff0c;我们需要认识到两将军问题虽然与拜占庭将军问题相关&#xff0c;但两者不是一个东西。拜占庭将军问题是一个更通用的两将军问题版本&…

微信小程序开发系列五:微信小程序中如何响应用户输入事件

2019独角兽企业重金招聘Python工程师标准>>> 微信小程序开发系列教程 微信小程序开发系列一&#xff1a;微信小程序的申请和开发环境的搭建 微信小程序开发系列二&#xff1a;微信小程序的视图设计 微信小程序开发系列三&#xff1a;微信小程序的调试方法 微信小程序…

理解Object.defineProperty的作用

Object.defineProperty 是vue中双向绑定的基础。vue是通过数据劫持的方式来做数据绑定的&#xff0c;最核心的方法是通过 Object.defineProperty()方法来实现对属性的劫持&#xff0c;达到能监听到数据的变动。要实现数据的双向绑定&#xff0c; 当使用存取器描述属性的特性的时…

直播修仙:使用.NET 的 WebView2 如何获取请求的响应内容,以微信直播的互动直播为例...

背景近几年直播行业快速发展&#xff0c;门槛也越来越低&#xff0c;越来越的人涌入直播大军。不得不说&#xff0c;直播不仅带来了更多的娱乐消遣&#xff0c;还提供了一个新型的就业方式。说起直播的类型&#xff0c;有一个非常小众的娱乐直播&#xff0c;没有主播&#xff0…

web第6次作业position

position 属性指定了元素的定位类型。 position 属性的五个值&#xff1a; static &#xff08;静态定位&#xff09; HTML元素的默认值&#xff0c;即没有定位&#xff0c;元素出现在正常的流中。 静态定位的元素不会受到 top, bottom, left, right影响。 div.stati…

GeneralUpdate版本更新公告20221009

大家好我是juster&#xff0c;GeneralUpdate的开源项目作者。这次将发布GeneralUpdate兼容.NET MAUI和多平台为核心的版本。经过国庆假期的打磨修复了大量开源社区开发者的提交的bug和不合理修改建议&#xff0c;重构、删除了大量代码和结构使用和上一个版本没有太大变化。1.更…

实验2 java_《Java程序设计》实验2

1、使用java语言编程&#xff0c;从键盘输入N个整数存储到数组中&#xff0c;求数组所有元素的和、最大值和平均值。import java.util.Scanner;public class Program01{public static void main(String [] args){Scanner scanner new Scanner(System.in);System.out.println(&…

WPF遍历当前容器中某种控件的方法

原文:WPF遍历当前容器中某种控件的方法版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/m0_37591671/article/details/79528845 WPF遍历当前容器中某种控件的方法 WPF遍历当前容器中某种控件的方法1.目的&#xff1a;2.实现思…

善用Object.defineProperty巧妙找到修改某个变量的准确代码位置

2019独角兽企业重金招聘Python工程师标准>>> 我今天的工作又遇到一个难题。前端UI右下角这个按钮被设置为"禁用(disabled)"状态。 这个按钮的可用状态由属性enabled控制。我通过调试发现&#xff0c;一旦下图第88行代码执行完毕之后&#xff0c;这个按钮的…

使用 C# 开发的轻量级开源数据库 LiteDB

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具或组件&#xff0c;希望对您有用&#xff01;简介 LiteDB 是一个小型、快速、轻量级的 .NET NoSQL 嵌入式数据库&#xff0c;也就是我们常说的 K/V 数据库&#xff0c;完全用 C# …

微信小程序仿微信SlideView组件slide-view

微信小程序仿微信SlideView组件。 使用 1、安装 slide-view 从小程序基础库版本 2.2.1 或以上、及开发者工具 1.02.1808300 或以上开始&#xff0c;小程序支持使用 npm 安装第三方包。 npm install --save miniprogram-slide-view2、在需要使用 slide-view 的页面 page.json 中…