The configuration window has been added. The screensaver now uses D2DForm as replacement for standard WinForms. The screensaver has been targeted to older .NET for compatibility.master
@@ -2,8 +2,17 @@ | |||
<PropertyGroup> | |||
<OutputType>WinExe</OutputType> | |||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||
<TargetFramework>net5.0-windows</TargetFramework> | |||
<UseWindowsForms>true</UseWindowsForms> | |||
<StartupObject>GameOfLife.Program</StartupObject> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
<PlatformTarget>x64</PlatformTarget> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="unvell.D2DLib-x64" Version="1.3.1" /> | |||
</ItemGroup> | |||
</Project> |
@@ -44,7 +44,6 @@ namespace GameOfLife | |||
this.Name = "MainForm"; | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; | |||
this.Load += new System.EventHandler(this.MainForm_Load); | |||
this.Paint += new System.Windows.Forms.PaintEventHandler(this.MainForm_Paint); | |||
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress); | |||
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseClick); | |||
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseMove); | |||
@@ -1,16 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Microsoft.Win32; | |||
using System; | |||
using System.Drawing; | |||
using System.Runtime.InteropServices; | |||
using System.Windows.Forms; | |||
using unvell.D2DLib; | |||
using unvell.D2DLib.WinForm; | |||
namespace GameOfLife | |||
{ | |||
public partial class MainForm : Form | |||
public partial class MainForm : D2DForm | |||
{ | |||
private Point mouseLocation; | |||
private bool[,] newCells; | |||
private bool[,] toggleCells; | |||
private bool[,] oldCells; | |||
private Random random; | |||
@@ -19,28 +21,125 @@ namespace GameOfLife | |||
private int magicCells = 0; | |||
private double density = 0.35; | |||
private double density = 0.5; | |||
private int interval = 500; | |||
private int interval = 100; | |||
// TODO color | |||
//private int color; | |||
public MainForm(Rectangle bounds) | |||
private D2DRect boundsRect; | |||
private D2DRect cellRect; | |||
private int maxX; | |||
private int maxY; | |||
private int firstX; | |||
private int lastX; | |||
private int firstY; | |||
private int lastY; | |||
private bool previewMode; | |||
[DllImport("user32.dll")] | |||
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); | |||
[DllImport("user32.dll")] | |||
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); | |||
[DllImport("user32.dll", SetLastError = true)] | |||
static extern int GetWindowLong(IntPtr hWnd, int nIndex); | |||
[DllImport("user32.dll")] | |||
static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect); | |||
private void LoadSettings() | |||
{ | |||
InitializeComponent(); | |||
random = new Random(); | |||
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\TheoryOfNekomata\\WindowsScreensavers\\GameOfLife"); | |||
var retrievedGridSize = 3; | |||
var retrievedSpores = 0; | |||
int retrievedDensity = 50; | |||
var retrievedInterval = 250; | |||
var gridSizes = new int[] { 1, 2, 4, 8 }; | |||
if (key != null) | |||
{ | |||
retrievedGridSize = (int)key.GetValue("GridSizeIndex", 3); | |||
retrievedSpores = (int)key.GetValue("Spores", 0); | |||
retrievedDensity = (int)key.GetValue("DensityPercentage", 50); | |||
retrievedInterval = (int)key.GetValue("IntervalMs", 250); | |||
} | |||
gridSize = gridSizes[retrievedGridSize]; | |||
magicCells = retrievedSpores; | |||
density = ((double)retrievedDensity) / 100.0; | |||
interval = retrievedInterval; | |||
} | |||
private void SetBounds(Rectangle bounds) { | |||
Bounds = bounds; | |||
newCells = new bool[bounds.Width / gridSize, bounds.Height / gridSize]; | |||
toggleCells = new bool[bounds.Width / gridSize, bounds.Height / gridSize]; | |||
oldCells = new bool[bounds.Width / gridSize, bounds.Height / gridSize]; | |||
boundsRect = new D2DRect(Bounds.Left, Bounds.Top, Bounds.Width, Bounds.Height); | |||
} | |||
private void RandomizeCells() { | |||
random = new Random(); | |||
maxX = Bounds.Width / gridSize; | |||
maxY = Bounds.Height / gridSize; | |||
newCells = new bool[maxX, maxY]; | |||
oldCells = new bool[maxX, maxY]; | |||
firstX = oldCells.GetLowerBound(0); | |||
lastX = oldCells.GetUpperBound(0); | |||
firstY = oldCells.GetLowerBound(1); | |||
lastY = oldCells.GetUpperBound(1); | |||
for (var x = 0; x < newCells.GetLength(0); x++) { | |||
for (var y = 0; y < newCells.GetLength(1); y++) { | |||
for (var x = 0; x < maxX; x++) | |||
{ | |||
for (var y = 0; y < maxY; y++) | |||
{ | |||
newCells[x, y] = random.NextDouble() <= density; | |||
oldCells[x, y] = false; | |||
toggleCells[x, y] = true; | |||
} | |||
} | |||
} | |||
public MainForm(Rectangle bounds) | |||
{ | |||
LoadSettings(); | |||
InitializeComponent(); | |||
SetBounds(bounds); | |||
RandomizeCells(); | |||
} | |||
public MainForm(IntPtr PreviewWndHandle) | |||
{ | |||
LoadSettings(); | |||
gridSize = 1; | |||
magicCells = 0; | |||
density = 0.5; | |||
InitializeComponent(); | |||
// Set the preview window as the parent of this window | |||
SetParent(this.Handle, PreviewWndHandle); | |||
// Make this a child window so it will close when the parent dialog closes | |||
// GWL_STYLE = -16, WS_CHILD = 0x40000000 | |||
SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000)); | |||
// Place our window inside the parent | |||
Rectangle ParentRect; | |||
GetClientRect(PreviewWndHandle, out ParentRect); | |||
Size = ParentRect.Size; | |||
Location = new Point(0, 0); | |||
RandomizeCells(); | |||
previewMode = true; | |||
} | |||
private void MainForm_Load(object sender, EventArgs e) | |||
{ | |||
Cursor.Hide(); | |||
@@ -53,64 +152,74 @@ namespace GameOfLife | |||
private void MainForm_MouseMove(object sender, MouseEventArgs e) | |||
{ | |||
if (!mouseLocation.IsEmpty) | |||
if (!previewMode) | |||
{ | |||
// Terminate if mouse is moved a significant distance | |||
if (Math.Abs(mouseLocation.X - e.X) > 5 || | |||
Math.Abs(mouseLocation.Y - e.Y) > 5) | |||
Application.Exit(); | |||
} | |||
// Update current mouse location | |||
mouseLocation = e.Location; | |||
if (!mouseLocation.IsEmpty) | |||
{ | |||
// Terminate if mouse is moved a significant distance | |||
if (Math.Abs(mouseLocation.X - e.X) > 5 || | |||
Math.Abs(mouseLocation.Y - e.Y) > 5) | |||
Application.Exit(); | |||
} | |||
// Update current mouse location | |||
mouseLocation = e.Location; | |||
} | |||
} | |||
private void MainForm_MouseClick(object sender, MouseEventArgs e) | |||
{ | |||
Application.Exit(); | |||
if (!previewMode) | |||
{ | |||
Application.Exit(); | |||
} | |||
} | |||
private void MainForm_KeyPress(object sender, KeyPressEventArgs e) | |||
{ | |||
Application.Exit(); | |||
if (!previewMode) | |||
{ | |||
Application.Exit(); | |||
} | |||
} | |||
private int GetAliveNeighbors(bool[,] cells, int x, int y) { | |||
int prevX = x == cells.GetLowerBound(0) ? cells.GetUpperBound(0) : x - 1; | |||
int nextX = x == cells.GetUpperBound(0) ? cells.GetLowerBound(0) : x + 1; | |||
int prevY = y == cells.GetLowerBound(1) ? cells.GetUpperBound(1) : y - 1; | |||
int nextY = y == cells.GetUpperBound(1) ? cells.GetLowerBound(1) : y + 1; | |||
private int GetAliveNeighbors(int x, int y) { | |||
int prevX = x == firstX ? lastX : x - 1; | |||
int nextX = x == lastX ? firstX : x + 1; | |||
int prevY = y == firstY ? lastY : y - 1; | |||
int nextY = y == lastY ? firstY : y + 1; | |||
int aliveNeighbors = 0; | |||
if (cells[prevX, prevY]) { | |||
if (oldCells[prevX, prevY]) { | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[x, prevY]) | |||
if (oldCells[x, prevY]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[nextX, prevY]) | |||
if (oldCells[nextX, prevY]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[prevX, y]) | |||
if (oldCells[prevX, y]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[nextX, y]) | |||
if (oldCells[nextX, y]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[prevX, nextY]) | |||
if (oldCells[prevX, nextY]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[x, nextY]) | |||
if (oldCells[x, nextY]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
if (cells[nextX, nextY]) | |||
if (oldCells[nextX, nextY]) | |||
{ | |||
aliveNeighbors += 1; | |||
} | |||
@@ -130,7 +239,7 @@ namespace GameOfLife | |||
{ | |||
for (var y = 0; y < newCells.GetLength(1); y++) | |||
{ | |||
int neighbors = GetAliveNeighbors(oldCells, x, y); | |||
int neighbors = GetAliveNeighbors(x, y); | |||
bool shouldLive = false; | |||
if (oldCells[x, y] && neighbors == 2) | |||
{ | |||
@@ -140,7 +249,6 @@ namespace GameOfLife | |||
} | |||
newCells[x, y] = shouldLive; | |||
toggleCells[x, y] = oldCells[x, y] == newCells[x, y]; | |||
} | |||
} | |||
@@ -149,41 +257,25 @@ namespace GameOfLife | |||
int magicY = random.Next(0, newCells.GetUpperBound(1)); | |||
newCells[magicX, magicY] = true; | |||
toggleCells[magicX, magicY] = oldCells[magicX, magicY] == newCells[magicX, magicY]; | |||
} | |||
Redraw(CreateGraphics()); | |||
Refresh(); | |||
} | |||
private void Redraw(Graphics graphics) { | |||
List<Rectangle> liveCells = new List<Rectangle>(); | |||
List<Rectangle> deadCells = new List<Rectangle>(); | |||
protected override void OnRender(D2DGraphics graphics) | |||
{ | |||
graphics.FillRectangle(boundsRect, D2DColor.White); | |||
for (var x = 0; x < newCells.GetLength(0); x++) | |||
{ | |||
for (var y = 0; y < newCells.GetLength(1); y++) | |||
{ | |||
if (newCells[x, y]) | |||
if (!newCells[x, y]) | |||
{ | |||
liveCells.Add(new Rectangle(x * gridSize, y * gridSize, gridSize, gridSize)); | |||
cellRect = new D2DRect(x * gridSize, y * gridSize, gridSize, gridSize); | |||
graphics.FillRectangle(cellRect, D2DColor.Black); | |||
} | |||
else { | |||
deadCells.Add(new Rectangle(x * gridSize, y * gridSize, gridSize, gridSize)); | |||
} | |||
//else if (!newCells[x, y]) { | |||
// graphics.FillRectangle(Brushes.Black, x * gridSize, y * gridSize, gridSize, gridSize); | |||
//} | |||
} | |||
} | |||
graphics.FillRectangle(Brushes.Black, Bounds); | |||
//graphics.FillRectangles(Brushes.Black, deadCells.ToArray()); | |||
graphics.FillRectangles(Brushes.White, liveCells.ToArray()); | |||
} | |||
private void MainForm_Paint(object sender, PaintEventArgs e) | |||
{ | |||
Redraw(e.Graphics); | |||
} | |||
} | |||
} |
@@ -1,7 +1,4 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using System.Windows.Forms; | |||
namespace GameOfLife | |||
@@ -35,11 +32,19 @@ namespace GameOfLife | |||
if (firstArgument == "/c") // Configuration mode | |||
{ | |||
// TODO | |||
Application.Run(new SettingsForm()); | |||
} | |||
else if (firstArgument == "/p") // Preview mode | |||
{ | |||
// TODO | |||
if (secondArgument == null) | |||
{ | |||
MessageBox.Show("Sorry, but the expected window handle was not provided.", | |||
"ScreenSaver", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); | |||
return; | |||
} | |||
IntPtr previewWndHandle = new IntPtr(long.Parse(secondArgument)); | |||
Application.Run(new MainForm(previewWndHandle)); | |||
} | |||
else if (firstArgument == "/s") // Full-screen mode | |||
{ | |||
@@ -55,7 +60,7 @@ namespace GameOfLife | |||
} | |||
else // No arguments - treat like /c | |||
{ | |||
// TODO | |||
Application.Run(new SettingsForm()); | |||
} | |||
} | |||
@@ -0,0 +1,344 @@ | |||
| |||
namespace GameOfLife | |||
{ | |||
partial class SettingsForm | |||
{ | |||
/// <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.ctrlGridSize = new System.Windows.Forms.ComboBox(); | |||
this.ctrlSpores = new System.Windows.Forms.NumericUpDown(); | |||
this.ctrlInterval = new System.Windows.Forms.TrackBar(); | |||
this.ctrlDensity = new System.Windows.Forms.TrackBar(); | |||
this.lblSpores = new System.Windows.Forms.Label(); | |||
this.lblGridSize = new System.Windows.Forms.Label(); | |||
this.grpGridSize = new System.Windows.Forms.GroupBox(); | |||
this.grpSpores = new System.Windows.Forms.GroupBox(); | |||
this.grpDensity = new System.Windows.Forms.GroupBox(); | |||
this.lblDensityValue = new System.Windows.Forms.Label(); | |||
this.lblDensity = new System.Windows.Forms.Label(); | |||
this.grpInterval = new System.Windows.Forms.GroupBox(); | |||
this.lblIntervalValue = new System.Windows.Forms.Label(); | |||
this.lblInterval = new System.Windows.Forms.Label(); | |||
this.panelMain = new System.Windows.Forms.TableLayoutPanel(); | |||
this.panelActions = new System.Windows.Forms.FlowLayoutPanel(); | |||
this.btnOK = new System.Windows.Forms.Button(); | |||
this.btnCancel = new System.Windows.Forms.Button(); | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlSpores)).BeginInit(); | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlInterval)).BeginInit(); | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlDensity)).BeginInit(); | |||
this.grpGridSize.SuspendLayout(); | |||
this.grpSpores.SuspendLayout(); | |||
this.grpDensity.SuspendLayout(); | |||
this.grpInterval.SuspendLayout(); | |||
this.panelMain.SuspendLayout(); | |||
this.panelActions.SuspendLayout(); | |||
this.SuspendLayout(); | |||
// | |||
// ctrlGridSize | |||
// | |||
this.ctrlGridSize.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.ctrlGridSize.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; | |||
this.ctrlGridSize.FormattingEnabled = true; | |||
this.ctrlGridSize.Items.AddRange(new object[] { | |||
"1", | |||
"2", | |||
"4", | |||
"8"}); | |||
this.ctrlGridSize.Location = new System.Drawing.Point(8, 70); | |||
this.ctrlGridSize.Name = "ctrlGridSize"; | |||
this.ctrlGridSize.Size = new System.Drawing.Size(177, 23); | |||
this.ctrlGridSize.TabIndex = 1; | |||
// | |||
// ctrlSpores | |||
// | |||
this.ctrlSpores.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.ctrlSpores.Location = new System.Drawing.Point(8, 70); | |||
this.ctrlSpores.Name = "ctrlSpores"; | |||
this.ctrlSpores.Size = new System.Drawing.Size(178, 23); | |||
this.ctrlSpores.TabIndex = 2; | |||
// | |||
// ctrlInterval | |||
// | |||
this.ctrlInterval.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.ctrlInterval.Location = new System.Drawing.Point(8, 70); | |||
this.ctrlInterval.Maximum = 3000; | |||
this.ctrlInterval.Minimum = 50; | |||
this.ctrlInterval.Name = "ctrlInterval"; | |||
this.ctrlInterval.Size = new System.Drawing.Size(177, 45); | |||
this.ctrlInterval.TabIndex = 3; | |||
this.ctrlInterval.TickFrequency = 250; | |||
this.ctrlInterval.Value = 250; | |||
this.ctrlInterval.Scroll += new System.EventHandler(this.ctrlInterval_Scroll); | |||
// | |||
// ctrlDensity | |||
// | |||
this.ctrlDensity.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.ctrlDensity.Location = new System.Drawing.Point(8, 70); | |||
this.ctrlDensity.Maximum = 100; | |||
this.ctrlDensity.Name = "ctrlDensity"; | |||
this.ctrlDensity.Size = new System.Drawing.Size(178, 45); | |||
this.ctrlDensity.TabIndex = 4; | |||
this.ctrlDensity.TickFrequency = 10; | |||
this.ctrlDensity.Value = 50; | |||
this.ctrlDensity.Scroll += new System.EventHandler(this.ctrlDensity_Scroll); | |||
// | |||
// lblSpores | |||
// | |||
this.lblSpores.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblSpores.Location = new System.Drawing.Point(8, 24); | |||
this.lblSpores.Name = "lblSpores"; | |||
this.lblSpores.Padding = new System.Windows.Forms.Padding(0, 8, 0, 8); | |||
this.lblSpores.Size = new System.Drawing.Size(178, 46); | |||
this.lblSpores.TabIndex = 5; | |||
this.lblSpores.Text = "This sets the count of live cells randomly spawning in the grid."; | |||
// | |||
// lblGridSize | |||
// | |||
this.lblGridSize.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblGridSize.Location = new System.Drawing.Point(8, 24); | |||
this.lblGridSize.Name = "lblGridSize"; | |||
this.lblGridSize.Padding = new System.Windows.Forms.Padding(0, 8, 0, 8); | |||
this.lblGridSize.Size = new System.Drawing.Size(177, 46); | |||
this.lblGridSize.TabIndex = 6; | |||
this.lblGridSize.Text = "This is the size of each cell in pixels."; | |||
// | |||
// grpGridSize | |||
// | |||
this.grpGridSize.AutoSize = true; | |||
this.grpGridSize.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.grpGridSize.Controls.Add(this.ctrlGridSize); | |||
this.grpGridSize.Controls.Add(this.lblGridSize); | |||
this.grpGridSize.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.grpGridSize.Location = new System.Drawing.Point(8, 8); | |||
this.grpGridSize.Margin = new System.Windows.Forms.Padding(8); | |||
this.grpGridSize.Name = "grpGridSize"; | |||
this.grpGridSize.Padding = new System.Windows.Forms.Padding(8); | |||
this.grpGridSize.Size = new System.Drawing.Size(193, 146); | |||
this.grpGridSize.TabIndex = 7; | |||
this.grpGridSize.TabStop = false; | |||
this.grpGridSize.Text = "Grid Size"; | |||
// | |||
// grpSpores | |||
// | |||
this.grpSpores.AutoSize = true; | |||
this.grpSpores.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.grpSpores.Controls.Add(this.ctrlSpores); | |||
this.grpSpores.Controls.Add(this.lblSpores); | |||
this.grpSpores.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.grpSpores.Location = new System.Drawing.Point(217, 170); | |||
this.grpSpores.Margin = new System.Windows.Forms.Padding(8); | |||
this.grpSpores.Name = "grpSpores"; | |||
this.grpSpores.Padding = new System.Windows.Forms.Padding(8); | |||
this.grpSpores.Size = new System.Drawing.Size(194, 147); | |||
this.grpSpores.TabIndex = 8; | |||
this.grpSpores.TabStop = false; | |||
this.grpSpores.Text = "Spores"; | |||
// | |||
// grpDensity | |||
// | |||
this.grpDensity.AutoSize = true; | |||
this.grpDensity.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.grpDensity.Controls.Add(this.lblDensityValue); | |||
this.grpDensity.Controls.Add(this.ctrlDensity); | |||
this.grpDensity.Controls.Add(this.lblDensity); | |||
this.grpDensity.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.grpDensity.Location = new System.Drawing.Point(217, 8); | |||
this.grpDensity.Margin = new System.Windows.Forms.Padding(8); | |||
this.grpDensity.Name = "grpDensity"; | |||
this.grpDensity.Padding = new System.Windows.Forms.Padding(8); | |||
this.grpDensity.Size = new System.Drawing.Size(194, 146); | |||
this.grpDensity.TabIndex = 9; | |||
this.grpDensity.TabStop = false; | |||
this.grpDensity.Text = "Density"; | |||
// | |||
// lblDensityValue | |||
// | |||
this.lblDensityValue.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblDensityValue.Location = new System.Drawing.Point(8, 115); | |||
this.lblDensityValue.Name = "lblDensityValue"; | |||
this.lblDensityValue.Size = new System.Drawing.Size(178, 30); | |||
this.lblDensityValue.TabIndex = 6; | |||
this.lblDensityValue.Text = "Current Value: 50%"; | |||
this.lblDensityValue.TextAlign = System.Drawing.ContentAlignment.MiddleRight; | |||
// | |||
// lblDensity | |||
// | |||
this.lblDensity.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblDensity.Location = new System.Drawing.Point(8, 24); | |||
this.lblDensity.Name = "lblDensity"; | |||
this.lblDensity.Padding = new System.Windows.Forms.Padding(0, 8, 0, 8); | |||
this.lblDensity.Size = new System.Drawing.Size(178, 46); | |||
this.lblDensity.TabIndex = 5; | |||
this.lblDensity.Text = "This controls the starting density of live cells throughout the grid."; | |||
// | |||
// grpInterval | |||
// | |||
this.grpInterval.AutoSize = true; | |||
this.grpInterval.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.grpInterval.Controls.Add(this.lblIntervalValue); | |||
this.grpInterval.Controls.Add(this.ctrlInterval); | |||
this.grpInterval.Controls.Add(this.lblInterval); | |||
this.grpInterval.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.grpInterval.Location = new System.Drawing.Point(8, 170); | |||
this.grpInterval.Margin = new System.Windows.Forms.Padding(8); | |||
this.grpInterval.Name = "grpInterval"; | |||
this.grpInterval.Padding = new System.Windows.Forms.Padding(8); | |||
this.grpInterval.Size = new System.Drawing.Size(193, 147); | |||
this.grpInterval.TabIndex = 10; | |||
this.grpInterval.TabStop = false; | |||
this.grpInterval.Text = "Interval"; | |||
// | |||
// lblIntervalValue | |||
// | |||
this.lblIntervalValue.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblIntervalValue.Location = new System.Drawing.Point(8, 115); | |||
this.lblIntervalValue.Name = "lblIntervalValue"; | |||
this.lblIntervalValue.Size = new System.Drawing.Size(177, 30); | |||
this.lblIntervalValue.TabIndex = 5; | |||
this.lblIntervalValue.Text = "Current Value: 250ms"; | |||
this.lblIntervalValue.TextAlign = System.Drawing.ContentAlignment.MiddleRight; | |||
// | |||
// lblInterval | |||
// | |||
this.lblInterval.Dock = System.Windows.Forms.DockStyle.Top; | |||
this.lblInterval.Location = new System.Drawing.Point(8, 24); | |||
this.lblInterval.Name = "lblInterval"; | |||
this.lblInterval.Padding = new System.Windows.Forms.Padding(0, 8, 0, 8); | |||
this.lblInterval.Size = new System.Drawing.Size(177, 46); | |||
this.lblInterval.TabIndex = 4; | |||
this.lblInterval.Text = "This specifies how often the screen updates."; | |||
// | |||
// panelMain | |||
// | |||
this.panelMain.AutoSize = true; | |||
this.panelMain.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
this.panelMain.ColumnCount = 2; | |||
this.panelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); | |||
this.panelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); | |||
this.panelMain.Controls.Add(this.grpDensity, 1, 0); | |||
this.panelMain.Controls.Add(this.grpSpores, 1, 1); | |||
this.panelMain.Controls.Add(this.grpInterval, 0, 1); | |||
this.panelMain.Controls.Add(this.grpGridSize, 0, 0); | |||
this.panelMain.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.panelMain.Location = new System.Drawing.Point(0, 0); | |||
this.panelMain.Name = "panelMain"; | |||
this.panelMain.RowCount = 2; | |||
this.panelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); | |||
this.panelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); | |||
this.panelMain.Size = new System.Drawing.Size(419, 325); | |||
this.panelMain.TabIndex = 11; | |||
// | |||
// panelActions | |||
// | |||
this.panelActions.AutoSize = true; | |||
this.panelActions.BackColor = System.Drawing.SystemColors.Window; | |||
this.panelActions.Controls.Add(this.btnOK); | |||
this.panelActions.Controls.Add(this.btnCancel); | |||
this.panelActions.Dock = System.Windows.Forms.DockStyle.Bottom; | |||
this.panelActions.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; | |||
this.panelActions.Location = new System.Drawing.Point(0, 325); | |||
this.panelActions.Margin = new System.Windows.Forms.Padding(0); | |||
this.panelActions.Name = "panelActions"; | |||
this.panelActions.Size = new System.Drawing.Size(419, 39); | |||
this.panelActions.TabIndex = 12; | |||
// | |||
// btnOK | |||
// | |||
this.btnOK.Location = new System.Drawing.Point(340, 8); | |||
this.btnOK.Margin = new System.Windows.Forms.Padding(4, 8, 4, 8); | |||
this.btnOK.Name = "btnOK"; | |||
this.btnOK.Size = new System.Drawing.Size(75, 23); | |||
this.btnOK.TabIndex = 0; | |||
this.btnOK.Text = "O&K"; | |||
this.btnOK.UseVisualStyleBackColor = true; | |||
this.btnOK.Click += new System.EventHandler(this.btnOK_Click); | |||
// | |||
// btnCancel | |||
// | |||
this.btnCancel.Location = new System.Drawing.Point(257, 8); | |||
this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 8, 4, 8); | |||
this.btnCancel.Name = "btnCancel"; | |||
this.btnCancel.Size = new System.Drawing.Size(75, 23); | |||
this.btnCancel.TabIndex = 1; | |||
this.btnCancel.Text = "C&ancel"; | |||
this.btnCancel.UseVisualStyleBackColor = true; | |||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); | |||
// | |||
// SettingsForm | |||
// | |||
this.AcceptButton = this.btnOK; | |||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); | |||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; | |||
this.CancelButton = this.btnCancel; | |||
this.ClientSize = new System.Drawing.Size(419, 364); | |||
this.Controls.Add(this.panelMain); | |||
this.Controls.Add(this.panelActions); | |||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; | |||
this.MaximizeBox = false; | |||
this.MinimizeBox = false; | |||
this.Name = "SettingsForm"; | |||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "Game of Life Settings"; | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlSpores)).EndInit(); | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlInterval)).EndInit(); | |||
((System.ComponentModel.ISupportInitialize)(this.ctrlDensity)).EndInit(); | |||
this.grpGridSize.ResumeLayout(false); | |||
this.grpSpores.ResumeLayout(false); | |||
this.grpDensity.ResumeLayout(false); | |||
this.grpDensity.PerformLayout(); | |||
this.grpInterval.ResumeLayout(false); | |||
this.grpInterval.PerformLayout(); | |||
this.panelMain.ResumeLayout(false); | |||
this.panelMain.PerformLayout(); | |||
this.panelActions.ResumeLayout(false); | |||
this.ResumeLayout(false); | |||
this.PerformLayout(); | |||
} | |||
#endregion | |||
private System.Windows.Forms.ComboBox ctrlGridSize; | |||
private System.Windows.Forms.NumericUpDown ctrlSpores; | |||
private System.Windows.Forms.TrackBar ctrlInterval; | |||
private System.Windows.Forms.TrackBar ctrlDensity; | |||
private System.Windows.Forms.Label lblSpores; | |||
private System.Windows.Forms.Label lblGridSize; | |||
private System.Windows.Forms.GroupBox grpGridSize; | |||
private System.Windows.Forms.GroupBox grpSpores; | |||
private System.Windows.Forms.GroupBox grpDensity; | |||
private System.Windows.Forms.Label lblDensity; | |||
private System.Windows.Forms.GroupBox grpInterval; | |||
private System.Windows.Forms.Label lblInterval; | |||
private System.Windows.Forms.TableLayoutPanel panelMain; | |||
private System.Windows.Forms.Label lblDensityValue; | |||
private System.Windows.Forms.Label lblIntervalValue; | |||
private System.Windows.Forms.FlowLayoutPanel panelActions; | |||
private System.Windows.Forms.Button btnOK; | |||
private System.Windows.Forms.Button btnCancel; | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
using Microsoft.Win32; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel; | |||
using System.Data; | |||
using System.Drawing; | |||
using System.Text; | |||
using System.Windows.Forms; | |||
namespace GameOfLife | |||
{ | |||
public partial class SettingsForm : Form | |||
{ | |||
private void LoadSettings() { | |||
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\TheoryOfNekomata\\WindowsScreensavers\\GameOfLife"); | |||
object retrievedGridSize = 3; | |||
object retrievedSpores = 0; | |||
object retrievedDensity = 50; | |||
object retrievedInterval = 250; | |||
if (key != null) | |||
{ | |||
retrievedGridSize = key.GetValue("GridSizeIndex", 3); | |||
retrievedSpores = key.GetValue("Spores", 0); | |||
retrievedDensity = key.GetValue("DensityPercentage", 50); | |||
retrievedInterval = key.GetValue("IntervalMs", 250); | |||
} | |||
ctrlGridSize.SelectedIndex = (int) retrievedGridSize; | |||
ctrlSpores.Value = decimal.Parse(retrievedSpores.ToString()); | |||
ctrlDensity.Value = (int)retrievedDensity; | |||
lblDensityValue.Text = string.Format("Current Value: {0}%", ctrlDensity.Value); | |||
ctrlInterval.Value = (int)retrievedInterval; | |||
lblIntervalValue.Text = string.Format("Current Value: {0}ms", ctrlInterval.Value); | |||
} | |||
private void SaveSettings() { | |||
RegistryKey key = Registry.CurrentUser.CreateSubKey("SOFTWARE\\TheoryOfNekomata\\WindowsScreensavers\\GameOfLife"); | |||
key.SetValue("GridSizeIndex", ctrlGridSize.SelectedIndex); | |||
key.SetValue("Spores", int.Parse(ctrlSpores.Value.ToString())); | |||
key.SetValue("DensityPercentage", ctrlDensity.Value); | |||
key.SetValue("IntervalMs", ctrlInterval.Value); | |||
} | |||
public SettingsForm() | |||
{ | |||
InitializeComponent(); | |||
LoadSettings(); | |||
} | |||
private void ctrlDensity_Scroll(object sender, EventArgs e) | |||
{ | |||
lblDensityValue.Text = string.Format("Current Value: {0}%", (sender as TrackBar).Value); | |||
} | |||
private void ctrlInterval_Scroll(object sender, EventArgs e) | |||
{ | |||
lblIntervalValue.Text = string.Format("Current Value: {0}ms", (sender as TrackBar).Value); | |||
} | |||
private void btnOK_Click(object sender, EventArgs e) | |||
{ | |||
SaveSettings(); | |||
Close(); | |||
} | |||
private void btnCancel_Click(object sender, EventArgs e) | |||
{ | |||
Close(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
<root> | |||
<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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
<resheader name="writer"> | |||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
</root> |