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

摘要:
我一直在使用dtapp大神写的STK在工作时间查看股票。它简单、大方而且非常方便。由于该公司使用日本操作系统,stk菜单显示乱码,市场最近有所改善,导致使用频率增加。乱糟糟的菜单也让人难以忍受。所以我决定自己做一个。我花了大约3天的时间在业余时间完成初步功能。现在我将一步一步地解释它。不会粘贴用于计时器的计时器代码。这很简单。

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

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

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

先上图

WPF+VB.net制作桌面股票小助手第1张
先简单说说实现的功能吧

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的显示内容
如有想需要代码或者程序的同学给我地址即可。

免责声明:文章转载自《WPF+VB.net制作桌面股票小助手》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇GitHub 访问不了?教你几招轻松解决dev 的NavBarControl动态菜单下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

AntDesignVue中关于Table组件的使用

--下面这整个div都是设置每一列搜索的样式图标--˃searchInput=c":placeholder="`Search${column.dataIndex}`":value="selectedKeys[0]"@change="e=˃setSelectedKeys(e.target.value?...

C# 获取枚举 Enum 变量值的 Description 属性

如何在C#中读取枚举值的描述属性?有以下枚举:123456 public enum enum Langage{[System.ComponentModel.Description]Chinese,English}我们希望得到的是中文中的“Chinese”描述。123456789 publicstringGetEnumDescription{stringstr...

ElasticSearch的高级复杂查询:非聚合查询和聚合查询

它与SQL中的GROUPBY类似,但功能更强大。为了更好地理解这个概念,请参阅https://blog.csdn.net/dm_vincent/article/details/42387161Buckets(Bucket):满足特定条件的文档集合。度量:为存储桶中的文档计算的统计信息。一般来说,它可以大致转换为SQL:从tablegroupbyname中选择...

微信小程序生成带参数的二维码(小程序码)独家asp.net的服务端c#完整代码

1) 我第一次使用wx。小程序端请求调用API,发现这是一个坑!@-_~Page:'pages/index/index',//在此处填写要跳转到的小程序页面。你不能在它前面添加/oh。发布后必须为1024页//小程序代码的边长,以像素为单位,范围[2801280]},标头:{'content-type':“application/json;charset=U...

如何设置Navicat的显示字体与字体大小?

方法/步骤打开Navicat点击菜单,再选择在界面,点击下的设置网格字体和大小设置编辑器字体和大小设置命令列界面字体和大小设置ER图表字体和大小,最后点击END...

最新版Swagger 3升级指南和新功能体验!

因此,本期将为您带来一篇关于Swagger最新版本的文章。本文将向您展示Swagger最新版本的变化?如何将旧版本的Swagger升级到新版本?Swagger是一个用于生成、描述和调用RESTful接口的Web服务。Swagger 2.9.2的使用分为以下四个步骤:添加依赖项、启用Swagger功能、配置Swagger文档摘要信息和调用接口访问。让我们分别来...