You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ConfigForm.cs 15 kB

12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Text;
  6. using System.Windows.Forms;
  7. using System.Diagnostics;
  8. using Microsoft.Win32;
  9. using Shadowsocks.Controller;
  10. using Shadowsocks.Model;
  11. using Shadowsocks.Properties;
  12. namespace Shadowsocks.View
  13. {
  14. public partial class ConfigForm : Form
  15. {
  16. private ShadowsocksController controller;
  17. private UpdateChecker updateChecker;
  18. // this is a copy of configuration that we are working on
  19. private Configuration _modifiedConfiguration;
  20. private int _oldSelectedIndex = -1;
  21. private bool _isFirstRun;
  22. public ConfigForm(ShadowsocksController controller)
  23. {
  24. InitializeComponent();
  25. LoadTrayIcon();
  26. notifyIcon1.ContextMenu = contextMenu1;
  27. this.controller = controller;
  28. controller.EnableStatusChanged += controller_EnableStatusChanged;
  29. controller.ConfigChanged += controller_ConfigChanged;
  30. controller.PACFileReadyToOpen += controller_PACFileReadyToOpen;
  31. controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged;
  32. this.updateChecker = new UpdateChecker();
  33. updateChecker.NewVersionFound += updateChecker_NewVersionFound;
  34. LoadCurrentConfiguration();
  35. }
  36. private void LoadTrayIcon()
  37. {
  38. int dpi;
  39. Graphics graphics = this.CreateGraphics();
  40. dpi = (int)graphics.DpiX;
  41. graphics.Dispose();
  42. Bitmap icon = null;
  43. if (dpi < 97)
  44. {
  45. // dpi = 96;
  46. icon = Resources.ss16;
  47. }
  48. else if (dpi < 121)
  49. {
  50. // dpi = 120;
  51. icon = Resources.ss20;
  52. }
  53. else
  54. {
  55. icon = Resources.ss24;
  56. }
  57. notifyIcon1.Icon = Icon.FromHandle(icon.GetHicon());
  58. notifyIcon1.Visible = true;
  59. this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
  60. }
  61. private void controller_ConfigChanged(object sender, EventArgs e)
  62. {
  63. LoadCurrentConfiguration();
  64. }
  65. private void controller_EnableStatusChanged(object sender, EventArgs e)
  66. {
  67. enableItem.Checked = controller.GetConfiguration().enabled;
  68. }
  69. void controller_ShareOverLANStatusChanged(object sender, EventArgs e)
  70. {
  71. ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan;
  72. }
  73. void controller_PACFileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e)
  74. {
  75. string argument = @"/select, " + e.Path;
  76. System.Diagnostics.Process.Start("explorer.exe", argument);
  77. }
  78. void updateChecker_NewVersionFound(object sender, EventArgs e)
  79. {
  80. notifyIcon1.BalloonTipTitle = "Shadowsocks " + updateChecker.LatestVersionNumber + " Update Found";
  81. notifyIcon1.BalloonTipText = "Click here to download";
  82. notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
  83. notifyIcon1.BalloonTipClicked += notifyIcon1_BalloonTipClicked;
  84. notifyIcon1.ShowBalloonTip(5000);
  85. _isFirstRun = false;
  86. }
  87. void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
  88. {
  89. Process.Start(updateChecker.LatestVersionURL);
  90. }
  91. private void ShowWindow()
  92. {
  93. this.Opacity = 1;
  94. this.Show();
  95. IPTextBox.Focus();
  96. }
  97. private bool SaveOldSelectedServer()
  98. {
  99. try
  100. {
  101. if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count)
  102. {
  103. return true;
  104. }
  105. Server server = new Server
  106. {
  107. server = IPTextBox.Text,
  108. server_port = int.Parse(ServerPortTextBox.Text),
  109. password = PasswordTextBox.Text,
  110. local_port = int.Parse(ProxyPortTextBox.Text),
  111. method = EncryptionSelect.Text,
  112. remarks = RemarksTextBox.Text
  113. };
  114. Configuration.CheckServer(server);
  115. _modifiedConfiguration.configs[_oldSelectedIndex] = server;
  116. return true;
  117. }
  118. catch (FormatException)
  119. {
  120. MessageBox.Show("illegal port number format");
  121. }
  122. catch (Exception ex)
  123. {
  124. MessageBox.Show(ex.Message);
  125. }
  126. return false;
  127. }
  128. private void LoadSelectedServer()
  129. {
  130. if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < _modifiedConfiguration.configs.Count)
  131. {
  132. Server server = _modifiedConfiguration.configs[ServersListBox.SelectedIndex];
  133. IPTextBox.Text = server.server;
  134. ServerPortTextBox.Text = server.server_port.ToString();
  135. PasswordTextBox.Text = server.password;
  136. ProxyPortTextBox.Text = server.local_port.ToString();
  137. EncryptionSelect.Text = server.method ?? "aes-256-cfb";
  138. RemarksTextBox.Text = server.remarks;
  139. ServerGroupBox.Visible = true;
  140. //IPTextBox.Focus();
  141. }
  142. else
  143. {
  144. ServerGroupBox.Visible = false;
  145. }
  146. }
  147. private void LoadConfiguration(Configuration configuration)
  148. {
  149. ServersListBox.Items.Clear();
  150. foreach (Server server in _modifiedConfiguration.configs)
  151. {
  152. ServersListBox.Items.Add(string.IsNullOrEmpty(server.server) ? "New server" : string.IsNullOrEmpty(server.remarks)? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")");
  153. }
  154. }
  155. private void LoadCurrentConfiguration()
  156. {
  157. _modifiedConfiguration = controller.GetConfiguration();
  158. LoadConfiguration(_modifiedConfiguration);
  159. _oldSelectedIndex = _modifiedConfiguration.index;
  160. ServersListBox.SelectedIndex = _modifiedConfiguration.index;
  161. LoadSelectedServer();
  162. UpdateServersMenu();
  163. enableItem.Checked = _modifiedConfiguration.enabled;
  164. ShareOverLANItem.Checked = _modifiedConfiguration.shareOverLan;
  165. }
  166. private void UpdateServersMenu()
  167. {
  168. var items = ServersItem.MenuItems;
  169. items.Clear();
  170. Configuration configuration = controller.GetConfiguration();
  171. for (int i = 0; i < configuration.configs.Count; i++)
  172. {
  173. Server server = configuration.configs[i];
  174. MenuItem item = new MenuItem(string.IsNullOrEmpty(server.remarks) ? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")");
  175. item.Tag = i;
  176. item.Click += AServerItem_Click;
  177. items.Add(item);
  178. }
  179. items.Add(SeperatorItem);
  180. items.Add(ConfigItem);
  181. if (configuration.index >= 0 && configuration.index < configuration.configs.Count)
  182. {
  183. items[configuration.index].Checked = true;
  184. }
  185. }
  186. private void ConfigForm_Load(object sender, EventArgs e)
  187. {
  188. if (!controller.GetConfiguration().isDefault)
  189. {
  190. this.Opacity = 0;
  191. BeginInvoke(new MethodInvoker(delegate
  192. {
  193. this.Hide();
  194. }));
  195. }
  196. else
  197. {
  198. _isFirstRun = true;
  199. }
  200. updateChecker.CheckUpdate();
  201. }
  202. private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e)
  203. {
  204. if (_oldSelectedIndex == ServersListBox.SelectedIndex)
  205. {
  206. // we are moving back to oldSelectedIndex or doing a force move
  207. return;
  208. }
  209. if (!SaveOldSelectedServer())
  210. {
  211. // why this won't cause stack overflow?
  212. ServersListBox.SelectedIndex = _oldSelectedIndex;
  213. return;
  214. }
  215. LoadSelectedServer();
  216. _oldSelectedIndex = ServersListBox.SelectedIndex;
  217. }
  218. private void AddButton_Click(object sender, EventArgs e)
  219. {
  220. if (!SaveOldSelectedServer())
  221. {
  222. return;
  223. }
  224. Server server = Configuration.GetDefaultServer();
  225. _modifiedConfiguration.configs.Add(server);
  226. LoadConfiguration(_modifiedConfiguration);
  227. ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1;
  228. _oldSelectedIndex = ServersListBox.SelectedIndex;
  229. }
  230. private void DeleteButton_Click(object sender, EventArgs e)
  231. {
  232. _oldSelectedIndex = ServersListBox.SelectedIndex;
  233. if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count)
  234. {
  235. _modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex);
  236. }
  237. if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count)
  238. {
  239. // can be -1
  240. _oldSelectedIndex = _modifiedConfiguration.configs.Count - 1;
  241. }
  242. ServersListBox.SelectedIndex = _oldSelectedIndex;
  243. LoadConfiguration(_modifiedConfiguration);
  244. ServersListBox.SelectedIndex = _oldSelectedIndex;
  245. LoadSelectedServer();
  246. }
  247. private void Config_Click(object sender, EventArgs e)
  248. {
  249. ShowWindow();
  250. }
  251. private void Quit_Click(object sender, EventArgs e)
  252. {
  253. this.Close();
  254. }
  255. private void ShowFirstTimeBalloon()
  256. {
  257. if (_isFirstRun)
  258. {
  259. notifyIcon1.BalloonTipTitle = "Shadowsocks is here";
  260. notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu";
  261. notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
  262. notifyIcon1.ShowBalloonTip(0);
  263. _isFirstRun = false;
  264. }
  265. }
  266. private void OKButton_Click(object sender, EventArgs e)
  267. {
  268. if (!SaveOldSelectedServer())
  269. {
  270. return;
  271. }
  272. if (_modifiedConfiguration.configs.Count == 0)
  273. {
  274. MessageBox.Show("Please add at least one server");
  275. return;
  276. }
  277. controller.SaveServers(_modifiedConfiguration.configs);
  278. this.Hide();
  279. ShowFirstTimeBalloon();
  280. }
  281. private void CancelButton_Click(object sender, EventArgs e)
  282. {
  283. this.Hide();
  284. LoadCurrentConfiguration();
  285. ShowFirstTimeBalloon();
  286. }
  287. private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e)
  288. {
  289. controller.Stop();
  290. }
  291. private void AboutItem_Click(object sender, EventArgs e)
  292. {
  293. Process.Start("https://github.com/clowwindy/shadowsocks-csharp");
  294. }
  295. private void notifyIcon1_DoubleClick(object sender, EventArgs e)
  296. {
  297. ShowWindow();
  298. }
  299. private void EnableItem_Click(object sender, EventArgs e)
  300. {
  301. enableItem.Checked = !enableItem.Checked;
  302. controller.ToggleEnable(enableItem.Checked);
  303. }
  304. private void ShareOverLANItem_Click(object sender, EventArgs e)
  305. {
  306. ShareOverLANItem.Checked = !ShareOverLANItem.Checked;
  307. controller.ToggleShareOverLAN(ShareOverLANItem.Checked);
  308. }
  309. private void EditPACFileItem_Click(object sender, EventArgs e)
  310. {
  311. controller.TouchPACFile();
  312. }
  313. private void AServerItem_Click(object sender, EventArgs e)
  314. {
  315. MenuItem item = (MenuItem)sender;
  316. controller.SelectServerIndex((int)item.Tag);
  317. }
  318. private void ShowLogItem_Click(object sender, EventArgs e)
  319. {
  320. string argument = Logging.LogFile;
  321. System.Diagnostics.Process.Start("notepad.exe", argument);
  322. }
  323. private void ConfigForm_Shown(object sender, EventArgs e)
  324. {
  325. IPTextBox.Focus();
  326. }
  327. private void QRCodeItem_Click(object sender, EventArgs e)
  328. {
  329. QRCodeForm qrCodeForm = new QRCodeForm(controller.GetQRCodeForCurrentServer());
  330. qrCodeForm.Icon = this.Icon;
  331. qrCodeForm.Show();
  332. }
  333. private bool setAutoStartup(bool enabled) {
  334. try {
  335. string path = Application.ExecutablePath;
  336. RegistryKey runKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
  337. if (enabled) {
  338. runKey.SetValue("Shadowsocks-CSharp", path);
  339. } else {
  340. runKey.DeleteValue("Shadowsocks-CSharp");
  341. }
  342. runKey.Close();
  343. return true;
  344. } catch (Exception e) {
  345. return false;
  346. }
  347. }
  348. private bool checkAutoStartup() {
  349. try {
  350. string path = Application.ExecutablePath;
  351. RegistryKey runKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
  352. string[] runList = runKey.GetValueNames();
  353. runKey.Close();
  354. foreach(string item in runList){
  355. if (item.Equals("Shadowsocks-CSharp"))
  356. return true;
  357. }
  358. return false;
  359. } catch (Exception e) {
  360. return false;
  361. }
  362. }
  363. private void autoStartup_Click(object sender, EventArgs e) {
  364. autoStartup.Checked = !autoStartup.Checked;
  365. if (!setAutoStartup(autoStartup.Checked)) {
  366. //MessageBox.Show("Failed to edit registry");
  367. }
  368. }
  369. private void contextMenu1_Popup(object sender, EventArgs e) {
  370. autoStartup.Checked = checkAutoStartup();
  371. }
  372. }
  373. }