Skip to content

Commit 4ff4549

Browse files
committed
Port Checker Petzold sample from WInterop
1 parent 26657f4 commit 4ff4549

File tree

12 files changed

+1604
-3
lines changed

12 files changed

+1604
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project Sdk="Microsoft.NET.Sdk">
3+
<PropertyGroup>
4+
<OutputType>WinExe</OutputType>
5+
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<ProjectReference Include="..\..\..\..\thirtytwo\thirtytwo.csproj" />
9+
</ItemGroup>
10+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Drawing;
5+
using Windows;
6+
using Windows.Win32;
7+
using Windows.Win32.Foundation;
8+
9+
namespace Checker;
10+
11+
public class Checker1 : MainWindow
12+
{
13+
private const int DIVISIONS = 5;
14+
private readonly bool[,] _fState = new bool[DIVISIONS, DIVISIONS];
15+
private int _cxBlock, _cyBlock;
16+
17+
public Checker1(string title) : base(title)
18+
{
19+
}
20+
21+
protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
22+
{
23+
switch (message)
24+
{
25+
case MessageType.Size:
26+
_cxBlock = lParam.LOWORD / DIVISIONS;
27+
_cyBlock = lParam.HIWORD / DIVISIONS;
28+
return (LRESULT)0;
29+
case MessageType.LeftButtonDown:
30+
int x = lParam.LOWORD / _cxBlock;
31+
int y = lParam.HIWORD / _cyBlock;
32+
if (x < DIVISIONS && y < DIVISIONS)
33+
{
34+
_fState[x, y] ^= true;
35+
Rectangle rect = Rectangle.FromLTRB
36+
(
37+
x * _cxBlock,
38+
y * _cyBlock,
39+
(x + 1) * _cxBlock,
40+
(y + 1) * _cyBlock
41+
);
42+
window.InvalidateRectangle(rect, false);
43+
}
44+
else
45+
{
46+
Interop.MessageBeep(0);
47+
}
48+
49+
return (LRESULT)0;
50+
case MessageType.Paint:
51+
using (DeviceContext dc = window.BeginPaint())
52+
{
53+
for (x = 0; x < DIVISIONS; x++)
54+
for (y = 0; y < DIVISIONS; y++)
55+
{
56+
dc.Rectangle(new Rectangle(
57+
x * _cxBlock, y * _cyBlock, (x + 1) * _cxBlock, (y + 1) * _cyBlock));
58+
59+
if (_fState[x, y])
60+
{
61+
dc.MoveTo(new Point(x * _cxBlock, y * _cyBlock));
62+
dc.LineTo(new Point((x + 1) * _cxBlock, (y + 1) * _cyBlock));
63+
dc.MoveTo(new Point(x * _cxBlock, (y + 1) * _cyBlock));
64+
dc.LineTo(new Point((x + 1) * _cxBlock, y * _cyBlock));
65+
}
66+
}
67+
}
68+
69+
return (LRESULT)0;
70+
}
71+
72+
return base.WindowProcedure(window, message, wParam, lParam);
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Drawing;
5+
using Windows;
6+
using Windows.Win32;
7+
using Windows.Win32.Foundation;
8+
using Windows.Win32.System.SystemServices;
9+
using Windows.Win32.UI.Input.KeyboardAndMouse;
10+
11+
namespace Checker;
12+
13+
internal class Checker2 : MainWindow
14+
{
15+
private const int DIVISIONS = 5;
16+
private readonly bool[,] _state = new bool[DIVISIONS, DIVISIONS];
17+
private int _cxBlock, _cyBlock;
18+
19+
public Checker2(string title) : base(title)
20+
{
21+
}
22+
23+
protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
24+
{
25+
switch (message)
26+
{
27+
case MessageType.Size:
28+
_cxBlock = lParam.LOWORD / DIVISIONS;
29+
_cyBlock = lParam.HIWORD / DIVISIONS;
30+
return (LRESULT)0;
31+
case MessageType.SetFocus:
32+
_ = Interop.ShowCursor(true);
33+
return (LRESULT)0;
34+
case MessageType.KillFocus:
35+
_ = Interop.ShowCursor(false);
36+
return (LRESULT)0;
37+
case MessageType.KeyDown:
38+
Interop.GetCursorPos(out Point point);
39+
window.ScreenToClient(ref point);
40+
int x = Math.Max(0, Math.Min(DIVISIONS - 1, point.X / _cxBlock));
41+
int y = Math.Max(0, Math.Min(DIVISIONS - 1, point.Y / _cyBlock));
42+
switch ((VIRTUAL_KEY)(ushort)(uint)wParam)
43+
{
44+
case VIRTUAL_KEY.VK_UP:
45+
y--;
46+
break;
47+
case VIRTUAL_KEY.VK_DOWN:
48+
y++;
49+
break;
50+
case VIRTUAL_KEY.VK_LEFT:
51+
x--;
52+
break;
53+
case VIRTUAL_KEY.VK_RIGHT:
54+
x++;
55+
break;
56+
case VIRTUAL_KEY.VK_HOME:
57+
x = y = 0;
58+
break;
59+
case VIRTUAL_KEY.VK_END:
60+
x = y = DIVISIONS - 1;
61+
break;
62+
case VIRTUAL_KEY.VK_RETURN:
63+
case VIRTUAL_KEY.VK_SPACE:
64+
window.SendMessage(
65+
MessageType.LeftButtonDown,
66+
(WPARAM)(uint)MODIFIERKEYS_FLAGS.MK_LBUTTON,
67+
LPARAM.MAKELPARAM(y * _cyBlock, x * _cxBlock));
68+
break;
69+
}
70+
x = (x + DIVISIONS) % DIVISIONS;
71+
y = (y + DIVISIONS) % DIVISIONS;
72+
73+
point = new Point(x * _cxBlock + _cxBlock / 2, y * _cyBlock + _cyBlock / 2);
74+
window.ClientToScreen(ref point);
75+
Interop.SetCursorPos(point.X, point.Y);
76+
return (LRESULT)0;
77+
case MessageType.LeftButtonDown:
78+
x = lParam.LOWORD / _cxBlock;
79+
y = lParam.HIWORD / _cyBlock;
80+
if (x < DIVISIONS && y < DIVISIONS)
81+
{
82+
_state[x, y] ^= true;
83+
Rectangle rect = Rectangle.FromLTRB
84+
(
85+
x * _cxBlock,
86+
y * _cyBlock,
87+
(x + 1) * _cxBlock,
88+
(y + 1) * _cyBlock
89+
);
90+
window.InvalidateRectangle(rect, false);
91+
}
92+
else
93+
{
94+
Interop.MessageBeep(0);
95+
}
96+
97+
return (LRESULT)0;
98+
case MessageType.Paint:
99+
using (DeviceContext dc = window.BeginPaint())
100+
{
101+
for (x = 0; x < DIVISIONS; x++)
102+
for (y = 0; y < DIVISIONS; y++)
103+
{
104+
dc.Rectangle(new Rectangle(x * _cxBlock, y * _cyBlock, (x + 1) * _cxBlock, (y + 1) * _cyBlock));
105+
if (_state[x, y])
106+
{
107+
dc.MoveTo(new Point(x * _cxBlock, y * _cyBlock));
108+
dc.LineTo(new Point((x + 1) * _cxBlock, (y + 1) * _cyBlock));
109+
dc.MoveTo(new Point(x * _cxBlock, (y + 1) * _cyBlock));
110+
dc.LineTo(new Point((x + 1) * _cxBlock, y * _cyBlock));
111+
}
112+
}
113+
}
114+
115+
return (LRESULT)0;
116+
}
117+
118+
return base.WindowProcedure(window, message, wParam, lParam);
119+
}
120+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Drawing;
5+
using Windows;
6+
using Windows.Win32;
7+
using Windows.Win32.Foundation;
8+
using Windows.Win32.UI.WindowsAndMessaging;
9+
10+
namespace Checker;
11+
12+
internal class Checker3 : MainWindow
13+
{
14+
private const int DIVISIONS = 5;
15+
private readonly HWND[,] _hwndChild = new HWND[DIVISIONS, DIVISIONS];
16+
private int _cxBlock, _cyBlock;
17+
private readonly Checker3Child _childClass = (Checker3Child)(new Checker3Child().Register());
18+
19+
public Checker3(string title) : base(title)
20+
{
21+
}
22+
23+
protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
24+
{
25+
switch (message)
26+
{
27+
case MessageType.Create:
28+
for (int x = 0; x < DIVISIONS; x++)
29+
for (int y = 0; y < DIVISIONS; y++)
30+
_hwndChild[x, y] = _childClass.CreateWindow(
31+
style: WindowStyles.ChildWindow | WindowStyles.Visible,
32+
parentWindow: window);
33+
return (LRESULT)0;
34+
case MessageType.Size:
35+
_cxBlock = lParam.LOWORD / DIVISIONS;
36+
_cyBlock = lParam.HIWORD / DIVISIONS;
37+
for (int x = 0; x < DIVISIONS; x++)
38+
for (int y = 0; y < DIVISIONS; y++)
39+
_hwndChild[x, y].MoveWindow(
40+
new Rectangle(x * _cxBlock, y * _cyBlock, _cxBlock, _cyBlock),
41+
repaint: true);
42+
return (LRESULT)0;
43+
case MessageType.LeftButtonDown:
44+
Interop.MessageBeep(MESSAGEBOX_STYLE.MB_OK);
45+
return (LRESULT)0;
46+
}
47+
48+
return base.WindowProcedure(window, message, wParam, lParam);
49+
}
50+
}
51+
52+
internal unsafe class Checker3Child : WindowClass
53+
{
54+
public Checker3Child() : base(windowExtraBytes: sizeof(void*))
55+
{
56+
}
57+
58+
protected override LRESULT WindowProcedure(HWND window, MessageType message, WPARAM wParam, LPARAM lParam)
59+
{
60+
switch (message)
61+
{
62+
case MessageType.Create:
63+
window.SetWindowLong(0, 0); // on/off flag
64+
return (LRESULT)0;
65+
case MessageType.LeftButtonDown:
66+
window.SetWindowLong(0, 1 ^ (int)window.GetWindowLong(0));
67+
window.Invalidate(false);
68+
return (LRESULT)0;
69+
case MessageType.Paint:
70+
using (DeviceContext dc = window.BeginPaint())
71+
{
72+
Rectangle rect = window.GetClientRectangle();
73+
dc.Rectangle(rect);
74+
75+
if (window.GetWindowLong(0) != 0)
76+
{
77+
dc.MoveTo(default);
78+
dc.LineTo(new Point(rect.Right, rect.Bottom));
79+
dc.MoveTo(new Point(0, rect.Bottom));
80+
dc.LineTo(new Point(rect.Right, 0));
81+
}
82+
}
83+
84+
return (LRESULT)0;
85+
}
86+
87+
return base.WindowProcedure(window, message, wParam, lParam);
88+
}
89+
}

0 commit comments

Comments
 (0)