News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

RECT Structure

Started by frozen, August 05, 2020, 06:51:25 AM

Previous topic - Next topic

frozen

Hi all,

I have a question regarding the RECT structure. If I understand correctly, the four values are defined as unsigned long in windows.inc (line 7624). However, the official documentation says that they should be signed long (https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect).

The issue I'm having is that GetWindowRect should return negative values for top and left when a window is maximized. However, due to the way the structure is defined, I'm getting top and left as huge positive numbers. As a workaround, I've created my own structure like this and it works fine.

MYRECT STRUCT
  left    SDWORD      ?
  top     SDWORD      ?
  right   SDWORD      ?
  bottom  SDWORD      ?
MYRECT ENDS

Since I'm still learning, I would like to know if this is a bug in windows.inc (very unlikely) or if I should have handled the negative values differently.

Thanks in advance!



hutch--

Hi frozen,

When it comes to a value being signed or unsigned, at the assembler level it is neither until its evaluated with conditional evaluation, mainly conditional jumps and some of the other instructions. While the DWORD / SDWORD distinction exists higher up that MASM handles with its pseudo high level constructs, neither a 32 bit register nor a 32 bit variable maintains that distinction, its just a bit pattern in the right sized storage.

Have a look at the conditional jumps list in the Intel manual or if you have it, a simpler reference and you will find complimentary pairs which have the distinction, just for example the distinction between the unsigned JA (jump if above) verses the signed JG (jump if greater).

jj2007

MYRECT STRUCT
  left    SDWORD      ?
  top     SDWORD      ?
  right   SDWORD      ?
  bottom  SDWORD      ?
MYRECT ENDS


This is what Hutch means - and it works regardless of "left" being DWORD or SDWORD:
cmp somerect.left, 0
jl itsnegative


However, to be fair, this works only with SDWORDs:
.if somerect.left<0
   ... do something for the negative case ...
.endif


With the existing Windows.inc version, you can use this workaround:
.if sdword ptr somerect.left<0
   ... do something for the negative case ...
.endif

hutch--

Knowing the distinction between JA verses JG allows you do a do a few tricks. If you have a finite number of ascending values as positive integers and you need to control the range, if you do the comparison with JA (the signed version) of say 0 to 10 with only one comparison,

  cmp var, 10
  ja errlbl

This works because with an unsigned compare, there are no negative number so you don't have to test for below zero. The high level notation is useful enough but learn your mnemonics (instructions) as they are more powerful and more flexible.

TouEnMasm


The RECT structure is badly defined,she don't know  the x y coordinate (basic knowledge)
To avoid mistakes you can redefine it as follow.
Quote
   FRECT   STRUCT
      min POINT <>
      max POINT <>
   FRECT ENDS
;-------------------------------------------
POINT   STRUCT DEFALIGNMASM
   x DWORD ?
   y DWORD ?
POINT      ENDS

rect FRECT <>

then searching the lenght or the hight
       length = rect.max.X - rect.min.X      ;couldn't be negative even maximize
       Hight   = rect.max.Y - rect.min.Y      ;couldn't be negative even maximize



Fa is a musical note to play with CL

hutch--

This is not correct, a RECT structure is no more than 4 DWORD sized variables in a structure. If you only ever use it for a client area, then left and top are always zero but it can be used for many more things. Get a Window's co-ordinates and left and top are not zero.

Vortex

Hi ToutEnMasm,

Hutch is right, here is how the structure is defined in windows.inc :

RECT STRUCT
  left    dd      ?
  top     dd      ?
  right   dd      ?
  bottom  dd      ?
RECT ENDS


The size of RECT is 16 bytes.

TouEnMasm

WRONG!
Quote
POINT   STRUCT DEFALIGNMASM
   x DWORD ?
   y DWORD ?
POINT      ENDS
There is two points in the FSTRUCT I have given so 2+2=4 DWORD
The structure can replace the RECT structure in all API call.

Fa is a musical note to play with CL

Vortex

Hi ToutEnMasm,

typedef struct tagRECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;


https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect

Retrieving the size of the structure ( 32-bit application ) :

#include <windows.h>
#include <stdio.h>

int main(void)
{
printf("sizeof(RECT)=%u\n",sizeof(RECT));
return 0;
}


sizeof(RECT)=16

hutch--

Yves,

One trick between a POINT struct and a RECT struct is you can use the address of a RECT struct as the target of a POINT API for the first two RECT members. What you are doing will work in some contexts but it is not a valid RECT structure.

If for example you do a GetWindowRect() rather than GetClientRect() you get the screen co-ordinates where with a GetClientRect() you only get the lower X Y. You use the two API calls to convert between the two. ScreenToClient() and ClientToScreen().

I would ask this much of you, when a new member asks a question and gets an answer, we don't need arguments about the details.

TouEnMasm

The point was
Quote
This is not correct, a RECT structure is no more than 4 DWORD sized variables in a structure. If you only ever use it for a client area, then left and top are always zero but it can be used for many more things. Get a Window's co-ordinates and left and top are not zero.
I have corrected that,after if 16 bytes = 4 dword = 2 QWORD ,no matter
then if
Quote
If for example you do a GetWindowRect() rather than GetClientRect() you get the screen co-ordinates where with a GetClientRect() you only get the lower X Y. You use the two API calls to convert between the two. ScreenToClient() and ClientToScreen().
It is the same problem with the RECT structure than with the FRECT



Fa is a musical note to play with CL

hutch--

It is not a problem, its just knowing how the API functions work. Again, we do not need arguments when a new member asks a question.

jj2007

Quote from: Vortex on August 05, 2020, 11:24:31 PM
typedef struct tagRECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;


https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect

Exactly, 4 SDWORDs. It's a small glitch in Windows.inc that hasn't bothered anybody in the last 20 years because Assembly coders know their stuff :cool:

hutch--

I don't know where this folklore comes from but in assembler, the distinction does not exist, the same 32 bit value can be either signed or unsigned, try minus one (-1). The equates for either long OR SDWORD refer exclusively to the data SIZE, a DWORD 32 bit value.

Now yet again when a new member asks a question, the topic get flooded out with nonsense.

jj2007

Quote from: hutch-- on August 06, 2020, 03:00:57 AM
I don't know where this folklore comes from but in assembler, the distinction does not exist

include \masm32\include\masm32rt.inc

.data
MyDwords dd -1, 0, 1
MySDwords SDWORD -1, 0, 1

.code
start:
  cls
  xor ebx, ebx
  print "DWORDS:", 13, 10
  .Repeat
.if MyDwords[4*ebx]<0
print str$(MyDwords[4*ebx]), " is below zero", 13, 10
.else
print str$(MyDwords[4*ebx]), " is zero or above", 13, 10
.endif
inc ebx
  .Until ebx>2
  xor ebx, ebx
  print "SDWORDS:", 13, 10
  .Repeat
.if MySDwords[4*ebx]<0
print str$(MySDwords[4*ebx]), " is below zero", 13, 10
.else
print str$(MySDwords[4*ebx]), " is zero or above", 13, 10
.endif
inc ebx
  .Until ebx>2
  inkey " "
  exit
end start


Output:
DWORDS:
-1 is zero or above
0 is zero or above
1 is zero or above
SDWORDS:
-1 is below zero
0 is zero or above
1 is zero or above