zoukankan      html  css  js  c++  java
  • 图解使用Win8Api进行Metro风格的程序开发十二上下文菜单

      我们紧接着上篇,这篇将介绍如何使用Windows.UI.Popups API,创建PopupMenu菜单
    和处理oncontextmenu事件.
    -----------------------------------我是华丽的分割线-----------------------------------------
    我们紧接着上篇,这篇将介绍如何使用Windows.UI.Popups API,创建PopupMenu菜单
    和处理oncontextmenu事件.

    本篇将介绍如下2个方面:
      a)为一个文件创建一个上下文菜单
      b)在显示文本中替换原来的上下文菜单

    我们的创建的步骤如下:
      1)为了组织文件方便,我们先建一个文件夹ContextMenu
      2)向文件夹中添加如下文件:
        ShowAContextMenu.xaml,ReplaceADefaultContextMenu.xaml
      创建方法请参照前一篇.
    3)此时的解决方案结构如下:

    4)向我们的DataSource添加导航所需要的信息
      修改我们的SampleDataSource.cs文件中的SampleDataSource类中的代码,
      代码如下: 

    View Code
            public SampleDataSource()
            {
                #region Group1
                var group1 = new SampleDataGroup("FilePicker",
                  "Use Windows.Storage.Pickers API",
                  "Access and save files using the file picker",
                  "Assets/FilePicker.jpg",
                  "");
                group1.Items.Add(new SampleDataItem("FilePicker-PickASinglePhoto",
                        "Pick a single photo",
                        "only one file can selected,file type is jpg,jpeg,png",
                        "Assets/FilePicker.jpg",
                        "only one file can selected ",
                        "",
                        group1,
                        typeof(PickASinglePhoto)));
                group1.Items.Add(new SampleDataItem("FilePicker-PickMultipleFiles",
                        "Pick multiple files",
                        "you can pick multiple files",
                        "Assets/FilePicker.jpg",
                        "pick multiple files",
                        "",
                        group1,
                        typeof(PickMultipleFiles)));
                group1.Items.Add(new SampleDataItem("FilePicker-PickAFolder",
                        "Pick a folder",
                        "you can pick a folder",
                        "Assets/FilePicker.jpg",
                        "Pick a folder",
                        "",
                        group1,
                        typeof(PickAFolder)));
                group1.Items.Add(new SampleDataItem("FilePicker-SaveAFile",
                        "Save a file",
                        "you can save a file",
                        "Assets/FilePicker.jpg",
                        "Save a file",
                        "",
                        group1,
                        typeof(SaveAFile)));
                this.AllGroups.Add(group1);
                #endregion
    
                #region Group2
                var group2 = new SampleDataGroup("FileAceess",
               "Using Windows.Storage API",
               "File access",
               "Assets/FileAccess.jpg",
               "");
                group2.Items.Add(new SampleDataItem("FileAceess-CreatingAFile",
                        "Create a file",
                        "Using CreateFileAsync Create a file",
                        "Assets/FileAccess.jpg",
                        "Using CreateFileAsync",
                        "",
                        group2,
                        typeof(CreatingAFile)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingText",
                   "Write And Read A Text",
                   "Using WriteTextAsync,ReadTextAsync Write And Read  Text",
                   "Assets/FileAccess.jpg",
                   "Using WriteTextAsync,ReadTextAsync",
                   "",
                   group2,
                   typeof(WritingAndReadingText)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingBytes",
                  "Writing and reading bytes in a file",
                  "Using WriteBufferAsync,ReadBufferAsync Write And Read bytes",
                  "Assets/FileAccess.jpg",
                  "Using WriteBufferAsync,ReadBufferAsync",
                  "",
                  group2,
                  typeof(WritingAndReadingBytes)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingUsingStream",
                    "Writing and reading using a stream",
                    "Using OpenAsync Writing and reading using a stream",
                    "Assets/FileAccess.jpg",
                    "Using OpenAsync",
                    "",
                    group2,
                    typeof(WritingAndReadingUsingStream)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-DisplayingFileProperties",
                    "Displaying file properties",
                    "Using GetBasicPropertiesAsync  Get File Properties",
                    "Assets/FileAccess.jpg",
                    "Using GetBasicPropertiesAsync",
                    "",
                    group2,
                    typeof(DisplayingFileProperties)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-PersistingAccess",
                    "Persisting access to a storage item for future use",
                    "Using MostRecentlyUsedList",
                    "Assets/FileAccess.jpg",
                    "Using MostRecentlyUsedList",
                    "",
                    group2,
                    typeof(PersistingAccess)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-CopyAFile",
                    "Copy a file",
                    "Using CopyAsync Copy a file",
                    "Assets/FileAccess.jpg",
                    "Using CopyAsync",
                    "",
                    group2,
                    typeof(CopyAFile)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-DeleteAFile",
                    "Delete a file",
                    "Using DeleteAsync Delete a file",
                    "Assets/FileAccess.jpg",
                    "Using DeleteAsync",
                    "",
                    group2,
                    typeof(DeleteAFile)));
    
                this.AllGroups.Add(group2);
                #endregion
    
                #region Group3
                var group3 = new SampleDataGroup("AccountPictureName",
                  "Use Windows.System.UserProfile API",
                  "Account Picture Name",
                  "Assets/AccountPictureName.jpg",
                  "");
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetUserDisplayName",
                        "Get User DisplayName",
                        "Use UserInformation.GetDisplayNameAsync Get User DisplayName",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetDisplayNameAsync",
                        "",
                        group3,
                        typeof(GetUserDisplayName)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetUserFirstLastName",
                        "Get First Last Name",
                        "Use UserInformation.GetFirstNameAsync,GetLastNameAsync Get First Name",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetFirstNameAsync ",
                        "",
                        group3,
                        typeof(GetUserFirstLastName)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetAccountPicture",
                        "Get Account Picture",
                        "Use UserInformation.GetAccountPicture Get Account Picture",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetAccountPicture",
                        "",
                        group3,
                        typeof(GetAccountPicture)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-SetAccountPictureAndListen",
                        "Set AccountPicture And Listen",
                        "Use UserInformation.SetAccountPicturesAsync Set AccountPicture",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.SetAccountPicturesAsync",
                        "",
                        group3,
                        typeof(SetAccountPictureAndListen)));
                this.AllGroups.Add(group3);
                #endregion
    
                #region Group4
                var group4 = new SampleDataGroup("ApplicationSettings",
                  "ApplicationSettings",
                  " Use the Windows.UI.ApplicationSettings namespace and WinJS.UI.SettingsFlyout",
                  "Assets/ApplicationSettings.jpg",
                  "");
                group4.Items.Add(new SampleDataItem("ApplicationSettings-Default",
                        "Default behavior with no settings integration",
                        "Default behavior ",
                        "Assets/ApplicationSettings.jpg",
                        "Default behavior with no settings integration",
                        "",
                        group4,
                        typeof(Default)));
                group4.Items.Add(new SampleDataItem("ApplicationSettings-AddSettings",
                        "Add settings commands to the settings charm",
                        "Add settings",
                        "Assets/ApplicationSettings.jpg",
                        "Add settings commands to the settings charm ",
                        "",
                        group4,
                        typeof(AddSettings)));
    
                this.AllGroups.Add(group4);
                #endregion
    
                #region Group5
                var Group5 = new SampleDataGroup("AssociationLaunching",
                  "Use Windows.System.Launcher API",
                  "Association Launching",
                  "Assets/AssociationLaunching.jpg",
                  "");
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-LaunchFile",
                        "Launching a file",
                        "Use Windows.System.Launcher.LaunchFileAsync",
                        "Assets/AssociationLaunching.jpg",
                        "Use Windows.System.Launcher.LaunchFileAsync",
                        "",
                        Group5,
                        typeof(LaunchFile)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-LaunchUri",
                        "Launching a URI",
                        "Use Windows.System.Launcher.LaunchUriAsync",
                        "Assets/AssociationLaunching.jpg",
                        "Use Windows.System.Launcher.LaunchUriAsync",
                        "",
                        Group5,
                        typeof(LaunchUri)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-ReceiveFile",
                        "Receiving a file",
                        "Receiving a file",
                        "Assets/AssociationLaunching.jpg",
                        "Receiving a file",
                        "",
                        Group5,
                        typeof(ReceiveFile)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-ReceiveUri",
                        "Receiving a URI",
                        "Receiving a URI",
                        "Assets/AssociationLaunching.jpg",
                        "Receiving a URI",
                        "",
                        Group5,
                        typeof(ReceiveUri)));
                this.AllGroups.Add(Group5);
                #endregion
    
                #region Group6
                var Group6 = new SampleDataGroup("BackgroundTransfer",
                  "Use Windows.Networking.BackgroundTransfer API",
                  "BackgroundDownloader And BackgroundUploader",
                  "Assets/BackgroundTransfer.jpg",
                  "");
                Group6.Items.Add(new SampleDataItem("BackgroundTransfer-DownloadFile",
                        "Download Files",
                        "Use BackgroundDownloader",
                        "Assets/BackgroundTransfer.jpg",
                        "BackgroundDownloader",
                        "",
                        Group6,
                        typeof(DownloadFile)));
                Group6.Items.Add(new SampleDataItem("BackgroundTransfer-UploadFile",
                        "Upload Files",
                        "Use BackgroundUploader",
                        "Assets/BackgroundTransfer.jpg",
                        "BackgroundUploader",
                        "",
                        Group6,
                        typeof(UploadFile)));
    
                this.AllGroups.Add(Group6);
                #endregion
    
                #region Group7
                var Group7 = new SampleDataGroup("Clipboard",
                  "Use Windows.ApplicationModel.DataTransfer API",
                  "ClipboardOperation",
                  "Assets/Clipboard.jpg",
                  "");
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteText",
                        "Copy and paste text",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteText)));
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteImage",
                        "Copy and paste an image",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteImage)));
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteFile",
                        "Copy and paste files",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteFile)));
                Group7.Items.Add(new SampleDataItem("Clipboard-OtherClipboardOperation",
                        "Other Clipboard operations",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(OtherClipboardOperation)));
    
                this.AllGroups.Add(Group7);
                #endregion
    
                #region Group8
                var Group8 = new SampleDataGroup("Compression",
                  "Use Windows.Storage.Compression API",
                  "Compression And Decompression",
                  "Assets/Compression.jpg",
                  "");
                Group8.Items.Add(new SampleDataItem("Compression-CompressionAndDecompression",
                        "Compression And Decompression",
                        "Use Windows.Storage.Compression API",
                        "Assets/Compression.jpg",
                        "Compression And Decompression",
                        "",
                        Group8,
                        typeof(CompressionAndDecompression)));
    
                this.AllGroups.Add(Group8);
                #endregion
    
                #region Group9
                var Group9 = new SampleDataGroup("MediaButtons",
                  "Use Windows.Media API",
                  "Media Buttons",
                  "Assets/MediaButtons.jpg",
                  "");
                Group9.Items.Add(new SampleDataItem("MediaButtons-MediaEvents",
                        "Media Events",
                        "Use Windows.Media API",
                        "Assets/MediaButtons.jpg",
                        "Listening to hardware media transport events",
                        "",
                        Group9,
                        typeof(MediaEvents)));
    
                this.AllGroups.Add(Group9);
                #endregion
    
                #region Group10
                var Group10 = new SampleDataGroup("ContactPicker",
                  "Use Windows.ApplicationModel.Contacts API",
                  "Contact Picker",
                  "Assets/ContactPicker.jpg",
                  "");
                Group10.Items.Add(new SampleDataItem("ContactPicker-SinglePicker",
                        "Pick a single contact",
                        "Use ContactPicker.PickSingleContactAsync()",
                        "Assets/ContactPicker.jpg",
                        "PickSingleContactAsync",
                        "",
                        Group10,
                        typeof(SinglePicker)));
                Group10.Items.Add(new SampleDataItem("ContactPicker-MultiplePicker",
                        "Pick multiple contacts",
                        "Use ContactPicker.PickMultipleContactsAsync()",
                        "Assets/ContactPicker.jpg",
                        "PickMultipleContactsAsync",
                        "",
                        Group10,
                        typeof(MultiplePicker)));
    
                this.AllGroups.Add(Group10);
                #endregion
    
                #region Group11
                var Group11 = new SampleDataGroup("ContextMenu",
                  "Use Windows.UI.Popups API",
                  "Context Menu",
                  "Assets/ContextMenu.jpg",
                  "");
                Group11.Items.Add(new SampleDataItem("ContextMenu-ShowAContextMenu",
                        "Show a context menu",
                        "Show a context menu",
                        "Assets/ContextMenu.jpg",
                        "Show a context menu",
                        "",
                        Group11,
                        typeof(ShowAContextMenu)));
                Group11.Items.Add(new SampleDataItem("ContextMenu-ReplaceADefaultContextMenu",
                        "Replace a default context menu",
                        "Replace a default context menu",
                        "Assets/ContextMenu.jpg",
                        "Replace a default context menu",
                        "",
                        Group11,
                        typeof(ReplaceADefaultContextMenu)));
    
                this.AllGroups.Add(Group11);
                #endregion
            }

    5)我们的导航这样就做好了,效果图:

      点击 ContextMenu

    6)为一个文件创建一个上下文菜单
      我们使用控件的RightTapped事件,来处理右击,然后在右击的位置创建一个PopupMenu,
      使用PopupMenu的ShowForSelectionAsync方法显示上下文菜单。
      修改ShowAContextMenu.xaml的xaml

    View Code
       <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
    
                <TextBlock Grid.Row="0" Style="{StaticResource SubheaderTextStyle}" TextWrapping="Wrap">
                    Right-click the image to show a simple context menu. Using touch, the press-and-hold gesture will also trigger the context menu.
                </TextBlock>
                <Image x:Name="AttachmentImage" Grid.Row="1" HorizontalAlignment="Left" Stretch="None" Source="../Assets/logo.jpg" />
            </Grid>
    
            <Grid x:Name="Output" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">
                <TextBlock x:Name="OutputTextBlock" Style="{StaticResource SubheaderTextStyle}" TextWrapping="Wrap"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class ShowAContextMenu : Page
        {
            public ShowAContextMenu()
            {
                this.InitializeComponent();
                //注册右击事件
                AttachmentImage.RightTapped += new RightTappedEventHandler(AttachmentImage_RightTapped);
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private async void AttachmentImage_RightTapped(object sender, RightTappedRoutedEventArgs e)
            {
                // Create a menu and add commands specifying a callback delegate for each.
                // Since command delegates are unique, no need to specify command Ids.
                var menu = new PopupMenu();
                menu.Commands.Add(new UICommand("Open with", (command) =>
                {
                    OutputTextBlock.Text = "'" + command.Label + "' selected";
                }));
                menu.Commands.Add(new UICommand("Save attachment", (command) =>
                {
                    OutputTextBlock.Text = "'" + command.Label + "' selected";
                }));
    
                // We don't want to obscure content, so pass in a rectangle representing the sender of the context menu event.
                // We registered command callbacks; no need to handle the menu completion event
                OutputTextBlock.Text = "Context menu shown";
                //显示上下文菜单
                var chosenCommand = await menu.ShowForSelectionAsync(GetElementRect((FrameworkElement)sender));
                if (chosenCommand == null) // The command is null if no command was invoked.
                {
                    OutputTextBlock.Text = "Context menu dismissed";
                }
            }
    
            public static Rect GetElementRect(FrameworkElement element)
            {
                GeneralTransform buttonTransform = element.TransformToVisual(null);
                Point point = buttonTransform.TransformPoint(new Point());
                return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
            }
        }

      效果图

      点击 Open with

    7)在显示文本中替换原来的上下文菜单
      我们使用控件的ContextMenuOpening事件,通过设置 e.Handled = true;来处理掉系统默认的
      上下文菜单,然后在右击的位置创建一个PopupMenu,
      使用PopupMenu的ShowForSelectionAsync方法显示上下文菜单。
      修改ReplaceADefaultContextMenu.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
    
                <TextBlock Grid.Row="0" Style="{StaticResource SubheaderTextStyle}" TextWrapping="Wrap">
                    Select and right-click or tap on the selection in the below text box to show a custom context menu for text.
                </TextBlock>
                <TextBox x:Name="ReadOnlyTextBox" Grid.Row="1" IsReadOnly="True" TextWrapping="Wrap" Text="http://www.cnblogs.com/refactor"/>
            </Grid>
    
            <Grid x:Name="Output" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">
                <TextBlock x:Name="OutputTextBlock" Style="{StaticResource SubheaderTextStyle}" TextWrapping="Wrap"/>
            </Grid>
    
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class ReplaceADefaultContextMenu : Page
        {
            public ReplaceADefaultContextMenu()
            {
                this.InitializeComponent();
                //在系统处理显示上下文菜单交互时发生的时间
                ReadOnlyTextBox.ContextMenuOpening += new ContextMenuOpeningEventHandler(ReadOnlyTextBox_ContextMenuOpening);
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            // returns a rect for selected text
            // if selection is multiline then rect is unreliable
            // if no text is selected, returns caret location
            // textbox should not be empty
            private Rect GetTextboxSelectionRect(TextBox textbox)
            {
                Rect rectFirst, rectLast;
                if (textbox.SelectionStart == textbox.Text.Length)
                {
                    rectFirst = textbox.GetRectFromCharacterIndex(textbox.SelectionStart - 1, true);
                }
                else
                {
                    rectFirst = textbox.GetRectFromCharacterIndex(textbox.SelectionStart, false);
                }
    
                int lastIndex = textbox.SelectionStart + textbox.SelectionLength;
                if (lastIndex == textbox.Text.Length)
                {
                    rectLast = textbox.GetRectFromCharacterIndex(lastIndex - 1, true);
                }
                else
                {
                    rectLast = textbox.GetRectFromCharacterIndex(lastIndex, false);
                }
    
                GeneralTransform buttonTransform = textbox.TransformToVisual(null);
                Point point = buttonTransform.TransformPoint(new Point());
    
                return new Rect(point.X + rectFirst.Left,
                    point.Y + rectFirst.Top,
                    rectLast.Right - rectFirst.Left,
                    rectLast.Bottom - rectFirst.Top);
            }
    
            private async void ReadOnlyTextBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
            {
                //将系统上下文菜单标记成已处理
                e.Handled = true;
                TextBox textbox = (TextBox)sender;
                if (textbox.SelectionLength > 0)
                {
                    // Create a menu and add commands specifying an id value for each instead of a delegate.
                    var menu = new PopupMenu();
                    menu.Commands.Add(new UICommand("Copy", null, 1));
                    menu.Commands.Add(new UICommandSeparator());
                    menu.Commands.Add(new UICommand("Highlight", null, 2));
                    menu.Commands.Add(new UICommand("Look up", null, 3));
    
                    OutputTextBlock.Text = "Context menu shown";
                    Rect rect = GetTextboxSelectionRect(textbox);
                    //显示上下文菜单
                    var chosenCommand = await menu.ShowForSelectionAsync(rect);
                    if (chosenCommand != null)
                    {
                        switch ((int)chosenCommand.Id)
                        {
                            case 1:
                                String selectedText = ((TextBox)sender).SelectedText;
                                var dataPackage = new DataPackage();
                                dataPackage.SetText(selectedText);
                                //Copy
                                Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage);
                                OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected; '" + selectedText + "' copied to clipboard";
                                break;
    
                            case 2:
                                OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected";
                                break;
    
                            case 3:
                                OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected";
                                break;
                        }
                    }
                    else
                    {
                        OutputTextBlock.Text = "Context menu dismissed";
                    }
                }
                else
                {
                    OutputTextBlock.Text = "Context menu not shown because there is no text selected";
                }
            }
        }

      效果图

      点击Copy


    未完待续,敬请期待...
    转载请注明出处:http://www.cnblogs.com/refactor/

  • 相关阅读:
    jQuery 选择器
    pf_ring 编译移植
    Android wifi 扫描机制
    wifi 万能钥匙协议
    linux下CJson使用
    libxml -- 解析 XML 文档
    关闭浏览器复制行为
    Ubuntu 语言设置
    Socket编程之非阻塞connect
    Java多维数组
  • 原文地址:https://www.cnblogs.com/refactor/p/2551894.html
Copyright © 2011-2022 走看看