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.....
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.
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.
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
if you want the screen dimensions, use GetSystemMetrics
INVOKE GetSystemMetrics,SM_CXSCREEN
mov dwScreenWidth,eax
INVOKE GetSystemMetrics,SM_CYSCREEN
mov dwScreenHeight,eax
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 (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947%28v=vs.85%29.aspx)
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.
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 (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
Thanks Dave.
I think that should solve my problem.
My goodness you are up early :biggrin:
yah - i have to get up early so i can take my early nap :lol:
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.
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
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
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.
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