Browse Source

refine qrcode

tags/2.3
clowwindy 9 years ago
parent
commit
794c8bb080
6 changed files with 291 additions and 229 deletions
  1. +3
    -4
      shadowsocks-csharp/Properties/Resources.Designer.cs
  2. +3
    -3
      shadowsocks-csharp/View/MenuViewController.cs
  3. +0
    -72
      shadowsocks-csharp/View/QRCodeSplashForm.Designer.cs
  4. +285
    -24
      shadowsocks-csharp/View/QRCodeSplashForm.cs
  5. +0
    -120
      shadowsocks-csharp/View/QRCodeSplashForm.resx
  6. +0
    -6
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 3
- 4
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -76,12 +76,13 @@ namespace Shadowsocks.Properties {
///Mode=代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=服务器选择
///Servers=服务器
///Edit Servers...=编辑服务器...
///Start on Boot=开机启动
///Share over LAN=在局域网共享代理
///Edit PAC File...=编辑 PAC 文件...
///Show QRCode...=显示二维码...
///Scan QRCode from Screen...=扫描屏幕上的二维码...
///Show Logs...=显示日志...
///About...=关于...
///Quit=退出
@@ -99,9 +100,7 @@ namespace Shadowsocks.Properties {
///Cancel=取消
///New server=未配置的服务器
///QRCode=二维码
///Shadowsocks Error: {0}=Shadowsocks 错误: {0}
///Port already in use=端口已被占用
///Il [rest of string was truncated]";.
///Shadowsocks Error: {0}=Shadowsocks [rest of string was truncated]";.
/// </summary>
internal static string cn {
get {


+ 3
- 3
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -425,10 +425,10 @@ namespace Shadowsocks.View
maxX += margin + marginLeft;
minY += -margin + marginTop;
maxY += margin + marginTop;
splash.Location = new Point((int)minX, (int)minY);
splash.Location = new Point(0, 0);
// we need a panel because a window has a minimal size
splash.Panel.Size = new Size((int)maxX - (int)minX, (int)maxY - (int)minY);
splash.Size = splash.Panel.Size;
splash.TargetRect = new Rectangle((int)minX, (int)minY, (int)maxX - (int)minX, (int)maxY - (int)minY);
splash.Size = new Size(fullImage.Width, fullImage.Height);
splash.Show();
return;
}


+ 0
- 72
shadowsocks-csharp/View/QRCodeSplashForm.Designer.cs View File

@@ -1,72 +0,0 @@
namespace Shadowsocks.View
{
partial class QRCodeSplashForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Panel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// Panel
//
this.Panel.BackColor = System.Drawing.Color.Crimson;
this.Panel.Location = new System.Drawing.Point(0, 0);
this.Panel.Margin = new System.Windows.Forms.Padding(0);
this.Panel.Name = "Panel";
this.Panel.Size = new System.Drawing.Size(168, 158);
this.Panel.TabIndex = 0;
//
// QRCodeSplashForm
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(284, 262);
this.ControlBox = false;
this.Controls.Add(this.Panel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "QRCodeSplashForm";
this.Opacity = 0.3D;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "QRCodeSplashForm";
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.White;
this.Load += new System.EventHandler(this.QRCodeSplashForm_Load);
this.ResumeLayout(false);
}
#endregion
public System.Windows.Forms.Panel Panel;
}
}

+ 285
- 24
shadowsocks-csharp/View/QRCodeSplashForm.cs View File

@@ -5,60 +5,321 @@ using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace Shadowsocks.View
{
public partial class QRCodeSplashForm : Form
public class QRCodeSplashForm : PerPixelAlphaForm
{
public class QRRectView : Control
{
private Pen pen;
private Brush brush;
public QRRectView()
{
pen = new Pen(Color.Red, 3);
brush = new SolidBrush(Color.FromArgb(100, Color.Red));
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle(brush, 0, 0, Width, Height);
g.DrawRectangle(pen, 0, 0, Width, Height);
}
}
public Rectangle TargetRect;
public QRCodeSplashForm()
{
InitializeComponent();
this.Load += QRCodeSplashForm_Load;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(284, 262);
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "QRCodeSplashForm";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.TopMost = true;
}
private Timer timer;
private int step;
private int animationStep;
private int flashStep;
private static int ANIMATION_STEPS = 30;
private static double ANIMATION_TIME = 0.3;
private QRRectView codeRectView;
int x;
int y;
int w;
int h;
Bitmap bitmap;
Graphics g;
Pen pen;
SolidBrush brush;
private void QRCodeSplashForm_Load(object sender, EventArgs e)
{
step = 0;
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
animationStep = 0;
flashStep = 0;
//codeRectView = new QRRectView();
x = 0;
y = 0;
w = Width;
h = Height;
//this.Controls.Add(codeRectView);
timer = new Timer();
timer.Interval = 300;
timer.Interval = (int)(ANIMATION_TIME * 1000 / ANIMATION_STEPS);
timer.Tick += timer_Tick;
timer.Start();
bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
g = Graphics.FromImage(bitmap);
pen = new Pen(Color.Red, 3);
brush = new SolidBrush(Color.FromArgb(30, Color.Red));
}
void timer_Tick(object sender, EventArgs e)
protected override CreateParams CreateParams
{
timer.Interval = 40;
if (step == 0)
get
{
this.Opacity = 0;
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
else if (step == 1)
{
this.Opacity = 0.3;
}
else if (step == 1)
}
void timer_Tick(object sender, EventArgs e)
{
if (animationStep < ANIMATION_STEPS)
{
this.Opacity = 0.0;
animationStep++;
double percent = (double)animationStep / (double)ANIMATION_STEPS;
// ease out
percent = 1 - Math.Pow((1 - percent), 4);
x = (int)(TargetRect.X * percent);
y = (int)(TargetRect.Y * percent);
w = (int)(TargetRect.Width * percent + this.Size.Width * (1 - percent));
h = (int)(TargetRect.Height * percent + this.Size.Height * (1 - percent));
//codeRectView.Location = new Point(x, y);
//codeRectView.Size = new Size(w, h);
pen.Color = Color.FromArgb((int)(255 * percent), Color.Red);
brush.Color = Color.FromArgb((int)(30 * percent), Color.Red);
g.Clear(Color.Transparent);
g.FillRectangle(brush, x, y, w, h);
g.DrawRectangle(pen, x, y, w, h);
SetBitmap(bitmap);
}
else if (step == 2)
else
{
this.Opacity = 0.3;
timer.Interval = 50;
if (flashStep == 0)
{
g.Clear(Color.Transparent);
SetBitmap(bitmap);
}
else if (flashStep == 1)
{
g.FillRectangle(brush, x, y, w, h);
g.DrawRectangle(pen, x, y, w, h);
SetBitmap(bitmap);
}
else if (flashStep == 1)
{
g.Clear(Color.Transparent);
SetBitmap(bitmap);
}
else if (flashStep == 2)
{
g.FillRectangle(brush, x, y, w, h);
g.DrawRectangle(pen, x, y, w, h);
SetBitmap(bitmap);
}
else if (flashStep == 3)
{
g.Clear(Color.Transparent);
SetBitmap(bitmap);
}
else if (flashStep == 4)
{
g.FillRectangle(brush, x, y, w, h);
g.DrawRectangle(pen, x, y, w, h);
SetBitmap(bitmap);
}
else
{
timer.Stop();
pen.Dispose();
brush.Dispose();
bitmap.Dispose();
this.Close();
}
flashStep++;
}
else if (step == 3)
}
}
// class that exposes needed win32 gdi functions.
class Win32
{
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public Int32 x;
public Int32 y;
public Point(Int32 x, Int32 y) { this.x = x; this.y = y; }
}
[StructLayout(LayoutKind.Sequential)]
public struct Size
{
public Int32 cx;
public Int32 cy;
public Size(Int32 cx, Int32 cy) { this.cx = cx; this.cy = cy; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ARGB
{
public byte Blue;
public byte Green;
public byte Red;
public byte Alpha;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
public const Int32 ULW_COLORKEY = 0x00000001;
public const Int32 ULW_ALPHA = 0x00000002;
public const Int32 ULW_OPAQUE = 0x00000004;
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", ExactSpelling = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hObject);
}
public class PerPixelAlphaForm : Form
{
// http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C
// Rui Lopes
public PerPixelAlphaForm()
{
// This form should not have a border or else Windows will clip it.
FormBorderStyle = FormBorderStyle.None;
}
public void SetBitmap(Bitmap bitmap)
{
SetBitmap(bitmap, 255);
}
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
public void SetBitmap(Bitmap bitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
// The ideia of this is very simple,
// 1. Create a compatible DC with screen;
// 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
// 3. Call the UpdateLayeredWindow.
IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try
{
this.Opacity = 0.0;
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
oldBitmap = Win32.SelectObject(memDc, hBitmap);
Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Point pointSource = new Win32.Point(0, 0);
Win32.Point topPos = new Win32.Point(Left, Top);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = opacity;
blend.AlphaFormat = Win32.AC_SRC_ALPHA;
Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
}
else if (step == 4)
finally
{
this.Opacity = 0.3;
Win32.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
Win32.SelectObject(memDc, oldBitmap);
//Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
else
}
protected override CreateParams CreateParams
{
get
{
this.Close();
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
step++;
}
}
}

+ 0
- 120
shadowsocks-csharp/View/QRCodeSplashForm.resx View File

@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 0
- 6
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -169,9 +169,6 @@
<Compile Include="View\QRCodeSplashForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\QRCodeSplashForm.Designer.cs">
<DependentUpon>QRCodeSplashForm.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="View\ConfigForm.resx">
<DependentUpon>ConfigForm.cs</DependentUpon>
<SubType>Designer</SubType>
@@ -184,9 +181,6 @@
<EmbeddedResource Include="View\QRCodeForm.resx">
<DependentUpon>QRCodeForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\QRCodeSplashForm.resx">
<DependentUpon>QRCodeSplashForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.config" />
<None Include="app.manifest">
<SubType>Designer</SubType>


Loading…
Cancel
Save