Search code examples
pythonwindowsconsolepywin32

Why does SetConsoleInfo window give incorrect parameter error?


I am trying to make a console program using the pywin32 module

My code is:

import win32con, win32console, time, random

MyCon = win32console.CreateConsoleScreenBuffer(DesiredAccess = win32con.GENERIC_READ | win32con.GENERIC_WRITE, ShareMode = 0, SecurityAttributes = None, Flags = 1)
MyCon.SetConsoleActiveScreenBuffer()
rect = win32console.PySMALL_RECTType(20, 30, 600, 600)
MyCon.SetConsoleWindowInfo(Absolute = False, ConsoleWindow = rect)

while True:
    y = str(random.randint(1,100)) + ' '
    MyCon.WriteConsoleOutputCharacter(Characters = y, WriteCoord = win32console.PyCOORDType(5,6))
    time.sleep(0.1)

This is the error i am facing when i am trying to run the program from cmd.exe The error

I am giving the parameters as said in the docs here http://timgolden.me.uk/pywin32-docs/PyConsoleScreenBuffer__SetConsoleWindowInfo_meth.html

How to fix this ?


Solution

  • According to [MS.Docs]: SetConsoleWindowInfo function - Remarks (emphasis is mine):

    The function fails if the specified window rectangle extends beyond the boundaries of the console screen buffer. This means that the Top and Left members of the lpConsoleWindow rectangle (or the calculated top and left coordinates, if bAbsolute is FALSE) cannot be less than zero. Similarly, the Bottom and Right members (or the calculated bottom and right coordinates) cannot be greater than (screen buffer height – 1) and (screen buffer width – 1), respectively. The function also fails if the Right member (or calculated right coordinate) is less than or equal to the Left member (or calculated left coordinate) or if the Bottom member (or calculated bottom coordinate) is less than or equal to the Top member (or calculated top coordinate).

    Your argument combination (relative coordinates + given rectangle) must have gone beyond screen buffer boundaries.
    Below is an example that works.

    code00.py:

    #!/usr/bin/env python
    
    import msvcrt
    import random
    import sys
    import time
    
    import win32api as wapi
    import win32con as wcon
    import win32console as wcons
    
    
    def main(*argv):
        buf = wcons.CreateConsoleScreenBuffer(DesiredAccess=wcon.GENERIC_READ | wcon.GENERIC_WRITE, ShareMode=0, SecurityAttributes=None, Flags=wcons.CONSOLE_TEXTMODE_BUFFER)
        buf.SetConsoleActiveScreenBuffer()
        #print("csbi: {:}\nlcws: {:}".format(buf.GetConsoleScreenBufferInfo(), buf.GetLargestConsoleWindowSize()))
    
        so_buf = wcons.GetStdHandle(wcons.STD_OUTPUT_HANDLE)
        so_csbi = so_buf.GetConsoleScreenBufferInfo()
        #print("csbi: {:}\nlcws: {:}".format(so_csbi, so_buf.GetLargestConsoleWindowSize()))
        #rect = wcons.PySMALL_RECTType(0, 1, 0, 1)
        buf.SetConsoleWindowInfo(Absolute=True, ConsoleWindow=so_csbi["Window"])
        write_coord = wcons.PyCOORDType(10, 4)
        buf = so_buf  # @TODO - cfati: Uncomment this line to write on the same output buffer (and thus preserve screen contents)
        while not msvcrt.kbhit():
            chrs = "------- {:d} -------".format(random.randint(1, 100))
            buf.WriteConsoleOutputCharacter(Characters=chrs, WriteCoord=write_coord)
            time.sleep(0.5)
        wapi.CloseHandle(buf)
    
    
    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 (last value after pressing a key):

    [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073678914]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code00.py
    Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32
    
              ------- 63 -------
    Done.