Console WinAPI - Problem with passing a structure

Just starting out? Need help? Post your questions and find answers here.
ewardd
User
User
Posts: 33
Joined: Tue Jul 16, 2013 12:28 pm

Console WinAPI - Problem with passing a structure

Post by ewardd »

Hey guys. I got a weird problem. Cant get "coord" structure working in WinAPI functions.

https://msdn.microsoft.com/en-us/librar ... s.85).aspx

MSDN quote:
BOOL WINAPI FillConsoleOutputCharacter(
_In_ HANDLE hConsoleOutput,
_In_ TCHAR cCharacter,
_In_ DWORD nLength,
_In_ COORD dwWriteCoord,
_Out_ LPDWORD lpNumberOfCharsWritten
);
dwWriteCoord
A COORD structure that specifies the character coordinates of the first cell to which the character is to be written.

Code: Select all

Structure bufInfo
  dwSize.coord
  dwCursorPosition.coord
  wAttributes.w
  srWindow.small_rect
  dwMaximumWindowSize.coord
EndStructure

buf.bufInfo

Structure crd
  x.l
  y.l
EndStructure

Global ary.crd

ary\x = 0
ary\y = 0

OpenConsole()
size = 25*80
dwI = 0

hI.l = GetStdHandle_(#STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo_(hI, @buf)

;** Here it is. If u run this code nothing will actually happen with FillConsoleOutputCharacter.
FillConsoleOutputCharacter_(hI, Asc("a"), size, ary, @dwi)

;** But if you replace it to 
;FillConsoleOutputCharacter_(hI, Asc("a"), size, 0, @dwi)
;It will work. It will fill console with 'a' character starting from 0, 0 coord cell.
;If you change 0 to 5 it gonna start from 5 cell in a first row and so on untill 80


Input()
I know that in PB already exist "coord" and "ConsoleScreenBufferInfo" structures,
and i tried to use PBs "coord" too. Same result -> nothing on screen.
Doing this for experence and i just wonder why it wont work.

Can anyone explain me why this happens and how to fix this, but Not replace function using other ways?
infratec
Always Here
Always Here
Posts: 7699
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Console WinAPI - Problem with passing a structure

Post by infratec »

Hi,

I'm not sure from where the problem comes, but I have an ugly fix:

Code: Select all

Define lpNumberOfCharsWritten.l, nLength.l, hI.i
Define dwWriteCoord.coord
Define buf.CONSOLE_SCREEN_BUFFER_INFO

OpenConsole()

dwWriteCoord\x = 10
dwWriteCoord\y = 2

nLength = 25*80


hI = GetStdHandle_(#STD_OUTPUT_HANDLE)
GetConsoleScreenBufferInfo_(hI, @buf)
Debug buf\dwSize\x
Debug buf\dwSize\y

Debug RSet(Hex(dwWriteCoord\x << 16 | dwWriteCoord\y, #PB_Long), 8, "0")

;Debug FillConsoleOutputCharacter_(hI, 'a', nLength, dwWriteCoord, @lpNumberOfCharsWritten)
Debug FillConsoleOutputCharacter_(hI, 'a', nLength, dwWriteCoord\y << 16 | dwWriteCoord\x, @lpNumberOfCharsWritten)

Debug lpNumberOfCharsWritten

Input()
Or directly for your code:

Code: Select all

FillConsoleOutputCharacter_(hI, Asc("a"), size, ary\y << 16 | ary\x, @dwi)
Btw. COORD uses short, which is .w in PB.

Bernd
PureGuy
Enthusiast
Enthusiast
Posts: 102
Joined: Mon Aug 30, 2010 11:51 am

Re: Console WinAPI - Problem with passing a structure

Post by PureGuy »

Code: Select all

FillConsoleOutputCharacter_(hI, Asc("a"), size, PeekL(@ary), @dwi)
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Console WinAPI - Problem with passing a structure

Post by luis »

ewardd wrote: Can anyone explain me why this happens
The parameter COORD dwWriteCoord as you see from the docs is not a pointer, it's a structure passed by value.

PB can't pass a structure by value, even if you write its name omitting the @ in front of it it's implicitly there.

The structure you need to pass contains two words (2 x 16 bits), so you can see them as one long (1 x 32 bit).

That's why using simply PeekL() you can read the equivalent long from the base address of the structure, reading the two words as the low and high part of the long.

At that point, we know PB can pass a long by value, and it does just that.

The API doesn't now that's a long (from PB point of view) it just see the package of 32 bits coming to its side, and unpack it to the two x and y components it was expecting, and all works.

In your case you were just passing a random number, the address of your structure.


Both the PeeKL() and the bits manipulation give the same result, PeekL() is just more handy.

Code: Select all

Global dwWriteCoord.COORD
Global hConsoleOutput, NumberOfCharsWritten, nLength

dwWriteCoord\x = 0
dwWriteCoord\y = 10

OpenConsole()
nLength = 80
hConsoleOutput = GetStdHandle_(#STD_OUTPUT_HANDLE);

Debug dwWriteCoord\y << 16 | dwWriteCoord\x
Debug PeekL(dwWriteCoord)

FillConsoleOutputCharacter_(hConsoleOutput, 'a', nLength, PeekL(dwWriteCoord), @NumberOfCharsWritten)

Input()
"Have you tried turning it off and on again ?"
ewardd
User
User
Posts: 33
Joined: Tue Jul 16, 2013 12:28 pm

Re: Console WinAPI - Problem with passing a structure

Post by ewardd »

Thanks you, luis, for explaining everything and you, guys, for attention
Post Reply