- Use ElementHost in QRCodeForm - Cleanup: Server.Equalstags/4.2.1.0
@@ -58,11 +58,7 @@ namespace Shadowsocks.Model | |||
return server.GetHashCode() ^ server_port; | |||
} | |||
public override bool Equals(object obj) | |||
{ | |||
Server o2 = (Server)obj; | |||
return server == o2.server && server_port == o2.server_port; | |||
} | |||
public override bool Equals(object obj) => obj is Server o2 && server == o2.server && server_port == o2.server_port; | |||
public override string ToString() | |||
{ | |||
@@ -28,73 +28,39 @@ | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
this.pictureBox1 = new System.Windows.Forms.PictureBox(); | |||
this.listBox1 = new System.Windows.Forms.ListBox(); | |||
this.textBoxURL = new System.Windows.Forms.TextBox(); | |||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); | |||
this.elementHost1 = new System.Windows.Forms.Integration.ElementHost(); | |||
this.serverSharingView1 = new Shadowsocks.Views.ServerSharingView(); | |||
this.SuspendLayout(); | |||
// | |||
// pictureBox1 | |||
// elementHost1 | |||
// | |||
this.pictureBox1.Location = new System.Drawing.Point(10, 10); | |||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0); | |||
this.pictureBox1.Name = "pictureBox1"; | |||
this.pictureBox1.Size = new System.Drawing.Size(210, 210); | |||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; | |||
this.pictureBox1.TabIndex = 1; | |||
this.pictureBox1.TabStop = false; | |||
// | |||
// listBox1 | |||
// | |||
this.listBox1.DisplayMember = "Value"; | |||
this.listBox1.FormattingEnabled = true; | |||
this.listBox1.ItemHeight = 12; | |||
this.listBox1.Location = new System.Drawing.Point(224, 10); | |||
this.listBox1.Name = "listBox1"; | |||
this.listBox1.ScrollAlwaysVisible = true; | |||
this.listBox1.Size = new System.Drawing.Size(227, 208); | |||
this.listBox1.TabIndex = 2; | |||
this.listBox1.ValueMember = "Key"; | |||
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); | |||
// | |||
// textBoxURL | |||
// | |||
this.textBoxURL.Location = new System.Drawing.Point(10, 227); | |||
this.textBoxURL.Name = "textBoxURL"; | |||
this.textBoxURL.ReadOnly = true; | |||
this.textBoxURL.Size = new System.Drawing.Size(441, 21); | |||
this.textBoxURL.TabIndex = 3; | |||
this.textBoxURL.Click += new System.EventHandler(this.textBoxURL_Click); | |||
this.elementHost1.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.elementHost1.Location = new System.Drawing.Point(0, 0); | |||
this.elementHost1.Margin = new System.Windows.Forms.Padding(0); | |||
this.elementHost1.Name = "elementHost1"; | |||
this.elementHost1.Size = new System.Drawing.Size(600, 340); | |||
this.elementHost1.TabIndex = 0; | |||
this.elementHost1.Text = "elementHost1"; | |||
this.elementHost1.Child = this.serverSharingView1; | |||
// | |||
// QRCodeForm | |||
// | |||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); | |||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; | |||
this.AutoSize = true; | |||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.BackColor = System.Drawing.Color.White; | |||
this.ClientSize = new System.Drawing.Size(457, 257); | |||
this.Controls.Add(this.textBoxURL); | |||
this.Controls.Add(this.listBox1); | |||
this.Controls.Add(this.pictureBox1); | |||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; | |||
this.MaximizeBox = false; | |||
this.MinimizeBox = false; | |||
this.ClientSize = new System.Drawing.Size(600, 340); | |||
this.Controls.Add(this.elementHost1); | |||
this.Margin = new System.Windows.Forms.Padding(8); | |||
this.Name = "QRCodeForm"; | |||
this.Padding = new System.Windows.Forms.Padding(10); | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "QRCode and URL"; | |||
this.Load += new System.EventHandler(this.QRCodeForm_Load); | |||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); | |||
this.ResumeLayout(false); | |||
this.PerformLayout(); | |||
} | |||
#endregion | |||
private System.Windows.Forms.PictureBox pictureBox1; | |||
private System.Windows.Forms.ListBox listBox1; | |||
private System.Windows.Forms.TextBox textBoxURL; | |||
private System.Windows.Forms.Integration.ElementHost elementHost1; | |||
private Views.ServerSharingView serverSharingView1; | |||
} | |||
} |
@@ -27,64 +27,9 @@ namespace Shadowsocks.View | |||
this.Text = I18N.GetString("QRCode and URL"); | |||
} | |||
private void GenQR(string ssconfig) | |||
{ | |||
string qrText = ssconfig; | |||
QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M); | |||
ByteMatrix m = code.Matrix; | |||
int blockSize = Math.Max(pictureBox1.Height/m.Height, 1); | |||
var qrWidth = m.Width*blockSize; | |||
var qrHeight = m.Height*blockSize; | |||
var dWidth = pictureBox1.Width - qrWidth; | |||
var dHeight = pictureBox1.Height - qrHeight; | |||
var maxD = Math.Max(dWidth, dHeight); | |||
pictureBox1.SizeMode = maxD >= 7*blockSize ? PictureBoxSizeMode.Zoom : PictureBoxSizeMode.CenterImage; | |||
Bitmap drawArea = new Bitmap((m.Width*blockSize), (m.Height*blockSize)); | |||
using (Graphics g = Graphics.FromImage(drawArea)) | |||
{ | |||
g.Clear(Color.White); | |||
using (Brush b = new SolidBrush(Color.Black)) | |||
{ | |||
for (int row = 0; row < m.Width; row++) | |||
{ | |||
for (int col = 0; col < m.Height; col++) | |||
{ | |||
if (m[row, col] != 0) | |||
{ | |||
g.FillRectangle(b, blockSize*row, blockSize*col, blockSize, blockSize); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
pictureBox1.Image = drawArea; | |||
} | |||
private void QRCodeForm_Load(object sender, EventArgs e) | |||
{ | |||
Configuration config = Configuration.Load(); | |||
List<KeyValuePair<string, string>> serverDatas = config.configs.Select( | |||
server => | |||
new KeyValuePair<string, string>(server.GetURL(config.generateLegacyUrl), server.ToString()) | |||
).ToList(); | |||
listBox1.DataSource = serverDatas; | |||
int selectIndex = serverDatas.FindIndex(serverData => serverData.Key.StartsWith(code)); | |||
if (selectIndex >= 0) listBox1.SetSelected(selectIndex, true); | |||
} | |||
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) | |||
{ | |||
var url = (sender as ListBox)?.SelectedValue.ToString(); | |||
GenQR(url); | |||
textBoxURL.Text = url; | |||
} | |||
private void textBoxURL_Click(object sender, EventArgs e) | |||
{ | |||
textBoxURL.SelectAll(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,109 @@ | |||
using ReactiveUI; | |||
using Shadowsocks.Model; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Drawing; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Windows.Media.Imaging; | |||
namespace Shadowsocks.ViewModels | |||
{ | |||
public class ServerSharingViewModel : ReactiveObject | |||
{ | |||
/// <summary> | |||
/// The view model class for the server sharing user control. | |||
/// </summary> | |||
public ServerSharingViewModel() | |||
{ | |||
_config = Configuration.Load(); | |||
_servers = _config.configs; | |||
_selectedServer = _servers.First(); | |||
//_selectedServerUrlImage = new BitmapImage(); | |||
UpdateUrlAndImage(); | |||
} | |||
private readonly Configuration _config; | |||
private List<Server> _servers; | |||
private Server _selectedServer; | |||
private string _selectedServerUrl; | |||
private BitmapImage _selectedServerUrlImage; | |||
/// <summary> | |||
/// Called when SelectedServer changed | |||
/// to update SelectedServerUrl and SelectedServerUrlImage | |||
/// </summary> | |||
private void UpdateUrlAndImage() | |||
{ | |||
// update SelectedServerUrl | |||
SelectedServerUrl = _selectedServer.GetURL(_config.generateLegacyUrl); | |||
// generate QR code | |||
var qrCode = ZXing.QrCode.Internal.Encoder.encode(_selectedServerUrl, ZXing.QrCode.Internal.ErrorCorrectionLevel.L); | |||
var byteMatrix = qrCode.Matrix; | |||
// paint bitmap | |||
int blockSize = Math.Max(1024 / byteMatrix.Height, 1); | |||
Bitmap drawArea = new Bitmap((byteMatrix.Width * blockSize), (byteMatrix.Height * blockSize)); | |||
using (var graphics = Graphics.FromImage(drawArea)) | |||
{ | |||
graphics.Clear(Color.White); | |||
using (var solidBrush = new SolidBrush(Color.Black)) | |||
{ | |||
for (int row = 0; row < byteMatrix.Width; row++) | |||
{ | |||
for (int column = 0; column < byteMatrix.Height; column++) | |||
{ | |||
if (byteMatrix[row, column] != 0) | |||
{ | |||
graphics.FillRectangle(solidBrush, blockSize * row, blockSize * column, blockSize, blockSize); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// transform to BitmapImage for binding | |||
BitmapImage bitmapImage = new BitmapImage(); | |||
using (MemoryStream memoryStream = new MemoryStream()) | |||
{ | |||
drawArea.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp); | |||
memoryStream.Position = 0; | |||
bitmapImage.BeginInit(); | |||
bitmapImage.StreamSource = memoryStream; | |||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad; | |||
bitmapImage.EndInit(); | |||
} | |||
SelectedServerUrlImage = bitmapImage; | |||
} | |||
public List<Server> Servers | |||
{ | |||
get => _servers; | |||
set => this.RaiseAndSetIfChanged(ref _servers, value); | |||
} | |||
public Server SelectedServer | |||
{ | |||
get => _selectedServer; | |||
set | |||
{ | |||
this.RaiseAndSetIfChanged(ref _selectedServer, value); | |||
UpdateUrlAndImage(); | |||
} | |||
} | |||
public string SelectedServerUrl | |||
{ | |||
get => _selectedServerUrl; | |||
set => this.RaiseAndSetIfChanged(ref _selectedServerUrl, value); | |||
} | |||
public BitmapImage SelectedServerUrlImage | |||
{ | |||
get => _selectedServerUrlImage; | |||
set => this.RaiseAndSetIfChanged(ref _selectedServerUrlImage, value); | |||
} | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
<UserControl x:Class="Shadowsocks.Views.ServerSharingView" | |||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
xmlns:local="clr-namespace:Shadowsocks.Views" | |||
mc:Ignorable="d" | |||
d:DesignHeight="320" d:DesignWidth="600"> | |||
<Grid Margin="8"> | |||
<Grid.RowDefinitions> | |||
<RowDefinition Height="*" /> | |||
<RowDefinition Height="Auto" /> | |||
</Grid.RowDefinitions> | |||
<Grid.ColumnDefinitions> | |||
<ColumnDefinition Width="*" /> | |||
<ColumnDefinition Width="*" /> | |||
</Grid.ColumnDefinitions> | |||
<Image Grid.Row="0" | |||
Grid.Column="0" | |||
Margin="8" | |||
Source="{Binding SelectedServerUrlImage}"/> | |||
<ListBox Grid.Row="0" | |||
Grid.Column="1" | |||
Margin="8" | |||
ItemsSource="{Binding Servers}" | |||
SelectedItem="{Binding SelectedServer}"/> | |||
<TextBox x:Name="urlTextBox" | |||
Grid.Row="1" | |||
Grid.Column="0" | |||
Grid.ColumnSpan="2" | |||
Margin="8" | |||
IsReadOnly="True" | |||
Text="{Binding SelectedServerUrl}" | |||
PreviewMouseDoubleClick="urlTextBox_PreviewMouseDoubleClick"/> | |||
</Grid> | |||
</UserControl> |
@@ -0,0 +1,24 @@ | |||
using Shadowsocks.ViewModels; | |||
using System.Windows.Controls; | |||
using System.Windows.Input; | |||
namespace Shadowsocks.Views | |||
{ | |||
/// <summary> | |||
/// Interaction logic for ServerSharingView.xaml | |||
/// </summary> | |||
public partial class ServerSharingView : UserControl | |||
{ | |||
public ServerSharingView() | |||
{ | |||
InitializeComponent(); | |||
DataContext = new ServerSharingViewModel(); | |||
} | |||
private void urlTextBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) | |||
{ | |||
urlTextBox.SelectAll(); | |||
} | |||
} | |||
} |
@@ -268,6 +268,7 @@ | |||
<Compile Include="Util\SystemProxy\Sysproxy.cs" /> | |||
<Compile Include="Util\Util.cs" /> | |||
<Compile Include="Util\ViewUtils.cs" /> | |||
<Compile Include="ViewModels\ServerSharingViewModel.cs" /> | |||
<Compile Include="View\ConfigForm.cs"> | |||
<SubType>Form</SubType> | |||
</Compile> | |||
@@ -320,6 +321,9 @@ | |||
<Compile Include="View\QRCodeSplashForm.cs"> | |||
<SubType>Form</SubType> | |||
</Compile> | |||
<Compile Include="Views\ServerSharingView.xaml.cs"> | |||
<DependentUpon>ServerSharingView.xaml</DependentUpon> | |||
</Compile> | |||
<Compile Include="View\StatisticsStrategyConfigurationForm.cs"> | |||
<SubType>Form</SubType> | |||
</Compile> | |||
@@ -416,6 +420,12 @@ | |||
<Install>true</Install> | |||
</BootstrapperPackage> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Page Include="Views\ServerSharingView.xaml"> | |||
<SubType>Designer</SubType> | |||
<Generator>MSBuild:Compile</Generator> | |||
</Page> | |||
</ItemGroup> | |||
<ItemGroup /> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<Import Project="..\packages\Fody.4.2.1\build\Fody.targets" Condition="Exists('..\packages\Fody.4.2.1\build\Fody.targets')" /> | |||