試著建立看看吧

在 Extension(RC+ 自定義)中,提供了可將自定義功能整合至 Epson RC+ 的機制(擴展點),例如新增選單項目、管理專案檔案、顯示停駐視窗等。
這些功能是透過將 Extensions API 所提供的擴展點介面,以 .NET 內建的擴展框架 Managed Extensibility Framework(MEF)的 Export 形式實作來運作。
建立 Extension 專案時,可以將欲使用的擴展點作為 Initial Feature 進行選擇,專案建立後亦可作為新項目新增。

此處將說明擴展點實作方法的一例,並說明從建立 RC+ Extensions 專案到在 Epson RC+ 中使用為止的流程。

以下步驟中,將在 Extension 的停駐視窗配置按鈕,並建立使用 Extension API 的介面進行控制器連線/切斷的範例。

  1. 請依照「開始使用」的步驟,建立 Extension 的新專案。

    • 名稱設為 ConnectControllerSample。
    • 初始功能請勾選 Main menu and tool bar item、以及 Docking window
    • 於 ARM64 版 Windows 上,請將組態設為 x64。
  2. 請於 Visual Studio 上進行建置與除錯,確認功能可正常運作。

    • 於 Epson RC+ 主選單的擴展標籤下的選單項目中會新增ConnectControllerSample (xx)(xx)(xx 為顯示語言名稱),選取該項目後若能顯示停駐視窗即表示設定成功。
  3. 範本確認完成後,請結束 Epson RC+。

  4. 於 Visual Studio 上編輯 DockingWindow 資料夾下的 DockingWindowContent.xaml 檔案。

    • 在自動產生並配置的 TextBlock 下方 Grid 內,新增控制器連線的 Button、以及控制器切斷的 Button。
    • 請留意 TextBlock 的 Text。其綁定至 Captions[WindowHeader].Value。於 Extension 中,欲依 Epson RC+ 顯示語言進行在地化的字串,請記述於 Captions.xlsx。詳細內容將於後述說明,透過使用 Captions.xlsx 的 symbol 欄定義名稱(本例為 WindowHeader),並同樣進行繫結,即可依 Epson RC+ 的顯示語言進行在地化。
    <UserControl x:Class="ConnectControllerSample.DockingWindow.DockingWindowContent"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:local="clr-namespace:ConnectControllerSample.DockingWindow"
                 mc:Ignorable="d"
                 d:DesignHeight="450" d:DesignWidth="800">
    
        <UserControl.DataContext>
            <local:DockingWindowContentViewModel />
        </UserControl.DataContext>
    
        <DockPanel
            Background="White"
            LastChildFill="True">
    
            <TextBlock
                Margin="3,0,0,0"
                DockPanel.Dock="Top"
                FontSize="24"
                FontWeight="Bold"
                Foreground="DarkBlue"
                Text="{Binding Captions[WindowHeader].Value}" />
    
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
    
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
    
                <Button
                    x:Name="ConnectButton"
                    Grid.Row="0"
                    Grid.Column="0"
                    Margin="4"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Command="{Binding ConnectCommand}"
                    Content="Connect Controller" />
    
                <Button
                    x:Name="DisconnectButton"
                    Grid.Row="0"
                    Grid.Column="1"
                    Margin="4"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Command="{Binding DisconnectCommand}"
                    Content="Disconnect Controller" />
            </Grid>
    
        </DockPanel>
    
    </UserControl>
    
  5. 請編輯 DockingWindow 資料夾下的 DockingWindowContentViewModelAddition.cs 檔案。

    • 在 .xaml 中,新增繫結至控制器連線與切斷 Button 的 ConnectCommand、以及 DisconnectCommand 命令。
    • 透過參照 IRCXControllerConnectionAPI(控制器連線 API)的 IsOnline 屬性,即可確認與機器人控制器的連線狀態。IsOnline 於連線建立時為 true,斷線時為 false,其他(如連線建立中等中間狀態)為 null。
    • 與機器人控制器的連線,會呼叫 IRCXControllerConnectionAPI 的 ConnectControllerAsync 方法。與機器人控制器的切斷,會呼叫控制器連線 API 的 DisconnectControllerAsync 方法。
    • 訊息方塊的顯示,會呼叫 IRCXWindowAPI(視窗 API)的 ShowMessageBox 方法。
    • 在建構函式中,透過 Main 類別的 GetAPI 方法,從 MEF 的容器取得 IRCXControllerConnectionAPI、以及 IRCXWindowAPI 的實例。
    (前略)
    namespace ConnectControllerSample.DockingWindow
    {
        /// <summary>
        /// Extension : Docking Window (Specific Part)
        /// </summary>
        internal partial class DockingWindowContentViewModel
        {
            /// <summary>
            /// Connect controller command
            /// </summary>
            public AsyncReactiveCommand ConnectCommand { get; } = new AsyncReactiveCommand();
    
            /// <summary>
            /// Disconnect controller command
            /// </summary>
            public AsyncReactiveCommand DisconnectCommand { get; } = new AsyncReactiveCommand();
    
            /// <summary>
            /// Window-related API
            /// </summary>
            private IRCXWindowAPI _windowAPI;
    
            /// <summary>
            /// Controller Connection API
            /// </summary>
            private IRCXControllerConnectionAPI _connectionAPI;
    
            /// <summary>
            /// Constructor
            /// </summary>
            public DockingWindowContentViewModel()
            {
                _windowAPI = Main.GetAPI<IRCXWindowAPI>();
                _connectionAPI = Main.GetAPI<IRCXControllerConnectionAPI>();
    
                ConnectCommand.Subscribe(OnConnect);
                DisconnectCommand.Subscribe(OnDiscconect);
            }
    
            private async Task OnConnect()
            {
                if (_connectionAPI.IsOnline == false)
                {
                    var result = await _connectionAPI.ConnectControllerAsync();
    
                    _windowAPI.ShowMessageBox(
                        new RCXCaption(Main.CommonId, Caption.ExtensionName),
                        new RCXCaption(result ? "Controller connection succeed." : "Controller connection failed."),
                        IRCXWindowAPI.ButtonType.OK,
                        IRCXWindowAPI.IconType.Information);
                }
                else
                { 
                    _windowAPI.ShowMessageBox(
                        new RCXCaption(Main.CommonId, Caption.ExtensionName),
                        new RCXCaption("The controller cannot be connected."),
                        IRCXWindowAPI.ButtonType.OK,
                        IRCXWindowAPI.IconType.Warning);
                }
            }
    
            private async Task OnDiscconect()
            {
                if (_connectionAPI.IsOnline == true)
                {
                    await _connectionAPI.DisconnectControllerAsync();
                }
                else
                {
                    _windowAPI.ShowMessageBox(
                        new RCXCaption(Main.CommonId, Caption.ExtensionName),
                        new RCXCaption("The controller cannot be disconnected."),
                        IRCXWindowAPI.ButtonType.OK,
                        IRCXWindowAPI.IconType.Warning);
                }
            }
    
            /// <inheritdoc />
            public Task WindowCreated()
            {
                return Task.CompletedTask;
            }
        }
    }
    
  6. 編輯專案資料夾根目錄下的 Captions.xlsx 檔案。

    • 修改 symbol 欄為 WindowHeader 的行中各語言的標題。

  7. 請重新建置與除錯。

    • 在啟動的 Epson RC+ 中,點擊已開發 Extension 的選單或工具列圖示,顯示所建立的 DockingWindow。
    • 確認於畫面上方顯示在對應目前 Epson RC+ 語言的 Captions.xlsx 中所設置的標題。
    • 確認可透過 [Connect Controller] 按鈕與 [Disconnect Controller] 按鈕進行控制器連線與切斷。
  8. 在 Visual Studio 上編輯 PackageItems 資料夾中的 manifest.rcxmanifest。

    • 修改 Vendor Info, Extension Name, Summary, Description 行中各語言的字串。

  9. 依照 [Extension 的發布] 的步驟,在擴展功能管理器中顯示已開發的 Extension。

    • 確認畫面上顯示在對應目前 Epson RC+ 語言的 manifest.rcxmanifest 中所設置的資訊。
  10. 依照 [Extension 的使用] 步驟,啟用 Extension,並確認可使用已開發的功能。