News:

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

Main Menu

savemiddleofX

Started by shankle, December 05, 2015, 04:04:34 AM

Previous topic - Next topic

shankle

This is the code I use to find the middle of X on a Dell 1905f9; 
   mov eax,RR.right
   shr eax,1
   mov savemiddleofX,eax  ; middle of screen

The result is that the line is slightly off center.
I hate to hard code it as a different size monitor wouldn't work.
Suggestions please.....

 


TouEnMasm

My clairvoyant vision see that you try to center Something in a Windows using
     getwindowsrect,addr rr  (rr:RECT)     ;perhaps getclientrect ???

If i am clairvoyant,you can try Something like that:
   mov eax,rr.right
   sub eax,rr.left
   shr eax,1    ;divide by 2
I don't see which fonction you are using,(I am blend here) and the returned coordinates are not the same
with the two functions!
Perhaps also it is a child Windows ? or not,coordinates are not the same .......
A little more code is needed.

Fa is a musical note to play with CL

shankle

Thank you ToutEnMasm,
I think I have to use GetClientRect instead of what I tried.
That should give me a true width of the screen.

dedndave

that will work ok for a client rectangle or screen because left and top are always 0

for a window rectangle
    mov     eax,RR.right
    sub     eax,RR.left
    sar     eax,1


i use SAR in preference to SHR because it will handle signed values
in the above example, it's not likely to be negative   :P
but, if you are centering a window in a screen or in another window, it is possible

dedndave

if you want the screen dimensions, use GetSystemMetrics

    INVOKE  GetSystemMetrics,SM_CXSCREEN
    mov     dwScreenWidth,eax

    INVOKE  GetSystemMetrics,SM_CYSCREEN
    mov     dwScreenHeight,eax

dedndave

if you want the "workspace" (screen less task bars, etc), use SystemParametersInfo with SPI_GETWORKAREA

QuoteSPI_GETWORKAREA   

Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen not obscured by the system taskbar or by application desktop toolbars. The pvParam parameter must point to a RECT structure that receives the coordinates of the work area, expressed in virtual screen coordinates.

To get the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947%28v=vs.85%29.aspx

shankle

             12-5-2015
using GoAsm syntax.
Monitor width is 1024
middle of screen is 512

cxclient              dd   0
savemiddleofX    dd   0

ScrnWndProc:
   LOCAL RR:RECT

   invoke SystemParametersInfo, SPI_GETWORKAREA,0,addr RR,0
   mov eax,[RR.right]
   shr eax,1
   mov [savemiddleofX],eax  ; middle of screen

I checked the value of savemiddleofX and it is 512
The field I am trying to center is 40 bytes long.
I then subtract 20 from the value in savemiddleofX.

   mov eax,[savemiddleofX]  ; middle of screen
   sub eax,20
   mov D[cxclient],eax
   invoke TextOut, [hdc],[cxclient],[cyclient],addr msg6,40

The result of all this is the message is off center.

Dave - I tried your other 2 methods and they also don't work.
The way I see it I have some other setting wrong in relation
to the monitor.

dedndave

Quote from: shankle on December 05, 2015, 11:05:25 PM
The field I am trying to center is 40 bytes long.
I then subtract 20 from the value in savemiddleofX.

a 40 byte (40 character) string is more than 40 pixels wide

you can use the GetTextExtentPoint32 function to get some idea of the text width
but - many fonts are variable-pitch, and the function is rarely 100% accurate
the function uses the font that is currently selected into the HDC to estimate width and height

https://msdn.microsoft.com/en-us/library/dd144938%28v=vs.85%29.aspx

once you know the width of the text, subtract it from the window width and divide the result by 2
that should give you a nearly centered X position

shankle

Thanks Dave.
I think that should solve my problem.
My goodness you are up early :biggrin:

dedndave

yah - i have to get up early so i can take my early nap   :lol:

shankle

Latest attempt             12-5-2015 #2

GoAsm syntax
Monitor width is 1024
middle of screen is 512

cxclient              dd   0
savemiddleofX    dd   0

ScrnWndProc:
   Local hInst,pt:POINT,sz:SIZE,RR:RECT

I left this alone
   invoke SystemParametersInfo, SPI_GETWORKAREA,0,addr RR,0
   mov eax,[RR.right]
   shr eax,1
   mov [savemiddleofX],eax  ; middle of screen

The field I am trying to center is 40 bytes long.
   invoke GetTextExtentPoint32, [hdc],addr msg6,40,addr sz
   mov eax,[sz.cx]
   sub eax,20    ; this might be the culprit
                       ; but how to fix??? The GTEP32 says the output
             ; is in Logical units
   shr eax,1
   mov D[cxclient],eax
   invoke TextOut, [hdc],[cxclient],[cyclient],addr msg6,40
The result of all this is the message is off center to the left.

dedndave

you've got all the pieces, just need to put them together

call SystemParametersInfo to get screen dimensions
call GetTextExtentPoint32 to get text dimensions

then...
    mov     ecx,<ScreenWidthValue>
    sub     ecx,<TextWidthValue>
    sar     ecx,1                                ;ECX = text X position

    mov     edx,<ScreenHeightValue>
    sub     edx,<TextHeightValue>
    sar     edx,1                                ;EDX = text Y position

dedndave

ScrnWndProc:
    Local hInst,pt:POINT,sz:SIZE,RR:RECT

    invoke  SystemParametersInfo, SPI_GETWORKAREA,0,addr RR,0

    invoke  GetTextExtentPoint32, [hdc],addr msg6,40,addr sz

    mov     ecx,[RR.right]
    sub     ecx,[RR.left]                        ;ECX = screen width
    sub     ecx,[sz.cx]
    sar     ecx,1                                ;ECX = text X position

    mov     edx,[RR.bottom]
    sub     edx,[RR.top]                         ;EDX = screen height
    sub     edx,[sz.cy]
    sar     edx,1                                ;EDX = text Y position

    invoke  TextOut, [hdc],ecx,edx,addr msg6,40


i don't know much about GoAsm
but for Masm, "cx" is a reserved word (so is "SIZE")

so, the "SIZE" structure is replaced with "_SIZE"
and the members are named "x" and "y", rather than "cx" and "cy"
you may or may not have to worry about that with GoAsm

shankle

#13
Thanks Dave for helping.
So you have to get up early to get all the honeydos done.
Then you are worn out and have to nap. Such is life :biggrin:

             12-5-2015 #3
GoAsm syntax
Monitor width is 1024
middle of screen is 512

cxclient     dd   0
msg6        db   '1234567890123456789012345678901234567890',0

ScrnWndProc:
   Local hInst,sz:SIZE,RR:RECT

The field I am trying to center is 40 bytes long.
   invoke GetTextExtentPoint32, [hdc],addr msg6,40,addr sz
   mov eax,[RR.right]   ; 1024 in eax
   sub eax,[RR.left]      ; this should be zero - so why is it needed - still 1024
   sub eax,[sz.cx]        ; value of sz.cx is 273?????? - 751
   sar eax,1                 ; both should work - my figures should
                                 ; never be zero - 375.5
;  shr eax,1
;  value in eax - 1024-273 = 751 divided by 2 = 375.5
   mov D[cxclient],eax
   invoke TextOut, [hdc],[cxclient],[cyclient],addr msg6,40
The result of all this is the message is near column 1.


shankle

#14
             12-13-2015 #4
This works on my puter running Windows 7 pro 64-bit
Yes, it is slightly off center but good enough.
I have not tested it on other monitors but I think the way
I handle RR-right will get the right results on any monitor.
GoAsm syntax
My Monitor width is 1024 pixels

cxclient     dd   0
cyclient     dd   0
holdtop      dd   0
holdright2   dd   0
msg6         db   '1234567890123456789012345678901234567890',0
msg7         db   '12345678901234567890123456789012345678901',0

WinMain:
   LOCAL RR:RECT,hWnd
   invoke SystemParametersInfo, SPI_GETWORKAREA,0,addr RR,0

   mov eax,[RR.top]
   mov [holdtop],eax
   mov eax,[RR.right]
   dec eax
   mov [holdright2],eax   ; pixels

ScrnWndProc:
   FRAME hWnd,iMsg,wParam,lParam
   Local RR:RECT,pt:POINT
.WM_PAINT
   cmp D[iMsg],WM_PAINT
   jne >>.WM_DESTROY

   invoke SetMapMode, [hdc],MM_TEXT
   invoke SetCursorPos, addr RR.right,addr RR.top    ;pixels
   mov eax,[holdright2]         ; ex: 1024 - 1 pixels
   mov D[pt.x],eax
   mov D[pt.y],1

   invoke ScreenToClient, [hWnd],addr pt  ; after execution - client
   mov eax,[pt.x]   ; client
   shr eax,1        ; screen width divided by 2
   sub eax,20   ; msg6 is 40 so half is 20
   mov D[cxclient],eax
   mov D[cyclient],50
   invoke SetTextAlign, [hdc],TA_CENTER
   invoke TextOut, [hdc],[cxclient],[cyclient],addr msg6,40
   add D[cyclient],20
   invoke TextOut, [hdc],[cxclient],[cyclient],addr msg7,41
   add D[cyclient],75
   mov D[cxclient],25
   invoke SetTextAlign, [hdc],TA_LEFT    ; reset for next message