热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WPF读取Docx文件并显示(附下载链接)

在wpf中直接显示Docx文件,直接看看效果吧:下面直接看代码,添加主要有两个类:DocxReader类:us

在wpf中直接显示Docx文件 ,直接看看效果吧:

下面直接看代码,添加主要有两个类:

DocxReader类:

using System;
using System.IO;
using System.IO.Packaging;
using System.Xml;namespace WpfEmbeddedDocx
{class DocxReader : IDisposable{protected const stringMainDocumentRelationshipType ="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",// XML namespacesWordprocessingMLNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main",RelationshipsNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships",// Miscellaneous elementsDocumentElement = "document",BodyElement = "body",// Block-Level elementsParagraphElement = "p",TableElement = "tbl",// Inline-Level elementsSimpleFieldElement = "fldSimple",HyperlinkElement = "hyperlink",RunElement = "r",// Run content elementsBreakElement = "br",TabCharacterElement = "tab",TextElement = "t",// Table elementsTableRowElement = "tr",TableCellElement = "tc",// Properties elementsParagraphPropertiesElement = "pPr",RunPropertiesElement = "rPr";// Note: new members should also be added to nameTable in CreateNameTable method.protected virtual XmlNameTable CreateNameTable(){var nameTable = new NameTable();nameTable.Add(WordprocessingMLNamespace);nameTable.Add(RelationshipsNamespace);nameTable.Add(DocumentElement);nameTable.Add(BodyElement);nameTable.Add(ParagraphElement);nameTable.Add(TableElement);nameTable.Add(ParagraphPropertiesElement);nameTable.Add(SimpleFieldElement);nameTable.Add(HyperlinkElement);nameTable.Add(RunElement);nameTable.Add(BreakElement);nameTable.Add(TabCharacterElement);nameTable.Add(TextElement);nameTable.Add(RunPropertiesElement);nameTable.Add(TableRowElement);nameTable.Add(TableCellElement);return nameTable;}private readonly Package package;private readonly PackagePart mainDocumentPart;protected PackagePart MainDocumentPart{get { return this.mainDocumentPart; }}public DocxReader(Stream stream){if (stream == null)throw new ArgumentNullException("stream");this.package = Package.Open(stream, FileMode.Open, FileAccess.Read);foreach (var relationship in this.package.GetRelationshipsByType(MainDocumentRelationshipType)){this.mainDocumentPart = package.GetPart(PackUriHelper.CreatePartUri(relationship.TargetUri));break;}}public void Read(){using (var mainDocumentStream = this.mainDocumentPart.GetStream(FileMode.Open, FileAccess.Read))using (var reader = XmlReader.Create(mainDocumentStream, new XmlReaderSettings(){NameTable = this.CreateNameTable(),IgnoreComments = true,IgnoreProcessingInstructions = true,IgnoreWhitespace = true}))this.ReadMainDocument(reader);}private static void ReadXmlSubtree(XmlReader reader, Action action){using (var subtreeReader = reader.ReadSubtree()){// Position on the first node.subtreeReader.Read();if (action != null)action(subtreeReader);}}private void ReadMainDocument(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == DocumentElement){ReadXmlSubtree(reader, this.ReadDocument);break;}}protected virtual void ReadDocument(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == BodyElement){ReadXmlSubtree(reader, this.ReadBody);break;}}private void ReadBody(XmlReader reader){while (reader.Read())this.ReadBlockLevelElement(reader);}private void ReadBlockLevelElement(XmlReader reader){if (reader.NodeType == XmlNodeType.Element){Action action = null;if (reader.NamespaceURI == WordprocessingMLNamespace)switch (reader.LocalName){case ParagraphElement:action = this.ReadParagraph;break;case TableElement:action = this.ReadTable;break;}ReadXmlSubtree(reader, action);}}protected virtual void ReadParagraph(XmlReader reader){while (reader.Read()){if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == ParagraphPropertiesElement)ReadXmlSubtree(reader, this.ReadParagraphProperties);elsethis.ReadInlineLevelElement(reader);}}protected virtual void ReadParagraphProperties(XmlReader reader){}private void ReadInlineLevelElement(XmlReader reader){if (reader.NodeType == XmlNodeType.Element){Action action = null;if (reader.NamespaceURI == WordprocessingMLNamespace)switch (reader.LocalName){case SimpleFieldElement:action = this.ReadSimpleField;break;case HyperlinkElement:action = this.ReadHyperlink;break;case RunElement:action = this.ReadRun;break;}ReadXmlSubtree(reader, action);}}private void ReadSimpleField(XmlReader reader){while (reader.Read())this.ReadInlineLevelElement(reader);}protected virtual void ReadHyperlink(XmlReader reader){while (reader.Read())this.ReadInlineLevelElement(reader);}protected virtual void ReadRun(XmlReader reader){while (reader.Read()){if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == RunPropertiesElement)ReadXmlSubtree(reader, this.ReadRunProperties);elsethis.ReadRunContentElement(reader);}}protected virtual void ReadRunProperties(XmlReader reader){}private void ReadRunContentElement(XmlReader reader){if (reader.NodeType == XmlNodeType.Element){Action action = null;if (reader.NamespaceURI == WordprocessingMLNamespace)switch (reader.LocalName){case BreakElement:action = this.ReadBreak;break;case TabCharacterElement:action = this.ReadTabCharacter;break;case TextElement:action = this.ReadText;break;}ReadXmlSubtree(reader, action);}}protected virtual void ReadBreak(XmlReader reader){}protected virtual void ReadTabCharacter(XmlReader reader){}protected virtual void ReadText(XmlReader reader){}protected virtual void ReadTable(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == TableRowElement)ReadXmlSubtree(reader, this.ReadTableRow);}protected virtual void ReadTableRow(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace &&reader.LocalName == TableCellElement)ReadXmlSubtree(reader, this.ReadTableCell);}protected virtual void ReadTableCell(XmlReader reader){while (reader.Read())this.ReadBlockLevelElement(reader);}public void Dispose(){this.package.Close();}}
}

DocxToFlowDocumentConverter类:

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Xml;namespace WpfEmbeddedDocx
{class DocxToFlowDocumentConverter : DocxReader{private const string// Run properties elementsBoldElement = "b",ItalicElement = "i",UnderlineElement = "u",StrikeElement = "strike",DoubleStrikeElement = "dstrike",VerticalAlignmentElement = "vertAlign",ColorElement = "color",HighlightElement = "highlight",FontElement = "rFonts",FontSizeElement = "sz",RightToLeftTextElement = "rtl",// Paragraph properties elementsAlignmentElement = "jc",PageBreakBeforeElement = "pageBreakBefore",SpacingElement = "spacing",IndentationElement = "ind",ShadingElement = "shd",// AttributesIdAttribute = "id",ValueAttribute = "val",ColorAttribute = "color",AsciiFontFamily = "ascii",SpacingAfterAttribute = "after",SpacingBeforeAttribute = "before",LeftIndentationAttribute = "left",RightIndentationAttribute = "right",HangingIndentationAttribute = "hanging",FirstLineIndentationAttribute = "firstLine",FillAttribute = "fill";private FlowDocument document;private TextElement current;private bool hasAnyHyperlink;public FlowDocument Document{get { return this.document; }}public DocxToFlowDocumentConverter(Stream stream): base(stream){}protected override XmlNameTable CreateNameTable(){var nameTable = base.CreateNameTable();nameTable.Add(BoldElement);nameTable.Add(ItalicElement);nameTable.Add(UnderlineElement);nameTable.Add(StrikeElement);nameTable.Add(DoubleStrikeElement);nameTable.Add(VerticalAlignmentElement);nameTable.Add(ColorElement);nameTable.Add(HighlightElement);nameTable.Add(FontElement);nameTable.Add(FontSizeElement);nameTable.Add(RightToLeftTextElement);nameTable.Add(AlignmentElement);nameTable.Add(PageBreakBeforeElement);nameTable.Add(SpacingElement);nameTable.Add(IndentationElement);nameTable.Add(ShadingElement);nameTable.Add(IdAttribute);nameTable.Add(ValueAttribute);nameTable.Add(ColorAttribute);nameTable.Add(AsciiFontFamily);nameTable.Add(SpacingAfterAttribute);nameTable.Add(SpacingBeforeAttribute);nameTable.Add(LeftIndentationAttribute);nameTable.Add(RightIndentationAttribute);nameTable.Add(HangingIndentationAttribute);nameTable.Add(FirstLineIndentationAttribute);nameTable.Add(FillAttribute);return nameTable;}protected override void ReadDocument(XmlReader reader){this.document = new FlowDocument();this.document.BeginInit();this.document.ColumnWidth = double.NaN;base.ReadDocument(reader);if (this.hasAnyHyperlink)this.document.AddHandler(Hyperlink.RequestNavigateEvent,new RequestNavigateEventHandler((sender, e) => Process.Start(e.Uri.ToString())));this.document.EndInit();}protected override void ReadParagraph(XmlReader reader){using (this.SetCurrent(new Paragraph()))base.ReadParagraph(reader);}protected override void ReadTable(XmlReader reader){// Skip table for now.}protected override void ReadParagraphProperties(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace){var paragraph = (Paragraph)this.current;switch (reader.LocalName){case AlignmentElement:var textAlignment = ConvertTextAlignment(GetValueAttribute(reader));if (textAlignment.HasValue)paragraph.TextAlignment = textAlignment.Value;break;case PageBreakBeforeElement:paragraph.BreakPageBefore = GetOnOffValueAttribute(reader);break;case SpacingElement:paragraph.Margin = GetSpacing(reader, paragraph.Margin);break;case IndentationElement:SetParagraphIndent(reader, paragraph);break;case ShadingElement:var background = GetShading(reader);if (background != null)paragraph.Background = background;break;}}}protected override void ReadHyperlink(XmlReader reader){var id = reader[IdAttribute, RelationshipsNamespace];if (!string.IsNullOrEmpty(id)){var relationship = this.MainDocumentPart.GetRelationship(id);if (relationship.TargetMode == TargetMode.External){this.hasAnyHyperlink = true;var hyperlink = new Hyperlink(){NavigateUri = relationship.TargetUri};using (this.SetCurrent(hyperlink))base.ReadHyperlink(reader);return;}}base.ReadHyperlink(reader);}protected override void ReadRun(XmlReader reader){using (this.SetCurrent(new Span()))base.ReadRun(reader);}protected override void ReadRunProperties(XmlReader reader){while (reader.Read())if (reader.NodeType == XmlNodeType.Element && reader.NamespaceURI == WordprocessingMLNamespace){var inline = (Inline)this.current;switch (reader.LocalName){case BoldElement:inline.FontWeight = GetOnOffValueAttribute(reader) ? FontWeights.Bold : FontWeights.Normal;break;case ItalicElement:inline.FontStyle = GetOnOffValueAttribute(reader) ? FontStyles.Italic : FontStyles.Normal;break;case UnderlineElement:var underlineTextDecorations = GetUnderlineTextDecorations(reader, inline);if (underlineTextDecorations != null)inline.TextDecorations.Add(underlineTextDecorations);break;case StrikeElement:if (GetOnOffValueAttribute(reader))inline.TextDecorations.Add(TextDecorations.Strikethrough);break;case DoubleStrikeElement:if (GetOnOffValueAttribute(reader)){inline.TextDecorations.Add(new TextDecoration(){Location = TextDecorationLocation.Strikethrough,PenOffset = this.current.FontSize * 0.015});inline.TextDecorations.Add(new TextDecoration(){Location = TextDecorationLocation.Strikethrough,PenOffset = this.current.FontSize * -0.015});}break;case VerticalAlignmentElement:var baselineAlignment = GetBaselineAlignment(GetValueAttribute(reader));if (baselineAlignment.HasValue){inline.BaselineAlignment = baselineAlignment.Value;if (baselineAlignment.Value == BaselineAlignment.Subscript ||baselineAlignment.Value == BaselineAlignment.Superscript)inline.FontSize *=0.65; //MS Word 2002 size: 65% http://en.wikipedia.org/wiki/Subscript_and_superscript}break;case ColorElement:var color = GetColor(GetValueAttribute(reader));if (color.HasValue)inline.Foreground = new SolidColorBrush(color.Value);break;case HighlightElement:var highlight = GetHighlightColor(GetValueAttribute(reader));if (highlight.HasValue)inline.Background = new SolidColorBrush(highlight.Value);break;case FontElement:var fontFamily = reader[AsciiFontFamily, WordprocessingMLNamespace];if (!string.IsNullOrEmpty(fontFamily))inline.FontFamily =(FontFamily)new FontFamilyConverter().ConvertFromString(fontFamily);break;case FontSizeElement:var fontSize = reader[ValueAttribute, WordprocessingMLNamespace];if (!string.IsNullOrEmpty(fontSize))// Attribute Value / 2 = Points// Points * (96 / 72) = Pixelsinline.FontSize = uint.Parse(fontSize) * 0.6666666666666667;break;case RightToLeftTextElement:inline.FlowDirection = (GetOnOffValueAttribute(reader))? FlowDirection.RightToLeft: FlowDirection.LeftToRight;break;}}}protected override void ReadBreak(XmlReader reader){this.AddChild(new LineBreak());}protected override void ReadTabCharacter(XmlReader reader){this.AddChild(new Run("\t"));}protected override void ReadText(XmlReader reader){this.AddChild(new Run(reader.ReadString()));}private void AddChild(TextElement textElement){((IAddChild)this.current ?? this.document).AddChild(textElement);}private static bool GetOnOffValueAttribute(XmlReader reader){var value = GetValueAttribute(reader);switch (value){case null:case "1":case "on":case "true":return true;default:return false;}}private static string GetValueAttribute(XmlReader reader){return reader[ValueAttribute, WordprocessingMLNamespace];}private static Color? GetColor(string colorString){if (string.IsNullOrEmpty(colorString) || colorString == "auto")return null;return (Color)ColorConverter.ConvertFromString('#' + colorString);}private static Color? GetHighlightColor(string highlightString){if (string.IsNullOrEmpty(highlightString) || highlightString == "auto")return null;return (Color)ColorConverter.ConvertFromString(highlightString);}private static BaselineAlignment? GetBaselineAlignment(string verticalAlignmentString){switch (verticalAlignmentString){case "baseline":return BaselineAlignment.Baseline;case "subscript":return BaselineAlignment.Subscript;case "superscript":return BaselineAlignment.Superscript;default:return null;}}private static double? ConvertTwipsToPixels(string twips){if (string.IsNullOrEmpty(twips))return null;elsereturn ConvertTwipsToPixels(double.Parse(twips, CultureInfo.InvariantCulture));}private static double ConvertTwipsToPixels(double twips){return 96d / (72 * 20) * twips;}private static TextAlignment? ConvertTextAlignment(string value){switch (value){case "both":return TextAlignment.Justify;case "left":return TextAlignment.Left;case "right":return TextAlignment.Right;case "center":return TextAlignment.Center;default:return null;}}private static Thickness GetSpacing(XmlReader reader, Thickness margin){var after = ConvertTwipsToPixels(reader[SpacingAfterAttribute, WordprocessingMLNamespace]);if (after.HasValue)margin.Bottom = after.Value;var before = ConvertTwipsToPixels(reader[SpacingBeforeAttribute, WordprocessingMLNamespace]);if (before.HasValue)margin.Top = before.Value;return margin;}private static void SetParagraphIndent(XmlReader reader, Paragraph paragraph){var margin = paragraph.Margin;var left = ConvertTwipsToPixels(reader[LeftIndentationAttribute, WordprocessingMLNamespace]);if (left.HasValue)margin.Left = left.Value;var right = ConvertTwipsToPixels(reader[RightIndentationAttribute, WordprocessingMLNamespace]);if (right.HasValue)margin.Right = right.Value;paragraph.Margin = margin;var firstLine = ConvertTwipsToPixels(reader[FirstLineIndentationAttribute, WordprocessingMLNamespace]);if (firstLine.HasValue)paragraph.TextIndent = firstLine.Value;var hanging = ConvertTwipsToPixels(reader[HangingIndentationAttribute, WordprocessingMLNamespace]);if (hanging.HasValue)paragraph.TextIndent -= hanging.Value;}private static Brush GetShading(XmlReader reader){var color = GetColor(reader[FillAttribute, WordprocessingMLNamespace]);return color.HasValue ? new SolidColorBrush(color.Value) : null;}private static TextDecorationCollection GetUnderlineTextDecorations(XmlReader reader, Inline inline){TextDecoration textDecoration;Brush brush;var color = GetColor(reader[ColorAttribute, WordprocessingMLNamespace]);if (color.HasValue)brush = new SolidColorBrush(color.Value);elsebrush = inline.Foreground;var textDecorations = new TextDecorationCollection(){(textDecoration = new TextDecoration(){Location = TextDecorationLocation.Underline,Pen = new Pen(){Brush = brush}})};switch (GetValueAttribute(reader)){case "single":break;case "double":textDecoration.PenOffset = inline.FontSize * 0.05;textDecoration = textDecoration.Clone();textDecoration.PenOffset = inline.FontSize * -0.05;textDecorations.Add(textDecoration);break;case "dotted":textDecoration.Pen.DashStyle = DashStyles.Dot;break;case "dash":textDecoration.Pen.DashStyle = DashStyles.Dash;break;case "dotDash":textDecoration.Pen.DashStyle = DashStyles.DashDot;break;case "dotDotDash":textDecoration.Pen.DashStyle = DashStyles.DashDotDot;break;case "none":default:// If underline type is none or unsupported then it will be ignored.return null;}return textDecorations;}private IDisposable SetCurrent(TextElement current){return new CurrentHandle(this, current);}private struct CurrentHandle : IDisposable{private readonly DocxToFlowDocumentConverter converter;private readonly TextElement previous;public CurrentHandle(DocxToFlowDocumentConverter converter, TextElement current){this.converter = converter;this.converter.AddChild(current);this.previous = this.converter.current;this.converter.current = current;}public void Dispose(){this.converter.current = this.previous;}}}
}

,最后,在MainWindow.xaml代码:



MainWindow.cs的代码:

using System.IO;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;namespace WpfEmbeddedDocx
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void ReadDocx(string path){using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){var flowDocumentConverter = new DocxToFlowDocumentConverter(stream);flowDocumentConverter.Read();FlowDocumentScrollViewer.Document = flowDocumentConverter.Document;this.Title = Path.GetFileName(path);}}private void OnOpenFileClicked(object sender, RoutedEventArgs e){var openFileDialog = new OpenFileDialog(){DefaultExt = ".docx",Filter = "Word documents (.docx)|*.docx"};if (openFileDialog.ShowDialog() == true)this.ReadDocx(openFileDialog.FileName);}}
}

这样就能实现视频中的效果啦。。

下载链接:https://pan.baidu.com/s/1UO9GYYsUmoPWd49aVGR4rQ 

提取码:bybq 

原Git仓库代码地址:https://github.com/ArtMalykhin/wpf-embedded-docx

感谢作者无私分享



推荐阅读
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • Python如何调用类里面的方法
    本文介绍了在Python中调用同一个类中的方法需要加上self参数,并且规范写法要求每个函数的第一个参数都为self。同时还介绍了如何调用另一个类中的方法。详细内容请阅读剩余部分。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
author-avatar
rare懿然
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有