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> | <PropertyGroup> | ||||
<OutputType>WinExe</OutputType> | <OutputType>WinExe</OutputType> | ||||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||||
<TargetFramework>net5.0-windows</TargetFramework> | |||||
<UseWindowsForms>true</UseWindowsForms> | <UseWindowsForms>true</UseWindowsForms> | ||||
<StartupObject>GameOfLife.Program</StartupObject> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||||
<PlatformTarget>x64</PlatformTarget> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="unvell.D2DLib-x64" Version="1.3.1" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -44,7 +44,6 @@ namespace GameOfLife | |||||
this.Name = "MainForm"; | this.Name = "MainForm"; | ||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; | ||||
this.Load += new System.EventHandler(this.MainForm_Load); | 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.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress); | ||||
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseClick); | this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseClick); | ||||
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseMove); | 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.Drawing; | ||||
using System.Runtime.InteropServices; | |||||
using System.Windows.Forms; | using System.Windows.Forms; | ||||
using unvell.D2DLib; | |||||
using unvell.D2DLib.WinForm; | |||||
namespace GameOfLife | namespace GameOfLife | ||||
{ | { | ||||
public partial class MainForm : Form | |||||
public partial class MainForm : D2DForm | |||||
{ | { | ||||
private Point mouseLocation; | private Point mouseLocation; | ||||
private bool[,] newCells; | private bool[,] newCells; | ||||
private bool[,] toggleCells; | |||||
private bool[,] oldCells; | private bool[,] oldCells; | ||||
private Random random; | private Random random; | ||||
@@ -19,28 +21,125 @@ namespace GameOfLife | |||||
private int magicCells = 0; | 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; | 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; | newCells[x, y] = random.NextDouble() <= density; | ||||
oldCells[x, y] = false; | 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) | private void MainForm_Load(object sender, EventArgs e) | ||||
{ | { | ||||
Cursor.Hide(); | Cursor.Hide(); | ||||
@@ -53,64 +152,74 @@ namespace GameOfLife | |||||
private void MainForm_MouseMove(object sender, MouseEventArgs e) | 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) | private void MainForm_MouseClick(object sender, MouseEventArgs e) | ||||
{ | { | ||||
Application.Exit(); | |||||
if (!previewMode) | |||||
{ | |||||
Application.Exit(); | |||||
} | |||||
} | } | ||||
private void MainForm_KeyPress(object sender, KeyPressEventArgs e) | 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; | int aliveNeighbors = 0; | ||||
if (cells[prevX, prevY]) { | |||||
if (oldCells[prevX, prevY]) { | |||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[x, prevY]) | |||||
if (oldCells[x, prevY]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[nextX, prevY]) | |||||
if (oldCells[nextX, prevY]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[prevX, y]) | |||||
if (oldCells[prevX, y]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[nextX, y]) | |||||
if (oldCells[nextX, y]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[prevX, nextY]) | |||||
if (oldCells[prevX, nextY]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[x, nextY]) | |||||
if (oldCells[x, nextY]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
if (cells[nextX, nextY]) | |||||
if (oldCells[nextX, nextY]) | |||||
{ | { | ||||
aliveNeighbors += 1; | aliveNeighbors += 1; | ||||
} | } | ||||
@@ -130,7 +239,7 @@ namespace GameOfLife | |||||
{ | { | ||||
for (var y = 0; y < newCells.GetLength(1); y++) | for (var y = 0; y < newCells.GetLength(1); y++) | ||||
{ | { | ||||
int neighbors = GetAliveNeighbors(oldCells, x, y); | |||||
int neighbors = GetAliveNeighbors(x, y); | |||||
bool shouldLive = false; | bool shouldLive = false; | ||||
if (oldCells[x, y] && neighbors == 2) | if (oldCells[x, y] && neighbors == 2) | ||||
{ | { | ||||
@@ -140,7 +249,6 @@ namespace GameOfLife | |||||
} | } | ||||
newCells[x, y] = shouldLive; | 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)); | int magicY = random.Next(0, newCells.GetUpperBound(1)); | ||||
newCells[magicX, magicY] = true; | 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 x = 0; x < newCells.GetLength(0); x++) | ||||
{ | { | ||||
for (var y = 0; y < newCells.GetLength(1); y++) | 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; | ||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Threading.Tasks; | |||||
using System.Windows.Forms; | using System.Windows.Forms; | ||||
namespace GameOfLife | namespace GameOfLife | ||||
@@ -35,11 +32,19 @@ namespace GameOfLife | |||||
if (firstArgument == "/c") // Configuration mode | if (firstArgument == "/c") // Configuration mode | ||||
{ | { | ||||
// TODO | |||||
Application.Run(new SettingsForm()); | |||||
} | } | ||||
else if (firstArgument == "/p") // Preview mode | 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 | else if (firstArgument == "/s") // Full-screen mode | ||||
{ | { | ||||
@@ -55,7 +60,7 @@ namespace GameOfLife | |||||
} | } | ||||
else // No arguments - treat like /c | 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> |