├── .gitattributes ├── .gitignore ├── README.md ├── WeChatClient.ChatContent ├── ChatContentModule.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── MessageTemplateSelector.cs ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── ChatContentViewModel.cs ├── Views │ ├── ChatContentView.xaml │ └── ChatContentView.xaml.cs ├── WeChatClient.ChatContent.csproj ├── app.config └── packages.config ├── WeChatClient.ChatList ├── ChatListModule.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── ChatListViewModel.cs ├── Views │ ├── ChatListView.xaml │ └── ChatListView.xaml.cs ├── WeChatClient.ChatList.csproj ├── app.config └── packages.config ├── WeChatClient.ContactContent ├── ContactContentModule.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── ContactContentViewModel.cs ├── Views │ ├── ContactContentView.xaml │ └── ContactContentView.xaml.cs ├── WeChatClient.ContactContent.csproj ├── app.config └── packages.config ├── WeChatClient.ContactList ├── ContactListModule.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── ContactListViewModel.cs ├── Views │ ├── ContactListView.xaml │ └── ContactListView.xaml.cs ├── WeChatClient.ContactList.csproj ├── app.config └── packages.config ├── WeChatClient.Core ├── Converters │ ├── BoolToValueConverter.cs │ ├── BoolToVisibilityConverter.cs │ ├── InverseConverter.cs │ ├── UriToBitmapConverter.cs │ └── WxResConverter.cs ├── Dependency │ ├── DependencyExtension.cs │ ├── ExposeServicesAttribute.cs │ └── ServiceLifetime.cs ├── Events │ ├── ChatWithContactEvent.cs │ ├── LoginSuccessfulEvent.cs │ └── SendTextMsgEvent.cs ├── Extensions │ ├── RichTextBoxExtensions.cs │ ├── ScrollViewerExtensions.cs │ └── TextBoxExtensions.cs ├── Helpers │ ├── ImageHelper.cs │ ├── RandomHelper.cs │ └── TimeStampHelper.cs ├── Http │ ├── BaseRequest.cs │ ├── BaseService.cs │ ├── ImageCacheService.cs │ ├── ImageDownloadService.cs │ ├── LoginService.cs │ ├── MethodEnum.cs │ ├── StaticCode.cs │ ├── StaticUrl.cs │ └── WeChatService.cs ├── Interfaces │ ├── IChatContentManager.cs │ ├── IChatListManager.cs │ ├── IContactContentManager.cs │ ├── IContactListManager.cs │ ├── IImageDownloadService.cs │ ├── IMainManager.cs │ └── INeedDownloadImageModel.cs ├── Models │ ├── BaseNotifyModel.cs │ ├── ChatRoomMember.cs │ ├── WeChatMessage.cs │ ├── WeChatUser.cs │ └── WxStatus.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Resources │ ├── 2KriyDK.png │ ├── NTI4MWU5.ico │ └── wx_res.png ├── Theme │ ├── Generic.xaml │ └── ScrollViewerStyle.xaml ├── WeChatClient.Core.csproj ├── WeChatClientConst.cs └── packages.config ├── WeChatClient.EmojiCore ├── Converters │ ├── FaceImgConverter.cs │ └── StringToTextBlockConverter.cs ├── Emoji │ ├── EmojiManager.cs │ ├── emoji.json │ ├── emoji_code_map.json │ ├── emoji_map.json │ ├── qq_emoji.json │ └── qq_emoji_map.json ├── EmojiModel.cs ├── Events │ └── InputEmojiEvent.cs ├── Face │ ├── FaceManager.cs │ ├── emoji_face.json │ └── qq_face.json ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── 15BPafa.png │ ├── 1BJVkIX.png │ ├── 3gXSfR9.png │ └── 6AfH8-r.png ├── Theme │ └── Generic.xaml ├── WeChatClient.EmojiCore.csproj └── packages.config ├── WeChatClient.Face ├── FaceModule.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── FaceViewModel.cs ├── Views │ ├── FaceView.xaml │ └── FaceView.xaml.cs ├── WeChatClient.Face.csproj ├── app.config └── packages.config ├── WeChatClient.Login ├── Events │ ├── ShowErrorMsgEvent.cs │ ├── SwitchAccountEvent.cs │ ├── UpdateHeadImageEvent.cs │ └── UpdateQRCodeEvent.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── LoginModule.cs ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ ├── ErrorViewModel.cs │ ├── HeadViewModel.cs │ └── QRCodeViewModel.cs ├── Views │ ├── ErrorView.xaml │ ├── ErrorView.xaml.cs │ ├── HeadView.xaml │ ├── HeadView.xaml.cs │ ├── QRCodeView.xaml │ └── QRCodeView.xaml.cs ├── WeChatClient.Login.csproj ├── app.config └── packages.config ├── WeChatClient.Main ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── MainModule.cs ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ └── MainViewModel.cs ├── Views │ ├── MainView.xaml │ └── MainView.xaml.cs ├── WeChatClient.Main.csproj ├── app.config └── packages.config ├── WeChatClient.Search ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ └── AssemblyInfo.cs ├── SearchModule.cs ├── ViewModels │ └── SearchViewModel.cs ├── Views │ ├── SearchView.xaml │ └── SearchView.xaml.cs ├── WeChatClient.Search.csproj ├── app.config └── packages.config ├── WeChatClient.UI ├── App.config ├── App.xaml ├── App.xaml.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Views │ ├── Shell.xaml │ └── Shell.xaml.cs ├── WeChatClient.UI.csproj └── packages.config ├── WeChatClient.sln └── images ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png └── 7.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WeChatClient 2 | 一个高仿微信网页版 https://wx.qq.com 的WPF应用程序,基本完成了网页微信的主要基础功能,例如聊天,联系人,搜索,表情等。 3 | 4 | 软件中的图标和表情都是使用网页微信的资源,还有很多功能是待实现的,例如任务栏托盘图标,图片文件发送,截屏,创建群聊等。 5 | 6 | 项目中用到了prism和reactiveui框架,虽然它们都是MVVM框架,这里用它们做不同的事情。使用prism是为了将应用程序划分为多个离散的、松散耦合的、半独立的组件,使用reactiveui是为了反应式编程。 7 | 8 | 9 | 这里暂时提供一些软件截图。 10 | 11 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/1.png) 12 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/2.png) 13 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/3.png) 14 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/4.png) 15 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/5.png) 16 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/6.png) 17 | ![Image text](https://github.com/845669495/WeChatClient/blob/master/images/7.png) 18 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/ChatContentModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.ChatContent.Views; 11 | using WeChatClient.Core.Dependency; 12 | 13 | namespace WeChatClient.ChatContent 14 | { 15 | [Module(OnDemand = true)] 16 | [ModuleDependency(WeChatClientConst.FaceModuleName)] 17 | public class ChatContentModule : IModule 18 | { 19 | public void OnInitialized(IContainerProvider containerProvider) 20 | { 21 | //内容区域默认显示聊天内容 22 | var regionManager = containerProvider.Resolve(); 23 | regionManager.RegisterViewWithRegion(WeChatClientConst.ContentRegionName, typeof(ChatContentView)); 24 | } 25 | 26 | public void RegisterTypes(IContainerRegistry containerRegistry) 27 | { 28 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/MessageTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using WeChatClient.Core.Models; 9 | 10 | namespace WeChatClient.ChatContent 11 | { 12 | public class MessageTemplateSelector : DataTemplateSelector 13 | { 14 | public override DataTemplate SelectTemplate(object item, DependencyObject container) 15 | { 16 | DataTemplate dt = null; 17 | if (item is WeChatMessage obj && container is FrameworkElement fe) 18 | { 19 | if (obj.MsgType == 10000) 20 | dt = fe.FindResource("SystemMessageTemplate") as DataTemplate; 21 | else if (obj.IsReceive) 22 | dt = fe.FindResource("ReceiveMessageTemplate") as DataTemplate; 23 | else 24 | dt = fe.FindResource("SelfMessageTemplate") as DataTemplate; 25 | } 26 | return dt; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.ChatContent")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.ChatContent")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("2bdb603f-2524-4685-b0d9-015fcb8b314e")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/ViewModels/ChatContentViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.ComponentModel; 7 | using System.Linq; 8 | using System.Reactive.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Data; 12 | using System.Windows.Documents; 13 | using System.Windows.Input; 14 | using WeChatClient.Core.Dependency; 15 | using WeChatClient.Core.Events; 16 | using WeChatClient.Core.Interfaces; 17 | using WeChatClient.Core.Models; 18 | using WeChatClient.EmojiCore.Emoji; 19 | 20 | namespace WeChatClient.ChatContent.ViewModels 21 | { 22 | [ExposeServices(ServiceLifetime.Singleton, typeof(IChatContentManager))] 23 | public class ChatContentViewModel : ReactiveObject, IChatContentManager 24 | { 25 | /// 26 | /// 当前选中聊天 27 | /// 28 | [Reactive] 29 | public WeChatUser SelectedChat { get; set; } 30 | /// 31 | /// 有聊天被选中 32 | /// 33 | public bool HasChatSelected { [ObservableAsProperty]get; } 34 | /// 35 | /// 文本框 36 | /// 37 | [Reactive] 38 | public FlowDocument Message { get; private set; } 39 | /// 40 | /// 发送文本消息命令 41 | /// 42 | public ICommand SendTextMsgCommand { get; private set; } 43 | 44 | public ChatContentViewModel(IEventAggregator ea, EmojiManager emojiManager) 45 | { 46 | Message = new FlowDocument(); 47 | 48 | SendTextMsgCommand = ReactiveCommand.Create(() => 49 | { 50 | string msg = emojiManager.FlowDocumentToString(Message); 51 | if (string.IsNullOrWhiteSpace(msg)) 52 | return; 53 | ea.GetEvent().Publish(msg); 54 | Message.Blocks.Clear(); 55 | }); 56 | 57 | var observable = this.WhenAnyValue(p => p.SelectedChat); 58 | observable.Select(p => p != null).ToPropertyEx(this, p => p.HasChatSelected); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/Views/ChatContentView.xaml.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | using WeChatClient.ChatContent.ViewModels; 17 | using WeChatClient.EmojiCore; 18 | using WeChatClient.EmojiCore.Events; 19 | 20 | namespace WeChatClient.ChatContent.Views 21 | { 22 | /// 23 | /// ChatContentView.xaml 的交互逻辑 24 | /// 25 | public partial class ChatContentView : UserControl 26 | { 27 | public ChatContentView(ChatContentViewModel viewModel, IEventAggregator ea) 28 | { 29 | InitializeComponent(); 30 | DataContext = viewModel; 31 | 32 | ea.GetEvent().Subscribe(InputEmoji); 33 | } 34 | 35 | /// 36 | /// 输入表情 37 | /// 38 | /// 39 | private void InputEmoji(EmojiModel emoji) 40 | { 41 | ContentControl image = new ContentControl 42 | { 43 | Content = emoji, 44 | Width = 20, 45 | Height = 20, 46 | Style = (Style)FindResource("FaceImgStyle") 47 | }; 48 | var container = new InlineUIContainer(image, rtb.CaretPosition) { BaselineAlignment = BaselineAlignment.Bottom }; 49 | rtb.CaretPosition = container.ElementEnd; 50 | rtb.Focus(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.ChatContent/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/ChatListModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.ChatList.Views; 11 | using WeChatClient.Core.Dependency; 12 | 13 | namespace WeChatClient.ChatList 14 | { 15 | [Module(OnDemand = true)] //按需加载模块 16 | [ModuleDependency(WeChatClientConst.ContactListModuleName)] 17 | [ModuleDependency(WeChatClientConst.ChatContentModuleName)] 18 | public class ChatListModule : IModule 19 | { 20 | public void OnInitialized(IContainerProvider containerProvider) 21 | { 22 | //导航区域默认显示聊天列表 23 | var regionManager = containerProvider.Resolve(); 24 | regionManager.RegisterViewWithRegion(WeChatClientConst.NavRegionName, typeof(ChatListView)); 25 | } 26 | 27 | public void RegisterTypes(IContainerRegistry containerRegistry) 28 | { 29 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.ChatList")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.ChatList")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("3b4700f5-d8cc-4111-b3a9-0ff8afd3e3a0")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/Views/ChatListView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.ChatList.ViewModels; 16 | 17 | namespace WeChatClient.ChatList.Views 18 | { 19 | /// 20 | /// ChatListView.xaml 的交互逻辑 21 | /// 22 | public partial class ChatListView : UserControl 23 | { 24 | public ChatListView(ChatListViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | 30 | private void ListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) 31 | { 32 | //阻止ListBox右键选中 33 | if (e.RightButton == MouseButtonState.Pressed) 34 | e.Handled = true; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.ChatList/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/ContactContentModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using WeChatClient.ContactContent.Views; 10 | using WeChatClient.Core.Dependency; 11 | 12 | namespace WeChatClient.ContactContent 13 | { 14 | [Module(OnDemand = true)] 15 | public class ContactContentModule: IModule 16 | { 17 | public void OnInitialized(IContainerProvider containerProvider) 18 | { 19 | } 20 | 21 | public void RegisterTypes(IContainerRegistry containerRegistry) 22 | { 23 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 24 | containerRegistry.RegisterForNavigation(); //将联系人内容注册到导航 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.ContactContent")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.ContactContent")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("2bc643bc-ac00-4b1a-b055-d101fcd27ffb")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/ViewModels/ContactContentViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reactive.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Input; 11 | using WeChatClient.Core.Dependency; 12 | using WeChatClient.Core.Events; 13 | using WeChatClient.Core.Interfaces; 14 | using WeChatClient.Core.Models; 15 | 16 | namespace WeChatClient.ContactContent.ViewModels 17 | { 18 | [ExposeServices(ServiceLifetime.Singleton, typeof(IContactContentManager))] 19 | public class ContactContentViewModel : ReactiveObject, IContactContentManager 20 | { 21 | /// 22 | /// 当前选中联系人 23 | /// 24 | [Reactive] 25 | public WeChatUser SelectedContact { get; set; } 26 | /// 27 | /// 有联系人被选中 28 | /// 29 | public bool HasContactSelected { [ObservableAsProperty]get; } 30 | 31 | public ICommand ToChatCommand { get; } 32 | 33 | public ContactContentViewModel(IEventAggregator ea) 34 | { 35 | var observable = this.WhenAnyValue(p => p.SelectedContact).Select(p => p != null); 36 | observable.ToPropertyEx(this, p => p.HasContactSelected); 37 | ToChatCommand = ReactiveCommand.Create(() => 38 | { 39 | ea.GetEvent().Publish(SelectedContact); 40 | }, observable); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/Views/ContactContentView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.ContactContent.ViewModels; 16 | 17 | namespace WeChatClient.ContactContent.Views 18 | { 19 | /// 20 | /// ContactContentView.xaml 的交互逻辑 21 | /// 22 | public partial class ContactContentView : UserControl 23 | { 24 | public ContactContentView(ContactContentViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.ContactContent/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/ContactListModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.ContactList.Views; 11 | using WeChatClient.Core.Dependency; 12 | 13 | namespace WeChatClient.ContactList 14 | { 15 | [Module(OnDemand = true)] //按需加载模块 16 | [ModuleDependency(WeChatClientConst.ContactContentModuleName)] 17 | public class ContactListModule : IModule 18 | { 19 | public void OnInitialized(IContainerProvider containerProvider) 20 | { 21 | } 22 | 23 | public void RegisterTypes(IContainerRegistry containerRegistry) 24 | { 25 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 26 | containerRegistry.RegisterForNavigation(); //将联系人列表注册到导航 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.ContactList")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.ContactList")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("fac8ad54-72fa-465a-a897-39e62e5fb9f6")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/ViewModels/ContactListViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Regions; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.ComponentModel; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Data; 12 | using System.Windows.Input; 13 | using Unity.Attributes; 14 | using WeChatClient.Core.Dependency; 15 | using WeChatClient.Core.Interfaces; 16 | using WeChatClient.Core.Models; 17 | 18 | namespace WeChatClient.ContactList.ViewModels 19 | { 20 | [ExposeServices(ServiceLifetime.Singleton, typeof(IContactListManager))] //注册为IContactListManager接口(单例) 21 | public class ContactListViewModel : ReactiveObject, IContactListManager, INavigationAware 22 | { 23 | private readonly List _allContactList = new List(); 24 | 25 | public ObservableCollection ContactList { get; private set; } = new ObservableCollection(); 26 | 27 | [Reactive] 28 | public WeChatUser SelectedItem { get; set; } 29 | 30 | public ICommand ItemDoubleClickCommand { get; } 31 | 32 | [Dependency] 33 | protected IImageDownloadService ImageDownloadService { get; set; } 34 | 35 | public ContactListViewModel(IContactContentManager contactContentManager) 36 | { 37 | ICollectionView cv = CollectionViewSource.GetDefaultView(ContactList); 38 | cv.GroupDescriptions.Add(new PropertyGroupDescription(nameof(WeChatUser.StartChar))); 39 | 40 | this.WhenAnyValue(p => p.SelectedItem).Subscribe(p => contactContentManager.SelectedContact = p); 41 | 42 | ItemDoubleClickCommand = ReactiveCommand.Create(() => 43 | { 44 | contactContentManager.ToChatCommand.Execute(null); 45 | }); 46 | } 47 | 48 | public void AddContact(params WeChatUser[] chat) 49 | { 50 | _allContactList.AddRange(chat); 51 | ContactList.AddRange(chat.Where(p => p.StartChar.Length == 1)); 52 | ImageDownloadService.Add(ContactList.ToArray()); 53 | } 54 | 55 | public WeChatUser FindContact(string userName) 56 | { 57 | return _allContactList.FirstOrDefault(p => p.UserName == userName); 58 | } 59 | 60 | public void DelContact(params string[] userNames) 61 | { 62 | foreach (var item in userNames) 63 | { 64 | var user = _allContactList.FirstOrDefault(p => p.UserName == item); 65 | if(user != null) 66 | { 67 | _allContactList.Remove(user); 68 | if (ContactList.Contains(user)) 69 | ContactList.Remove(user); 70 | } 71 | } 72 | } 73 | 74 | public void ModContact(params WeChatUser[] contact) 75 | { 76 | foreach (var item in contact) 77 | { 78 | if (item.IsRoomContact()) //这里不包含群聊 79 | continue; 80 | 81 | var local = _allContactList.FirstOrDefault(p => p.UserName == item.UserName); 82 | if (local != null) 83 | { 84 | _allContactList.Remove(local); 85 | ContactList.Remove(local); 86 | } 87 | _allContactList.Add(item); 88 | if (item.StartChar.Length == 1) 89 | ContactList.Add(item); 90 | } 91 | 92 | ImageDownloadService.Add(contact.ToArray()); 93 | } 94 | 95 | public WeChatUser[] SearchContact(string searchText) 96 | { 97 | return ContactList.Where(p => p.ShowName?.Contains(searchText) == true || p.ShowPinYin?.Contains(searchText) == true).ToArray(); 98 | } 99 | 100 | #region INavigationAware 101 | public void OnNavigatedTo(NavigationContext navigationContext) 102 | { 103 | navigationContext.NavigationService.Region.RegionManager.RequestNavigate(WeChatClientConst.ContentRegionName, "ContactContentView"); 104 | } 105 | 106 | public bool IsNavigationTarget(NavigationContext navigationContext) 107 | { 108 | return true; 109 | } 110 | 111 | public void OnNavigatedFrom(NavigationContext navigationContext) 112 | { 113 | 114 | } 115 | #endregion 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/Views/ContactListView.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/Views/ContactListView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.ContactList.ViewModels; 16 | 17 | namespace WeChatClient.ContactList.Views 18 | { 19 | /// 20 | /// ContactListView.xaml 的交互逻辑 21 | /// 22 | public partial class ContactListView : UserControl 23 | { 24 | public ContactListView(ContactListViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.ContactList/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WeChatClient.Core/Converters/BoolToValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace WeChatClient.Core.Converters 11 | { 12 | /// 13 | /// 通用的BoolToXXX转换类,这个类使用Binding对象的ConverterParameter和FallbackValue来实现布尔类型与任意值转换的功能 14 | /// 15 | public class BoolToValueConverter : IValueConverter 16 | { 17 | 18 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | bool v = false; 21 | if (value == null) 22 | v = false; 23 | else if (value.GetType() == typeof(bool)) 24 | v = (bool)value; 25 | else if (value.GetType() == typeof(int)) 26 | v = (int)value > 0; 27 | else if (value.GetType() == typeof(string)) 28 | v = !string.IsNullOrEmpty((string)value); 29 | 30 | if (v) 31 | return parameter; 32 | else 33 | return DependencyProperty.UnsetValue; 34 | } 35 | 36 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 37 | { 38 | return object.Equals(value, parameter); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WeChatClient.Core/Converters/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace WeChatClient.Core.Converters 11 | { 12 | public class BoolToVisibilityConverter : IValueConverter 13 | { 14 | /// 15 | /// 是否反转转换源参数值 16 | /// 17 | public bool Inverse { get; set; } 18 | 19 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | bool v = false; 22 | if (value == null) 23 | v = false; 24 | else if (value.GetType() == typeof(bool)) 25 | v = (bool)value; 26 | else if (value.GetType() == typeof(int)) 27 | v = (int)value > 0; 28 | else if (value.GetType() == typeof(string)) 29 | v = !string.IsNullOrEmpty((string)value); 30 | 31 | if (Inverse) 32 | v = !v; 33 | return v ? Visibility.Visible : Visibility.Hidden; 34 | } 35 | 36 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 37 | { 38 | throw new NotImplementedException(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WeChatClient.Core/Converters/InverseConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace WeChatClient.Core.Converters 10 | { 11 | /// 12 | /// bool类型取反转换器 13 | /// 14 | public class InverseConverter : IValueConverter 15 | { 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | return !(bool)value; 19 | } 20 | 21 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WeChatClient.Core/Converters/UriToBitmapConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Data; 9 | using System.Windows.Media; 10 | using System.Windows.Media.Imaging; 11 | using WeChatClient.Core.Helpers; 12 | using WeChatClient.Core.Http; 13 | 14 | namespace WeChatClient.Core.Converters 15 | { 16 | public sealed class UriToBitmapConverter : IValueConverter //这种方式还是会很卡,弃用(采用后台队列下载图片) 17 | { 18 | private static readonly Dictionary ImageCache = new Dictionary(); 19 | 20 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 21 | { 22 | if (value == null) 23 | return null; 24 | 25 | string uri = value.ToString(); 26 | if (!ImageCache.TryGetValue(uri, out ImageSource res)) 27 | { 28 | try 29 | { 30 | byte[] bytes = BaseService.Request(uri, MethodEnum.GET); 31 | res = ImageHelper.MemoryToImageSourceOther(new MemoryStream(bytes)); 32 | ImageCache.Add(uri, res); 33 | } 34 | catch (Exception) 35 | { 36 | } 37 | } 38 | return res; 39 | } 40 | 41 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 42 | { 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /WeChatClient.Core/Converters/WxResConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace WeChatClient.Core.Converters 12 | { 13 | public class WxResConverter : IMultiValueConverter, IValueConverter 14 | { 15 | /// 16 | /// 从微信Web版扒下来的资源 17 | /// 18 | private static readonly BitmapFrame WxRes = BitmapFrame.Create(new Uri("pack://application:,,,/WeChatClient.Core;component/Resources/wx_res.png", UriKind.Absolute)); 19 | 20 | #region IMultiValueConverter 21 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 22 | { 23 | int[] ps = values[0].ToString().Split(' ')[(bool)values[1] ? 0 : 1].Split(',').Select(p => int.Parse(p)).ToArray(); 24 | return GetCroppedBitmap(ps[0], ps[1], ps[2], ps[3]); 25 | } 26 | 27 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | #endregion 32 | 33 | #region IValueConverter 34 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 35 | { 36 | if (value == null) 37 | return null; 38 | int[] ps = value.ToString().Split(',').Select(p => int.Parse(p)).ToArray(); 39 | return GetCroppedBitmap(ps[0], ps[1], ps[2], ps[3]); 40 | } 41 | 42 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 43 | { 44 | throw new NotImplementedException(); 45 | } 46 | #endregion 47 | 48 | /// 49 | /// 获取一张图片中的一部分 50 | /// 51 | /// 图片路径 52 | /// 要截取部分的X坐标 53 | /// 要截取部分的Y坐标 54 | /// 截取的宽度 55 | /// 截取的高度 56 | /// 57 | private static BitmapSource GetCroppedBitmap(int XCoordinate, int YCoordinate, int Width, int Height) 58 | { 59 | return new CroppedBitmap(WxRes, new Int32Rect(XCoordinate, YCoordinate, Width, Height)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WeChatClient.Core/Dependency/DependencyExtension.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace WeChatClient.Core.Dependency 10 | { 11 | /// 12 | /// 依赖注入扩展类 13 | /// 14 | public static class DependencyExtension 15 | { 16 | /// 17 | /// 注册程序集中标注了ExposeServicesAttribute属性的类 18 | /// 19 | /// 20 | /// 21 | public static void RegisterAssembly(this IContainerRegistry container, Assembly assembly) 22 | { 23 | var types = assembly.GetTypes() 24 | .Where( 25 | type => type != null && 26 | type.IsClass && 27 | !type.IsAbstract && 28 | !type.IsGenericType && 29 | type.CustomAttributes.Any(t => t.AttributeType == typeof(ExposeServicesAttribute)) 30 | ).ToArray(); 31 | 32 | foreach (var type in types) 33 | { 34 | RegisterType(container, type); 35 | } 36 | } 37 | 38 | /// 39 | /// 注册类型 40 | /// 41 | /// 42 | /// 43 | private static void RegisterType(IContainerRegistry container, Type type) 44 | { 45 | foreach (var exposedServices in GetExposedServices(type)) 46 | { 47 | if(exposedServices.ServiceLifetime == ServiceLifetime.Singleton) 48 | { 49 | //Prism.Ioc使用Unity框架,默认注册为Transient,这里需要改变自身为Singleton 50 | container.RegisterSingleton(type); 51 | } 52 | foreach (var serviceType in exposedServices.ExposedServiceTypes) 53 | { 54 | if (exposedServices.ServiceLifetime == ServiceLifetime.Singleton) 55 | { 56 | container.RegisterSingleton(serviceType, type); 57 | } 58 | else if(exposedServices.ServiceLifetime == ServiceLifetime.Transient) 59 | { 60 | container.Register(serviceType, type); 61 | } 62 | } 63 | 64 | } 65 | } 66 | 67 | /// 68 | /// 获取要注册的服务 69 | /// 70 | /// 71 | /// 72 | private static IEnumerable GetExposedServices(Type type) 73 | { 74 | var typeInfo = type.GetTypeInfo(); 75 | 76 | var customExposedServices = typeInfo 77 | .GetCustomAttributes() 78 | .OfType() 79 | .ToList(); 80 | 81 | return customExposedServices; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /WeChatClient.Core/Dependency/ExposeServicesAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Dependency 8 | { 9 | /// 10 | /// 公开服务,用来注册接口 11 | /// 12 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 13 | public class ExposeServicesAttribute : Attribute 14 | { 15 | public ServiceLifetime ServiceLifetime { get; } 16 | 17 | public Type[] ExposedServiceTypes { get; } 18 | 19 | public ExposeServicesAttribute(ServiceLifetime serviceLifetime, params Type[] exposedServiceTypes) 20 | { 21 | ServiceLifetime = serviceLifetime; 22 | ExposedServiceTypes = exposedServiceTypes ?? new Type[0]; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WeChatClient.Core/Dependency/ServiceLifetime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Dependency 8 | { 9 | /// 10 | /// 生命周期 11 | /// 12 | public enum ServiceLifetime 13 | { 14 | /// 15 | /// 单例 16 | /// 17 | Singleton = 0, 18 | /// 19 | /// 多实例 20 | /// 21 | Transient = 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WeChatClient.Core/Events/ChatWithContactEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using WeChatClient.Core.Models; 8 | 9 | namespace WeChatClient.Core.Events 10 | { 11 | public class ChatWithContactEvent: PubSubEvent 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WeChatClient.Core/Events/LoginSuccessfulEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WeChatClient.Core.Events 9 | { 10 | public class LoginSuccessfulEvent : PubSubEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WeChatClient.Core/Events/SendTextMsgEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WeChatClient.Core.Events 9 | { 10 | public class SendTextMsgEvent : PubSubEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WeChatClient.Core/Extensions/RichTextBoxExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | 11 | namespace WeChatClient.Core.Extensions 12 | { 13 | public class RichTextBoxExtensions 14 | { 15 | /// 16 | /// 给RichTextBox提供依赖属性DocumentProperty,默认Document属性不支持数据绑定 17 | /// 18 | public static readonly DependencyProperty DocumentProperty = DependencyProperty.RegisterAttached( 19 | "Document", typeof(FlowDocument), typeof(RichTextBoxExtensions), 20 | new PropertyMetadata(default(FlowDocument), OnDocumentChanged)); 21 | 22 | private static void OnDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 23 | { 24 | FlowDocument document = (FlowDocument)e.NewValue; 25 | if (document.Parent is RichTextBox parent) 26 | { 27 | //这里很重要,WPF的控件元素有且仅有一个父对象(如果不这样设置,会报错:Document已属于另一RichTextBox) 28 | parent.Document = new FlowDocument(); 29 | } 30 | document.LineHeight = 1; 31 | Binding width_bind = new Binding 32 | { 33 | RelativeSource = new RelativeSource 34 | { 35 | Mode = RelativeSourceMode.FindAncestor, 36 | AncestorType = typeof(RichTextBox) 37 | }, 38 | Path = new PropertyPath("ActualWidth"), 39 | Mode = BindingMode.OneWay 40 | }; 41 | document.SetBinding(FlowDocument.PageWidthProperty, width_bind); 42 | 43 | RichTextBox rtb = (RichTextBox)d; 44 | rtb.Document = document; 45 | } 46 | 47 | public static void SetDocument(DependencyObject element, FlowDocument value) 48 | { 49 | element.SetValue(DocumentProperty, value); 50 | } 51 | 52 | public static FlowDocument GetDocument(DependencyObject element) 53 | { 54 | return (FlowDocument)element.GetValue(DocumentProperty); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WeChatClient.Core/Extensions/ScrollViewerExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | 9 | namespace WeChatClient.Core.Extensions 10 | { 11 | public class ScrollViewerExtensions 12 | { 13 | /// 14 | /// 总是滚动到底部 15 | /// 16 | public static readonly DependencyProperty AlwaysScrollToEndProperty = DependencyProperty.RegisterAttached("AlwaysScrollToEnd", typeof(bool), typeof(ScrollViewerExtensions), new PropertyMetadata(false, AlwaysScrollToEndChanged)); 17 | private static bool _autoScroll; 18 | 19 | 20 | private static void AlwaysScrollToEndChanged(object sender, DependencyPropertyChangedEventArgs e) 21 | { 22 | if (sender is ScrollViewer scroll) 23 | { 24 | bool alwaysScrollToEnd = (e.NewValue != null) && (bool)e.NewValue; 25 | if (alwaysScrollToEnd) 26 | { 27 | scroll.ScrollToEnd(); 28 | scroll.ScrollChanged += ScrollChanged; 29 | // scroll.SizeChanged += Scroll_SizeChanged; 30 | } 31 | else { scroll.ScrollChanged -= ScrollChanged; /*scroll.ScrollChanged -= ScrollChanged; */} 32 | } 33 | else { throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances."); } 34 | } 35 | 36 | 37 |         public static bool GetAlwaysScrollToEnd(ScrollViewer scroll) 38 | { 39 | if (scroll == null) { throw new ArgumentNullException("scroll"); } 40 | return (bool)scroll.GetValue(AlwaysScrollToEndProperty); 41 | } 42 | 43 | 44 | public static void SetAlwaysScrollToEnd(ScrollViewer scroll, bool alwaysScrollToEnd) 45 | { 46 | if (scroll == null) { throw new ArgumentNullException("scroll"); } 47 | scroll.SetValue(AlwaysScrollToEndProperty, alwaysScrollToEnd); 48 | } 49 | 50 | 51 | private static void ScrollChanged(object sender, ScrollChangedEventArgs e) 52 | { 53 | if (!(sender is ScrollViewer scroll)) { throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances."); } 54 | 55 | 56 | if (e.ExtentHeightChange == 0) { _autoScroll = scroll.VerticalOffset == scroll.ScrollableHeight; } 57 | if (_autoScroll && e.ExtentHeightChange != 0) { scroll.ScrollToVerticalOffset(scroll.ExtentHeight); } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /WeChatClient.Core/Extensions/TextBoxExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Media; 9 | 10 | namespace WeChatClient.Core.Extensions 11 | { 12 | public class TextBoxExtensions 13 | { 14 | /// 15 | /// 当文本超出显示时,文本是否靠右侧显示 16 | /// 17 | public static readonly DependencyProperty ScrollEndWhenTextTrimmedProperty = DependencyProperty.RegisterAttached( 18 | "ScrollEndWhenTextTrimmed", typeof(bool), typeof(TextBoxExtensions), 19 | new PropertyMetadata(default(bool), OnScrollEndWhenTextTrimmedChanged)); 20 | 21 | private static void OnScrollEndWhenTextTrimmedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 22 | { 23 | var textBox = (TextBox)d; 24 | textBox.TextChanged -= TextBoxOnTextChanged; 25 | if ((bool)e.NewValue) 26 | { 27 | textBox.FlowDirection = IsTextTrimmed(textBox) ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; 28 | textBox.TextChanged += TextBoxOnTextChanged; 29 | } 30 | } 31 | static void TextBoxOnTextChanged(object sender, TextChangedEventArgs args) 32 | { 33 | var textBox = sender as TextBox; 34 | textBox.FlowDirection = IsTextTrimmed(textBox) ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; 35 | } 36 | 37 | private static bool IsTextTrimmed(TextBox textBox) 38 | { 39 | Typeface typeface = new Typeface( 40 | textBox.FontFamily, 41 | textBox.FontStyle, 42 | textBox.FontWeight, 43 | textBox.FontStretch); 44 | 45 | FormattedText formattedText = new FormattedText( 46 | textBox.Text, 47 | System.Threading.Thread.CurrentThread.CurrentCulture, 48 | textBox.FlowDirection, 49 | typeface, 50 | textBox.FontSize, 51 | textBox.Foreground); bool isTrimmed = formattedText.Width > textBox.Width; 52 | return isTrimmed; 53 | } 54 | 55 | public static void SetScrollEndWhenTextTrimmed(DependencyObject element, bool value) 56 | { 57 | element.SetValue(ScrollEndWhenTextTrimmedProperty, value); 58 | } 59 | 60 | public static bool GetScrollEndWhenTextTrimmed(DependencyObject element) 61 | { 62 | return (bool)element.GetValue(ScrollEndWhenTextTrimmedProperty); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /WeChatClient.Core/Helpers/ImageHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Media; 8 | using System.Windows.Media.Imaging; 9 | 10 | namespace WeChatClient.Core.Helpers 11 | { 12 | public class ImageHelper 13 | { 14 | /// 15 | /// Memory转成ImageSource 16 | /// 17 | /// 18 | /// 19 | public static ImageSource MemoryToImageSource(MemoryStream ms) 20 | { 21 | return (ImageSource)(new ImageSourceConverter()).ConvertFrom(ms); 22 | } 23 | /// 24 | /// Memory转成ImageSource 25 | /// 26 | /// 27 | /// 28 | public static ImageSource MemoryToImageSourceOther(MemoryStream ms) 29 | { 30 | Image img = Image.FromStream(ms); 31 | Bitmap bmp = new Bitmap(img); 32 | BitmapSource bi = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 33 | return bi; 34 | } 35 | /// 36 | /// Memory转成ImageSource 37 | /// 二维码的白色部分变成透明 38 | /// 39 | /// 40 | /// 41 | public static ImageSource MemoryToImageSource_Transparent(MemoryStream ms) 42 | { 43 | Image img = Image.FromStream(ms); 44 | Bitmap bmp = new Bitmap(img); 45 | bmp.MakeTransparent(System.Drawing.Color.White); 46 | BitmapSource bi= System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 47 | return bi; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /WeChatClient.Core/Helpers/RandomHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace WeChatClient.Core.Helpers 7 | { 8 | public class RandomHelper 9 | { 10 | /// 11 | /// 返回一个随机数 12 | /// 13 | /// 位数 14 | /// 15 | public static string RandomNum(int N) 16 | { 17 | string resultNum = string.Empty; 18 | Random random = new Random(); 19 | for (int i = 0; i < N; i++) 20 | { 21 | resultNum += random.Next(9); 22 | } 23 | return resultNum; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WeChatClient.Core/Helpers/TimeStampHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Helpers 8 | { 9 | public static class TimeStampHelper 10 | { 11 | /// 12 | /// DateTime时间格式转换为Unix时间戳格式 13 | /// 14 | /// DateTime时间格式 15 | /// Unix时间戳格式 16 | public static int ToTimeStamp(this System.DateTime time) 17 | { 18 | System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); 19 | return (int)(time - startTime).TotalSeconds; 20 | } 21 | 22 | /// 23 | /// 时间戳转为C#格式时间 24 | /// 25 | /// Unix时间戳格式 26 | /// C#格式时间 27 | public static DateTime ToTime(this int timeStamp) 28 | { 29 | DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); 30 | long lTime = long.Parse(timeStamp + "0000000"); 31 | TimeSpan toNow = new TimeSpan(lTime); 32 | return dtStart.Add(toNow); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/BaseRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Http 8 | { 9 | public class BaseRequest 10 | { 11 | public string DeviceID { get; set; } 12 | public string Sid { get; set; } 13 | public string Skey { get; set; } 14 | public int Uin { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/BaseService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace WeChatClient.Core.Http 11 | { 12 | /// 13 | /// 访问http服务器类 14 | /// 15 | public class BaseService 16 | { 17 | /// 18 | /// 访问服务器时的cookies 19 | /// 20 | public static CookieContainer CookiesContainer; 21 | /// 22 | /// 向服务器发送Request 23 | /// 24 | /// 字符串 25 | /// 枚举类型的方法Get或者Post 26 | /// Post时必须传值 27 | /// 28 | public static byte[] Request(string url, MethodEnum method, string body = "", string contentType = null) 29 | { 30 | try 31 | { 32 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 33 | request.Method = method.ToString(); 34 | //如果是Post的话,则设置body 35 | if (method == MethodEnum.POST) 36 | { 37 | byte[] request_body = Encoding.UTF8.GetBytes(body); 38 | request.ContentLength = request_body.Length; 39 | if (contentType != null) 40 | request.ContentType = contentType; 41 | 42 | Stream request_stream = request.GetRequestStream(); 43 | request_stream.Write(request_body, 0, request_body.Length); 44 | } 45 | if (CookiesContainer == null) 46 | { 47 | CookiesContainer = new CookieContainer(); 48 | } 49 | //启用Cookie 50 | request.CookieContainer = CookiesContainer; 51 | 52 | return Response(request); 53 | } 54 | catch (Exception ex) 55 | { 56 | throw new Exception(ex.Message); 57 | } 58 | } 59 | 60 | /// 61 | /// 返回Response数据 62 | /// 63 | /// 64 | /// 65 | private static byte[] Response(HttpWebRequest request) 66 | { 67 | try 68 | { 69 | HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 70 | Stream response_stream = response.GetResponseStream(); 71 | //获取返回报文内容长度 72 | int count = (int)response.ContentLength; 73 | int offset = 0; 74 | byte[] buf = new byte[count]; 75 | //读取返回数据 76 | while (count > 0) 77 | { 78 | int n = response_stream.Read(buf, offset, count); 79 | if (n == 0) 80 | { 81 | break; 82 | } 83 | count -= n; 84 | offset += n; 85 | } 86 | return buf; 87 | } 88 | catch (Exception ex) 89 | { 90 | throw new Exception(ex.Message); 91 | } 92 | } 93 | 94 | /// 95 | /// 获取所有的Cookie 96 | /// 97 | /// 98 | /// 99 | private static List GetAllCookies(CookieContainer cc) 100 | { 101 | List lstCookies = new List(); 102 | Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cc, new object[] { }); 103 | 104 | foreach (object pathList in table.Values) 105 | { 106 | SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { }); 107 | foreach (CookieCollection colCookies in lstCookieCol.Values) 108 | { 109 | foreach (Cookie c in colCookies) 110 | { 111 | lstCookies.Add(c); 112 | } 113 | } 114 | } 115 | 116 | return lstCookies; 117 | } 118 | 119 | /// 120 | /// 获取指定cookie 121 | /// 122 | /// 123 | /// 124 | public static Cookie GetCookie(string name) 125 | { 126 | List cookies = GetAllCookies(CookiesContainer); 127 | foreach (Cookie c in cookies) 128 | { 129 | if (c.Name == name) 130 | { 131 | return c; 132 | } 133 | } 134 | return null; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/ImageCacheService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Media; 7 | using WeChatClient.Core.Dependency; 8 | 9 | namespace WeChatClient.Core.Http 10 | { 11 | /// 12 | /// 图片全局缓存 13 | /// 14 | [ExposeServices(ServiceLifetime.Singleton)] 15 | public class ImageCacheService 16 | { 17 | private readonly Dictionary _cache = new Dictionary(); 18 | public bool TryGetValue(string uri, out ImageSource image) 19 | { 20 | return _cache.TryGetValue(uri, out image); 21 | } 22 | public void Add(string uri, ImageSource image) 23 | { 24 | lock (this) 25 | { 26 | if (_cache.ContainsKey(uri)) 27 | return; 28 | _cache.Add(uri, image); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/ImageDownloadService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Media; 10 | using System.Windows.Media.Imaging; 11 | using Unity.Attributes; 12 | using WeChatClient.Core.Dependency; 13 | using WeChatClient.Core.Helpers; 14 | using WeChatClient.Core.Interfaces; 15 | 16 | namespace WeChatClient.Core.Http 17 | { 18 | [ExposeServices(ServiceLifetime.Transient,typeof(IImageDownloadService))] //因为多个模块都需要下载图片,为了互不影响,则采用多实例 19 | public class ImageDownloadService : IImageDownloadService 20 | { 21 | /// 22 | /// 需要下载图片的模型队列 23 | /// 24 | private readonly Queue _modelQueue = new Queue(); 25 | private readonly object _sync = new object(); 26 | 27 | private readonly static BitmapImage _default = WeChatClientConst.DefaultHeadImage; 28 | 29 | [Dependency] 30 | protected ImageCacheService ImageCacheService { get; set; } 31 | public ImageDownloadService() 32 | { 33 | StartDownloadTask(); 34 | } 35 | 36 | /// 37 | /// 添加模型 38 | /// 39 | /// 40 | public void Add(params INeedDownloadImageModel[] models) 41 | { 42 | lock (_sync) 43 | { 44 | foreach (var item in models) 45 | { 46 | _modelQueue.Enqueue(item); 47 | } 48 | } 49 | } 50 | 51 | /// 52 | /// 开启下载图片后台任务 53 | /// 54 | private void StartDownloadTask() 55 | { 56 | Task.Run(() => 57 | { 58 | while (true) 59 | { 60 | if (_modelQueue.Count > 0) 61 | { 62 | INeedDownloadImageModel model = null; 63 | lock (_sync) 64 | { 65 | model = _modelQueue.Dequeue(); 66 | } 67 | try 68 | { 69 | if (model.Image != null) 70 | continue; 71 | 72 | if (ImageCacheService.TryGetValue(model.Uri, out ImageSource image)) 73 | { 74 | model.Image = image; 75 | continue; 76 | } 77 | byte[] bytes = BaseService.Request(model.Uri, MethodEnum.GET); 78 | //这里赋值ImageSource时,需要在UI线程上执行,才能绑定到界面 79 | Application.Current.Dispatcher.BeginInvoke(new Action(() => 80 | { 81 | try 82 | { 83 | model.Image = bytes.Length == 0 ? _default : ImageHelper.MemoryToImageSourceOther(new MemoryStream(bytes)); 84 | ImageCacheService.Add(model.Uri, model.Image); 85 | } 86 | catch (Exception) 87 | { 88 | 89 | } 90 | })); 91 | } 92 | catch (Exception) 93 | { 94 | 95 | } 96 | } 97 | else 98 | { 99 | Thread.Sleep(100); 100 | } 101 | } 102 | }); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/MethodEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Http 8 | { 9 | public enum MethodEnum 10 | { 11 | GET, 12 | POST 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/StaticCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Http 8 | { 9 | public class StaticCode 10 | { 11 | public static class LoginCode 12 | { 13 | /// 14 | /// 确认登录 15 | /// 16 | public static string code_LoginSuccess = "200"; 17 | /// 18 | /// 扫描成功 19 | /// 20 | public static string code_LoginWait = "201"; 21 | /// 22 | /// 登陆超时 23 | /// 24 | public static string code_LoginTimeOut = "408"; 25 | } 26 | 27 | //public static class MethodCode 28 | //{ 29 | // /// 30 | // /// POST 31 | // /// 32 | // public static string code_Post = "POST"; 33 | // /// 34 | // /// GET 35 | // /// 36 | // public static string code_Get = "GET"; 37 | //} 38 | 39 | public static class RetCode 40 | { 41 | /// 42 | /// 正常 43 | /// 44 | public static string code_Normal = "0"; 45 | /// 46 | /// 失败/退出微信 47 | /// 48 | public static string code_Miss = "1100"; 49 | } 50 | 51 | public static class SelectorCode 52 | { 53 | /// 54 | /// 正常 55 | /// 56 | public static string code_Normal = "0"; 57 | /// 58 | /// 新的消息 59 | /// 60 | public static string code_New = "2"; 61 | /// 62 | /// 进入/离开聊天界面 63 | /// 64 | public static string code_InOrLeave = "7"; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /WeChatClient.Core/Http/StaticUrl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Helpers; 7 | 8 | namespace WeChatClient.Core.Http 9 | { 10 | /// 11 | /// 所有的Url 12 | /// 13 | public class StaticUrl 14 | { 15 | public static string stringWx = "https://wx.qq.com"; 16 | 17 | public static string stringWebPush = "https://webpush.weixin.qq.com"; 18 | 19 | /// 20 | /// 获取会话的UUID 21 | /// 22 | public static string Url_GetUUID = "https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&fun=new&lang=zh_CN&_="; 23 | /// 24 | /// 获取二维码的URL 25 | /// 26 | public static string Url_GetQrCode = "https://login.weixin.qq.com/qrcode/"; 27 | /// 28 | /// 等待扫码登陆 29 | /// 30 | public static string Url_WaitLogin = "https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid="; 31 | /// 32 | /// 微信初始化 33 | /// 34 | public static string Url_Init = "/cgi-bin/mmwebwx-bin/webwxinit?r="; 35 | /// 36 | /// 开启微信状态通知 37 | /// 38 | public static string Url_StatusNotify = stringWx + "/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN&pass_ticket="; 39 | /// 40 | /// 获取好友列表 41 | /// 42 | public static string Url_GetContact = "/cgi-bin/mmwebwx-bin/webwxgetcontact"; 43 | /// 44 | /// 获取指定用户或群组列表 45 | /// 46 | public static string Url_wxbatchgetcontact = stringWx + "/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex"; 47 | /// 48 | /// 消息检查 49 | /// 50 | public static string Url_SyncCheck = "/cgi-bin/mmwebwx-bin/synccheck?"; 51 | /// 52 | /// 获取最新消息 53 | /// 54 | public static string Url_Sync = "/cgi-bin/mmwebwx-bin/webwxsync?"; 55 | /// 56 | /// 发送消息 57 | /// 58 | public static string Url_SendMsg = "/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&sid="; 59 | /// 60 | /// 获取好友头像 61 | /// 62 | public static string Url_GetIcon = "/cgi-bin/mmwebwx-bin/webwxgeticon?username="; 63 | /// 64 | /// 获取群组头像 65 | /// 66 | public static string Url_GetHeadImg = "/cgi-bin/mmwebwx-bin/webwxgetheadimg?username="; 67 | /// 68 | /// 获取登录参数--拼接部分 69 | /// 70 | public static string Url_redirect_ext = "&fun=new&version=v2&lang=zh_CN"; 71 | /// 72 | /// 同步检查扩展部分 73 | /// 74 | public static string Url_SyncCheck_ext = "sid={0}&uin={1}&synckey={2}&r={3}&skey={4}&deviceid={5}&_="; 75 | /// 76 | /// 同步扩展部分 77 | /// 78 | public static string Url_Sync_ext = "sid={0}&lang=zh_CN&skey={1}&pass_ticket={2}"; 79 | public static string Uri_logout = stringWx + "/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&skey="; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IChatContentManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Models; 7 | 8 | namespace WeChatClient.Core.Interfaces 9 | { 10 | public interface IChatContentManager 11 | { 12 | /// 13 | /// 设置当前选中的聊天 14 | /// 15 | WeChatUser SelectedChat { set; get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IChatListManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Models; 7 | 8 | namespace WeChatClient.Core.Interfaces 9 | { 10 | public interface IChatListManager 11 | { 12 | /// 13 | /// 添加聊天 14 | /// 15 | /// 16 | void AddChat(params WeChatUser[] chat); 17 | /// 18 | /// 修改聊天 19 | /// 20 | /// 21 | void ModChat(params WeChatUser[] chat); 22 | /// 23 | /// 删除聊天 24 | /// 25 | /// 26 | void DelChat(params string[] userNames); 27 | /// 28 | /// 是否包含该用户名的聊天 29 | /// 30 | /// 31 | /// 32 | bool Contains(string userName); 33 | /// 34 | /// 同步消息 35 | /// 36 | /// 37 | void SyncMessage(params WeChatMessage[] messages); 38 | /// 39 | /// 更新初始化的群成员 40 | /// 41 | /// 42 | void UpdateInitGroupMember(params WeChatUser[] groupChats); 43 | /// 44 | /// 和联系人聊天 45 | /// 46 | /// 47 | void ChatWithContact(WeChatUser contact); 48 | /// 49 | /// 搜索群聊 50 | /// 51 | /// 52 | /// 53 | WeChatUser[] SearchRoomChat(string searchText); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IContactContentManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Input; 7 | using WeChatClient.Core.Models; 8 | 9 | namespace WeChatClient.Core.Interfaces 10 | { 11 | public interface IContactContentManager 12 | { 13 | /// 14 | /// 当前选中的联系人 15 | /// 16 | WeChatUser SelectedContact { set; get; } 17 | /// 18 | /// 去和选中的联系人聊天 19 | /// 20 | ICommand ToChatCommand { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IContactListManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Models; 7 | 8 | namespace WeChatClient.Core.Interfaces 9 | { 10 | public interface IContactListManager 11 | { 12 | void AddContact(params WeChatUser[] contact); 13 | WeChatUser FindContact(string userName); 14 | void DelContact(params string[] userNames); 15 | void ModContact(params WeChatUser[] contact); 16 | WeChatUser[] SearchContact(string searchText); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IImageDownloadService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Interfaces 8 | { 9 | /// 10 | /// 图片下载服务 11 | /// 12 | public interface IImageDownloadService 13 | { 14 | /// 15 | /// 添加需要下载图片的模型 16 | /// 17 | /// 18 | void Add(params INeedDownloadImageModel[] models); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/IMainManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Models; 7 | 8 | namespace WeChatClient.Core.Interfaces 9 | { 10 | public interface IMainManager 11 | { 12 | /// 13 | /// 自己 14 | /// 15 | WeChatUser WeChatUser { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WeChatClient.Core/Interfaces/INeedDownloadImageModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Media; 7 | 8 | namespace WeChatClient.Core.Interfaces 9 | { 10 | /// 11 | /// 需要下载图片的模型 12 | /// 13 | public interface INeedDownloadImageModel 14 | { 15 | /// 16 | /// 图片网络uri 17 | /// 18 | string Uri { get; } 19 | /// 20 | /// 图片对象 21 | /// 22 | ImageSource Image { set; get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WeChatClient.Core/Models/BaseNotifyModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace WeChatClient.Core.Models 10 | { 11 | public class BaseNotifyModel : INotifyPropertyChanged 12 | { 13 | #region INotifyPropertyChanged 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | protected void OnPropertyChanged([CallerMemberName]string propertyName = null) 16 | { 17 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 18 | } 19 | #endregion 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WeChatClient.Core/Models/ChatRoomMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WeChatClient.Core.Models 8 | { 9 | /// 10 | /// 群成员 11 | /// 12 | public class ChatRoomMember 13 | { 14 | /// 15 | /// 昵称 16 | /// 17 | public string NickName { get; set; } 18 | /// 19 | /// 备注名称 20 | /// 21 | public string DisplayName { get; set; } 22 | /// 23 | /// 用户id 24 | /// 25 | public string UserName { get; set; } 26 | /// 27 | /// 显示名称 28 | /// 29 | public string ShowName 30 | { 31 | get 32 | { 33 | return string.IsNullOrEmpty(DisplayName) ? NickName : DisplayName; 34 | } 35 | } 36 | /// 37 | /// 关联的联系人对象 38 | /// 39 | public WeChatUser User { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WeChatClient.Core/Models/WeChatMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Media; 7 | using WeChatClient.Core.Interfaces; 8 | 9 | namespace WeChatClient.Core.Models 10 | { 11 | /// 12 | /// 微信消息 13 | /// 14 | public class WeChatMessage: BaseNotifyModel, INeedDownloadImageModel 15 | { 16 | /// 17 | /// 消息id 18 | /// 19 | public string MsgId { get; set; } 20 | /// 21 | /// 消息发送人 22 | /// 23 | public string FromUserName { get; set; } 24 | /// 25 | /// 消息发送人显示名称 26 | /// 27 | public string FromUserShowName { get; set; } 28 | /// 29 | /// 消息接收人 30 | /// 31 | public string ToUserName { get; set; } 32 | /// 33 | /// 消息内容 34 | /// 35 | public string Content { get; set; } 36 | /// 37 | /// 消息类型 38 | /// 39 | public int MsgType { get; set; } 40 | /// 41 | /// 消息时间(时间戳格式) 42 | /// 43 | public int CreateTime { get; set; } 44 | 45 | public DateTime CreateDateTime { get; set; } 46 | 47 | public string ShortTime { get; set; } 48 | /// 49 | /// 是否显示时间 50 | /// 51 | public bool ShowShortTime { get; set; } 52 | 53 | /// 54 | /// 状态通知码(如果为4,则加载更多聊天列表) 55 | /// 56 | public int StatusNotifyCode { get; set; } 57 | /// 58 | /// 状态通知用户名(如果状态通知码为4,则加载这些用户,添加到聊天列表) 59 | /// 60 | public string StatusNotifyUserName { get; set; } 61 | 62 | /// 63 | /// 是否为加载更多聊天列表消息 64 | /// 65 | public bool IsLoadMoreChats => MsgType == 51 && StatusNotifyCode == 4 && FromUserName == ToUserName; 66 | 67 | /// 68 | /// 是否为收到的消息 69 | /// 70 | public bool IsReceive { get; set; } 71 | /// 72 | /// 是否为群消息 73 | /// 74 | public bool IsRoom { get; set; } 75 | /// 76 | /// 只有收到的群消息需要显示发消息的人的名字 77 | /// 78 | public bool NeedShowName => IsReceive && IsRoom; 79 | 80 | public string Uri { get; set; } 81 | 82 | private ImageSource _image; 83 | public ImageSource Image 84 | { 85 | get { return _image; } 86 | set 87 | { 88 | _image = value; 89 | OnPropertyChanged(); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /WeChatClient.Core/Models/WxStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WeChatClient.Core.Http; 7 | 8 | namespace WeChatClient.Core.Models 9 | { 10 | public static class WxStatus 11 | { 12 | /// 13 | /// 联系人消息免打扰 14 | /// 15 | private const int CONTACTFLAG_NOTIFYCLOSECONTACT = 512; 16 | /// 17 | /// 群聊消息免打扰 18 | /// 19 | private const int CHATROOM_NOTIFY_CLOSE = 0; 20 | 21 | public static bool IsRoomContact(this WeChatUser user) 22 | { 23 | return user.UserName.StartsWith("@@"); 24 | } 25 | 26 | /// 27 | /// 是否消息免打扰 28 | /// 29 | /// 30 | /// 31 | public static bool IsChatNotifyClose(this WeChatUser user) 32 | { 33 | return user.UserName.StartsWith("@@") 34 | ? user.Statues == CHATROOM_NOTIFY_CLOSE 35 | : (user.ContactFlag & CONTACTFLAG_NOTIFYCLOSECONTACT) > 0; 36 | } 37 | 38 | /// 39 | /// 获取分组的头 40 | /// 41 | /// 42 | /// 43 | public static string GetStartChar(this WeChatUser user) 44 | { 45 | string start_char; 46 | 47 | if (user.KeyWord == "gh_" && user.SnsFlag.Equals("0") || user.KeyWord == "cmb")//user.KeyWord =="cmb"是招商银行信用卡,实在找不出区别了 48 | { 49 | start_char = "公众号"; 50 | } 51 | else if (user.UserName.StartsWith("@@") && user.SnsFlag.Equals("0")) 52 | { 53 | start_char = "群聊"; 54 | } 55 | else if (!user.UserName.StartsWith("@")) 56 | { 57 | start_char = "微信官方号"; 58 | } 59 | else 60 | { 61 | start_char = string.IsNullOrEmpty(user.ShowPinYin) ? string.Empty : user.ShowPinYin[0].ToString().ToUpper(); 62 | } 63 | return start_char; 64 | } 65 | 66 | /// 67 | /// 根据用户名获取图片地址 68 | /// 69 | /// 70 | /// 71 | public static string GetIconUrl(this string userName) 72 | { 73 | if (string.IsNullOrEmpty(userName)) 74 | { 75 | return null; 76 | } 77 | string _iconUrl; 78 | //讨论组 79 | if (userName.Contains("@@")) 80 | { 81 | _iconUrl = StaticUrl.stringWx + StaticUrl.Url_GetHeadImg + userName; 82 | } 83 | //好友 84 | else if (userName.Contains("@")) 85 | { 86 | _iconUrl = StaticUrl.stringWx + StaticUrl.Url_GetIcon + userName; 87 | } 88 | else 89 | { 90 | _iconUrl = StaticUrl.stringWx + StaticUrl.Url_GetIcon + userName; 91 | } 92 | return _iconUrl; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /WeChatClient.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.Core")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("ad3bf41c-c10b-4ccd-8907-59b7bba4d492")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.Core/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WeChatClient.Core.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WeChatClient.Core.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /WeChatClient.Core/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /WeChatClient.Core/Resources/2KriyDK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.Core/Resources/2KriyDK.png -------------------------------------------------------------------------------- /WeChatClient.Core/Resources/NTI4MWU5.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.Core/Resources/NTI4MWU5.ico -------------------------------------------------------------------------------- /WeChatClient.Core/Resources/wx_res.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.Core/Resources/wx_res.png -------------------------------------------------------------------------------- /WeChatClient.Core/Theme/Generic.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 24 | 35 | 51 | 52 | 53 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /WeChatClient.Core/WeChatClientConst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Media.Imaging; 7 | 8 | namespace WeChatClient 9 | { 10 | public class WeChatClientConst 11 | { 12 | #region Modules 13 | /// 14 | /// 登录模块 15 | /// 16 | //public const string LoginModuleName = "LoginModule"; 17 | /// 18 | /// 主模块 19 | /// 20 | public const string MainModuleName = "MainModule"; 21 | /// 22 | /// 聊天列表模块 23 | /// 24 | public const string ChatListModuleName = "ChatListModule"; 25 | /// 26 | /// 联系人列表模块 27 | /// 28 | public const string ContactListModuleName = "ContactListModule"; 29 | /// 30 | /// 聊天内容模块 31 | /// 32 | public const string ChatContentModuleName = "ChatContentModule"; 33 | /// 34 | /// 联系人内容模块 35 | /// 36 | public const string ContactContentModuleName = "ContactContentModule"; 37 | /// 38 | /// 搜索模块 39 | /// 40 | public const string SearchModuleName = "SearchModule"; 41 | /// 42 | /// 表情模块 43 | /// 44 | public const string FaceModuleName = "FaceModule"; 45 | #endregion 46 | 47 | #region Regions 48 | /// 49 | /// 主程序区域 50 | /// 51 | public static readonly string MainRegionName = "MainRegion"; 52 | /// 53 | /// 导航区域 54 | /// 55 | public const string NavRegionName = "NavRegion"; 56 | /// 57 | /// 内容区域 58 | /// 59 | public const string ContentRegionName = "ContentRegion"; 60 | /// 61 | /// 搜索区域 62 | /// 63 | public const string SearchRegionName = "SearchRegion"; 64 | /// 65 | /// 表情区域 66 | /// 67 | public const string FaceRegionName = "FaceRegion"; 68 | #endregion 69 | 70 | /// 71 | /// 默认头像 72 | /// 73 | public readonly static BitmapImage DefaultHeadImage; 74 | 75 | static WeChatClientConst() 76 | { 77 | DefaultHeadImage = new BitmapImage(new Uri("pack://application:,,,/WeChatClient.Core;component/Resources/2KriyDK.png", UriKind.Absolute)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /WeChatClient.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Converters/FaceImgConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace WeChatClient.EmojiCore.Converters 12 | { 13 | public class FaceImgConverter : IValueConverter 14 | { 15 | private static readonly BitmapFrame emoji_face_res = BitmapFrame.Create(new Uri("pack://application:,,,/WeChatClient.EmojiCore;component/Resources/6AfH8-r.png", UriKind.Absolute)); 16 | private static readonly BitmapFrame qq_face_res = BitmapFrame.Create(new Uri("pack://application:,,,/WeChatClient.EmojiCore;component/Resources/15BPafa.png", UriKind.Absolute)); 17 | 18 | private static readonly BitmapFrame emoji_res = BitmapFrame.Create(new Uri("pack://application:,,,/WeChatClient.EmojiCore;component/Resources/1BJVkIX.png", UriKind.Absolute)); 19 | private static readonly BitmapFrame qq_emoji_res = BitmapFrame.Create(new Uri("pack://application:,,,/WeChatClient.EmojiCore;component/Resources/3gXSfR9.png", UriKind.Absolute)); 20 | 21 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 22 | { 23 | EmojiModel model = (EmojiModel)value; 24 | int size = model.Size == EmojiSize.Medium ? 28 : 20; 25 | BitmapFrame res = null; 26 | if (model.Size == EmojiSize.Medium) 27 | { 28 | if (model.Type == EmojiType.Emoji) 29 | { 30 | res = emoji_face_res; 31 | } 32 | else 33 | { 34 | res = qq_face_res; 35 | } 36 | } 37 | else 38 | { 39 | if (model.Type == EmojiType.Emoji) 40 | { 41 | res = emoji_res; 42 | } 43 | else 44 | { 45 | res = qq_emoji_res; 46 | } 47 | } 48 | 49 | if (res == null) 50 | return null; 51 | 52 | return new CroppedBitmap(res, new Int32Rect((int)model.Position.X , (int)model.Position.Y, size, size)); 53 | } 54 | 55 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 56 | { 57 | throw new NotImplementedException(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Converters/StringToTextBlockConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | using WeChatClient.EmojiCore.Emoji; 10 | 11 | namespace WeChatClient.EmojiCore.Converters 12 | { 13 | public class StringToTextBlockConverter : IValueConverter 14 | { 15 | public TextTrimming TextTrimming { get; set; } 16 | private static readonly EmojiManager _emojiManager = new EmojiManager(); 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | return _emojiManager.StringToTextBlock(value?.ToString(), TextTrimming); 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Emoji/emoji_code_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "1f64f": "", 3 | "1f604": "", 4 | "1f60a": "", 5 | "1f603": "", 6 | "263a": "", 7 | "1f609": "", 8 | "1f60d": "", 9 | "1f618": "", 10 | "1f61a": "", 11 | "1f633": "", 12 | "1f63c": "", 13 | "1f60c": "", 14 | "1f61c": "", 15 | "1f445": "", 16 | "1f612": "", 17 | "1f60f": "", 18 | "1f613": "", 19 | "1f640": "", 20 | "1f61e": "", 21 | "1f616": "", 22 | "1f625": "", 23 | "1f630": "", 24 | "1f628": "", 25 | "1f62b": "", 26 | "1f622": "", 27 | "1f62d": "", 28 | "1f602": "", 29 | "1f632": "", 30 | "1f631": "", 31 | "1f620": "", 32 | "1f63e": "", 33 | "1f62a": "", 34 | "1f637": "", 35 | "1f47f": "", 36 | "1f47d": "", 37 | "2764": "", 38 | "1f494": "", 39 | "1f498": "", 40 | "2728": "", 41 | "1f31f": "", 42 | "2755": "", 43 | "2754": "", 44 | "1f4a4": "", 45 | "1f4a6": "", 46 | "1f3b5": "", 47 | "1f525": "", 48 | "1f4a9": "", 49 | "1f44d": "", 50 | "1f44e": "", 51 | "1f44a": "", 52 | "270c": "", 53 | "1f446": "", 54 | "1f447": "", 55 | "1f449": "", 56 | "1f448": "", 57 | "261d": "", 58 | "1f4aa": "", 59 | "1f48f": "", 60 | "1f491": "", 61 | "1f466": "", 62 | "1f467": "", 63 | "1f469": "", 64 | "1f468": "", 65 | "1f47c": "", 66 | "1f480": "", 67 | "1f48b": "", 68 | "2600": "", 69 | "2614": "", 70 | "2601": "", 71 | "26c4": "", 72 | "1f319": "", 73 | "26a1": "", 74 | "1f30a": "", 75 | "1f431": "", 76 | "1f429": "", 77 | "1f42d": "", 78 | "1f439": "", 79 | "1f430": "", 80 | "1f43a": "", 81 | "1f438": "", 82 | "1f42f": "", 83 | "1f428": "", 84 | "1f43b": "", 85 | "1f437": "", 86 | "1f42e": "", 87 | "1f417": "", 88 | "1f435": "", 89 | "1f434": "", 90 | "1f40d": "", 91 | "1f426": "", 92 | "1f414": "", 93 | "1f427": "", 94 | "1f41b": "", 95 | "1f419": "", 96 | "1f420": "", 97 | "1f433": "", 98 | "1f42c": "", 99 | "1f339": "", 100 | "1f33a": "", 101 | "1f334": "", 102 | "1f335": "", 103 | "1f49d": "", 104 | "1f383": "", 105 | "1f47b": "", 106 | "1f385": "", 107 | "1f384": "", 108 | "1f381": "", 109 | "1f514": "", 110 | "1f389": "", 111 | "1f388": "", 112 | "1f4bf": "", 113 | "1f4f7": "", 114 | "1f3a5": "", 115 | "1f4bb": "", 116 | "1f4fa": "", 117 | "1f4de": "", 118 | "1f513": "", 119 | "1f512": "", 120 | "1f511": "", 121 | "1f528": "", 122 | "1f4a1": "", 123 | "1f4eb": "", 124 | "1f6c0": "", 125 | "1f4b2": "", 126 | "1f4a3": "", 127 | "1f52b": "", 128 | "1f48a": "", 129 | "1f3c8": "", 130 | "1f3c0": "", 131 | "26bd": "", 132 | "26be": "", 133 | "26f3": "", 134 | "1f3c6": "", 135 | "1f47e": "", 136 | "1f3a4": "", 137 | "1f3b8": "", 138 | "1f459": "", 139 | "1f451": "", 140 | "1f302": "", 141 | "1f45c": "", 142 | "1f484": "", 143 | "1f48d": "", 144 | "1f48e": "", 145 | "2615": "", 146 | "1f37a": "", 147 | "1f37b": "", 148 | "1f377": "", 149 | "1f354": "", 150 | "1f35f": "", 151 | "1f35d": "", 152 | "1f363": "", 153 | "1f35c": "", 154 | "1f373": "", 155 | "1f366": "", 156 | "1f382": "", 157 | "1f34f": "", 158 | "2708": "", 159 | "1f680": "", 160 | "1f6b2": "", 161 | "1f684": "", 162 | "26a0": "", 163 | "1f3c1": "", 164 | "1f6b9": "", 165 | "1f6ba": "", 166 | "2b55": "", 167 | "274e": "", 168 | "a9": "", 169 | "ae": "", 170 | "2122": "" 171 | } -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/EmojiModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace WeChatClient.EmojiCore 9 | { 10 | /// 11 | /// 表情数据模型 12 | /// 13 | public class EmojiModel 14 | { 15 | /// 16 | /// 编码值 17 | /// 18 | public string Code { get; set; } 19 | /// 20 | /// 图片位置 21 | /// 22 | public Point Position { get; set; } 23 | /// 24 | /// 类型 25 | /// 26 | public EmojiType Type { get; set; } 27 | /// 28 | /// 大小 29 | /// 30 | public EmojiSize Size { get; set; } 31 | 32 | public override string ToString() 33 | { 34 | if (Type == EmojiType.Emoji) 35 | return $""; 36 | else 37 | return $"[{Code}]"; 38 | } 39 | } 40 | 41 | /// 42 | /// 表情类型 43 | /// 44 | public enum EmojiType 45 | { 46 | /// 47 | /// Emoji表情 48 | /// 49 | Emoji, 50 | /// 51 | /// QQ表情 52 | /// 53 | QQ 54 | } 55 | 56 | /// 57 | /// 表情大小 58 | /// 59 | public enum EmojiSize 60 | { 61 | /// 62 | /// 小的是富文本中的表情 63 | /// 64 | Small, 65 | /// 66 | /// 中的是表情对话框中的表情 67 | /// 68 | Medium 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Events/InputEmojiEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WeChatClient.EmojiCore.Events 9 | { 10 | public class InputEmojiEvent : PubSubEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Face/FaceManager.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using WeChatClient.Core.Dependency; 9 | 10 | namespace WeChatClient.EmojiCore.Face 11 | { 12 | [ExposeServices(ServiceLifetime.Singleton)] 13 | public class FaceManager 14 | { 15 | public List EmojiFaceList { get; } 16 | public List QQFaceList { get; } 17 | public FaceManager() 18 | { 19 | string emojiFaceJson = File.ReadAllText("Face/emoji_face.json"); 20 | EmojiFaceList = JsonConvert.DeserializeObject>(emojiFaceJson); 21 | EmojiFaceList.ForEach(p => 22 | { 23 | p.Type = EmojiType.Emoji; 24 | p.Size = EmojiSize.Medium; 25 | }); 26 | 27 | string qqFaceJson = File.ReadAllText("Face/qq_face.json"); 28 | QQFaceList = JsonConvert.DeserializeObject>(qqFaceJson); 29 | QQFaceList.ForEach(p => 30 | { 31 | p.Type = EmojiType.QQ; 32 | p.Size = EmojiSize.Medium; 33 | }); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Face/qq_face.json: -------------------------------------------------------------------------------- 1 | [{"Code":"微笑","Position":"0,0"},{"Code":"撇嘴","Position":"29,0"},{"Code":"色","Position":"58,0"},{"Code":"发呆","Position":"87,0"},{"Code":"得意","Position":"116,0"},{"Code":"流泪","Position":"145,0"},{"Code":"害羞","Position":"174,0"},{"Code":"闭嘴","Position":"203,0"},{"Code":"睡","Position":"232,0"},{"Code":"大哭","Position":"261,0"},{"Code":"尴尬","Position":"290,0"},{"Code":"发怒","Position":"319,0"},{"Code":"调皮","Position":"348,0"},{"Code":"呲牙","Position":"377,0"},{"Code":"惊讶","Position":"406,0"},{"Code":"难过","Position":"0,29"},{"Code":"酷","Position":"29,29"},{"Code":"冷汗","Position":"58,29"},{"Code":"抓狂","Position":"87,29"},{"Code":"吐","Position":"116,29"},{"Code":"偷笑","Position":"145,29"},{"Code":"愉快","Position":"174,29"},{"Code":"白眼","Position":"203,29"},{"Code":"傲慢","Position":"232,29"},{"Code":"饥饿","Position":"261,29"},{"Code":"困","Position":"290,29"},{"Code":"惊恐","Position":"319,29"},{"Code":"流汗","Position":"348,29"},{"Code":"憨笑","Position":"377,29"},{"Code":"悠闲","Position":"406,29"},{"Code":"奋斗","Position":"0,58"},{"Code":"咒骂","Position":"29,58"},{"Code":"疑问","Position":"58,58"},{"Code":"嘘","Position":"87,58"},{"Code":"晕","Position":"116,58"},{"Code":"疯了","Position":"145,58"},{"Code":"衰","Position":"174,58"},{"Code":"骷髅","Position":"203,58"},{"Code":"敲打","Position":"232,58"},{"Code":"再见","Position":"261,58"},{"Code":"擦汗","Position":"290,58"},{"Code":"抠鼻","Position":"319,58"},{"Code":"鼓掌","Position":"348,58"},{"Code":"糗大了","Position":"377,58"},{"Code":"坏笑","Position":"406,58"},{"Code":"左哼哼","Position":"0,87"},{"Code":"右哼哼","Position":"29,87"},{"Code":"哈欠","Position":"58,87"},{"Code":"鄙视","Position":"87,87"},{"Code":"委屈","Position":"116,87"},{"Code":"快哭了","Position":"145,87"},{"Code":"阴险","Position":"174,87"},{"Code":"亲亲","Position":"203,87"},{"Code":"吓","Position":"232,87"},{"Code":"可怜","Position":"261,87"},{"Code":"菜刀","Position":"290,87"},{"Code":"西瓜","Position":"319,87"},{"Code":"啤酒","Position":"348,87"},{"Code":"篮球","Position":"377,87"},{"Code":"乒乓","Position":"406,87"},{"Code":"咖啡","Position":"0,116"},{"Code":"饭","Position":"29,116"},{"Code":"猪头","Position":"58,116"},{"Code":"玫瑰","Position":"87,116"},{"Code":"凋谢","Position":"116,116"},{"Code":"嘴唇","Position":"145,116"},{"Code":"爱心","Position":"174,116"},{"Code":"心碎","Position":"203,116"},{"Code":"蛋糕","Position":"232,116"},{"Code":"闪电","Position":"261,116"},{"Code":"炸弹","Position":"290,116"},{"Code":"刀","Position":"319,116"},{"Code":"足球","Position":"348,116"},{"Code":"瓢虫","Position":"377,116"},{"Code":"便便","Position":"406,116"},{"Code":"月亮","Position":"0,145"},{"Code":"太阳","Position":"29,145"},{"Code":"礼物","Position":"58,145"},{"Code":"拥抱","Position":"87,145"},{"Code":"强","Position":"116,145"},{"Code":"弱","Position":"145,145"},{"Code":"握手","Position":"174,145"},{"Code":"胜利","Position":"203,145"},{"Code":"抱拳","Position":"232,145"},{"Code":"勾引","Position":"261,145"},{"Code":"拳头","Position":"290,145"},{"Code":"差劲","Position":"319,145"},{"Code":"爱你","Position":"348,145"},{"Code":"NO","Position":"377,145"},{"Code":"OK","Position":"406,145"},{"Code":"爱情","Position":"0,174"},{"Code":"飞吻","Position":"29,174"},{"Code":"跳跳","Position":"58,174"},{"Code":"发抖","Position":"87,174"},{"Code":"怄火","Position":"116,174"},{"Code":"转圈","Position":"145,174"},{"Code":"磕头","Position":"174,174"},{"Code":"回头","Position":"203,174"},{"Code":"跳绳","Position":"232,174"},{"Code":"投降","Position":"261,174"},{"Code":"激动","Position":"290,174"},{"Code":"乱舞","Position":"319,174"},{"Code":"献吻","Position":"348,174"},{"Code":"左太极","Position":"377,174"},{"Code":"右太极","Position":"406,174"}] -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.EmojiCore")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.EmojiCore")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("7d2e1e77-cb84-4501-a161-5aaac97701f5")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Resources/15BPafa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.EmojiCore/Resources/15BPafa.png -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Resources/1BJVkIX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.EmojiCore/Resources/1BJVkIX.png -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Resources/3gXSfR9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.EmojiCore/Resources/3gXSfR9.png -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Resources/6AfH8-r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/WeChatClient.EmojiCore/Resources/6AfH8-r.png -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/Theme/Generic.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/WeChatClient.EmojiCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7D2E1E77-CB84-4501-A161-5AAAC97701F5} 8 | Library 9 | Properties 10 | WeChatClient.EmojiCore 11 | WeChatClient.EmojiCore 12 | v4.6.1 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll 36 | 37 | 38 | 39 | 40 | ..\packages\Prism.Core.7.1.0.431\lib\net45\Prism.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | PreserveNewest 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {ad3bf41c-c10b-4ccd-8907-59b7bba4d492} 75 | WeChatClient.Core 76 | 77 | 78 | 79 | 80 | PreserveNewest 81 | 82 | 83 | PreserveNewest 84 | 85 | 86 | PreserveNewest 87 | 88 | 89 | PreserveNewest 90 | 91 | 92 | PreserveNewest 93 | 94 | 95 | PreserveNewest 96 | 97 | 98 | 99 | 100 | 101 | MSBuild:Compile 102 | Designer 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /WeChatClient.EmojiCore/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WeChatClient.Face/FaceModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.Core.Dependency; 11 | using WeChatClient.Face.Views; 12 | 13 | namespace WeChatClient.Face 14 | { 15 | [Module(OnDemand = true)] 16 | public class FaceModule : IModule 17 | { 18 | public void OnInitialized(IContainerProvider containerProvider) 19 | { 20 | var regionManager = containerProvider.Resolve(); 21 | regionManager.RegisterViewWithRegion(WeChatClientConst.FaceRegionName, typeof(FaceView)); 22 | } 23 | 24 | public void RegisterTypes(IContainerRegistry containerRegistry) 25 | { 26 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WeChatClient.Face/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.Face/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.Face/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.Face")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.Face")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("407fc3c9-77bf-4252-afc1-d96c676d1be2")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.Face/ViewModels/FaceViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Input; 10 | using Unity.Attributes; 11 | using WeChatClient.EmojiCore; 12 | using WeChatClient.EmojiCore.Emoji; 13 | using WeChatClient.EmojiCore.Events; 14 | using WeChatClient.EmojiCore.Face; 15 | 16 | namespace WeChatClient.Face.ViewModels 17 | { 18 | public class FaceViewModel : ReactiveObject 19 | { 20 | [Reactive] 21 | public List EmojiFaceList { get; private set; } 22 | [Reactive] 23 | public List QQFaceList { get; private set; } 24 | public ICommand ClickFaceCommand { get; } 25 | 26 | public FaceViewModel(FaceManager faceManager, EmojiManager emojiManager, IEventAggregator ea) 27 | { 28 | EmojiFaceList = faceManager.EmojiFaceList; 29 | QQFaceList = faceManager.QQFaceList; 30 | 31 | ClickFaceCommand = ReactiveCommand.Create(face => 32 | { 33 | EmojiModel emoji = emojiManager.FaceToEmoji(face); 34 | if (emoji != null) 35 | ea.GetEvent().Publish(emoji); 36 | }); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /WeChatClient.Face/Views/FaceView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.Face.ViewModels; 16 | 17 | namespace WeChatClient.Face.Views 18 | { 19 | /// 20 | /// FaceView.xaml 的交互逻辑 21 | /// 22 | public partial class FaceView : UserControl 23 | { 24 | public FaceView(FaceViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.Face/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.Face/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WeChatClient.Login/Events/ShowErrorMsgEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Media; 8 | 9 | namespace WeChatClient.Login.Events 10 | { 11 | public class ShowErrorMsgEvent : PubSubEvent 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WeChatClient.Login/Events/SwitchAccountEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WeChatClient.Login.Events 9 | { 10 | public class SwitchAccountEvent: PubSubEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WeChatClient.Login/Events/UpdateHeadImageEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Media; 8 | 9 | namespace WeChatClient.Login.Events 10 | { 11 | public class UpdateHeadImageEvent : PubSubEvent 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WeChatClient.Login/Events/UpdateQRCodeEvent.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WeChatClient.Login.Events 9 | { 10 | public class UpdateQRCodeEvent : PubSubEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WeChatClient.Login/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.Login/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.Login/LoginModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using Prism.Ioc; 3 | using Prism.Modularity; 4 | using Prism.Regions; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Media; 13 | using WeChatClient.Core.Events; 14 | using WeChatClient.Core.Http; 15 | using WeChatClient.Login.Events; 16 | using WeChatClient.Login.Views; 17 | 18 | namespace WeChatClient.Login 19 | { 20 | //[Module(OnDemand = true)] //暂时禁用登录 21 | public class LoginModule : IModule 22 | { 23 | public void OnInitialized(IContainerProvider containerProvider) 24 | { 25 | var regionManager = containerProvider.Resolve(); 26 | var ea = containerProvider.Resolve(); 27 | 28 | IRegion region = regionManager.Regions[WeChatClientConst.MainRegionName]; 29 | 30 | var qrView = containerProvider.Resolve(); 31 | region.Add(qrView); 32 | 33 | var headView = containerProvider.Resolve(); 34 | region.Add(headView); 35 | 36 | var errorView = containerProvider.Resolve(); 37 | region.Add(errorView); 38 | 39 | Task.Run(() => 40 | { 41 | LoopLoginCheck(ea, region, qrView, headView, errorView); 42 | }); 43 | 44 | ea.GetEvent().Subscribe(() => 45 | { 46 | region.Activate(qrView); 47 | }); 48 | } 49 | 50 | public void RegisterTypes(IContainerRegistry containerRegistry) 51 | { 52 | 53 | } 54 | 55 | /// 56 | /// 循环检测是否登录了 57 | /// 58 | private void LoopLoginCheck(IEventAggregator ea, IRegion region, QRCodeView qrView, HeadView headView, ErrorView errorView) 59 | { 60 | LoginService ls = new LoginService(); 61 | 62 | object login_result = null; 63 | //循环判断手机扫描二维码结果 64 | while (true) 65 | { 66 | login_result = ls.LoginCheck(); 67 | //已扫描 未登录 68 | if (login_result is ImageSource) 69 | { 70 | ea.GetEvent().Publish(login_result as ImageSource); 71 | Application.Current.Dispatcher.BeginInvoke(new Action(() => 72 | { 73 | region.Activate(headView); 74 | })); 75 | } 76 | //已完成登录 77 | if (login_result is string) 78 | { 79 | //访问登录跳转URL 80 | if (ls.GetSidUid(login_result as string, out string errorMsg)) 81 | { 82 | Application.Current.Dispatcher.BeginInvoke(new Action(() => 83 | { 84 | region.RemoveAll(); 85 | ea.GetEvent().Publish(); 86 | })); 87 | break; 88 | } 89 | else 90 | { 91 | ea.GetEvent().Publish(errorMsg); 92 | Application.Current.Dispatcher.BeginInvoke(new Action(() => 93 | { 94 | region.Activate(errorView); 95 | })); 96 | break; 97 | } 98 | } 99 | ////超时 100 | if (login_result is int) 101 | { 102 | ea.GetEvent().Publish(); 103 | } 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /WeChatClient.Login/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.Login")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.Login")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("24421d7b-0986-46d8-a005-a03a400de2ac")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.Login/ViewModels/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using WeChatClient.Login.Events; 12 | 13 | namespace WeChatClient.Login.ViewModels 14 | { 15 | public class ErrorViewModel : ReactiveObject 16 | { 17 | [Reactive] 18 | public string ErrorMsg { get; set; } 19 | 20 | public ErrorViewModel(IEventAggregator ea) 21 | { 22 | ea.GetEvent().Subscribe(i => ErrorMsg = i, ThreadOption.UIThread); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WeChatClient.Login/ViewModels/HeadViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using WeChatClient.Login.Events; 12 | 13 | namespace WeChatClient.Login.ViewModels 14 | { 15 | public class HeadViewModel : ReactiveObject 16 | { 17 | [Reactive] 18 | public ImageSource HeadImage { get; set; } 19 | 20 | public ICommand SwitchAccountCommand { get; } 21 | 22 | public HeadViewModel(IEventAggregator ea) 23 | { 24 | SwitchAccountCommand = ReactiveCommand.Create(() => 25 | { 26 | ea.GetEvent().Publish(); 27 | }); 28 | 29 | ea.GetEvent().Subscribe(i => HeadImage = i, ThreadOption.UIThread); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WeChatClient.Login/ViewModels/QRCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism; 2 | using Prism.Events; 3 | using ReactiveUI; 4 | using ReactiveUI.Fody.Helpers; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Reactive; 9 | using System.Reactive.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows.Media; 13 | using System.Windows.Threading; 14 | using WeChatClient.Core.Http; 15 | using WeChatClient.Login.Events; 16 | 17 | namespace WeChatClient.Login.ViewModels 18 | { 19 | public class QRCodeViewModel : ReactiveObject 20 | { 21 | private LoginService ls = new LoginService(); 22 | 23 | [Reactive] 24 | public ImageSource QRCode { get; private set; } 25 | 26 | public QRCodeViewModel(IEventAggregator ea) 27 | { 28 | SetQRCode(); 29 | 30 | ea.GetEvent().Subscribe(SetQRCode, ThreadOption.UIThread); 31 | } 32 | 33 | private void SetQRCode() 34 | { 35 | QRCode = ls.GetQRCode(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/ErrorView.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/ErrorView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.Login.ViewModels; 16 | 17 | namespace WeChatClient.Login.Views 18 | { 19 | /// 20 | /// ErrorView.xaml 的交互逻辑 21 | /// 22 | public partial class ErrorView : UserControl 23 | { 24 | public ErrorView(ErrorViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/HeadView.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/HeadView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using WeChatClient.Login.ViewModels; 9 | 10 | namespace WeChatClient.Login.Views 11 | { 12 | /// 13 | /// HeadView.xaml 的交互逻辑 14 | /// 15 | public partial class HeadView : UserControl 16 | { 17 | public HeadView(HeadViewModel viewModel) 18 | { 19 | InitializeComponent(); 20 | 21 | DataContext = viewModel; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/QRCodeView.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 使用手机微信扫码登录 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WeChatClient.Login/Views/QRCodeView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.Login.ViewModels; 16 | 17 | namespace WeChatClient.Login.Views 18 | { 19 | /// 20 | /// QRCodeView.xaml 的交互逻辑 21 | /// 22 | public partial class QRCodeView : UserControl 23 | { 24 | public QRCodeView(QRCodeViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | 28 | DataContext = viewModel; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WeChatClient.Login/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.Login/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WeChatClient.Main/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.Main/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.Main/MainModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.Core; 11 | using WeChatClient.Core.Dependency; 12 | using WeChatClient.Main.Views; 13 | 14 | namespace WeChatClient.Main 15 | { 16 | [Module(OnDemand = true)] //按需加载模块 17 | [ModuleDependency(WeChatClientConst.SearchModuleName)] //设置模块依赖 18 | public class MainModule : IModule 19 | { 20 | public void OnInitialized(IContainerProvider containerProvider) 21 | { 22 | var regionManager = containerProvider.Resolve(); 23 | regionManager.RegisterViewWithRegion(WeChatClientConst.MainRegionName, typeof(MainView)); 24 | } 25 | 26 | public void RegisterTypes(IContainerRegistry containerRegistry) 27 | { 28 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WeChatClient.Main/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.Main")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.Main")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("5a619c05-c380-4a58-a642-d71f30b495fc")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.Main/Views/MainView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.Main.ViewModels; 16 | 17 | namespace WeChatClient.Main.Views 18 | { 19 | /// 20 | /// MainView.xaml 的交互逻辑 21 | /// 22 | public partial class MainView : UserControl 23 | { 24 | public MainView(MainViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.Main/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.Main/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WeChatClient.Search/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.Search/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.Search/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WeChatClient.Search")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WeChatClient.Search")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("f20f8cfd-a86e-45f5-92a4-13e6346a272a")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WeChatClient.Search/SearchModule.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Regions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using WeChatClient.Core.Dependency; 11 | using WeChatClient.Search.Views; 12 | 13 | namespace WeChatClient.Search 14 | { 15 | [Module(OnDemand = true)] 16 | [ModuleDependency(WeChatClientConst.ChatListModuleName)] 17 | public class SearchModule : IModule 18 | { 19 | public void OnInitialized(IContainerProvider containerProvider) 20 | { 21 | var regionManager = containerProvider.Resolve(); 22 | regionManager.RegisterViewWithRegion(WeChatClientConst.SearchRegionName, typeof(SearchView)); 23 | } 24 | 25 | public void RegisterTypes(IContainerRegistry containerRegistry) 26 | { 27 | containerRegistry.RegisterAssembly(Assembly.GetExecutingAssembly()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.Search/ViewModels/SearchViewModel.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using ReactiveUI; 3 | using ReactiveUI.Fody.Helpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.ComponentModel; 8 | using System.Linq; 9 | using System.Reactive.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows.Data; 13 | using System.Windows.Input; 14 | using Unity.Attributes; 15 | using WeChatClient.Core.Events; 16 | using WeChatClient.Core.Interfaces; 17 | using WeChatClient.Core.Models; 18 | 19 | namespace WeChatClient.Search.ViewModels 20 | { 21 | public class SearchViewModel : ReactiveObject 22 | { 23 | [Dependency] 24 | protected IContactListManager ContactListManager { get; set; } 25 | [Dependency] 26 | protected IChatListManager ChatListManager { get; set; } 27 | 28 | [Reactive] 29 | public string SearchText { get; set; } 30 | [Reactive] 31 | public bool IsOpen { get; set; } 32 | 33 | public ObservableCollection ContactList { get; private set; } = new ObservableCollection(); 34 | 35 | public ICommand SelectCommand { get; } 36 | 37 | public SearchViewModel(IEventAggregator ea) 38 | { 39 | ICollectionView cv = CollectionViewSource.GetDefaultView(ContactList); 40 | cv.GroupDescriptions.Add(new PropertyGroupDescription(nameof(WeChatUser.SearchGroupDesc))); 41 | 42 | SelectCommand = ReactiveCommand.Create(c => 43 | { 44 | ea.GetEvent().Publish(c); 45 | IsOpen = false; 46 | SearchText = null; 47 | }); 48 | 49 | this.WhenAnyValue(p => p.SearchText).Select(p => !string.IsNullOrWhiteSpace(p)).Subscribe(p => IsOpen = p); 50 | this.WhenAnyValue(p => p.SearchText).Throttle(TimeSpan.FromMilliseconds(100)) //延迟100毫秒再异步查询 51 | .Where(p => !string.IsNullOrWhiteSpace(p)).Select(p => p?.Trim()) 52 | .DistinctUntilChanged().Select(Search).ObserveOn(RxApp.MainThreadScheduler).Subscribe(UpdateData); 53 | } 54 | 55 | /// 56 | /// 查询好友和群聊 57 | /// 58 | /// 59 | /// 60 | private List Search(string searchText) 61 | { 62 | List list = new List(); 63 | list.AddRange(ContactListManager.SearchContact(searchText)); 64 | list.AddRange(ChatListManager.SearchRoomChat(searchText)); 65 | return list; 66 | } 67 | 68 | private void UpdateData(List list) 69 | { 70 | ContactList.Clear(); 71 | ContactList.AddRange(list); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /WeChatClient.Search/Views/SearchView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using WeChatClient.Search.ViewModels; 16 | 17 | namespace WeChatClient.Search.Views 18 | { 19 | /// 20 | /// SearchView.xaml 的交互逻辑 21 | /// 22 | public partial class SearchView : UserControl 23 | { 24 | public SearchView(SearchViewModel viewModel) 25 | { 26 | InitializeComponent(); 27 | DataContext = viewModel; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.Search/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WeChatClient.Search/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WeChatClient.UI/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WeChatClient.UI/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WeChatClient.UI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Prism.Ioc; 2 | using Prism.Modularity; 3 | using Prism.Unity; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Configuration; 7 | using System.Data; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using WeChatClient.Core.Dependency; 12 | using WeChatClient.EmojiCore; 13 | using WeChatClient.UI.Views; 14 | 15 | namespace WeChatClient.UI 16 | { 17 | /// 18 | /// App.xaml 的交互逻辑 19 | /// 20 | public partial class App : PrismApplication 21 | { 22 | protected override Window CreateShell() 23 | { 24 | return Container.Resolve(); 25 | } 26 | 27 | protected override void RegisterTypes(IContainerRegistry containerRegistry) 28 | { 29 | containerRegistry.RegisterAssembly(typeof(WeChatClientConst).Assembly); 30 | containerRegistry.RegisterAssembly(typeof(EmojiModel).Assembly); 31 | } 32 | 33 | protected override IModuleCatalog CreateModuleCatalog() 34 | { 35 | return new DirectoryModuleCatalog() { ModulePath = "Modules" }; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /WeChatClient.UI/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WeChatClient.UI/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeChatClient.UI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("WeChatClient.UI")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("WeChatClient.UI")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请设置 25 | //.csproj 文件中的 CultureYouAreCodingWith 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(未在页面中找到资源时使用, 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(未在页面中找到资源时使用, 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 52 | // 方法是按如下所示使用“*”: : 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /WeChatClient.UI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本: 4.0.30319.42000 5 | // 6 | // 对此文件的更改可能导致不正确的行为,如果 7 | // 重新生成代码,则所做更改将丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WeChatClient.UI.Properties 12 | { 13 | 14 | 15 | /// 16 | /// 强类型资源类,用于查找本地化字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// 返回此类使用的缓存 ResourceManager 实例。 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WeChatClient.UI.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// 覆盖当前线程的 CurrentUICulture 属性 56 | /// 使用此强类型的资源类的资源查找。 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /WeChatClient.UI/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /WeChatClient.UI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WeChatClient.UI.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WeChatClient.UI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WeChatClient.UI/Views/Shell.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | -------------------------------------------------------------------------------- /WeChatClient.UI/Views/Shell.xaml.cs: -------------------------------------------------------------------------------- 1 | using Prism.Events; 2 | using Prism.Ioc; 3 | using Prism.Modularity; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | using System.Windows.Data; 12 | using System.Windows.Documents; 13 | using System.Windows.Input; 14 | using System.Windows.Media; 15 | using System.Windows.Media.Imaging; 16 | using System.Windows.Shapes; 17 | using WeChatClient.Core; 18 | using WeChatClient.Core.Events; 19 | 20 | namespace WeChatClient.UI.Views 21 | { 22 | /// 23 | /// Shell.xaml 的交互逻辑 24 | /// 25 | public partial class Shell : Window 26 | { 27 | private readonly IContainerExtension _containerProvider; 28 | private readonly IEventAggregator _ea; 29 | public Shell(IContainerExtension containerProvider) 30 | { 31 | InitializeComponent(); 32 | _containerProvider = containerProvider; 33 | _ea = containerProvider.Resolve(); 34 | } 35 | 36 | private void Window_Loaded(object sender, RoutedEventArgs e) 37 | { 38 | _ea.GetEvent().Subscribe(() => 39 | { 40 | var moduleManager = _containerProvider.Resolve(); 41 | moduleManager.LoadModule(WeChatClientConst.MainModuleName); //加载主程序模块 42 | SizeToContent = SizeToContent.Manual; 43 | ResizeMode = ResizeMode.CanResize; 44 | Width = 1000; 45 | Height = 750; 46 | }, ThreadOption.UIThread); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /WeChatClient.UI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/1.png -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/2.png -------------------------------------------------------------------------------- /images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/3.png -------------------------------------------------------------------------------- /images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/4.png -------------------------------------------------------------------------------- /images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/5.png -------------------------------------------------------------------------------- /images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/6.png -------------------------------------------------------------------------------- /images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/845669495/WeChatClient/f41e9e77ff5a523c3796e765f01a3ce0ae66fc7c/images/7.png --------------------------------------------------------------------------------