Skip to content

Commit

Permalink
Port Checker Petzold sample from WInterop
Browse files Browse the repository at this point in the history
  • Loading branch information
JeremyKuhne committed Feb 4, 2024
1 parent 26657f4 commit 4ff4549
Show file tree
Hide file tree
Showing 12 changed files with 1,604 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/samples/Petzold/5th/Checker1/Checker.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\thirtytwo\thirtytwo.csproj" />
</ItemGroup>
</Project>
74 changes: 74 additions & 0 deletions src/samples/Petzold/5th/Checker1/Checker1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using Windows;
using Windows.Win32;
using Windows.Win32.Foundation;

namespace Checker;

public class Checker1 : MainWindow
{
private const int DIVISIONS = 5;
private readonly bool[,] _fState = new bool[DIVISIONS, DIVISIONS];
private int _cxBlock, _cyBlock;

public Checker1(string title) : base(title)
{
}

protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case MessageType.Size:
_cxBlock = lParam.LOWORD / DIVISIONS;
_cyBlock = lParam.HIWORD / DIVISIONS;
return (LRESULT)0;
case MessageType.LeftButtonDown:
int x = lParam.LOWORD / _cxBlock;
int y = lParam.HIWORD / _cyBlock;
if (x < DIVISIONS && y < DIVISIONS)
{
_fState[x, y] ^= true;
Rectangle rect = Rectangle.FromLTRB
(
x * _cxBlock,
y * _cyBlock,
(x + 1) * _cxBlock,
(y + 1) * _cyBlock
);
window.InvalidateRectangle(rect, false);
}
else
{
Interop.MessageBeep(0);
}

return (LRESULT)0;
case MessageType.Paint:
using (DeviceContext dc = window.BeginPaint())
{
for (x = 0; x < DIVISIONS; x++)
for (y = 0; y < DIVISIONS; y++)
{
dc.Rectangle(new Rectangle(
x * _cxBlock, y * _cyBlock, (x + 1) * _cxBlock, (y + 1) * _cyBlock));

if (_fState[x, y])
{
dc.MoveTo(new Point(x * _cxBlock, y * _cyBlock));
dc.LineTo(new Point((x + 1) * _cxBlock, (y + 1) * _cyBlock));
dc.MoveTo(new Point(x * _cxBlock, (y + 1) * _cyBlock));
dc.LineTo(new Point((x + 1) * _cxBlock, y * _cyBlock));
}
}
}

return (LRESULT)0;
}

return base.WindowProcedure(window, message, wParam, lParam);
}
}
120 changes: 120 additions & 0 deletions src/samples/Petzold/5th/Checker1/Checker2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using Windows;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.SystemServices;
using Windows.Win32.UI.Input.KeyboardAndMouse;

namespace Checker;

internal class Checker2 : MainWindow
{
private const int DIVISIONS = 5;
private readonly bool[,] _state = new bool[DIVISIONS, DIVISIONS];
private int _cxBlock, _cyBlock;

public Checker2(string title) : base(title)
{
}

protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case MessageType.Size:
_cxBlock = lParam.LOWORD / DIVISIONS;
_cyBlock = lParam.HIWORD / DIVISIONS;
return (LRESULT)0;
case MessageType.SetFocus:
_ = Interop.ShowCursor(true);
return (LRESULT)0;
case MessageType.KillFocus:
_ = Interop.ShowCursor(false);
return (LRESULT)0;
case MessageType.KeyDown:
Interop.GetCursorPos(out Point point);
window.ScreenToClient(ref point);
int x = Math.Max(0, Math.Min(DIVISIONS - 1, point.X / _cxBlock));
int y = Math.Max(0, Math.Min(DIVISIONS - 1, point.Y / _cyBlock));
switch ((VIRTUAL_KEY)(ushort)(uint)wParam)
{
case VIRTUAL_KEY.VK_UP:
y--;
break;
case VIRTUAL_KEY.VK_DOWN:
y++;
break;
case VIRTUAL_KEY.VK_LEFT:
x--;
break;
case VIRTUAL_KEY.VK_RIGHT:
x++;
break;
case VIRTUAL_KEY.VK_HOME:
x = y = 0;
break;
case VIRTUAL_KEY.VK_END:
x = y = DIVISIONS - 1;
break;
case VIRTUAL_KEY.VK_RETURN:
case VIRTUAL_KEY.VK_SPACE:
window.SendMessage(
MessageType.LeftButtonDown,
(WPARAM)(uint)MODIFIERKEYS_FLAGS.MK_LBUTTON,
LPARAM.MAKELPARAM(y * _cyBlock, x * _cxBlock));
break;
}
x = (x + DIVISIONS) % DIVISIONS;
y = (y + DIVISIONS) % DIVISIONS;

point = new Point(x * _cxBlock + _cxBlock / 2, y * _cyBlock + _cyBlock / 2);
window.ClientToScreen(ref point);
Interop.SetCursorPos(point.X, point.Y);
return (LRESULT)0;
case MessageType.LeftButtonDown:
x = lParam.LOWORD / _cxBlock;
y = lParam.HIWORD / _cyBlock;
if (x < DIVISIONS && y < DIVISIONS)
{
_state[x, y] ^= true;
Rectangle rect = Rectangle.FromLTRB
(
x * _cxBlock,
y * _cyBlock,
(x + 1) * _cxBlock,
(y + 1) * _cyBlock
);
window.InvalidateRectangle(rect, false);
}
else
{
Interop.MessageBeep(0);
}

return (LRESULT)0;
case MessageType.Paint:
using (DeviceContext dc = window.BeginPaint())
{
for (x = 0; x < DIVISIONS; x++)
for (y = 0; y < DIVISIONS; y++)
{
dc.Rectangle(new Rectangle(x * _cxBlock, y * _cyBlock, (x + 1) * _cxBlock, (y + 1) * _cyBlock));
if (_state[x, y])
{
dc.MoveTo(new Point(x * _cxBlock, y * _cyBlock));
dc.LineTo(new Point((x + 1) * _cxBlock, (y + 1) * _cyBlock));
dc.MoveTo(new Point(x * _cxBlock, (y + 1) * _cyBlock));
dc.LineTo(new Point((x + 1) * _cxBlock, y * _cyBlock));
}
}
}

return (LRESULT)0;
}

return base.WindowProcedure(window, message, wParam, lParam);
}
}
89 changes: 89 additions & 0 deletions src/samples/Petzold/5th/Checker1/Checker3.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using Windows;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;

namespace Checker;

internal class Checker3 : MainWindow
{
private const int DIVISIONS = 5;
private readonly HWND[,] _hwndChild = new HWND[DIVISIONS, DIVISIONS];
private int _cxBlock, _cyBlock;
private readonly Checker3Child _childClass = (Checker3Child)(new Checker3Child().Register());

public Checker3(string title) : base(title)
{
}

protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case MessageType.Create:
for (int x = 0; x < DIVISIONS; x++)
for (int y = 0; y < DIVISIONS; y++)
_hwndChild[x, y] = _childClass.CreateWindow(
style: WindowStyles.ChildWindow | WindowStyles.Visible,
parentWindow: window);
return (LRESULT)0;
case MessageType.Size:
_cxBlock = lParam.LOWORD / DIVISIONS;
_cyBlock = lParam.HIWORD / DIVISIONS;
for (int x = 0; x < DIVISIONS; x++)
for (int y = 0; y < DIVISIONS; y++)
_hwndChild[x, y].MoveWindow(
new Rectangle(x * _cxBlock, y * _cyBlock, _cxBlock, _cyBlock),
repaint: true);
return (LRESULT)0;
case MessageType.LeftButtonDown:
Interop.MessageBeep(MESSAGEBOX_STYLE.MB_OK);
return (LRESULT)0;
}

return base.WindowProcedure(window, message, wParam, lParam);
}
}

internal unsafe class Checker3Child : WindowClass
{
public Checker3Child() : base(windowExtraBytes: sizeof(void*))
{
}

protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case MessageType.Create:
window.SetWindowLong(0, 0); // on/off flag
return (LRESULT)0;
case MessageType.LeftButtonDown:
window.SetWindowLong(0, 1 ^ (int)window.GetWindowLong(0));
window.Invalidate(false);
return (LRESULT)0;
case MessageType.Paint:
using (DeviceContext dc = window.BeginPaint())
{
Rectangle rect = window.GetClientRectangle();
dc.Rectangle(rect);

if (window.GetWindowLong(0) != 0)
{
dc.MoveTo(default);
dc.LineTo(new Point(rect.Right, rect.Bottom));
dc.MoveTo(new Point(0, rect.Bottom));
dc.LineTo(new Point(rect.Right, 0));
}
}

return (LRESULT)0;
}

return base.WindowProcedure(window, message, wParam, lParam);
}
}
Loading

0 comments on commit 4ff4549

Please sign in to comment.