none
Actual physical position of a control RRS feed

  • Question

  • Hi there everyone!

    I am trying to get the physical on screen position of a control in ms access. Unfortunately this is not as simple as its left/top property.

    My goal - graphical highlighting around specific controls within screenshots saved automatically from within access. Note the highlighting is not just altering the background colour (or equivalent) of the access control, there are other requirements going on and highlighting is semi-transparent.

    My process:

    - I generate a bitmap of my access window/form/subform (it can vary), highlight sections of this (using gdi+ graphics calls) within the bitmap, save to image. All works beautifully. except...

    Where on earth is the control!!!!

    A control's .left/.top will give you its position in relation to its parent. So converting this to a coordinate relative to its parent is easy.

    If that parent is a subform, then it gets more complicated, as you have to account for its parent form.

    Are there record selectors? More spacing complications.

    Is the control part of a tab/tab control? That's another level of fun and games working out where on earth the control is in relation to parent controls and calculating extra offsets of where the control might actually be.

    Then of course you can have headers/footers, so these must be accounted for in working out where a control is.

    So finally, you finish handling the above... - OH - MY - GOODNESS - Anchoring. Yes - if your using anchoring, your control might be moved dynamically - so its actual position might be completely different to what you've calculated.

    :(

    Does anyone have any idea's?

    Thanks :)

    Monday, February 27, 2017 12:37 PM

Answers

  • Ok I think I have a solution!

    Basically...

    ctrl = control I want the position of

    frm = its parent form

    TwipsToPixels is your favorite twips-to-pixels function

    Area is just a type with .left .top .width and .height properties

    Public Declare Function apiGetWindowRect Lib "user32" Alias "GetWindowRect" (ByVal hWnd As Long, lpRect As Rect) As Long

    Public Declare Function apiScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hWnd As Long, ByRef Point As Point) As Boolean

    Private Function GetControlsArea(ByRef ctrl As control, ByRef frm As Form) As Area Dim a As Area Dim r As Rect Dim pt As Point Set a = New Area apiGetWindowRect apiGetFocus(), r pt.X = r.Left pt.Y = r.Top apiScreenToClient frm.hWnd, pt a.Left = pt.X a.Top = pt.Y a.Width = TwipsToPixels(ctrl.Width, DIRECTION_HORIZONTAL) a.Height = TwipsToPixels(ctrl.Height, DIRECTION_VERTICAL) Set GetControlsArea = a End Function

    So far so good, though I think I might need an exception for when command buttons have the focus!

    • Marked as answer by Babbage Wednesday, March 1, 2017 1:24 PM
    Wednesday, March 1, 2017 12:33 PM

All replies

  • Does anyone have any idea's?

    Hi Babbage,

    You are already pretty close. You still have to account for a border around the form (dialog forms have no border). Further the form's top and left positions of the forms are relative to the Access window, and for dialog forms relative to the screen.

    When you have this, then it is a conditional summation of all these elements.

    I have no total formula for all this, but I use a comparable calculation to position dialog or non-dialog dynamical menus.

    Imb.

    Monday, February 27, 2017 1:34 PM
  • Hi Babbage,.

    Here I think that , it is very complex requirement and As there is no any inbuilt property or function provided by Access to fulfil this requirement , the output will not be accurate as you want.

    you had mentioned that the highlighting is not just to change the background color of control but you have many more requirements.

    so you are trying to fetch the control's position left, top etc.

    in many situations you get the incorrect values for the control to be highlighted.

    so here I think that to make the process simple is only the way to fulfil this requirement correctly.

    may I ask you , why changing the background color of control and then take the snap shot of it not working for you?

    with this way you can see the highlighted control in your image and this is the simplest way to achieve this requirement.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, February 28, 2017 1:30 AM
    Moderator
  • Unfortunately that doesn't account for things like dynamic scaling with anchoring - controls are moved around the screen by access but their reference positions aren't (.left/.top)
    Tuesday, February 28, 2017 9:49 AM
  • Some controls don't have a background to change, some controls, changing the background doesn't work or display any visible changes, it can cause problems when done with continuous forms and with conditional formatting, and I am rendering extra content not just a background colour change. I also highlight some areas that cover e.g. entire subforms, not just individual controls within them, along with some extra annotations.

    Tuesday, February 28, 2017 9:51 AM
  • Unfortunately that doesn't account for things like dynamic scaling with anchoring - controls are moved around the screen by access but their reference positions aren't (.left/.top)

    Hi Babbage,

    I do not know, but things like dynamic scaling etc, seems more related to the OS than to Access.

    Imb.

    Tuesday, February 28, 2017 10:42 AM
  • Hi Babbage,

    Access is made for database purpose.

    so it does not provide any image processing features.

    I know you had try to manage to solve your issue with programming.

    but it also has some limitation, so currently you will not able to fulfil your requirement exactly.

    so, as I informed you earlier, it will not work accurately.

    currently no any perfect solution is available for this issue with MS Access VBA. 

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, March 1, 2017 4:22 AM
    Moderator
  • That's just standard MS Access anchoring of controls (if you've not used it before, it will automatically move/size controls as window sizes change), nothing special :)
    Wednesday, March 1, 2017 9:10 AM
  • That's just standard MS Access anchoring of controls (if you've not used it before, it will automatically move/size controls as window sizes change), nothing special :)

    Hi Babbage,

    Thank you for the clarification.

    I have not yet used this: I don't think it is part of A2003, that I am still using.

    In my systematics I use generalized forms, where I can manipulate the controls. including scaling, shifting, replacing, etc., so not feeling the necessity to move to newer Acces.

    Imb.

    Wednesday, March 1, 2017 9:44 AM
  • This isn't so much an image processing issue (and you can do all sorts of image processing if you put your mind to it), its a referencing problem. MS Access must know where a control is, otherwise it wouldn't be able to update it! I suspect its just hidden away as a private property somewhere deep in an object somewhere :( So we can't reference it.

    Wednesday, March 1, 2017 12:25 PM
  • Ok I think I have a solution!

    Basically...

    ctrl = control I want the position of

    frm = its parent form

    TwipsToPixels is your favorite twips-to-pixels function

    Area is just a type with .left .top .width and .height properties

    Public Declare Function apiGetWindowRect Lib "user32" Alias "GetWindowRect" (ByVal hWnd As Long, lpRect As Rect) As Long

    Public Declare Function apiScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hWnd As Long, ByRef Point As Point) As Boolean

    Private Function GetControlsArea(ByRef ctrl As control, ByRef frm As Form) As Area Dim a As Area Dim r As Rect Dim pt As Point Set a = New Area apiGetWindowRect apiGetFocus(), r pt.X = r.Left pt.Y = r.Top apiScreenToClient frm.hWnd, pt a.Left = pt.X a.Top = pt.Y a.Width = TwipsToPixels(ctrl.Width, DIRECTION_HORIZONTAL) a.Height = TwipsToPixels(ctrl.Height, DIRECTION_VERTICAL) Set GetControlsArea = a End Function

    So far so good, though I think I might need an exception for when command buttons have the focus!

    • Marked as answer by Babbage Wednesday, March 1, 2017 1:24 PM
    Wednesday, March 1, 2017 12:33 PM
  • Note: Apparently access creates a window in the position of the currently selected control. Find that window, you've found the control. Also note, the frm that I pass in doesn't have to be the control's parent - it can be further up the food chain for wider screenshots, and still get a relative position.
    • Edited by Babbage Wednesday, March 1, 2017 12:35 PM
    Wednesday, March 1, 2017 12:34 PM
  • Further note, use the windows width/height, not the controls, in case the control has been resized!
    Wednesday, March 1, 2017 1:26 PM