Square in Python GDI (with PatBLT)

Viewed 257

Hey there!

How do I create squares in Python GDI? (with PatBLT)

So I am having some fun with pywin32.
I am trying to make a sqaure to make some fun GDI effects
Heres what I have tried so far:

from win32gui import *
from win32api import *
from win32ui import *
from win32con import *


desk = GetDC(0)
x = 100
y = 100
x_2 = 100
y_2 = 100


for i in range(5):
    PatBlt(desk, x, y, x_2, y_2, PATINVERT)
    x += 10
    y += 10
    x_2 -= 10
    y_2 -= 10

and instead of something like this:

0 0 0 0 0
0 X X X 0
0 X 0 X 0
0 X X X 0
0 0 0 0 0

I am getting something like this:

0 0 0 0 0
0 X X X X
0 X 0 0 0
0 X 0 0 0
0 X 0 0 0

And I should be getting the expected results... but I am not. Does anyone know why?

1 Answers

According to [MS.Docs]: PatBlt function (wingdi.h), the rectangle is specified in (x, y, w, h) format, meaning the last 2 values are not the lower right corner coordinates, but width and height.

As a consequence, if you translate the x of the upper left corner, by n pixels and w by -n, the lower right x will remain unmodified. To have the 2 xes symmetrical in relation with the center ('s x), you should subtract twice the value:

  • Initial:

    • upper_left_x0 = i
    • lower_right_x0 = i + w0
  • Move both n towards center:

    • upper_left_x1 = i + n
    • lower_right_x1 = i + w0 - n

So:

w1 = lower_right_x1 - upper_left_x1
   = i + w0 - n - (i + n)
   = w0 - (2 * n)

Same thing happens on the vertical axis (y and height).

code00.py:

#!/usr/bin/env python

import sys

from win32con import PATINVERT
from win32gui import GetDC, PatBlt


def draw_rects(dc, x, y, w, h, count, dx, dy):
    for i in range(count):
        PatBlt(dc, x + i * dx, y + i * dy, w - 2 * i * dx, h - 2 * i * dy, PATINVERT)


def main(*argv):
    dc = GetDC(0)
    draw_rects(dc, 100, 100, 250, 250, 13, 10, 10)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Output:

enter image description here

Related