• WPF+VB.net制作桌面股票小助手


    一直在使用dtapp大神写的STK在工作时间看股票,简单大方,非常方便。

    由于单位使用的是日文的OS,stk的menu显示乱码,最近行情大好,导致使用频率增高,乱码的menu也无法忍受了。

    所以下决心自己做一个,这个东东用了大约3天的闲暇时间初步功能完成,现一步一步的说明一下。

    先上图


    先简单说说实现的功能吧

    1.定时刷新股票行情(HttpWebRequest取得新浪行情数据)

    2.自定义添加股票,保存到ini文件(ini读写)

    3.最小化时隐藏到任务栏,不在taskbar表示,双击任务栏图标启动程序(wpf使用NotifyIcon)

    4.热键表示/隐藏(hotkey)

    5.保存上次关闭时的位置,存到ini文件中

    ----------------------------------------------------------------------------

    接下来分别说明一下:

    1.定时刷新股票行情(HttpWebRequest取得新浪行情数据)

    1             Dim request As WebRequest = HttpWebRequest.Create(String.Format(dataURL, _stockCodes))
    2             Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
    3             Dim reader As New StreamReader(response.GetResponseStream, Encoding.GetEncoding(response.CharacterSet))
    4             Dim html = reader.ReadToEnd()

    说明:dataURL是去行情的网址,这里使用的是http://hq.sinajs.cn/list={0}。定时器就是使用的timer代码就不贴了,很简单。


    2.自定义添加股票,保存到ini文件(ini读写)

     1 Public Class INIHelper
     2 
     3     Private inipath As String = Environment.CurrentDirectory & "DtStock.ini"
     4 
     5     <DllImport("kernel32")> _
     6     Private Shared Function WritePrivateProfileString(section As String, key As String, val As String, filePath As String) As Long
     7     End Function
     8 
     9     <DllImport("kernel32")> _
    10     Private Shared Function GetPrivateProfileString(section As String, key As String, def As String, retVal As StringBuilder, size As Integer, filePath As String) As Integer
    11     End Function
    12 
    13     Public Sub IniWriteValue(Section As String, Key As String, Value As String)
    14         WritePrivateProfileString(Section, Key, Value, Me.inipath)
    15     End Sub
    16 
    17     Public Function IniReadValue(Section As String, Key As String) As String
    18         Dim temp As New StringBuilder(500)
    19         Dim i As Integer = GetPrivateProfileString(Section, Key, "", temp, 500, Me.inipath)
    20         Return temp.ToString()
    21     End Function
    22 
    23     Public Function ExistINIFile() As Boolean
    24         Return File.Exists(inipath)
    25     End Function
    26 End Class

    说明:这里是把ini读写专门做了一个helper,方便使用,调用的时候如下

    '
    iniHelper.IniReadValue("Stock", "Code")
    '
    iniHelper.IniWriteValue("Stock", "Code", String.Empty)


    3.最小化时隐藏到任务栏,不在taskbar表示(wpf使用NotifyIcon)

     1     Private Sub ShowNotifyIcon()
     2         _notifyIcon = New NotifyIcon()
     3         _notifyIcon.Text = "DeskTopStock v1.0"
     4         _notifyIcon.Icon = ExtractAssociatedIcon(System.Windows.Forms.Application.ExecutablePath)
     5         _notifyIcon.Visible = True
     6 
     7         Dim openMenu As New MenuItem("Add or Setting", AddressOf AddStock)
     8         Dim aboutMenu As New MenuItem("About us", AddressOf About)
     9         Dim exitMenu As New MenuItem("Exit me", AddressOf CloseMe)
    10 
    11         _notifyIcon.ContextMenu = New ContextMenu({openMenu, aboutMenu, exitMenu})
    12 
    13         AddHandler _notifyIcon.MouseDoubleClick, AddressOf OnNotifyIconDoubleClick
    14     End Sub

    说明:引入System.Windows.Forms,绑定上需要用的event就可以了


    4.热键表示/隐藏(hotkey)

    Imports System.Windows.Forms
    Imports System.Windows.Interop
    
    ''' <summary>
    ''' 直接构造类实例即可注册
    ''' 自动完成注销
    ''' 注意注册时会抛出异常
    ''' </summary>
    Class HotKey
        '注册系统热键类
        '热键会随着程序结束自动解除,不会写入注册表
    #Region "Member"
    
        Private KeyId As Integer
        '热键编号
        Private Handle As IntPtr
        '窗体句柄
        Private window As Window
        '热键所在窗体
        Private Controlkey As UInteger
        '热键控制键
        Private Key As UInteger
        '热键主键
        Public Delegate Sub OnHotkeyEventHandeler()
        '热键事件委托
        Public Event OnHotKey As OnHotkeyEventHandeler
        '热键事件    
        Shared KeyPair As New Hashtable()
        '热键哈希表
        Private Const WM_HOTKEY As Integer = &H312
        ' 热键消息编号
        Public Enum KeyFlags
            '控制键编码
            MOD_ALT = &H1
            MOD_CONTROL = &H2
            MOD_SHIFT = &H4
            MOD_WIN = &H8
        End Enum
    
    #End Region
    
        ''' <summary>
        ''' 构造函数
        ''' </summary>
        ''' <param name="win">注册窗体</param>
        ''' <param name="control">控制键</param>
        ''' <param name="key__1">主键</param>
        Public Sub New(win As Window, control As HotKey.KeyFlags, key__1 As Keys)
            '构造函数,注册热键
            Handle = New WindowInteropHelper(win).Handle
            window = win
            Controlkey = CUInt(control)
            Key = CUInt(key__1)
            KeyId = CInt(Controlkey) + CInt(Key) * 10
            If HotKey.KeyPair.ContainsKey(KeyId) Then
                Throw New Exception("热键已经被注册!")
            End If
    
            '注册热键
            If False = HotKey.RegisterHotKey(Handle, KeyId, Controlkey, Key) Then
                Throw New Exception("热键注册失败!")
            End If
            If HotKey.KeyPair.Count = 0 Then
                '消息挂钩只能连接一次!!
                If False = InstallHotKeyHook(Me) Then
                    Throw New Exception("消息挂钩连接失败!")
                End If
            End If
    
            '添加这个热键索引
    
            HotKey.KeyPair.Add(KeyId, Me)
        End Sub
    
    #Region "core"
    
        <System.Runtime.InteropServices.DllImport("user32")> _
        Private Shared Function RegisterHotKey(hWnd As IntPtr, id As Integer, controlKey As UInteger, virtualKey As UInteger) As Boolean
        End Function
    
        <System.Runtime.InteropServices.DllImport("user32")> _
        Private Shared Function UnregisterHotKey(hWnd As IntPtr, id As Integer) As Boolean
        End Function
    
        Private Shared Function InstallHotKeyHook(hk As HotKey) As Boolean
            '安装热键处理挂钩
            If hk.window Is Nothing OrElse hk.Handle = IntPtr.Zero Then
                Return False
            End If
    
            '获得消息源
            Dim source As System.Windows.Interop.HwndSource = System.Windows.Interop.HwndSource.FromHwnd(hk.Handle)
            If source Is Nothing Then
                Return False
            End If
    
            '挂接事件
            source.AddHook(AddressOf HotKey.HotKeyHook)
            Return True
        End Function
    
        Private Shared _status As Boolean = False
        Private Shared Function HotKeyHook(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
            '热键处理过程
            If msg = WM_HOTKEY Then
                Dim hk As HotKey = DirectCast(HotKey.KeyPair(CInt(wParam)), HotKey)
    
                _status = hk.window.IsVisible
                If _status Then
                    hk.window.Hide()
                    _status = False
                Else
                    hk.window.Show()
                    _status = True
                End If
            End If
            Return IntPtr.Zero
        End Function
    
        Protected Overrides Sub Finalize()
            Try
                '析构函数,解除热键
                HotKey.UnregisterHotKey(Handle, KeyId)
            Finally
                MyBase.Finalize()
            End Try
        End Sub
    
    #End Region
    End Class

    说明:这个是网上找到的一个类,作者写的很好,直接使用了(忘记作者的原贴地址了,抱歉!!)
    需要在Loaded之后调用,直接初期化一下传入热键就OK了,不写入注册表,程序关掉即释放。

     5.保存上次关闭时的位置,存到ini文件中

        Private Sub MainWindow_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
            _iniHelper.IniWriteValue("WinLocation", "Left", CStr(Me.Left))
            _iniHelper.IniWriteValue("WinLocation", "Top", CStr(Me.Top))
        End Sub
    
        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            If String.IsNullOrEmpty(_iniHelper.IniReadValue("WinLocation", "Left")) Then
                Me.WindowStartupLocation = Windows.WindowStartupLocation.CenterScreen
                Exit Sub
            End If
    
            Me.Left = Double.Parse(_iniHelper.IniReadValue("WinLocation", "Left"))
            Me.Top = Double.Parse(_iniHelper.IniReadValue("WinLocation", "Top"))
    
            Dim HotKey As New HotKey(Me, HotKey.KeyFlags.MOD_WIN, Keys.A)
        End Sub

    说明:窗口关闭的时候把位置保存起来,程序启动的时候再读出来,第一次启动程序的时候设定位置为屏幕中央。

    最后把XAML贴出来

     1 <Window x:Class="MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         Title="DeskTopStock" SizeToContent="WidthAndHeight"
     5         xmlns:my="clr-namespace:DeskTopStock" ResizeMode="CanMinimize" WindowStyle="None" 
     6         Opacity="0.8" AllowsTransparency ="True" ShowInTaskbar="False" Topmost="True"
     7          FontSize="11.5" FontFamily="Microsoft YaHei" MouseMove="TitleBar_MouseMove">
     8 
     9     <Window.Resources>
    10         <my:BackgroundConverter x:Key="myConverter"/>
    11 
    12         <ToolTip x:Key="InforTip">
    13             <StackPanel Orientation="Vertical">
    14                 <StackPanel Orientation="Horizontal">
    15                     <TextBlock Text="{Binding Name}" />
    16                     <TextBlock Text=" " />
    17                     <TextBlock Text="{Binding Code}"/>
    18                 </StackPanel>
    19                 <StackPanel Orientation="Horizontal">
    20                     <TextBlock Text="昨收盘:" />
    21                     <TextBlock Text="{Binding YesterdayClose}"/>
    22                 </StackPanel>
    23                 <StackPanel Orientation="Horizontal">
    24                     <TextBlock Text="今开盘:" />
    25                     <TextBlock Text="{Binding TodayOpen}"/>
    26                 </StackPanel>
    27                 <StackPanel Orientation="Horizontal">
    28                     <TextBlock Text="最 高:" />
    29                     <TextBlock Text="{Binding High}"/>
    30                 </StackPanel>
    31                 <StackPanel Orientation="Horizontal">
    32                     <TextBlock Text="最 低:" />
    33                     <TextBlock Text="{Binding Low}"/>
    34                 </StackPanel>
    35 
    36             </StackPanel>
    37         </ToolTip>
    38         
    39         <Style x:Key="myItemStyle" TargetType="{x:Type ListViewItem}">
    40             <Setter Property="Foreground">
    41                 <Setter.Value>
    42                     <Binding RelativeSource="{RelativeSource Self}" Converter="{StaticResource myConverter}" ConverterParameter="{RelativeSource Self}" />
    43                 </Setter.Value>
    44             </Setter>
    45             <Setter Property="ToolTip" Value="{Binding Source={StaticResource InforTip}}" />
    46         </Style>
    47 
    48     </Window.Resources>
    49     <Grid>
    50         <Grid.RowDefinitions>
    51             <RowDefinition Height="22" />
    52             <RowDefinition Height="*" />
    53             <RowDefinition Height="20" />
    54         </Grid.RowDefinitions>
    55         <DockPanel Background="AntiqueWhite" >
    56             <Button Name="C" ToolTip="关闭" Width="30" Height="20" Content="X" />
    57             <Button  Width="30" ToolTip="隐藏" Height="20" Content="—" Name="Button1" />
    58             <Button Name="Add" ToolTip="添加股票" Width="30" Height="20" Content="十" Margin="5,0,0,0" Command="{Binding AddCommand}" HorizontalAlignment="Left"  
    59                     CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window, AncestorLevel=1}}" />
    60         </DockPanel>
    61 
    62         <ListView HorizontalAlignment="Stretch" Name="ListView1" ItemsSource="{Binding StockCollection}" VerticalAlignment="Stretch" 
    63                   ItemContainerStyle="{StaticResource myItemStyle}" Grid.Row="1" >
    64             <ListView.View>
    65                 <GridView>
    66                     <GridViewColumn Width="60" Header="简称" DisplayMemberBinding="{Binding Name}" />
    67                     <GridViewColumn Width="75" Header="最新价" DisplayMemberBinding="{Binding Current}"/>
    68                     <GridViewColumn Width="65" Header="涨跌额" DisplayMemberBinding="{Binding ZDF}"/>
    69                     <GridViewColumn Width="60" Header="涨跌幅" DisplayMemberBinding="{Binding ZDF2}"/>
    70                 </GridView>
    71             </ListView.View>
    72         </ListView>
    73         <TextBlock Text="数据更新中,请稍候.." Visibility="{Binding IsUpdateVisilility}" HorizontalAlignment="Left" Grid.Row="2"/>
    74         <TextBlock Grid.Row="2" HorizontalAlignment="Right" Text="{Binding DateString}"/>
    75     </Grid>
    76 </Window>

     说明:1.BackgroundConverter是控制ListView的行颜色的,上涨的时候是红色,跌的时候绿色 2.InforTip是Tooltip的显示内容
    如有想需要代码或者程序的同学给我地址即可。

  • 相关阅读:
    箭头函数1
    变量结构赋值
    警惕32位程序在MethodImplOptions.Synchronized在x64机器上的同步缺陷[z]
    ListView的BeginUpdate()和EndUpdate()作用[z]
    如何用命令将本地项目上传到git[z]
    C# 两个datatable中的数据快速比较返回交集或差集[z]
    C# DataTable抽取Distinct数据(不重复数据)[z]
    【Thread】CountdownEvent任务并行[z]
    C#多线程--信号量(Semaphore)[z]
    VS2015一新建项目就出现未将对象引用设置到对象的实例怎么办?[z]
  • 原文地址:https://www.cnblogs.com/dapeng123/p/4363883.html
Copyright © 2020-2023  润新知