Link to home
Start Free TrialLog in
Avatar of cantrell
cantrell

asked on

Button location

How do I find out the exact location of a button on my form, relative to the screen size?
For example, is the right side of my "OK" button on my form (that's displayed in center screen) at pixel 400, or 900 on my 1024x768 resolution? And, where would it be if I changed my resolution to 800x600? How would I find out that location - exactly?
Avatar of Juilette
Juilette

' here is how to make sure it's on the screen

#VBIDEUtils#************************************************************
' * Programmer Name  : Mikhail Shmukler
' * Web Site         : www.geocities.com/ResearchTriangle/6311/ 
' * E-Mail           : waty.thierry@usa.net
' * Date             : 13/10/98
' * Time             : 10:24
' * Module Name      : class_Elastic
' * Module Filename  : Elastic.cls
' **********************************************************************
' * Comments         :
' * This class can change size and location of controls On your form
' * 1. Resize form
' * 2. Change screen resolution
' * Assumes:1. Add Elastic.cls
' *         2. Add declaration 'Private El as New class_Elastic'
' *         3. Insert string like 'El.init Me' (formload event)
' *         4. Insert string like 'El.FormResize Me' (Resize event)
' *         5. Press 'F5' and resize form ....
'
'****************************************************************

Option Explicit
Private nFormHeight      As Integer
Private nFormWidth       As Integer
Private nNumOfControls   As Integer
Private nTop()           As Integer
Private nLeft()          As Integer
Private nHeight()        As Integer
Private nWidth()         As Integer
Private nFontSize()      As Integer
Private nRightMargin()   As Integer
Private bFirstTime       As Boolean

Sub Init(frm As Form, Optional nWindState As Variant)
   
   Dim I          As Integer
   Dim bWinMax    As Boolean
   
   bWinMax = Not IsMissing(nWindState)
   
   nFormHeight = frm.Height
   nFormWidth = frm.Width
   nNumOfControls = frm.Controls.Count - 1
   bFirstTime = True
   ReDim nTop(nNumOfControls)
   ReDim nLeft(nNumOfControls)
   ReDim nHeight(nNumOfControls)
   ReDim nWidth(nNumOfControls)
   ReDim nFontSize(nNumOfControls)
   
   ReDim nRightMargin(nNumOfControls)
   On Error Resume Next
   For I = 0 To nNumOfControls
      If TypeOf frm.Controls(I) Is Line Then
         nTop(I) = frm.Controls(I).Y1
         nLeft(I) = frm.Controls(I).X1
         nHeight(I) = frm.Controls(I).Y2
         nWidth(I) = frm.Controls(I).X2
      Else
         nTop(I) = frm.Controls(I).Top
         nLeft(I) = frm.Controls(I).Left
         nHeight(I) = frm.Controls(I).Height
         nWidth(I) = frm.Controls(I).Width
         nFontSize(I) = frm.FontSize
         nRightMargin(I) = frm.Controls(I).RightMargin
      End If
   Next
   
   If bWinMax Or frm.WindowState = 2 Then ' maxim
      frm.Height = Screen.Height
      frm.Width = Screen.Width
   Else
      frm.Height = frm.Height * Screen.Height / 7290
      frm.Width = frm.Width * Screen.Width / 9690
   End If
   
   bFirstTime = True
   
End Sub

Sub FormResize(frm As Form)
   
   Dim I             As Integer
   Dim nCaptionSize  As Integer
   Dim dRatioX       As Double
   Dim dRatioY       As Double
   Dim nSaveRedraw   As Long
   
   On Error Resume Next
   nSaveRedraw = frm.AutoRedraw
   
   frm.AutoRedraw = True
   
   If bFirstTime Then
      bFirstTime = False
      Exit Sub
   End If
   
   If frm.Height < nFormHeight / 2 Then frm.Height = nFormHeight / 2
   
   If frm.Width < nFormWidth / 2 Then frm.Width = nFormWidth / 2
   nCaptionSize = 400
   dRatioY = 1# * (nFormHeight - nCaptionSize) / (frm.Height - nCaptionSize)
   dRatioX = 1# * nFormWidth / frm.Width
   On Error Resume Next ' for comboboxes, timeres and other nonsizible controls
   
   For I = 0 To nNumOfControls
      If TypeOf frm.Controls(I) Is Line Then
         frm.Controls(I).Y1 = Int(nTop(I) / dRatioY)
         frm.Controls(I).X1 = Int(nLeft(I) / dRatioX)
         frm.Controls(I).Y2 = Int(nHeight(I) / dRatioY)
         frm.Controls(I).X2 = Int(nWidth(I) / dRatioX)
      Else
         frm.Controls(I).Top = Int(nTop(I) / dRatioY)
         frm.Controls(I).Left = Int(nLeft(I) / dRatioX)
         frm.Controls(I).Height = Int(nHeight(I) / dRatioY)
         frm.Controls(I).Width = Int(nWidth(I) / dRatioX)
         frm.Controls(I).FontSize = Int(nFontSize(I) / dRatioX) + Int(nFontSize(I) / dRatioX) Mod 2
         frm.Controls(I).RightMargin = Int(nRightMargin(I) / dRatioY)
      End If
   Next
   
   frm.AutoRedraw = nSaveRedraw
   
End Sub
Avatar of cantrell

ASKER

Huh? I know it's on the screen, I just need to know where exactly. I want to know the exact pixel location relative to the screen resolution.
Use the following :

dim PixelX as integer
dim PixelY as integer

PixelX = mycontrol.left/screen.twipsperpixelx

PixelY = mycontrol.top/screen.twipsperpixely

Now pixelx and pixely have the location in pixels relative to screen resolution.
Umm, vett, you're close but no cigar!

The control's location is relative to it's CONTAINER. So you have to find the FORM's location, then the buttons location within that. Also, if the button is in another container (like a SSTab control) then the button's location is relative to THAT. As long as you're dealing with controls on a form the problem isn't too hard to solve, but when you get to objects on containers within the form the computations can get hairy because there is no easy way to test for container ownership. Thus you can't tell, programmatically, if Button is relative to the SSTAB or the FORM.

Cantrell: Why do you need this info? Generally you should be screen independent as users can reposition your window, etc. If you're trying to center your form you don't need pixels as the screen (and printer for that matter) are denominated in TWIPS.

If you're trying to make something land at a specific location on the screen you're going to run into problems if the program is run on a different rez screen. You can also P.O. users by automatically resizing as rez changes. This is more apt to be perceived as a *BUG* than as a FEATURE 'cause the whole point of the user upping the rez is to get *MORE* on the screen. If your app sucks up the available space your tech support folx are going to hear about it!

M
Juliette,

Your posts are getting as bad as Waty's! :-)

M
OH! I read the code. It *IS* WATY's stuff! No wonder it looked familiar! LOL!

M
Mark, picky picky picky! LOL

He's right, you need to do the above calc for the form left and top, and add it to the control's left and top. And if the control is in a container, add that in as well.

Maybe I'll just stop answer questions after consecutive 4AM programming nights! LOL Thanks for straightening me out Mark. :-)

Hey vett!  Check out Q.10226082. I've got SATWA foaming at the mouth! (snicker).

Cantrell, sorry for co-opting your Q for a little inter-expert chatter, but there's no other easy way for two experts to reach each other. Hope you don't mind. I've suggested an expert-to-expert mail *several* times... sigh.

M
No problem. Chat away. I am checking mark2150s' code now
No problem. Chat away. Funny stuff you guys. And "mark2150" is right about the control location being relative to the form. However I am checking mark2150s' code now...
mark2150 - you are right about the screen res thing. However, I know the screen res before hand, so I'm sure there has to be some way to figure out where a control button (or even a form) is, relative to the screen res. Just how, I don't know.
mark2150 - you are right about the screen res thing. However, I know the screen res before hand, so I'm sure there has to be some way to figure out where a control button (or even a form) is, relative to the screen res. Just how, I don't know.
mark2150 - you are right about the screen res thing. However, I know the screen res before hand, so I'm sure there has to be some way to figure out where a control button (or even a form) is, relative to the screen res. Just how, I don't know.
here is a test project that do what you are after :
start a new project with Form1,Module1, and Command1 on Form1.

paste this code into Module1 :
------------------------------
Option Explicit
Public Type Rect
     L As Long
     T As Long
     R As Long
     B As Long
End Type
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect) As Long
-------------------------------------

paste this code to Form1 code :
--------------------------------------
Private Sub Command1_Click()
    Dim i As Long
    Dim MyRect As Rect
    i = GetWindow(Command1.hwnd, 0)
    GetWindowRect i, MyRect
    MsgBox MyRect.L
End Sub
--------------------------------------
the msgbox display Command1's left corner screen coardinate.



ASKER CERTIFIED SOLUTION
Avatar of mark2150
mark2150

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
AnswerTheMan-Thanks for your posting, but I really didn't want to make an API calls. While your suggestion may work, mark2150s' answer is more like what I had in mind - and it worked perfectly, so thanks...

And, mark210 - post yours as an answer and I'll give you the points. Thanks for all the help. and to everyone else too.
Nevermind mark2150. They'll let me give the points to comments, so here you are. Thanks again.
Thank you sir!

Visit the web page - we've put up a Spoooooooky section for All Hallows Eve. There's lots of code and such as well as some jokes for adults.

www.cyberchute.com/rvbus/madmark

Oh, and have your speakers turned on to get my opinion of Windoze!

M
The problem with the Accepted answer is that it is not jeneric solution and it is works only when your button is "on the underlying form and not on another container", as M pointed out.
if the button is inside a container which is inside a container which is inside a container etc - you will have to write a hell of a code for each control's location search.

the API SHORT solution i gave you is a jeneric procedure that will just returns the location of any control realitive to screen in 2 API calls.

our goal is to seek jeneric solution rather then solving a local problem each time.

as for the "but I really didn't want to make an API calls" :
sounds ridiculous !! if you don't understand what's API calls are for VB -ask Mark1250. he'll explain it to you.




one more :
if Mark1250 would have thought himself
of my solution - he would post it himself rather then his answer.
if he's willing to TRUE - he will surly admit that.
AnswerTheMan -  I understand your reasoning, and I do understand "API calls" and what their for. I use many of them. In retrospect, your reply was a generic solution to a common situation and maybe should have been awarded points. However, at the time mark2150s' answer appealed to me more and seemed to be a more direct route.
Oh, and one more thing - AnswerTheMan. I did take the time to look over your code, and thank you for posting it. It looks like it's very clean - tight code.
don't forget to turn them speakers on to hear someone spitting into the pot
he eats from
AnswerTheMan,

You certainly sound bitter.

The sound effect represents the frustration I feel dealing with windoze and all of it's problems. Yes, it puts food on the table, but it also gives me ulcers.

Windoze is NOT the only OS I cut code for nor is VB the only language I use. I've had to develop my own languages to do an end run on the limits that M$ imposes. I've coded on every kind of machine there is from the early days of 360-65 and SEL32/55's down to little 8-bit embedded controllers. 6800, 6802, 6809, 68x00, Z80, CPM, Unix, 6502, TI's, Rockwells, Sparc's, HP's, etc. Why shouldn't I throw stones at M$? A *LOT* of their products are CRAP. I've used enough others to know there's better ways. Windows 9x/2000 will *NEVER* be stable enough to support real-time or life critical apps.

Your comments about the limits of my routine are 100% valid and they were mentioned in my first post as this would not be a generic solution:

"...but when you get to objects on containers within the form the computations can get hairy because there is no easy way to test for container ownership. Thus you can't tell, programmatically, if Button is relative to the SSTAB or the FORM."

You certainly don't have to take that snotty tone with me or the poser:

"ask Mark1250. he'll explain it to you."

Certainly sounds like a bad case of sour grapes.

Since you're so obviously upset by this I'm posting a 50 pt Q for you.

M
24 hours (or so) later :

mark2150 :

I'm sorry for my personal remarks.
really.
You are right in every word you say
just as i was right in the non-personal part of my comment(s).

i was not upset for the points....
such thing can't drive me that far.
i was just angry of wasting my time finding the best solution to this guy's problem. i did not had that code ready since i never needed such a code. i've spent some 15 minutes working it out to help him, after i saw that you and others don't come up with a proper generic solution.
getting angry very fast is my problem, and when i do - i tend to personal comments (here and in real time).
i'm cold now, and again - i'm sorry.
i apreciate your peacfull comment and you.
Forgiven, forgotten!

You can still have the points... :-)

I know how it gets when you invest time and trouble in an answer and get verschnitz in return.

M
AnswerTheMan, nicely said, and I think it expresses a frustration all of us have from time to time, but we have to deal with! I can't count the number of times I've spent considerable time writing and testing code for an answer, only to come back and see that someone has locked it with some two line answer.

I think that Mark2150 and I would both agree that your solution gets him right to the coordinate more directly than our method did.

And Cantrell. I notice you mentioned something about prefering not to use APIs. You may not be aware, but a lot of functions previously part of VB have been taken out because they are easily available in the API, so you need to keep an open mind to the API.

For example, the VB screen object used to have a lock method long long ago. Now it has disappeared, and you're expected to know how to use the LockWindowUpdate API call instead.
Yeah, no VB programmer's bookshelf is complete without a copy of Dan Appleman's "Programmers Guide to the Win32 API"...

M
ok. setteled..tnx.
one more thing :
Since i'm no Natural English speaker - i've no idea what the word "verschnitz"
stands for....
("I know how it gets when you invest
 time and trouble in an answer and get
 verschnitz in return")
..........:)



LOL AnswerTheMan, most native English speakers are going to have trouble with "verschnitz" also ... my guess is its German. What is your native language, by the way?
HEBREW.
imagain to yourself programming GUI that is written from RightToLeft...

manipulating RTL strings  back in 80X25 dos text screen...

you can't imagain. who can imagain HELL...
I don't envy that, I honestly wouldn't want to be doing it! LOL
Hmmm, You'ld think a native hebrew speaker would be able to decode transliterated German/Yiddish! :-) "verschnitz" = nothing, nil, nada... From my stint in NYC did my vocabulary pick up words like that... :-)

M
ha ! a common mistake....
80% of native hebrew speakers don't know a single word in the language you mentioned.
another 15% know between 1-10 words...
the rest knew it well, but now, they are too synil to remmember it.....
Sad. Yiddish is such an expressive language. Esp as spoken in NYC. You can be having a conversation with someone and in one breath they'll speak english, spanish, italian, german, and yiddish - sometimes in one *sentence*! Oy! :-)

My wife has never been in that area of the world and sometimes when we're talking she'll get this look that tells me I've *completely* lost her. I sometimes use "native idiom" that makes perfect sense - to me - but that is lost on anyone that didn't grow up in that area. (Isn't EVERYONE from NYC?) But just sometimes a word is "perfect". Verschnitz has a flavor that means "less than nothing". A zero without the edge. Nullity. A handful of empty. I just can't think of a better word! :-(

M
you said it all.