## Introduction

In my previous article SizerPanel and CaptionPanel, I had mentioned how it annoys me that `System.Drawing.Point`

, `.Size`

, and `.Rectangle`

always force me to write the same code twice: first for the horizontal direction, and then for the vertical. And I had also mentioned about the structure `Vector`

that I wrote to replace `System.Drawing.Point`

as well as `System.Drawing.Size`

. I also extended my geometric stuff with a `Rect`

structure to replace `Rectangle`

.

The basic idea of this is to make horizontal and vertical access indexed: index 0 accesses horizontal, index 1 vertical. Now I can write geometric code for only one direction, and the other will be covered by swapping the indices 0 and 1.

So my primary goal was not to create a remake of StickyWindows, but to test, proof, and improve the power of my geometric approach. I took StickyWindows as the topic because I liked the idea, and also the implementation-challenge, especially the geometric part is not that trivial (in the original, the pure geometric computing-code took about 250 lines). It's an excellent "sparring-partner" to become fit in geometric computations, and to try out my "weapons".

## What sticky/snap windows do

They make forms perform a kind of "magnetic behavior": when you resize or move a form, and it gets close enough to another form, the near edge snaps to the edge of the other. That really makes it easier to arrange multiple forms on screen in a clear manner.

## Implementation challenges

### Subclass the Form

You can't use the `Resize`

or `SizeChanged`

event to perform form-snapping, because that implies changing the size within the `SizeChanged`

event itself. My first trials were in that direction, and they ended up in some real puzzling behavior. Nor will you get `MouseMove`

events, because a `Form`

is just resized, when especially the *non*-client-area is hit, and there is no `MouseMove`

available. So you must access the required data before it appears on the .NET-managed level - in other words: you must subclass the `Form`

. To achieve this, .NET provides two ways: the simpler one is to override the `WndProc`

Sub in each `Form`

you want to behave as a `SnapWindow`

. The second way is to instantiate a `NativeWindow`

, assign the target form's handle, and override the `NativeWindow`

's `WndProc()`

. The `WndProc()`

will handle all the window messages to the target form. And I still believe as in my previous article, that this is the more flexible way, because you don't need to modify each form's user code, but can simply register a `Form`

as a `SnapWindow`

, from the outside.

Now, take a look at the subclassing code:

Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_NCLBUTTONDOWN As Integer = 161
Const WM_MOVING As Integer = &H216
Const WM_SIZING As Integer = &H214
Select Case m.Msg
Case WM_NCLBUTTONDOWN
Dim snapRects As New List(Of Rect)
_VForm = VirtualForm.TryCreate(_Form, m.WParam.ToInt32, snapRects)
If _VForm.Null Then Exit Select
Case WM_MOVING, WM_SIZING
Marshal.StructureToPtr(_VForm.GetSnapFormRect, m.LParam, False)
End Select
MyBase.WndProc(m)
End Sub

As it often happens: It's easy when you know how... - in this case, we need to know how to handle the members of the window message:

`m.Msg`

indicates the type of event to perform: `WM_NCLBUTTONDOWN`

- **W**indow**M**essage about a **N**on-**C**lient-area-**L**eft-**ButtonDown** - indicates the beginning of a `Form`

move or resize. `WM_MOVING`

, and `WM_SIZING`

are self-explanatory, aren't they?

When the form-bounds start to change (`WM_NCLBUTTONDOWN`

), I initialize an instance of my `VirtualForm`

class, passing three things to it: the `Form`

, the `snapRects`

(a list of `Rectangle`

s which can be snapped), and the window message's `.WParam`

- uh?

`m.WParam`

- this is more tricky than `m.Msg`

. In general, the `WParam`

can mean everything. But in combination with the `WM_NCLBUTTONDOWN`

message, it passes one of the following `HT`

(Hit-Test) constants: `HTCAPTION`

, `HTLEFT`

, `HTRIGHT`

, `HTTOP`

, `HTTOPLEFT`

, `HTTOPRIGHT`

, `HTBOTTOM`

, `HTBOTTOMLEFT`

, `HTBOTTOMRIGHT`

(and some other, which are out of interest - `TryCreate()`

rejects them, if they are there). Now, the `VirtualForm`

knows exactly what kind of bounds-changing is requested. (You will already suspect: `VirtualForm`

is designed to compute snapping form-bounds).

Well, and the next time we meet our `VirtualForm`

is when a moving or a sizing occurs - and the code-comment already mentions this: the computing result is written to the `LParam`

pointer - *and all of the form-bounds-change-task is done!* You see:

`m.LParam`

is tricky: combined with a move/size message, it *is* a pointer which points to the `RECT`

structure which defines the form-bounds after the change. And, changing the `RECT`

structure changes the bounds.

At this point, unmanaged code is directly accessed - since `LParam`

is an `IntPtr`

, you cannot simply assign a `Rectangle`

to it. You must copy the `Rect`

structure byte wise to the place in memory where the pointer points to. This does `Marshal.StructureToPtr()`

for us. And we hope that the data structure the WinAPI expects at that place in memory is compatible with the structure you submitted. Believe it or not - my `Rect`

structure *is* compatible .

Note that the WinAPI `RECT`

structure is different to the `System.Drawing.Rectangle`

structure. `Drawing.Rectangle`

defines a rectangle by a location-point and a size, while the WinAPI `RECT`

defines the top-left point (equals location) and the *bottom-right point* (not equal to `Size`

). I, for instance, found it more useful to see those things the "API-way", and that's why my `Rect`

structure fits better to WinAPI than `Drawing.Rectangle`

does.

#### From where did I get to know about the subclassing stuff?

(To be honest, I picked it up from the internet.) A more systematic method to find the info would be to open the Help-Index (offline-MSDN), set the filter to "Platform SDK", and type `"WM_MOVING"`

, `"WM_SIZING"`

or `"WM_NCLBUTTONDOWN"`

in the search-textbox. This brings up informative articles about these constants, and how you can work with them.

Unfortunately, the values of the constants aren't mentioned anywhere. You can download the VS2008 Platform SDK. This will install in your Program Files, and you will find a '*C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\WinUser.h*' on your system, where (among other things) all constants of the *user32.dll* are defined.

Unfortunately, Help for the "Platform SDK" isn't available for Express editions (not sure about this, though).

## Vector and Rect

A Vector is a Size and a Point in one. It provides `X`

, `Y`

and usual features to perform simple 2D-geometric math. I made a bunch of `CType`

operators to make it as flexible and compatible as possible. Its special feature is that you can access `X`

and `Y`

by using an `Integer`

index in order to avoid writing each piece of geometric code in two variants.

`Rect`

simply is two `Vector`

s. As I mentioned before, it doesn't define the described rectangle as a composition of a Point and a Size, but defines the top-left Point and the bottom-right one. I call them `.Near`

and `.Far`

, as a homage to the `System.Text.StringAlignment`

enumeration, which is the only item I know in the Framework which also works in both dimensions (you can align a text-drawing horizontally by setting `StringFormat.Alignment.Near/.Center/.Far`

, and align it vertically by setting `StringFormat.LineAlignment.Near/.Center/.Far`

). In following sections, I will use the terms Near or Far to distinguish between a top or left entity from a bottom or right one. And, of course, `Near`

and `Far`

are accessible by index too.

## VirtualForm

It only gets data once, in the constructor: `Rects`

and `Vectors`

. When new form-bounds are requested, it first computes the normal form-bounds, only using the globally accessible `Control.MousePosition`

as additional data. In the second step, all "snap-candidate-rectangles" are compared with the computed normal-form-bounds, and the edge with the minimum distance gets snapped. This is done with the horizontal edges as well as with the vertical ones.

VirtualForm must compute the `NormalFormRect`

without dependence to the real form, because the real bounds are different when another form's edge is snapped.

The `NormalFormRect`

must be known to perform the "snapping off", when the distance between the `NormalFormRect`

and a snapped edge exceeds the "magnetic distance".

So first, we have to understand how the `NormalFormRect`

is computed, that means: comprehend how a mouse moves or resizes the form.

In fact, there is no difference between moving a form and resizing it, if you understand the process a bit more in general. You will see that it is always done by dragging edges: you can drag one edge (mouse grabs a form-edge), two edges (mouse grabs a corner), or four edges (mouse grabs the caption (=title-bar)). (To drag *three *edges is a theoretical option, but not provided by the infrastructure.)

Edge-dragging must be initialized by storing the information about which edges are affected, and also storing the "Grab Offset", which is the distances of the affected edges to the mouse-position. The VirtualForm constructor does this in two lines of code:

_SizeType = HT2SizeOption(HT)
_GrabOffs = Rect.From(Control.MousePosition).Subtract(_FormRect)

(For simplicity in code, `_GrabOffs`

stores *all* edge-distances, although only the affected ones are needed.)

Now, it can recompute the NormalFormBounds, whenever requested, since the drag-principle is the simple: *always keep the offset constant*. But recomputing isn't quite that simple, because I'm not allowed to change all edges, and must distinguish between the edges according to `_SizeType`

.

To understand in depth how I achieve that distinction, let me do an egression about...

### Enumeration advanced

Enumerations are useful to store and query multiple boolean statements. With the bit operators `Or`

, `And`

, and `Xor`

, you can filter and modify all the 32 bool-statements of an (`Int32`

-)enumeration-member with one command. One of the first things the `VirtualForm`

constructer does is call `HT2SizeOption()`

to map the passed `HT`

-constant to an enumeration named `SizeOption`

.

Public Enum SizeOption As Integer
Top = 1
Right = 2
Bottom = 4
Left = 8
End Enum

For brevity in code, I added the mainly used bit-combinations too so that the complete definition comes up as:

Public Enum SizeOption As Integer
Top = 1
Right = 2
Bottom = 4
Left = 8
TopLeft = Top Or Left
TopRight = Top Or Right
BottomLeft = Bottom Or Left
BottomRight = Bottom Or Right
Caption = Top Or Left Or Bottom Or Right
End Enum

No rocket science, is it? And it defines clearly the nine options to drag a form.

Now you can check out whether a given (multiple) bool-statement (represented by an enumeration value) has one or more bits in common with a given other one:

(_SizeType And SizeOption.Top) = SizeOption.Top

will match, if `_SizeType`

is one of the following: `Top`

, `TopLeft`

, `TopRight`

, `Caption`

.

Another way to query is:

(_SizeType And SizeOption.TopLeft) <> 0

This will match, if *any* of the `_SizeType`

bits match any of the `TopLeft`

bits. In particular: `Top`

, `Left`

, `TopLeft`

, `TopRight`

, `BottomLeft`

, `Caption`

.

If you query against a 1-bit-statement, the code for comparison to 0 is shorter than the first variant:

(_SizeType And SizeOption.Top) = SizeOption.Top

has the same results as:

(_SizeType And SizeOption.Top) = 0

### Back to rectangle-computation

Indexable structures also imply that I can iterate them. In the case of `Rect`

, I can iterate in two different ways: from near to far as well as from horizontal to vertical. I can nest in two ways and end up with a *two-dimensional iteration*.

For far = 0 To 1
For vertical = 0 To 1
Dim edge As Integer = rct(far, vertical)
Next
Next

This loops the four edges in the following order: `Left`

, `Top`

, `Right`

, `Bottom`

. And now, I build four *"enumeration-queries"*, which can be iterated in the same way: I build a *two-dimensional* `Array`

of `Enum`

s:

Private Shared _SizeOptions As SizeOption(,) = New SizeOption(,) { _
{SizeOption.Left, SizeOption.Top}, _
{SizeOption.Right, SizeOption.Bottom}}

Now I can iterate `_SizeOptions`

, `_FormRect`

-edges, and `_GrabOffset`

s within a 2D-loop, select the affected edges, and assign values, to make the distances to the mouse position equal to the corresponding offset (principle of dragging).

Private Sub ComputeFormRect()
Dim ptMouse = Vector.From(Control.MousePosition)
For far = 0 To 1
For vertical = 0 To 1
If 0 <> (_SizeType And _SizeOptions(far, vertical)) Then
_FormRect(far, vertical) = ptMouse(vertical) - _GrabOffs(far, vertical)
End If
Next
Next
End Sub

### Computing the SnapRect

The whole story:

Public Function GetSnapFormRect() As Rect
ComputeFormRect()
Dim result = _FormRect
Dim snapSize = Vector.From(SnapWindow.SnapSize)
Dim inflated = _FormRect.Add(-snapSize, snapSize)
For vertical = 0 To 1
Dim horizontal = vertical Xor 1
Dim minDist = Integer.MaxValue
For far As Integer = 0 To 1
If 0 = (_SizeType And _SizeOptions(far, vertical)) Then Continue For
For Each rct2 In _SnapRects.Where( _
Function(r2) Intersect1D(r2, inflated, horizontal))
For far2 As Integer = 0 To 1
Dim distance = _FormRect(far, vertical) - rct2(far2, vertical)
If distance.Abs() < minDist.Abs() Then minDist = distance
Next
Next
Next
If minDist.Abs() > SnapWindow.SnapSize Then Continue For
For far = 0 To 1
If 0 <> (_SizeType And _SizeOptions(far, vertical)) Then _
result(far, vertical) -= minDist
Next
Next
If _SizeType <> SizeOption.Caption Then
result.Near = result.Near.Intersect(_NearClip.Far).Union(_NearClip.Near)
End If
Return result
End Function

Now we will examine it step by step:

ComputeFormRect()
Dim result = _FormRect
Dim snapSize = Vector.From(SnapWindow.SnapSize)
Dim inflated = _FormRect.Add(-snapSize, snapSize)

is not that complicated: compute the normal `_FormRect`

(a class member) and set it as the default return value. Then, create `inflated`

, as `_FormRect`

, inflated by the magnetic distance.

Then, enter the two-dimensional rectangle-loop:

For vertical = 0 To 1
Dim horizontal = vertical Xor 1
Dim minDist = Integer.MaxValue
For far As Integer = 0 To 1

Note the second line: `Dim horizontal = vertical Xor 1`

. `valueToSwitch Xor 1`

- the easiest way to switch an index from 0 to 1 and reverse.

Now we come to the kernel. First, skip the computation if the `_FormRect`

edge in question isn't moveable at all (check against `_SizeType`

):

If (_SizeType And _SizeOptions(far, vertical)) = 0 Then Continue For

If `_SizeType`

matches with the `(far, vertical)`

addressed `_SizeOption`

, we loop `_SnapRect`

s in order to search the minimum-distance-edge to the `(far, vertical)`

addressed `_FormRect`

edge:

For Each rct2 In _SnapRects.Where(Function(r2) Intersect1D(r2, inflated, horizontal))
For far2 As Integer = 0 To 1
Dim distance = _FormRect(far, vertical) - rct2(far2, vertical)
If distance.Abs() < minDist.Abs() Then minDist = distance
Next
Next

Again, there is a filter: `SnapRects.Where(Function(r2) Intersect1D(r2, inflated, horizontal))`

only takes those `Rect`

s to examine, which *intersect in the other direction* with the `inflated`

FormRect (mentioned before). Because, it doesn't make sense to snap an edge 15 pixels to the left, when it is located about 500 pixels below . **Note**: Here, I get an one-dimensional understanding of intersection: a rectangle may intersect in the horizontal direction, but not vertical (e.g., words in a line intersect horizontal, but not vertical ). See the intersection computation code:

Private Function Intersect1D(ByVal rct1 As Rect, _
ByVal rct2 As Rect, ByVal vertical As Integer) As Boolean
Return rct1.Far(vertical) >= rct2.Near(vertical) _
AndAlso rct2.Far(vertical) >= rct1.Near(vertical)
End Function

OK, now we have our `minDist`

, and can apply it to our return-result (if `minDist`

is small enough):

If minDist.Abs() > SnapWindow.SnapSize Then Continue For
For far = 0 To 1
If 0 <> (_SizeType And _SizeOptions(far, vertical)) Then _
result(far, vertical) -= minDist
Next

followed by the (I hope so) last point of surprise:

If _SizeType <> SizeOption.Caption Then
result.Near = result.Near.Intersect(_NearClip.Far).Union(_NearClip.Near)
End If

Eh? Why does WinAPI only care for far-edge-restriction, but not restrict the near-edges? What does it mean at all: *"caring for edge-restriction"*? To illustrate (and for your pleasure), I created a little demo, to show what happens if you comment out that final clip:

Got it? Violating the `MinimumSize`

from above is prevented by setting the form's `Height`

back to the minimum amount. But it was the *Top* which changed! - and so the form *moves*, although you're actually *sizing *the top edge.

## Some points of interest left open

### Vector.Intersect() and Vector.Union()

Let's begin with the above mentioned clip:

result.Near = result.Near.Intersect(_NearClip.Far).Union(_NearClip.Near)

`Intersect()`

and `Union()`

are not applied to `Rect`

s, but to `Vector`

s! How can a `Vector`

intersect with another - it has no size! And that's the point. Since a `Vector`

represents a point as well as a size, it *is* a size. And when I intersect two `Vector`

s, I take them as two `Rect`

s with `.Near-Vector= (0,0)`

. In another view: `Vector1.Intersect(Vector2)`

returns the minimum amount of both in each direction. And, that's exactly the one (the ceiling-) part of clipping a `Vector`

inside a `Rect`

. The other (floor-) part of clipping is a `Union`

with the `Rect`

's `.Near-Vector`

, which means the *maximum* amount in each direction. In summary: you clip the `Vector v`

within the `Rect rct`

by `Intersect`

ing the `union(v, rct.Near)`

with `rct.Far`

.

### Rects way of intersection

`System.Drawing.Rectangle.Intersect(other As Rectangle)`

returns `Rectangle.Empty`

, if the `Rectangle`

s do not intersect. Instead of that, `Rect.Intersect()`

is computed as follows:

Public Function Intersect(ByVal other As Rect) As Rect
For i = 0 To 1
Intersect.Near(i) = Near(i).Max(other.Near(i))
Intersect.Far(i) = Far(i).Min(other.Far(i))
Next
End Function
Public ReadOnly Property IsImaginary() As Boolean
Get
If Far.X - Near.X < 0 Then Return True
Return Far.Y - Near.Y < 0
End Get
End Property

The advantage is that an imaginary `Rect`

still delivers a valuable information: namely, the *distance* between both `Rect`

s. Got it? The *distance between two rectangles* is understood *as negative intersection*.

## The idea of "homogen structure"

Structures whose fields are only of one data type, I address them as *"homogen"*. In my opinion, we can apply some principles to them, e.g., the indexablity I already explained.

In general, you can try to transfer features from the unit-types to the whole structure.

### Inverting operator

Since `Integer`

is invertable, I want `Vector`

and `Rect`

also to support it:

Public Shared Operator -(ByVal v1 As Vector) As Vector
Return New Vector(-v1.X, -v1.Y)
End Operator
Public Shared Operator -(ByVal r As Rect) As Rect
Return New Rect(-r.Near, -r.Far)
End Operator

### Data-stretching

This means several operations may be applicable, although there may be passed too few data to explicitly assign to each member.

For instance, the operation `.From()`

. I take it as a public shared constructor, a bit more comfortable than the good old `New()`

:

Dim v = Vector.From(x As Integer, y As Integer)

That is the basic one. But also unambiguous is to do this:

Dim v = Vector.From(amount As Integer)

It only can mean to assign `amount`

to `v.X`

as well as to `v.Y`

.

See a data stretching equality-comparison here:

Dim b = v.EachEquals(amount As Integer)

And this is convenient: Suddenly, I have a sort of "inferred constants" (inferred by `Integer`

). That means, `Vector.From(0)`

is a perfect substitute of `Point.Empty`

. And I'm free to define other "special-points", e.g., `Vector.From(Integer.MaxValue)`

or `Vector.From(Integer.MinValue)`

, to indicate (by convention) an invalid location without using the `Nullable(Of T)`

structure.

Checking against each special-point is covered by `Vector.EachEquals()`

, e.g., `Vector.EachEquals(0)`

substitutes `Point.IsEmpty`

, and `Vector.EachEquals(Integer.MinValue)`

is a new feature with no equivalent in `Point`

or `Size`

, maybe at best the *really *ugly:

Dim pt = New Point(Integer.MinValue, Integer.MinValue)
Dim b = pt = New Point(Integer.MinValue, Integer.MinValue)

#### But go on stretching data

Theoretically, I could overload the `+`

operator as follows:

Public Shared Operator +(ByVal v As Vector, ByVal amount As Integer) As Vector
Return New Vector(v.X + amount, v.Y + amount)
End Operator

to puzzle the audience with expressions like:

Dim v = Vector.From(4, 5) + 9

But that's too inconsiderate for even me. Instead, see my `Add()`

overloads, the second one does data stretching:

Public Function Add(ByVal x As Integer, ByVal y As Integer) As Vector
Return New Vector(Me.X + x, Me.Y + y)
End Function
Public Function Add(ByVal amount As Integer) As Vector
Return New Vector(X + amount, Y + amount)
End Function
Public Function Add(ByVal v As Vector) As Vector
Return New Vector(X + v.X, Y + v.Y)
End Function

This performs Offset, Inflate/Deflate, and is compatible to `Point`

and `Size`

, because of some widening `CType()`

operators. (`.Subtract()`

works in the same manner.)

#### Datastretching with Rect

The benefits of `.From()`

and `.EachEquals()`

, of course, work as well, and in the case of `.From()`

, I support one more stretch option:

Public Shared Function From(ByVal eachMember As Integer) As Rect
Return Rect.From(Vector.From(eachMember))
End Function
Public Shared Function From(ByVal eachMember As Vector) As Rect
Return New Rect(eachMember, eachMember)
End Function

Also `.Add()`

becomes more interesting:

Public Function Add(ByVal toEach As Integer) As Rect
Return Add(Vector.From(toEach))
End Function
Public Function Add(ByVal toEach As Vector) As Rect
Return New Rect(Near + toEach, Far + toEach)
End Function
Public Function Add(ByVal v1 As Vector, ByVal v2 As Vector) As Rect
Return New Rect(Near + v1, Far + v2)
End Function
Public Function Add(ByVal r As Rect) As Rect
Return New Rect(Near + r.Near, Far + r.Far)
End Function

(`.Subtract()`

ditto.)

The above works behind the scenes, when VirtualForm gets the four-edges-offset within one line of code:

_GrabOffs = Rect.From(Control.MousePosition).Subtract(_FormRect)

or when I inflate `_FormRect`

with `snapSize`

:

Dim inflated = _FormRect.Add(-snapSize, snapSize)

### LINQ

Public Function GetEnumerator() As IEnumerator(Of Integer) Implements _
IEnumerable(Of Integer).GetEnumerator
Return DirectCast(New Integer() {X, Y}, IEnumerable(Of Integer)) _
.GetEnumerator
End Function
Private Function GetEnumerator1() As IEnumerator Implements _
IEnumerable.GetEnumerator
Return DirectCast(New Integer() {X, Y}, IEnumerable(Of Integer)) _
.GetEnumerator
End Function
Public Function GetEnumerator() As IEnumerator(Of Vector) Implements _
IEnumerable(Of Vector).GetEnumerator
Return DirectCast(New Vector() {Near, Far}, IEnumerable(Of Vector)) _
.GetEnumerator
End Function
Private Function GetEnumerator1() As IEnumerator Implements _
IEnumerable.GetEnumerator
Return DirectCast(New Vector() {Near, Far}, IEnumerable(Of Vector)) _
.GetEnumerator
End Function

I don't know whether that is useful. I, for instance, don't use it. But it looks interesting to me, and it was easy to implement.

## Replacing public shared functions with extension functions

It's a sort of off-topic, but I'd like to mention one more principle, to make you understand all the shown code:

When it comes to extension functions, in many cases, there is no more need for `Public Shared`

functions, which forces you to type full qualifiers to call them. Compare these clip-variants:

Public Function ClipIn(ByVal pt As Point, _
ByVal rct As Rectangle) As Point
Return New Point( _
Math.Max(Math.Min(pt.X, rct.Right), rct.X), _
Math.Max(Math.Min(pt.Y, rct.Bottom), rct.Y))
End Function
Public Function ClipIn2(ByVal pt As Point, _
ByVal rct As Rectangle) As Point
Return New Point(pt.X.Max(rct.X).Min(rct.Right), _
pt.Y.Max(rct.Y).Min(rct.Bottom))
End Function

In the second variant, `Min()/Max()`

appears as an extension function, which is shorter, easier to type (help from intellisense), and which resolves the nasty nesting of functions to an easier to handle concatenation. The same concept I applied to `Math.Abs()`

(maybe you have realized that already, seeing my previous code-samples).

Even tests to `Nothing`

, I'd prefer as an extension:

<Extension()> _
Public Function Null(Of T As Class)(ByVal Subj As T) As Boolean
Return Subj Is Nothing
End Function
<Extension()> _
Public Function NotNull(Of T As Class)(ByVal Subj As T) As Boolean
Return Subj IsNot Nothing
End Function

## More ideas - the third dimension

I don't really know much about DirectX, but I wonder how DirectX developers manage not to lose their minds. Aren't they forced to type each bit of code thrice? Or, worse, `2.Pow(2)`

times? I don't know the exact increase in complexity depending on the dimensions, but a square on a chess-board has 8 neighbors, while a packed cube touches 26 others!

I wonder what a *"StickyCubes"* application looks like?