zoukankan      html  css  js  c++  java
  • 在uwp中复活常用的vb库函数

    这个博文是纯原创的,转载一定要说明作者是 Nukepayload2!!

    在.Net Core 中,很多地方被精简了,有个重灾区就是vb语言库。从当初的囊括vb6库函数并且附带后期绑定到现在的几个函数加上后期绑定,连End和Mid语句对应的库函数都被删掉了。

    其中有些函数是不该删掉的。那么要用的话就得手动还原一下了。

    首先是各种Hello world里面喜闻乐见的 MsgBox 和 InputBox 函数。

    它们在Microsoft.VisualBasic的Interaction里面。

    新建个模块,叫Interaction。

    先分析一下 MsgBox 。这个函数作用是弹窗,显示标题,内容和选项按钮。

    按钮比较常用的是两个按钮和一个按钮的情况。帮助不常用,三个按钮也不常用。

    那么就实现一个或两个按钮的好了。返回值是True就按了确定,False是按了取消,如果没有值就说明对话框被强行关闭了。

    由于是uwp,同步版本的很难实现。那就写个异步版本的好了。

        Public Async Function MsgBoxAsync(Prompt$, HasCancel As Boolean, Title$, Optional OK$ = "确定", Optional Cancel$ = "取消") As Task(Of Boolean?)
            Dim dlg As New MessageDialog(Prompt, Title)
            Dim Result As Boolean?
            If HasCancel Then
                Dim msg As New MessageDialog(Prompt, Title)
                msg.Commands.Add(New UICommand(OK, Sub(command) Result = True))
                msg.Commands.Add(New UICommand(Cancel, Sub(command) Result = False))
                msg.DefaultCommandIndex = 0
                msg.CancelCommandIndex = 1
                Dim tsk = msg.ShowAsync
                Await tsk
                Return Result
            Else
                Await New MessageDialog(Prompt, Title).ShowAsync
                Return True
            End If
        End Function

    接下来轮到 InputBox 了。

    这个是用来收集输入的,一个文本框,一句提示语,两个常用的按钮,也附带了不常用的帮助功能按钮。

    为了图省事我还是不写帮助按钮了。取消按钮用处也不大,不写了,因为UWP的文本框自带清除按钮。

    首先新建个对话框,在Xaml代码写这个:

    <ContentDialog
        x:Class="Nukepayload2.VisualBasicExtensions.UWP.InputBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <ContentDialog.Content>
            <Grid MinWidth="100" MinHeight="100">
                <Grid.RowDefinitions>
                    <RowDefinition Height="13*"/>
                    <RowDefinition Height="7*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="71*"/>
                    <ColumnDefinition Width="19*"/>
                </Grid.ColumnDefinitions>
                <TextBlock x:Name="TxtPrompt"></TextBlock>
                <TextBox x:Name="TxtOutput" Grid.Row="1"></TextBox>
                <Button Grid.Row="1" Grid.Column="1" Click="BtnOk_Click">确定</Button>
            </Grid>
        </ContentDialog.Content>
    </ContentDialog>

    后面的vb代码(考虑了虚拟键盘):

    Public NotInheritable Class InputBox
        Inherits ContentDialog
        Public Overloads Async Function ShowAsync(Prompt As String, Title As String, Optional InputScope As InputScopeNameValue = InputScopeNameValue.Text) As Task(Of String)
            Me.Title = Title
            TxtPrompt.Text = Prompt
            TxtOutput.Text = ""
            TxtOutput.InputScope = New InputScope
            TxtOutput.InputScope.Names.Add(New InputScopeName(InputScope))
            Await ShowAsync()
            Return TxtOutput.Text
        End Function
    
        Private Sub BtnOk_Click(sender As Object, e As RoutedEventArgs)
            Hide()
        End Sub
    End Class

    我的控件命名方式有点奇葩,大家按照自己的习惯写就好。

    最后在Interaction模块写上这个函数的代码

        Dim inputbox As New InputBox()
        Public Async Function InputBoxAsync(Prompt$, Title$, Optional InputScope As InputScopeNameValue = InputScopeNameValue.Text) As Task(Of String)
            Return Await inputbox.ShowAsync(Prompt, Title, InputScope)
        End Function

    还有些比较常用的,比如Rnd和Randomize

    这两个随机数函数比直接用Random类方便一些,尤其是做单精度浮点数计算的时候。

    这里我没有用BitConverter转换Single和Integer,而是用联合体。读者自己实现的时候可以尝试一下BitConverter。

    还有,默认的0作为种子这个限制可以顺手去除。

    Imports System.Runtime.InteropServices
    
    Public Module VBMath
    
        Dim rand As New RandomPublic Sub Randomize()
            rand = New Random
        End Sub
    
        Public Sub Randomize(Number As Single)
            rand = New Random(New SingleInt32(Number).Int32Value)
        End Sub
    
        Public Function Rnd() As Single
            Return rand.NextDouble
        End Function
    
        Public Function Rnd(Number As Single) As Single
            rand = New Random(New SingleInt32(Number).Int32Value)
            Return Rnd
        End Function
    
        Private Structure SingleInt32
            Sub New(SingleValue!)
                Me.SingleValue = SingleValue
            End Sub
            Sub New(Int32Value%)
                Me.Int32Value = Int32Value
            End Sub
            <FieldOffset(0)>
            Dim SingleValue!
            <FieldOffset(0)>
            Dim Int32Value%
        End Structure
    End Module

    接下来要重新实现的函数在游戏角色名称处理,敏感词处理等场合用得比较多。

    多功能的字符串转换器 StrConv

    不管是简体繁体转换,还是全角半角转换,或者是特殊的大小写格式转换,它都能搞定。

    我写之前查了msdn,上面只能找到一个本机的函数能替代它。那么我就利用它实现StrConv。

    声明是这个,写之前要看看。这个函数在Windows.h里面声明了。

    int LCMapStringEx(
      _In_opt_  LPCWSTR          lpLocaleName,
      _In_      DWORD            dwMapFlags,
      _In_      LPCWSTR          lpSrcStr,
      _In_      int              cchSrc,
      _Out_opt_ LPWSTR           lpDestStr,
      _In_      int              cchDest,
      _In_opt_  LPNLSVERSIONINFO lpVersionInformation,
      _In_opt_  LPVOID           lpReserved,
      _In_opt_  LPARAM           sortHandle
    );

    看完之后就开始折腾!

    新建个windows 运行时组件,然后新建给类,把这个写进去:

    static String^ LCMapString(String^ LocaleName, int MapFlags, String^ Source)
    {
         int len = Source->Length();
         auto str = ref new String(new wchar_t[len + 1], len);
         LCMapStringEx(LocaleName->Begin(), MapFlags, Source->Begin(), len, const_cast<wchar_t*>(str->Begin()), len, NULL, NULL, NULL);
         return str;
    }

    上面和下面这段c++/cx代码只是传达一下意思,并没有经过测试。

    static String^ LCMapString(int MapFlags, String^ Source)
    {
         len = Source->Length();
         auto str = ref new String(new wchar_t[len + 1], len);
         LCMapStringEx(LOCALE_NAME_USER_DEFAULT, MapFlags, Source->Begin(), len, const_cast<wchar_t*>(str->Begin()), len, NULL, NULL, NULL);
         return str;
    }

    注意看参数,里面的MapFlags还跟本机的LCMapStringEx一样,需要把vb的常量转换为这种标记值。

    首先定义一下VbStrConv枚举。这个部分也可以用vb完成。

                public enum class VbStrConv
                {
                    Hiragana = 0x20,
                    Katakana = 0x10,
                    LinguisticCasing = 0x400,
                    Lowercase = 2,
                    Narrow = 8,
                    None = 0,
                    ProperCase = 3,
                    SimplifiedChinese = 0x100,
                    TraditionalChinese = 0x200,
                    Uppercase = 1,
                    Wide = 4
                };

      然后写转换函数。如果那个枚举是在vb实现的,转换函数也在vb写。

                        static int VbStrConvToMapFlags(VbStrConv value)
                        {
                            int val = static_cast<int>(value);
                            int flag = 0;
                            //宽窄
                            if (val & VbStrConv::Wide == VbStrConv::Wide)
                            {
                                flag |= LCMAP_FULLWIDTH;
                            }
                            else if (val & VbStrConv::Narrow == VbStrConv::Narrow)
                            {
                                flag |= LCMAP_HALFWIDTH;
                            }
                            //大小写
                            if (val & VbStrConv::ProperCase == VbStrConv::ProperCase)
                            {
                                flag |= LCMAP_TITLECASE;
                            }
                            else if (val & VbStrConv::Uppercase == VbStrConv::Uppercase)
                            {
                                flag |= LCMAP_UPPERCASE;
                            }
                            else if (val & VbStrConv::Lowercase == VbStrConv::Lowercase)
                            {
                                flag |= LCMAP_LOWERCASE;
                            }
                            else if (val & VbStrConv::LinguisticCasing == VbStrConv::LinguisticCasing)
                            {
                                flag |= LCMAP_LINGUISTIC_CASING;
                            }
                            //日语
                            if (val & VbStrConv::Hiragana == VbStrConv::Hiragana)
                            {
                                flag |= LCMAP_HIRAGANA;
                            }
                            else if (val & VbStrConv::Katakana == VbStrConv::Katakana)
                            {
                                flag |= LCMAP_KATAKANA;
                            }
                            //汉语
                            if (val & VbStrConv::SimplifiedChinese == VbStrConv::SimplifiedChinese)
                            {
                                flag |= LCMAP_SIMPLIFIED_CHINESE;
                            }
                            else if (val & VbStrConv::TraditionalChinese == VbStrConv::TraditionalChinese)
                            {
                                flag |= LCMAP_TRADITIONAL_CHINESE;
                            }
                            return flag;
                        }

    剩下的工作就交给vb了。Locale名称与之前的库函数不太一样,之前用的是LCID。重新实现后的用的是字符串,更加容易与已经存在的本地化API共同使用。

    Imports Nukepayload2.VisualBasicExtensions.UWP.Native.Strings
    Public Module Strings
        Public Function StrConv$(Source$, Conversion As VbStrConv)
            Return LCMapString(VbStrConvToMapFlags(Conversion), Source)
        End Function
        Public Function StrConv$(Source$, Conversion As VbStrConv, LocaleName$)
            Return LCMapString(LocaleName, VbStrConvToMapFlags(Conversion), Source)
        End Function
    End Module
  • 相关阅读:
    每种特定的迭代器如何使用
    常量迭代器
    容器迭代器
    三十分钟掌握STL
    高快省的排序算法
    FloatTest32 Example
    /浮点数的比较
    java第一天
    ACwing 898
    POJ 3268
  • 原文地址:https://www.cnblogs.com/Nukepayload2/p/uwp_libfuncs_remake_vbnet.html
Copyright © 2011-2022 走看看