一个跨平台的`ChatGPT`悬浮窗工具

这篇具有很好参考价值的文章主要介绍了一个跨平台的`ChatGPT`悬浮窗工具。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一个跨平台的ChatGPT悬浮窗工具

使用avalonia实现的ChatGPT的工具,设计成悬浮窗,并且支持插件。

如何实现悬浮窗?

在使用avalonia实现悬浮窗也是非常的简单的。

实现我们需要将窗体设置成无边框

Window根节点添加一下属性,想要在Linux下生效请务必添加SystemDecorations属性

ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="-1"
SystemDecorations="None"

这样我们的窗口就设置成了无边框。

然后我们还需要将窗体的大小固定,

Height="50"
MaxHeight="50"
Width="{Binding Width}"
MaxWidth="{Binding Width}"

高度固定,宽度绑定到ViewModelWidth属性中,默认270

接下来给出所有代码,

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:Gotrays.Suspension.Client.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:valueConverter="clr-namespace:Gotrays.Suspension.Client.ValueConverter"
        xmlns:md="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
        xmlns:avedit="https://github.com/avaloniaui/avaloniaedit"
        xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Gotrays.Suspension.Client.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        ExtendClientAreaToDecorationsHint="True"
        ExtendClientAreaChromeHints="NoChrome"
        ExtendClientAreaTitleBarHeightHint="-1"
        SystemDecorations="None"
        WindowStartupLocation="CenterScreen"
        Height="50"
        MaxHeight="50"
        Width="{Binding Width}"
        MaxWidth="{Binding Width}"
        Icon="/Assets/ai.png"
        Title="Gotrays.Suspension.Client">

    <Window.Resources>
        <valueConverter:ImageConverter x:Key="ImageConverter" />
        <valueConverter:ChatToStyleConverter x:Key="ChatToStyleConverter" />
    </Window.Resources>

    <Design.DataContext>
        <vm:MainWindowViewModel />
    </Design.DataContext>

    <Window.Styles>
        <Style Selector="Window">
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Padding" Value="0" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderBrush" Value="Transparent" />
        </Style>
        <Style Selector="TextBox.red:pointerover">
            <Setter Property="Opacity" Value="1" />
        </Style>
    </Window.Styles>

    <Border Name="MainBorder" CornerRadius="1000" Background="Black" Margin="0,0,0,0" Padding="0,0,0,0"
            HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="50">
        <Grid>
            <!-- 图标 -->
            <Image Source="../Assets/ai.png" Name="Logo" HorizontalAlignment="Left" VerticalAlignment="Center"
                   Width="46"
                   Tapped="Logo_OnTapped"
                   RenderOptions.BitmapInterpolationMode="HighQuality"
                   PointerPressed="OnLogoClick"
                   PointerEntered="Logo_OnPointerEntered"
                   PointerExited="Logo_OnPointerExited"
                   Height="46" Margin="0,0,0,0" />

            <!-- 模型选择 -->
            <Popup Name="ModulePopup" IsOpen="False" PlacementTarget="{Binding ElementName=MainBorder}"
                   PlacementMode="Top">
                <StackPanel Margin="5">
                    <Border Background="#1F1F1F" BorderBrush="Black" BorderThickness="1" CornerRadius="12"
                            MaxHeight="400" Width="120">
                        <ScrollViewer Name="ModuleScrollViewer" VerticalScrollBarVisibility="Auto">
                            <ItemsControl CornerRadius="12" ItemsSource="{Binding Modules}" Margin="2">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Border Margin="5"
                                                Background="{Binding Color}"
                                                PointerExited="OnSelectStackPointerExited"
                                                PointerEntered="OnSelectStackPointerEntered"
                                                PointerPressed="OnSelectStackPointerPressed"
                                                Tag="{Binding GetThis}"
                                                CornerRadius="8">
                                            <!-- 左边显示图标,右边显示名称 -->
                                            <StackPanel Orientation="Horizontal">
                                                <Image
                                                    RenderOptions.BitmapInterpolationMode="HighQuality"
                                                    Source="{Binding Icon, Converter={StaticResource ImageConverter}}"
                                                    HorizontalAlignment="Left"
                                                    Width="20"
                                                    Height="20" />
                                                <TextBlock TextWrapping="Wrap" Width="60" Text="{Binding Title}"
                                                           Margin="5" Foreground="White" />
                                            </StackPanel>
                                        </Border>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Border>
                </StackPanel>
            </Popup>

            <!-- 静止状态下的搜索按钮 -->
            <Border PointerPressed="SearchBorder_OnPointerPressed"
                    PointerEntered="searchBorder_PointerEnter"
                    PointerExited="OnPointerExited"
                    Name="searchBorder"
                    CornerRadius="1000" Background="#000000" BorderBrush="#FFFFFF"
                    BorderThickness="1" Margin="50,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Left"
                    VerticalAlignment="Center" Width="46" Height="46" Cursor="Hand">
                <Image Source="../Assets/search.png"
                       RenderOptions.BitmapInterpolationMode="HighQuality"
                       HorizontalAlignment="Center" VerticalAlignment="Center"
                       Width="20" Height="20" Margin="0,0,0,0" />
            </Border>

            <!-- 当点击搜索按钮时,显示搜索框 -->
            <TextBox FontSize="20" Name="SearchText" Margin="50,0,0,0" IsVisible="False" Width="0" Height="40"
                     HorizontalAlignment="Left" VerticalAlignment="Center">
                <TextBox.Styles>
                    <Styles>
                        <Style Selector="TextBox">
                            <Setter Property="CornerRadius" Value="0,50,50,0"></Setter>
                        </Style>
                    </Styles>
                </TextBox.Styles>
                <TextBox.Transitions>
                    <Transitions>
                        <DoubleTransition Property="Width" Duration="0:0:0.1" />
                    </Transitions>
                </TextBox.Transitions>
            </TextBox>
            <!-- 消息显示区域 -->
            <Popup x:Name="MessagePopup"
                   IsOpen="False"
                   PlacementTarget="{Binding ElementName=MainBorder}"
                   PlacementMode="Bottom">
                <StackPanel
                    PointerEntered="MessagePopup_OnPointerEntered"
                    PointerExited="MessagePopup_OnPointerExited" Margin="5">
                    <Border Name="MessageBorder"
                            Background="#1F1F1F"
                            BorderBrush="Black"
                            BorderThickness="1"
                            CornerRadius="12"
                            MaxHeight="300">
                        <ScrollViewer Name="ScrollViewer" VerticalScrollBarVisibility="Auto">
                            <ItemsControl ItemsSource="{Binding Messages}" CornerRadius="12" Margin="2">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <StackPanel Margin="5">
                                            <StackPanel.Resources>
                                                <valueConverter:ChatToBackgroundConverter
                                                    x:Key="ChatToBackgroundConverter" />
                                            </StackPanel.Resources>
                                            <Border
                                                Background="{Binding Chat, Converter={StaticResource ChatToBackgroundConverter}}"
                                                CornerRadius="5">

                                                <md:MarkdownScrollViewer
                                                    VerticalAlignment="Stretch"
                                                    MarkdownStyleName="Standard"
                                                    SaveScrollValueWhenContentUpdated="True"
                                                    Markdown="{Binding Message}">
                                                    <md:MarkdownScrollViewer.Styles>

                                                        <Style Selector="ctxt|CCode">
                                                            <Style.Setters>
                                                                <Setter Property="BorderBrush" Value="Green" />
                                                                <Setter Property="BorderThickness" Value="2" />
                                                                <Setter Property="Padding" Value="2" />
                                                                <Setter Property="MonospaceFontFamily" Value="Meiryo" />
                                                                <Setter Property="Foreground" Value="DarkGreen" />
                                                                <Setter Property="Background" Value="LightGreen" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="Border.CodeBlock">
                                                            <Style.Setters>
                                                                <Setter Property="BorderBrush" Value="Blue" />
                                                                <Setter Property="BorderThickness" Value="0,5,0,5" />
                                                                <Setter Property="Margin" Value="5,0,5,0" />
                                                                <Setter Property="Background" Value="LightBlue" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="TextBlock.CodeBlock">
                                                            <Style.Setters>
                                                                <Setter Property="Foreground" Value="DarkBlue" />
                                                                <Setter Property="FontFamily" Value="Meiryo" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="avedit|TextEditor">
                                                            <Setter Property="Background" Value="Gray" />
                                                            <Setter Property="CornerRadius" Value="10"></Setter>
                                                        </Style>

                                                    </md:MarkdownScrollViewer.Styles>
                                                </md:MarkdownScrollViewer>
                                            </Border>
                                        </StackPanel>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Border>
                </StackPanel>
            </Popup>

        </Grid>
        <Border.Transitions>
            <Transitions>
                <DoubleTransition Property="Width" Duration="0:0:0.2" />
            </Transitions>
        </Border.Transitions>
    </Border>

</Window>

只需要设置无边框并且固定大小。悬浮窗的效果就达到了。

我们看看执行效果

image-20230702133719931

就这样简单的悬浮窗写好了,我们使用一下悬浮窗的搜索功能

image-20230702133757221

这个就是简单的使用效果,对比其他的工具,这个悬浮窗更简洁,并且跨平台和开源。

image-20230702133839454

目前的项目结构。

plugin下面的项目是默认的插件,用于搜索系统文件(未完善)

Gotrays.Suspension.Client则是实际的客户端。

Gotrays.Suspension.PlugIn则是插件定义的接口规范。

Gotrays.Update则是检查更新程序,用于更新主程序。

实现插件

plug-in

插件模块,用于扩展功能。

插件开发

1. 创建插件项目

在解决方案中创建一个类库项目,项目名称以Gotrays.Suspension.PlugIn.开头,例如Gotrays.Suspension.PlugIn.Test
然后在项目中依赖Gotrays.Suspension.PlugIn类库。

2. 创建插件类

在项目中创建一个类,继承Gotrays.Suspension.PlugIn.PlugInBase类,例如:

using Gotrays.Suspension.PlugIn;

public class SystemTools : PlugInBase
{
    public SystemTools()
    {
        Name = "系统搜索";

​        // 获取system.png嵌入资源的Stream
​        var stream = GetType().Assembly.GetManifestResourceStream("SystemTools.system.png");
​        if (stream == null) return;

​        // 读取Stream到byte数组
​        var bytes = new byte[stream.Length];
​        var read = stream.Read(bytes, 0, bytes.Length);
​        Icon = bytes;
​    }

​    // 搜索触发
​    public override async Task SearchAsync(string value)
​    {
​        // 打开系统搜索
​        Process.Start("explorer.exe", "search://" + value);

​        await Task.CompletedTask;
​    }
​    
​    protected override async Task InitAsync(IServiceCollection services){
​        // 插件首次加载时执行
​    }
​    public override async Task BuilderServiceAsync(IServiceProvider provider)
​    {
​        // 这里可以得到服务提供者,可以通过服务提供者获取其他服务
​    }
​    protected override void Selection()
​    {
​        //  当插件被选中时执行
​    }
​    
​    protected override void UnSelection()
​    {
​        // 当插件被取消选中时执行
​    }
​    
​    protected override async Task UnloadAsync()
​    {
​        // 当插件被卸载插件发生
​    }
​    
}

工具服务会进行自动发现,无需手动注册。
只需要将程序集放置在./plug-in目录下即可。
服务会在一个程序集中发现所有的插件类,并且进行注册。

按照上面的方式非常的简单就集成了插件。

开源地址

Gitee:https://gitee.com/gotrays/gotrays-suspension

Github:https://github.com/239573049/Suspension
技术交流群:737776595文章来源地址https://www.toymoban.com/news/detail-514252.html

到了这里,关于一个跨平台的`ChatGPT`悬浮窗工具的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 好用的跨平台同步笔记工具,手机和电脑可同步的笔记工具

    在这个快节奏的工作环境中,每个人都在寻找一种方便又高效的方式来记录工作笔记。记录工作笔记可以帮助大家统计工作进展,了解工作进程,而如果工作中常在一个地方办公,直接选择电脑或者手机中笔记工具来记录即可,但是对于那些时常在不同地区出差的工作族,一

    2024年01月18日
    浏览(31)
  • 开源的跨平台的音视频处理工具FFmpeg

    FFmpeg是一个开源的跨平台的音视频处理工具,可以对音频、视频进行转码、裁剪、调节音量、添加水印等操作。 广泛的格式支持。 FFmpeg能够解码、编码、转码、复用、分离、流式传输、过滤和播放几乎人类和机器所创造的任何内容。它支持最古老且晦涩难懂的格式,也支持

    2024年02月15日
    浏览(38)
  • 一个基于.NET Core开源、跨平台的仓储管理系统

    今天给大家推荐一个基于.NET Core开源、跨平台的仓储管理系统,数据库支持MSSQL/MySQL:ZEQP.WMS。 仓储管理系统(Warehouse Management System,WMS)是一种用于管理和控制仓库操作的软件系统,它可以帮助企业实现对仓库内物品的跟踪、存储、拣选、包装和发运等全过程管理,提高仓

    2024年02月21日
    浏览(40)
  • 【Dotnet 工具箱】跨平台图表库 LiveCharts2

    你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用! LiveCharts2 是一个简单、灵活、交互式以及功能强大的跨平台图表库。 LiveCharts2 现在几乎可以在任何地方运行,包括 Maui、Uno Platform、Blazor-wasm、WPF、WinForms、Xamarin、Avalonia、WinUI、UWP。 Liv

    2023年04月13日
    浏览(42)
  • DBeaver:开源、跨平台、强大的数据库管理工具

    1.DBeaver 是什么 DBeaver 是一个流行的开源数据库客户端,它可以用于连接和管理多种不同类型的数据库系统,包括 MySQL、PostgreSQL、Oracle、Microsoft SQL Server 等等。 DBeaver 提供了一种直观的用户界面,允许用户执行各种数据库操作,如查询、修改、备份等等,同时也提供了一些高

    2024年01月25日
    浏览(55)
  • C#一个开源跨平台的 HTTP 客户端库——RestSharp

    GitHub - restsharp/RestSharp: Simple REST and HTTP API Client for .NET Simple REST and HTTP API Client for .NET. Contribute to restsharp/RestSharp development by creating an account on GitHub. https://github.com/restsharp/RestSharp          在进行软件开发的时侯,你可能经常需要使用一些公共的Web Api接口执行 CRUD 操作;要

    2024年02月13日
    浏览(41)
  • 一个现代化轻量级的跨平台Redis桌面客户端

    大家好,我是 Java陈序员 。 Redis 作为一款高性能的非关系型数据库,可是深受开发者的喜爱,无论是什么开发,都能看到 Redis 的身影。 今天,给大家介绍一款跨平台的 Redis 客户端连接工具,功能强大,界面美观! 关注微信公众号:【Java陈序员】,获取开源项目分享、AI副

    2024年04月08日
    浏览(72)
  • 无损剪切音视频文件的跨平台工具: LosslessCut | 开源日报 0908

    Stars: 17.3k License: GPL-2.0 LosslessCut是一款跨平台的FFmpeg GUI工具,它可以对视频、音频和字幕等相关媒体文件进行快速无损操作。 该软件最主要的功能是无损剪切和裁剪音视频文件,可以使用它快速提取出好的部分并丢弃其余片段而不会损失质量,这非常适合用于处理从摄像机、

    2024年02月07日
    浏览(28)
  • WEB跨平台桌面程序构建工具对比(Electron、Tauri、Wails)

    WEB 跨平台 桌面应用程序 顾名思义就是用 JavaScript、HTML、CSS 等前端技术构建跨平台的桌面应用,WEB 负责 GUI 渲染并与后端(如 Node.js、Python、Rust 等)交互,从而突破自身无法操作 OS 层级资源的限制。其实现在如火如荼的 小程序 原理也类似,只是把后端换成宿主 APP (如微信

    2024年02月05日
    浏览(38)
  • 一个基于.NET Core构建的简单、跨平台、模块化的商城系统

    今天大姚给大家分享一个基于.NET Core构建的简单、跨平台、模块化、完全开源免费(MIT License)的商城系统:Module Shop。 商品:分类、品牌、单位、选项(销售属性)、属性、属性模板、属性组。 销售:订单、物流。 内容:首页配置、评论、回复。 配置:国家、用户、仓库

    2024年03月27日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包