MyEasyTools:哈希值计算器(MD5+SHA1)

本文介绍了如何使用WPF重构WinForm应用,实现了一个功能类似的哈希值计算器,支持MD5和SHA1算法。核心代码中包含了DataGrid的Style设置,并采用单线程同步计算以确保正确性。

学习下WPF,顺便用WPF把WinForm的程序改成了WPF,功能和MFC版功能基本相同



主要代码:

1 设置DataGrid的Style

        <Style x:Key="Body_Content_DataGrid_Centering" TargetType="{x:Type DataGridCell}">
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="ForestGreen"/>
                </Trigger>
            </Style.Triggers>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="FontSize" Value="13" />
        </Style>
                    <DataGrid Grid.Row="0" Name="dgHashInfo"                              
                              AutoGenerateColumns="False" 
                              HeadersVisibility="All" RowHeaderWidth="18" RowHeight="25"
                              SelectionMode="Extended" 
                              SelectionUnit="FullRow"
                              CanUserSortColumns="False" 
                              CanUserResizeRows="False"
                              CanUserAddRows="False"
                              AllowDrop="True" 
                              DragEnter="dgHashInfo_DragEnter" 
                              DragOver="dgHashInfo_DragEnter"
                              Drop="dgHashInfo_Drop" 
                              LoadingRow="dgHashInfo_LoadingRow"
                              CellStyle="{StaticResource Body_Content_DataGrid_Centering}"
                              ItemsSource="{Binding}" >
                        <DataGrid.RowStyle>
                            <Style TargetType="DataGridRow">
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="DeepSkyBlue" />
                                        <Setter Property="Foreground" Value="White" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </DataGrid.RowStyle>
                        <DataGrid.RowHeaderStyle>
                            <Style TargetType="DataGridRowHeader">                                
                                <Setter Property="FontSize" Value="13"/>
                                <Setter Property="Width" Value="20"/>
                                <Setter Property="Background">
                                    <Setter.Value>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="SkyBlue" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Setter.Value>
                                </Setter>
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="ToolTip" Value="Select this row"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </DataGrid.RowHeaderStyle>
                        <DataGrid.ContextMenu>
                            <ContextMenu Name="cmRighMenu" StaysOpen="True" >
                                <MenuItem Name="cmAddNewRow" Header="Add new row" Click="cmAddNewRow_Click" />
                            </ContextMenu>                            
                        </DataGrid.ContextMenu>
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="File Attribute" Width="*" Binding="{Binding Attribute, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" />
                            <DataGridTextColumn Header="Attribute Value" Width="4*" Binding="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                        </DataGrid.Columns>
                    </DataGrid>

2 进度条的控制
        private bool InitProgressBar(string filePath)
        {
            bool result = true;
            string key = GenerateNameByHashCode(filePath);

            if (htProgressBar.ContainsKey(key))
            {
                result = false;
                Warnning("Wait for this file calculate completely");
            }
            else
            {
                ProgressBar pb = new ProgressBar();
                pb.IsIndeterminate = false;
                pb.Orientation = Orientation.Horizontal;
                pb.Width = 100;
                pb.Height = sbStatus.ActualHeight - 5;
                pb.Minimum = 0;
                pb.Maximum = 100;
                pb.Value = 0;
                pb.Visibility = Visibility.Visible;
                sbStatus.Items.Add(pb);

                htProgressBar.Add(key, pb);
            }
            return result;
        }
        private void UpdateHashInfo(FileHashInfo fileHashInfo)
        {
            MethodInvokerWithOnePara miProgress = new MethodInvokerWithOnePara(ProgressPerformStep);
            Dispatcher.Invoke(miProgress, new object[] { fileHashInfo });


            if (fileHashInfo.Percent == 100)
            {
                MethodInvokerWithOnePara miHashInfo = new MethodInvokerWithOnePara(AddFileHashInfo);
                Dispatcher.Invoke(miHashInfo, new object[] { fileHashInfo });
            }
        }

        private void ProgressPerformStep(FileHashInfo fileHashInfo)
        {
            string key = GenerateNameByHashCode(fileHashInfo.Path);
            ProgressBar pb = htProgressBar[key] as ProgressBar;

            double value = fileHashInfo.Percent;
            if ((value == -1) || (value >= pb.Maximum))
            {
                ClearProgressBar(key);
            }
            else
            {
                if (value > pb.Value)
                {
                    pb.SetValue(ProgressBar.ValueProperty, value);
                }
            }
        }

        private void ClearProgressBar(string key)
        {
            ProgressBar pb = htProgressBar[key] as ProgressBar;
            if (null != pb)
            {
                sbStatus.Items.Remove(pb);
                htProgressBar.Remove(key);
            }
        }

3 Drag-Drop文件功能实现
        private void rtbSourceText_PreviewDragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Copy;
                e.Handled = true;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void rtbSourceText_PreviewDrop(object sender, DragEventArgs e)
        {
            string filePath = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();

            if (!File.Exists(filePath))
            {
                if (Directory.Exists(filePath))
                {
                    Warnning("Does not support directory");
                }
                else
                {
                    Warnning("File not find");
                }
                return;
            }
            else
            {
                FileInfo fi = new FileInfo(filePath);
                if (fi.Extension != ".txt")
                {
                    Warnning("Only support text file");
                    return;
                }
            }

            StreamReader sr = new StreamReader(filePath);
            string content = sr.ReadToEnd();
            rtbSourceText.AppendText(content);
        }
NOTE:结合1 中的绿色背景代码才可以工作

4 计算MD5/SHA1
        public void GetFileHashInfo(string path, CalculateProgressHandle progress)
        {
            fileHashInfo = new FileHashInfo();
            bStopCalc = false;
            fileHashInfo.Path = path;
            fileHashInfo.Size = GetFileSize(path);
            fileHashInfo.LastModifyTime = GetFileTime(path);
            ChangeProgress = progress;

            AsyncGetHashValue(path);
        }

        private void AsyncGetHashValue(string path)
        {
            try
            {
                int bufferSize = 1024 * 1024 * 10; //10M

                buffer = new byte[bufferSize];

                //open file stream
                inputStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                hashAlgorithm_MD5 = new MD5CryptoServiceProvider();
                hashAlgorithm_SHA1 = new SHA1CryptoServiceProvider();

                //async read first data into buffer
                inputStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(AsyncComputeHashCallback), null);
            }
            catch
            {
                //
            }
        }
        private void AsyncComputeHashCallback(IAsyncResult result)
        {
            int bytesRead = inputStream.EndRead(result);
            if (inputStream.Length == 0)
            {
                fileHashInfo.Percent = 100;
            }
            else
            {
                fileHashInfo.Percent = (int)((double)inputStream.Position / inputStream.Length * 100);
            }

            if (inputStream.Position < inputStream.Length)
            {
                if (bStopCalc)
                {
                    fileHashInfo.Percent = -1;
                    if (null != ChangeProgress)
                    {
                        ChangeProgress(fileHashInfo);
                    }
                    return;
                }
                //caculate hash value
                var output = new byte[buffer.Length];
                hashAlgorithm_MD5.TransformBlock(buffer, 0, buffer.Length, output, 0);
                hashAlgorithm_SHA1.TransformBlock(buffer, 0, buffer.Length, output, 0);

                //async read next data into buffer
                inputStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(AsyncComputeHashCallback), null);
            }
            else
            {
                //caculate last block hash value
                hashAlgorithm_MD5.TransformFinalBlock(buffer, 0, bytesRead);
                hashAlgorithm_SHA1.TransformFinalBlock(buffer, 0, bytesRead);

                fileHashInfo.MD5 = BitConverter.ToString(hashAlgorithm_MD5.Hash).Replace("-", "");
                fileHashInfo.SHA1 = BitConverter.ToString(hashAlgorithm_SHA1.Hash).Replace("-", "");
                inputStream.Close();
            }

            if (null != ChangeProgress)
            {
                ChangeProgress(fileHashInfo);
            }
        }

        public static void StopCalculate()
        {
            bStopCalc = true;
        }

单线程同步计算MD5

        private static string GetMD5(string path)
        {
            string sMD5Value = string.Empty;

            Stream file = GetStream(path);
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] bMD5 = md5.ComputeHash(file);
            sMD5Value = System.BitConverter.ToString(bMD5);
            sMD5Value = sMD5Value.Replace("-", "");

            return sMD5Value;
        }

如果完全转载,请注明出处,谢谢


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值