├── source
├── SkypeQuoteCreator
│ ├── Icon.ico
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Program.cs
│ ├── Analytics.cs
│ ├── Settings.cs
│ ├── SkypeQuoteCreator.csproj
│ ├── MainForm.resx
│ ├── MainForm.Designer.cs
│ └── MainForm.cs
└── OverrideAssemblyVersion.targets
├── .gitignore
├── .gitattributes
├── SkypeQuoteCreator.sln
├── license.txt
└── readme.md
/source/SkypeQuoteCreator/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MatthewKing/SkypeQuoteCreator/HEAD/source/SkypeQuoteCreator/Icon.ico
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # build folders
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # build results
6 | [Dd]ebug/
7 | [Rr]elease/
8 | publish/
9 |
10 | # user-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 |
15 | # ncrunch
16 | *.crunchsolution*
17 | *.ncrunchsolution*
18 | *.ncrunchproject*
19 |
20 | # nuget
21 | packages/
22 |
23 | # other
24 | *.[Cc]ache
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: System.Reflection.AssemblyTitle("Skype Quote Creator")]
2 | [assembly: System.Reflection.AssemblyCompany("Matthew King")]
3 | [assembly: System.Reflection.AssemblyProduct("SkypeQuoteCreator")]
4 | [assembly: System.Reflection.AssemblyCopyright("Copyright © Matthew King 2013-2016")]
5 |
6 | [assembly: System.Runtime.InteropServices.ComVisible(false)]
7 | [assembly: System.Runtime.InteropServices.Guid("3390defc-1f8d-4166-8e29-2aa1b29d1e06")]
8 |
9 | [assembly: System.Reflection.AssemblyVersion("1.0.0.0")]
10 | [assembly: System.Reflection.AssemblyFileVersion("1.0.0.0")]
11 |
--------------------------------------------------------------------------------
/SkypeQuoteCreator.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkypeQuoteCreator", "source\SkypeQuoteCreator\SkypeQuoteCreator.csproj", "{2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Windows.Forms;
4 |
5 | namespace SkypeQuoteCreator
6 | {
7 | ///
8 | /// Contains the main entry point for the application.
9 | ///
10 | internal static class Program
11 | {
12 | ///
13 | /// The main entry point for the application.
14 | ///
15 | [STAThread]
16 | public static void Main()
17 | {
18 | try
19 | {
20 | if (!Directory.Exists(Settings.DefaultDirectory))
21 | {
22 | Directory.CreateDirectory(Settings.DefaultDirectory);
23 | }
24 | }
25 | catch
26 | {
27 | // Swallow all exceptions.
28 | }
29 |
30 | Application.EnableVisualStyles();
31 | Application.SetCompatibleTextRenderingDefault(false);
32 | Application.Run(new MainForm());
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-2016 Matthew King
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/Analytics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Text;
4 | using System.Windows.Forms;
5 |
6 | namespace SkypeQuoteCreator
7 | {
8 | ///
9 | /// Simple wrapper for keen.io Analytics.
10 | ///
11 | internal static class Analytics
12 | {
13 | private const string Resource = "https://api.keen.io/3.0/projects/{project_id}/events/{event_collection}?api_key={write_key}";
14 | private const string ProjectId = "53beb382709a39164a00000d";
15 | private const string WriteKey = "64e2b8a218379d6cfe838fc6999248a2406e68b17afa964a81559d3e63f8cd6e62867ea9c162a5144d477c3ffb2f9e731236fcc128f6e05f214cde257c1bfca2d37f2b6fc81dcfdb360e60cf8a22edea520e73afd7dfa4d32bffa4fc18f61ac4b46da363fd89ab15216839d95d7f4036";
16 | private const string PayloadFormat = "{'keen':{'addons':[{'name':'keen:ip_to_geo','input':{'ip':'ip_address'},'output':'ip_geo_info'}]},'ip_address':'${keen.ip}','app_name':'{app_name}','app_version':'{app_version}','user_id':'{user_id}','view_name':'{view_name}'}";
17 |
18 | ///
19 | /// Tracks the screen view.
20 | ///
21 | /// View name.
22 | /// Client ID.
23 | public static void TrackScreenView(string viewName, string clientId)
24 | {
25 | StringBuilder address = new StringBuilder(Resource);
26 | address.Replace("{project_id}", ProjectId);
27 | address.Replace("{event_collection}", "appviews");
28 | address.Replace("{write_key}", WriteKey);
29 |
30 | StringBuilder data = new StringBuilder(PayloadFormat);
31 | data.Replace("{app_name}", Application.ProductName);
32 | data.Replace("{app_version}", Application.ProductVersion);
33 | data.Replace("{user_id}", clientId);
34 | data.Replace("{view_name}", viewName);
35 | data.Replace("'", "\"");
36 |
37 | using (WebClient client = new WebClient())
38 | {
39 | client.Headers["Content-Type"] = "application/json";
40 |
41 | try
42 | {
43 | client.UploadStringAsync(
44 | address: new Uri(address.ToString()),
45 | method: "POST",
46 | data: data.ToString());
47 | }
48 | catch
49 | {
50 | // Swallow all exceptions.
51 | }
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | Skype Quote Creator
2 | ===================
3 |
4 | A simple WinForms app that allows the user to create a new quote in Skype's clipboard format.
5 |
6 | Deprecation notice
7 | ------------------
8 |
9 | Please note that this app is no longer actively maintained, and won't work with newer versions of Skype. Skype changed their quote system years ago, and this app does not support their new quote system. I'm no longer an active Skype user so I don't know the details of how the new quote system works. I'd be happy to accept a pull request from any community members who managed to work it out, though.
10 |
11 | Get the application
12 | -------------------
13 |
14 | You can download the application from the following sources:
15 |
16 | | Application | Description |
17 | |-----------------------------------------------------------------------------|--------------------------------------------|
18 | | [Recommended](https://mking.s3.amazonaws.com/SkypeQuoteCreator.application) | ClickOnce installer with automatic updates |
19 | | [Stand-alone](https://mking.s3.amazonaws.com/SkypeQuoteCreator.exe) | Stand-alone executable |
20 |
21 | Skype clipboard format
22 | ----------------------
23 |
24 | When a Skype quote is copied to the clipboard, the data object looks something like this:
25 |
26 | | Format | Description |
27 | |----------------------|-----------------------------------------------------------------|
28 | | System.String | Plain-text message |
29 | | Text | Plain-text message |
30 | | UnicodeText | Plain-text message |
31 | | OEMText | Plain-text message |
32 | | SkypeMessageFragment | MemoryStream containing UTF8 Skype message fragment (see below) |
33 | | Locale | MemoryStream containing Cultural identifier (LCID) |
34 |
35 | SkypeMessageFragment
36 | ------------------
37 |
38 | A simple XML string in the following format: `MessageText
`, where `AuthorName` is the Skype user name of the message author, `MessageText` is the message text itself, and `Timestamp` is the number of seconds since the Unix epoch. The actual fragment from Skype contains a few more attributes, but they can be ignored for the purposes of this simple app!
39 |
40 | Copyright
41 | ---------
42 | Copyright 2013-2016 Matthew King.
43 |
44 | License
45 | -------
46 | Skype Quote Creator is licensed under the [MIT License](http://opensource.org/licenses/MIT). Refer to license.txt for more information.
47 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/Settings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Xml.Linq;
6 |
7 | namespace SkypeQuoteCreator
8 | {
9 | ///
10 | /// Represents the application settings file.
11 | ///
12 | internal sealed class Settings
13 | {
14 | ///
15 | /// Gets the default directory for the settings file.
16 | ///
17 | public static string DefaultDirectory { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SkypeQuoteCreator");
18 |
19 | ///
20 | /// Gets the default settings file.
21 | ///
22 | public static Settings Default { get; } = new Settings(Path.Combine(DefaultDirectory, "settings.xml"));
23 |
24 | ///
25 | /// Gets or sets the user ID.
26 | ///
27 | public string UserId { get; set; }
28 |
29 | ///
30 | /// Gets a set containing the names that have been used.
31 | ///
32 | public ISet NameHistory { get; } = new HashSet(StringComparer.OrdinalIgnoreCase);
33 |
34 | ///
35 | /// Settings file path.
36 | ///
37 | private readonly string _path;
38 |
39 | ///
40 | /// Initializes a new instance of the Settings class.
41 | ///
42 | /// Settings file path.
43 | private Settings(string path)
44 | {
45 | _path = path;
46 | }
47 |
48 | ///
49 | /// Saves the settings to the settings file.
50 | ///
51 | public void Save()
52 | {
53 | try
54 | {
55 | string xml = new XDocument(new XElement("Settings",
56 | new XElement("UserId", UserId),
57 | new XElement("NameHistory", NameHistory.Select(name => new XElement("Name", name)).ToArray())))
58 | .ToString(SaveOptions.None);
59 |
60 | File.WriteAllText(_path, xml);
61 | }
62 | catch
63 | {
64 | // Swallow all exceptions.
65 | }
66 | }
67 |
68 | ///
69 | /// Populates the settings from the settings file.
70 | ///
71 | public void Load()
72 | {
73 | try
74 | {
75 | string xml = File.ReadAllText(_path);
76 | XDocument document = XDocument.Parse(xml);
77 |
78 | UserId = document.Root.Element("UserId")?.Value;
79 | foreach (string name in document.Root.Element("NameHistory").Elements("Name").Select(element => element.Value))
80 | {
81 | NameHistory.Add(name);
82 | }
83 | }
84 | catch
85 | {
86 | // Swallow all exceptions.
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/SkypeQuoteCreator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2596E3FD-D4B5-4E83-8DC8-8C25855FCD3E}
8 | WinExe
9 | Properties
10 | SkypeQuoteCreator
11 | SkypeQuoteCreator
12 | v4.0
13 | 512
14 | Client
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | Icon.ico
37 |
38 |
39 | true
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | Form
57 |
58 |
59 | MainForm.cs
60 |
61 |
62 |
63 |
64 |
65 | MainForm.cs
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/source/OverrideAssemblyVersion.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
9 |
10 |
11 |
12 | $(IntermediateOutputPath)\AssemblyInfo.override$(DefaultLanguageSourceExtension)
13 | Properties\AssemblyInfo$(DefaultLanguageSourceExtension)
14 | [assembly:
15 | ]
16 |
17 |
18 | My Project\AssemblyInfo$(DefaultLanguageSourceExtension)
19 | <Assembly:
20 | >
21 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | <_AssemblyInfoLines_Pass1 Include="@(AssemblyInfoLines)" Condition="'$(AssemblyVersion)'=='' or '$([System.Text.RegularExpressions.Regex]::IsMatch("%(Identity)","(?i)AssemblyVersion"))' == false" />
32 | <_AssemblyInfoLines_Pass2 Include="@(_AssemblyInfoLines_Pass1)" Condition="'$(AssemblyFileVersion)'=='' or '$([System.Text.RegularExpressions.Regex]::IsMatch("%(Identity)","(?i)AssemblyFileVersion"))' == false" />
33 | <_AssemblyInfoLines_Pass3 Include="@(_AssemblyInfoLines_Pass2)" Condition="'$(AssemblyInformationalVersion)'=='' or '$([System.Text.RegularExpressions.Regex]::IsMatch("%(Identity)","(?i)AssemblyInformationalVersion"))' == false" />
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/MainForm.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 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace SkypeQuoteCreator
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.uxNameLabel = new System.Windows.Forms.Label();
32 | this.uxMessageLabel = new System.Windows.Forms.Label();
33 | this.uxMessage = new System.Windows.Forms.TextBox();
34 | this.uxTimestamp = new System.Windows.Forms.MaskedTextBox();
35 | this.uxTimestampLabel = new System.Windows.Forms.Label();
36 | this.uxCopyToClipboard = new System.Windows.Forms.Button();
37 | this.uxUseCurrentDate = new System.Windows.Forms.Button();
38 | this.uxName = new System.Windows.Forms.ComboBox();
39 | this.uxUpdate = new System.Windows.Forms.LinkLabel();
40 | this.SuspendLayout();
41 | //
42 | // uxNameLabel
43 | //
44 | this.uxNameLabel.AutoSize = true;
45 | this.uxNameLabel.Location = new System.Drawing.Point(12, 15);
46 | this.uxNameLabel.Name = "uxNameLabel";
47 | this.uxNameLabel.Size = new System.Drawing.Size(38, 13);
48 | this.uxNameLabel.TabIndex = 5;
49 | this.uxNameLabel.Text = "Name:";
50 | //
51 | // uxMessageLabel
52 | //
53 | this.uxMessageLabel.AutoSize = true;
54 | this.uxMessageLabel.Location = new System.Drawing.Point(12, 70);
55 | this.uxMessageLabel.Name = "uxMessageLabel";
56 | this.uxMessageLabel.Size = new System.Drawing.Size(53, 13);
57 | this.uxMessageLabel.TabIndex = 7;
58 | this.uxMessageLabel.Text = "Message:";
59 | //
60 | // uxMessage
61 | //
62 | this.uxMessage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
63 | | System.Windows.Forms.AnchorStyles.Left)
64 | | System.Windows.Forms.AnchorStyles.Right)));
65 | this.uxMessage.Location = new System.Drawing.Point(79, 67);
66 | this.uxMessage.Multiline = true;
67 | this.uxMessage.Name = "uxMessage";
68 | this.uxMessage.Size = new System.Drawing.Size(293, 57);
69 | this.uxMessage.TabIndex = 3;
70 | //
71 | // uxTimestamp
72 | //
73 | this.uxTimestamp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
74 | | System.Windows.Forms.AnchorStyles.Right)));
75 | this.uxTimestamp.Location = new System.Drawing.Point(79, 40);
76 | this.uxTimestamp.Mask = "0000-00-00 00:00:00";
77 | this.uxTimestamp.Name = "uxTimestamp";
78 | this.uxTimestamp.Size = new System.Drawing.Size(196, 20);
79 | this.uxTimestamp.TabIndex = 1;
80 | //
81 | // uxTimestampLabel
82 | //
83 | this.uxTimestampLabel.AutoSize = true;
84 | this.uxTimestampLabel.Location = new System.Drawing.Point(12, 43);
85 | this.uxTimestampLabel.Name = "uxTimestampLabel";
86 | this.uxTimestampLabel.Size = new System.Drawing.Size(61, 13);
87 | this.uxTimestampLabel.TabIndex = 6;
88 | this.uxTimestampLabel.Text = "Timestamp:";
89 | //
90 | // uxCopyToClipboard
91 | //
92 | this.uxCopyToClipboard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
93 | this.uxCopyToClipboard.Location = new System.Drawing.Point(256, 127);
94 | this.uxCopyToClipboard.Name = "uxCopyToClipboard";
95 | this.uxCopyToClipboard.Size = new System.Drawing.Size(116, 23);
96 | this.uxCopyToClipboard.TabIndex = 4;
97 | this.uxCopyToClipboard.Text = "Copy to clipboard";
98 | this.uxCopyToClipboard.UseVisualStyleBackColor = true;
99 | this.uxCopyToClipboard.Click += new System.EventHandler(this.uxCopyToClipboard_Click);
100 | //
101 | // uxUseCurrentDate
102 | //
103 | this.uxUseCurrentDate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
104 | this.uxUseCurrentDate.Location = new System.Drawing.Point(281, 38);
105 | this.uxUseCurrentDate.Name = "uxUseCurrentDate";
106 | this.uxUseCurrentDate.Size = new System.Drawing.Size(91, 23);
107 | this.uxUseCurrentDate.TabIndex = 2;
108 | this.uxUseCurrentDate.Text = "Use current";
109 | this.uxUseCurrentDate.UseVisualStyleBackColor = true;
110 | this.uxUseCurrentDate.Click += new System.EventHandler(this.uxUseCurrentDate_Click);
111 | //
112 | // uxName
113 | //
114 | this.uxName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
115 | | System.Windows.Forms.AnchorStyles.Right)));
116 | this.uxName.FormattingEnabled = true;
117 | this.uxName.Location = new System.Drawing.Point(79, 11);
118 | this.uxName.Name = "uxName";
119 | this.uxName.Size = new System.Drawing.Size(293, 21);
120 | this.uxName.Sorted = true;
121 | this.uxName.TabIndex = 0;
122 | //
123 | // uxUpdate
124 | //
125 | this.uxUpdate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
126 | this.uxUpdate.AutoSize = true;
127 | this.uxUpdate.Location = new System.Drawing.Point(12, 132);
128 | this.uxUpdate.Name = "uxUpdate";
129 | this.uxUpdate.Size = new System.Drawing.Size(0, 13);
130 | this.uxUpdate.TabIndex = 8;
131 | this.uxUpdate.Visible = false;
132 | this.uxUpdate.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.uxUpdate_LinkClicked);
133 | //
134 | // MainForm
135 | //
136 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
137 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
138 | this.ClientSize = new System.Drawing.Size(384, 162);
139 | this.Controls.Add(this.uxUpdate);
140 | this.Controls.Add(this.uxName);
141 | this.Controls.Add(this.uxUseCurrentDate);
142 | this.Controls.Add(this.uxCopyToClipboard);
143 | this.Controls.Add(this.uxTimestampLabel);
144 | this.Controls.Add(this.uxTimestamp);
145 | this.Controls.Add(this.uxMessage);
146 | this.Controls.Add(this.uxMessageLabel);
147 | this.Controls.Add(this.uxNameLabel);
148 | this.MinimumSize = new System.Drawing.Size(400, 200);
149 | this.Name = "MainForm";
150 | this.Text = "Skype Quote Creator";
151 | this.Load += new System.EventHandler(this.MainForm_Load);
152 | this.ResumeLayout(false);
153 | this.PerformLayout();
154 |
155 | }
156 |
157 | #endregion
158 |
159 | private System.Windows.Forms.Label uxNameLabel;
160 | private System.Windows.Forms.Label uxMessageLabel;
161 | private System.Windows.Forms.TextBox uxMessage;
162 | private System.Windows.Forms.MaskedTextBox uxTimestamp;
163 | private System.Windows.Forms.Label uxTimestampLabel;
164 | private System.Windows.Forms.Button uxCopyToClipboard;
165 | private System.Windows.Forms.Button uxUseCurrentDate;
166 | private System.Windows.Forms.ComboBox uxName;
167 | private System.Windows.Forms.LinkLabel uxUpdate;
168 |
169 | }
170 | }
171 |
172 |
--------------------------------------------------------------------------------
/source/SkypeQuoteCreator/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Specialized;
3 | using System.ComponentModel;
4 | using System.Deployment.Application;
5 | using System.Drawing;
6 | using System.Globalization;
7 | using System.IO;
8 | using System.Text;
9 | using System.Windows.Forms;
10 | using System.Xml;
11 | using System.Xml.Linq;
12 |
13 | namespace SkypeQuoteCreator
14 | {
15 | ///
16 | /// Main form for the application.
17 | ///
18 | internal sealed partial class MainForm : Form
19 | {
20 | ///
21 | /// Unix time epoch.
22 | ///
23 | private static readonly DateTime epoch =
24 | new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
25 |
26 | ///
27 | /// Initializes a new instance of the MainForm class.
28 | ///
29 | public MainForm()
30 | {
31 | InitializeComponent();
32 | Font = SystemFonts.MessageBoxFont;
33 | Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
34 | }
35 |
36 | ///
37 | /// Handles the Load event for this form.
38 | ///
39 | /// The source of the event.
40 | /// An EventArgs that contains no event data.
41 | private void MainForm_Load(object sender, EventArgs e)
42 | {
43 | Settings.Default.Load();
44 |
45 | if (String.IsNullOrEmpty(Settings.Default.UserId))
46 | {
47 | Settings.Default.UserId = Guid.NewGuid().ToString();
48 | Settings.Default.Save();
49 | }
50 |
51 | UseCurrentDate();
52 | UseCachedNames();
53 | CheckForUpdates();
54 |
55 | Analytics.TrackScreenView("Main", Settings.Default.UserId);
56 | }
57 |
58 | ///
59 | /// Checks for any ClickOnce updates.
60 | ///
61 | private void CheckForUpdates()
62 | {
63 | if (ApplicationDeployment.IsNetworkDeployed)
64 | {
65 | ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;
66 | deployment.CheckForUpdateCompleted += CheckForUpdateCompleted;
67 | deployment.UpdateProgressChanged += UpdateProgressChanged;
68 | deployment.UpdateCompleted += UpdateCompleted;
69 |
70 | try
71 | {
72 | deployment.CheckForUpdateAsync();
73 | }
74 | catch (Exception ex)
75 | {
76 | if (ex is InvalidOperationException ||
77 | ex is InvalidDeploymentException ||
78 | ex is DeploymentDownloadException)
79 | {
80 | // Swallow.
81 | }
82 | else
83 | {
84 | throw;
85 | }
86 | }
87 | }
88 | }
89 |
90 | ///
91 | /// Handles the CheckForUpdateCompleted event.
92 | ///
93 | /// The source of the event.
94 | /// A CheckForUpdateCompletedEventArgs that contains the event data.
95 | private void CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
96 | {
97 | if (ApplicationDeployment.IsNetworkDeployed)
98 | {
99 | if (e.UpdateAvailable)
100 | {
101 | uxUpdate.Text = "Update available.";
102 | uxUpdate.Visible = true;
103 | }
104 | }
105 | }
106 |
107 | ///
108 | /// Handles the UpdateProgressChanged event.
109 | ///
110 | /// The source of the event.
111 | /// A DeploymentProgressChangedEventArgs that contains the event data.
112 | private void UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
113 | {
114 | uxUpdate.Text = String.Format(
115 | "{0:D}K out of {1:D}K downloaded - {2:D}% complete",
116 | e.BytesCompleted / 1024,
117 | e.BytesTotal / 1024,
118 | e.ProgressPercentage);
119 | }
120 |
121 | ///
122 | /// Handles the UpdateCompleted event.
123 | ///
124 | /// The source of the event.
125 | /// An AsyncCompletedEventArgs that contains the event data.
126 | private void UpdateCompleted(object sender, AsyncCompletedEventArgs e)
127 | {
128 | uxUpdate.Text = "Update will be applied next time program runs.";
129 | }
130 |
131 | ///
132 | /// Handles the Click event for uxUseCurrentDate.
133 | ///
134 | /// The source of the event.
135 | /// An EventArgs that contains no event data.
136 | private void uxUseCurrentDate_Click(object sender, EventArgs e)
137 | {
138 | UseCurrentDate();
139 | }
140 |
141 | ///
142 | /// Handles the Click event for uxCopyToClipboard.
143 | ///
144 | /// The source of the event.
145 | /// An EventArgs that contains no event data.
146 | private void uxCopyToClipboard_Click(object sender, EventArgs e)
147 | {
148 | SaveCurrentNameToCache();
149 | UseCachedNames();
150 | SaveToClipboard();
151 | }
152 |
153 | ///
154 | /// Handles the LinkClicked event for uxUpdate.
155 | ///
156 | /// The source of the event.
157 | /// A LinkLabelLinkClickedEventArgs that contains the event data.
158 | private void uxUpdate_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
159 | {
160 | uxUpdate.Enabled = false;
161 | if (ApplicationDeployment.IsNetworkDeployed)
162 | {
163 | ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;
164 | deployment.UpdateAsync();
165 | }
166 | }
167 |
168 | ///
169 | /// Saves the current name to the name cache.
170 | ///
171 | private void SaveCurrentNameToCache()
172 | {
173 | string name = uxName.Text;
174 |
175 | if (!Settings.Default.NameHistory.Contains(name))
176 | {
177 | Settings.Default.NameHistory.Add(name);
178 | Settings.Default.Save();
179 | }
180 | }
181 |
182 | ///
183 | /// Populates the items in uxName with the saved names.
184 | ///
185 | private void UseCachedNames()
186 | {
187 | uxName.Items.Clear();
188 |
189 | foreach (string name in Settings.Default.NameHistory)
190 | {
191 | uxName.Items.Add(name);
192 | }
193 | }
194 |
195 | ///
196 | /// Populates the Timestamp field with the current date.
197 | ///
198 | private void UseCurrentDate()
199 | {
200 | uxTimestamp.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
201 | }
202 |
203 | ///
204 | /// Saves the specified message to the clipboard.
205 | ///
206 | private void SaveToClipboard()
207 | {
208 | // Clear the current clipboard.
209 | Clipboard.SetText(" ");
210 |
211 | DateTime dateTime;
212 |
213 | // If the DateTime is invalid, we'll just stop right here.
214 | if (!DateTime.TryParse(uxTimestamp.Text, out dateTime))
215 | return;
216 |
217 | string user = uxName.Text;
218 | string message = uxMessage.Text;
219 | string skypeMessageFragment = new XDocument(
220 | new XElement("quote",
221 | new XAttribute("author", user),
222 | new XAttribute("authorname", user),
223 | new XAttribute("timestamp", (dateTime.ToUniversalTime() - epoch).TotalSeconds),
224 | message)).ToString();
225 |
226 | IDataObject dataObject = new DataObject();
227 | dataObject.SetData("System.String", message);
228 | dataObject.SetData("Text", message);
229 | dataObject.SetData("UnicodeText", message);
230 | dataObject.SetData("OEMText", message);
231 |
232 | dataObject.SetData("SkypeMessageFragment",
233 | new MemoryStream(Encoding.UTF8.GetBytes(skypeMessageFragment)));
234 |
235 | dataObject.SetData("Locale",
236 | new MemoryStream(BitConverter.GetBytes(CultureInfo.CurrentCulture.LCID)));
237 |
238 | Clipboard.SetDataObject(dataObject);
239 | }
240 | }
241 | }
242 |
--------------------------------------------------------------------------------