Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Excel API question: "is it possible .....?"

128 views
Skip to first unread message

David Lee

unread,
Jul 18, 2001, 9:30:15 AM7/18/01
to
... to obtain a handle to a window within an Excel worksheet?

Specifically I want a handle to an embedded chart window so that I can run
some API functions in a VBA procedure.

I'm beginning to suspect that it isn't possible to obtain a handle to any
window below the main window of a workbook. Certainly running a "Window
Title and Class Name Demo" VB program (from
http://www.mvps.org/vbnet/Win32) within Excel failed to return any lower
windows with obvious names or classes.

However my knowledge of the API is very basic - does anyone know any
better?

Thanks

David


S...@internet.org

unread,
Jul 18, 2001, 10:36:11 AM7/18/01
to
David,

You have now posted your request multiple times to multiple
groups over a few weeks - with apparently no satisifactory answer.

Perhaps it would be worthwhile paying MS for a support incident
and requesting the class name for an Excel chart. Using EXCEL.CHART
and EXCEL.CHART.8 did not give me any results with finding the window
handle using the FindWindowLike function from VB.net.

Good luck,

Sam

"David Lee" <dlee_m...@hotmail.com> wrote in message
news:01c10f8d$b64fc110$d00a5092@DAVID_LEE...

Tom Ogilvy

unread,
Jul 18, 2001, 12:19:22 PM7/18/01
to
Try downloading Stephen Bullen's Enumdlg.zip file from his site. It
contains an excel worksheet with code to enumerate all the open windows in
Windows. From what I could see, an embedded chart is not a window but you
can draw your own conclusion.

http://208.49.24.208/Excel/Default.htm

Regards,
Tom Ogilvy

"David Lee" <dlee_m...@hotmail.com> wrote in message
news:01c10f8d$b64fc110$d00a5092@DAVID_LEE...

David Lee

unread,
Jul 18, 2001, 12:56:11 PM7/18/01
to
Sam

I think you are being somewhat harsh in your implied criticism! I
initially posted a query in someone else's thread and so it may well have
been missed by many people. I reposted a request on this NG, to which you
kindly replied with some suggestions, but the title of the posting did not
clearly state my specific problem - hence the second ("multiple!") attempt
in the hope that someone in the know may actually read it.

As for the other news group of my "multiple" of TWO (m.p.e.sdk); it appears
on the basis of it's name to be a more appropriate forum for my request but
doesn't seem to see as much activity.

Paying MS for a support incident is not a possibility (and I'm NOT dipping
into my own salary to do it!). I'm sure that someone amongst the excellent
professionals active on this group MUST know whether or not what I am
trying to do is at least possible. A reply telling me that they think it's
impossible would have saved me much wasted time.

***************************************

Anyway, whereas the VBA property:
ActiveWindow.Caption
accessed from a mouse event in an embedded chart returns
[Book1]Sheet1 Chart1
as expected, running the API functions
GetWindowText(GetActiveWindow, strCaption, lngLen)
returns
Microsoft Excel - Book1
even when the chart has been activated as a Chart Window - complete with
title bar containing "[Book1]Sheet1 Chart1"!

So whilst Excel "knows" that an embedded chart is a separate window it
looks as though it is not accessible to the API.

I would still appreciate confirmation of this though!

And thanks for your earlier suggestions - whilst they didn't help to sove
my problem the links certainly improved my knowledge of VB/VBA!

David

S...@internet.org wrote in article <uBzfEc5DBHA.1352@tkmsftngp05>...

S...@internet.org

unread,
Jul 18, 2001, 1:17:40 PM7/18/01
to
No harshness was implied or intended, and I apologize that my message
led you to that inference.

Anyway, using Stephen Bullen's Enumdlg.xls file, with an embedded
chart in a chart window (right click chart and select the Chart Window
option) and without the window, it appears that the class name for the
chart is EXCELE.

It would be interesting to know whether this now allows you to solve
your original problem with client coordinates successfully.

-- Sam

"David Lee" <dlee_m...@hotmail.com> wrote in message

news:01c10faa$7b231c00$d00a5092@DAVID_LEE...

John Chauvin

unread,
Jul 18, 2001, 1:51:22 PM7/18/01
to
David,

I am rather surprised that you have not received an answer to this
question from the Microsoft MVP - Excel types.

The class name for an embedded chart is EXCELE.

'Get the handle on Excel's main window
hwnd = FindWindow("XLMAIN", Application.Caption)

'Get the handle on Excel's desktop
hWndDesk = FindWindowEx(hwnd, 0, "XLDESK", vbNullString)

'Get the handle for an embedded chart
hWndChart = FindWindowEx(hWndDesk, 0, "EXCELE", vbNullString)

You should be able to then call GetClientRect with hWndChart as
the window handle:

Using your original code:

err = GetClientRect(hWndChart,winRect)

In your original posting, you declared the user defined data type
RECT as:

Private Type RECT
Left As Integer
Top As Integer
Right As Integer
Bottom As Integer
End Type


This is incorrect. The data types must be Long not Integer.

Unfortunately, I do not think this is going to help you with
translating the client coordinates as returned from a MouseDown event
into "Chart coordinates". What you really need is the coordinates of
the plot area (specifically left top, left bottom, right bottom in
client coordinates). You were probably thinking you could ratio the
height and width of the chart object and use that relationship to
convert the Plot Area coordinates to client coordinates. It does not
work.

I setup a sample worksheet where I defined a chart, enabled chart
events, and using a crosshair cursor for precision, extracted various
client coordinates from the chart. The inside top property was defined
as 19 points. The same location in client coordinates is 30 pixels. If
you try and calculate this value you get about 25 pixels using the ratio
of object height in points to object height in client coordinates.

What we need is a coordinates transformation function which will work
no matter what the current scale or scroll position. Whether this
is possible given what we have to work with is still unknown.

These are just my thoughts and I am by no means an expert. Hopefully
we can figure this out once and for all.

John Chauvin


Jake Marx

unread,
Jul 18, 2001, 2:34:23 PM7/18/01
to
Hi David,

As you know, a few of us have told you that the class name for an embedded
chart is EXCELE. I just wanted to let you know how I found that info (for
your benefit and the group's). I used an app called Spy++, which is
included with Visual Studio 6.0. It is very handy for finding windows'
class names and other information like that. Anyway, if you have access to
VS6, check it out....

Regards,
Jake Marx


"David Lee" <dlee_m...@hotmail.com> wrote in message

news:01c10f8d$b64fc110$d00a5092@DAVID_LEE...

David Lee

unread,
Jul 18, 2001, 7:50:54 PM7/18/01
to
Thanks all for your input.

There is no window with class EXCELE on my machine at all. However using
Spy++ (as suggested by Jake) I was able to identify the active chart window
as a child of XLDESK with the class name EXCELC (the same as for a chart
sheet).
(I'm using XL97 - is there perhaps a difference in classe names between 97
and XL2000).

Unfortunately having now obtained a handle to the window, I have run into
similar problems to John Chauvin although I had thought that I had a better
way of transforming the coordinates.

I transform the X,Y (client) coordinates returned by MouseDown into points
using the window sizes returned by GetClientRect and ActiveWindow.Left,
.Top, .Width and .Height. I then map these onto my axis coordinates using
the length and positions of the category and value axes to define the plot
area. (category .Left & .Width and value .Top & .Height)

Whilst the coordinates returned by this means are close to the expected
values there are small but significant errors of the order of one or two
percent at the axis minima and maxima.

For x and y axes in the range 0 to 10, I obtained coordinates of (+0.112,
-0137) for the origin (0, 0) and (+10.093, +9.795) for x,y max (10, 10).
Repeating the excercise but deriving the points window size from the size
of the chart object (ActiveChart.Parent) gave the same results within
reasonable limits of error. Using dimensions from ActiveChart.Chart Area
gave slightly different results: (+0.102, +0.005) & (+10.093, +9.795).

It seems that Excel and the API have slightly different ideas about where
the chart window actually is!

The other possibility of calibration that occurs to me is to move the
cursor to known positions on the chart (ends of the axes?) using
SetCursorPos and fire the MouseDown event using mouse_event (both API
functions from User32.dll). Then at least we would know that Excel and the
API were looking at the same pair of points.

Unfortunately I don't know how to convert the points coordinates derived
from the XL Axis properties into screen coordinates. I just seem to have
gone round in a circle (and I still don't understand why GetActiveWindow
doesn't work for windows inside XL)!

Cheers all

David

Tom Ogilvy

unread,
Jul 18, 2001, 10:41:21 PM7/18/01
to
Jake,
I tried the Spy++ tonight and I believe you may be mistinterpreting the
results (maybe I don't know how to use it). If I use find and drop the find
icon on the chart, it finds the workbook window. The parent of EXCELE is
XLDESK, not the workbook (EXCEL7). I put two embedded charts on the
worksheet. There is still only one EXCELE window. If I have one selected,
the Caption for the EXCELE window is the name of the embedded chart
(whichever is selected - it changes, but the window handle doesn't). If I
have no chart selected, then EXCELE does not show a caption and the handle
remains the same. I believe the EXCELE is the highlight around the selected
chart which would be consistent with all of the above - thus the chart is
not itself a window. Also, if I delete both embedded charts, the EXCELE
continues to exist.

Also, using Stephen's enumdlg routine, no EXCELE is produced (in my tests).

Anyway, that is the way it appeared to me. Maybe it is a known fact that
the embedded chart class is EXCELE, but it doesn't appear to be to me. Any
thoughts?

Regards,
Tom Ogilvy


Jake Marx <ja...@longhead.com> wrote in message
news:OudAAh7DBHA.704@tkmsftngp07...

Jake Marx

unread,
Jul 19, 2001, 2:39:11 AM7/19/01
to
Hi Tom,

Now that I look into it more, I am confused as to what EXCELE represents.
If I resize the chart border, the window size in Spy++ changes along with
it. However, if I resize the chart itself, Spy++ doesn't mirror the
changes. And you're right, EXCELE doesn't seem to go away when you remove
the chart(s).

I guess I don't know enough about the Windows API to figure out exactly what
an embedded chart is. I figured it was a child window of XLDESK, which is a
child of XLMAIN, but I don't know if that is true (it doesn't seem to be).

> Anyway, that is the way it appeared to me. Maybe it is a known fact that
> the embedded chart class is EXCELE, but it doesn't appear to be to me.
Any
> thoughts?

No, I don't think it's a known fact - I was just coming up with my best
guess. Searches on "excele" and several related queries turned up nothing.
Maybe the OP will figure out the solution and let us all know.

Regards,
Jake Marx

"Tom Ogilvy" <twog...@email.msn.com> wrote in message
news:uAUdGw$DBHA.1412@tkmsftngp02...

S...@internet.org

unread,
Jul 19, 2001, 8:20:42 AM7/19/01
to
David,

In my earlier reply I should have been specific that EXCELE
appears to be the class that something to do with embedded
charts on XL2000.

However, as noted by TomOgilvy in his second post, only one
EXCELE window is reported regardless of the actual number
of embedded charts, and a window caption is returned only
when any object on a chart (and, therefore, the chart) is activated.
Also, I observed that EXCELE persists and is returned even after
all charts have been deleted and the file saved. EXCELE is not
reported only after the Excel application has been shut down, and
the (now) chart-less file reopened.

Note: EXCELC does not return any handles in XL2000 for
embedded charts.

Other things to consider:
1) Mouse sensitivity settings may affect the position returned, and
this may vary dpending upon the base units (twip, pixel, or point)
used by the object.
2) Whatever the screen display resolution that has been set
(640x480, 1024 x 768 etc), screen coordinates are oriented from
the top right (0,0) to the bottom left (65536,65536 always) of the
display.

--Sam

"David Lee" <dlee_m...@hotmail.com> wrote in message

news:01c10fe4$6ac833b0$d00a5092@DAVID_LEE...

S...@internet.org

unread,
Jul 19, 2001, 10:01:34 AM7/19/01
to
David,

You may find the following routine useful:

Option Explicit

Type POINT
x As Long
y As Long
End Type

Private Declare Sub GetCursorPos Lib "user32" (lpPoint As CURSOR)

Sub CursorPos()
Dim location As POINT

' Retrieve mouse coordinates
' Values returned in the range (0,0)
' to (display resolution X, display resolution Y)
Call GetCursorPos(location)

ActiveCell.Value = "Current X = " & location.x & Chr(10) & "Current Y = " & location.y

End Sub

Also, the API function "ClientToScreen" converts client coordinates to
screen coordinates.

Private Declare Sub ClientToScreen Lib "user32" _
(ByVal hWnd As Long, _
lpPoint As POINT)

-- Sam


"David Lee" <dlee_m...@hotmail.com> wrote in message

news:01c10fe4$6ac833b0$d00a5092@DAVID_LEE...

S...@internet.org

unread,
Jul 19, 2001, 10:15:56 AM7/19/01
to
Oops!

Change the line:


Private Declare Sub GetCursorPos Lib "user32" (lpPoint As CURSOR)

to

Private Declare Sub GetCursorPos Lib "user32" (lpPoint As POINT)
POINT is standard usage in the MSKB articles.

--Sam

<S...@internet.org> wrote in message news:OsZ9etFEBHA.696@tkmsftngp02...

Stephen Bullen

unread,
Jul 20, 2001, 8:34:06 AM7/20/01
to
Hi Jake,

> Now that I look into it more, I am confused as to what EXCELE represents.

It seems to me to be the editing window that Excel uses when an embedded
chart is activated (which may be exactly what Dave wants!). It provides
the drag handles for the chart, and the thick border and caption if you've
chosen the 'View in own window' option.

To find the EXCELE handle, it's easiest to drill down from XLMAIN, using
FindWindowEx:

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, _
ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Sub test()

Dim hWndXL As Long, hWndDesk As Long, hWndXLE As Long

hWndXL = FindWindow("XLMAIN", Application.Caption)

hWndDesk = FindWindowEx(hWndXL, 0&, "XLDESK", vbNullString)
hWndXLE = FindWindowEx(hWndDesk, 0&, "EXCELE", vbNullString)

End Sub


Regards

Stephen Bullen
Microsoft MVP - Excel
http://www.BMSLtd.co.uk or http://208.49.24.208


Stephen Bullen

unread,
Jul 20, 2001, 8:34:04 AM7/20/01
to
Hi David,

Sorry that I haven't replied sooner, but I've been away from the groups for
a while...

> .... to obtain a handle to a window within an Excel worksheet?

Yes, if the window exists, but not if the worksheet is controlling the
drawing of the object that appears to be in its own window. For example, an
embedded chart object shown on a sheet does not have its own window, but a
TreeView control on a sheet does.

> Specifically I want a handle to an embedded chart window so that I can run
> some API functions in a VBA procedure.

Embedded charts don't have their own window, though they get an editing
window when activated, of class type EXCELE (in XL2000), which appears to
provide the grab handles to resize the embedded chart and the Window title
etc when viewing the chart in its own window.


It appears, though, that you're trying to convert the X, Y coordinates given
in the chart Mouse events to numerical coordinates (e.g. the coordinates of
the data being displayed in the chart's plot area).

This conversion depends on a number of factors, as you've already
discovered:

- The worksheet zoom factor (impacting the conversion of pixels to points)
- Whether showing large or small fonts (impacting the conversion of pixels
to points)
- The differing coordinate systems of the X,Y numbers and the chart item's
dimensions 0,0 is top-left in mouse coords but bottom-left in chart coords.
- The differing origins of the coordinate systems. 0,0 in mouse coords is
the top-left of the chart area (a few pixels inside the window), while (0,0)
in chart coords is the bottom-left of the inside of the plot area.

Given the above, the following seems to provide +/- 1 pixel accuracy in
most settings I've tested it in (hope the word wrapping is OK):


'API's for getting the factors to convert points to pixels
Private Declare Function GetDC Lib "user32" ( _
ByVal hwnd As Long) As Long

Private Declare Function GetDeviceCaps Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal nIndex As Long) As Long

Private Declare Function ReleaseDC Lib "user32" ( _
ByVal hwnd As Long, _
ByVal hDC As Long) As Long

Private Const LOGPIXELSX = 88
Private Const LOGPIXELSY = 90

Public WithEvents oChart As Chart

Private Sub oChart_MouseMove(ByVal Button As Long, ByVal Shift As Long,
ByVal X As Long, ByVal Y As Long)

Dim dZoom As Double
Dim dMin As Double
Dim dMax As Double

dZoom = ActiveWindow.Zoom / 100

With oChart
dMin = .Axes(xlCategory).MinimumScale
dMax = .Axes(xlCategory).MaximumScale
xVal = dMin + (dMax - dMin) * ((X - IIf(dZoom > 1, 6 * (dZoom - 1),
0)) * PointsPerPixelX / dZoom - _
(.PlotArea.InsideLeft +
.ChartArea.Left)) / .PlotArea.InsideWidth

dMin = .Axes(xlValue).MinimumScale
dMax = .Axes(xlValue).MaximumScale
yVal = dMin + (dMax - dMin) * (1 - ((Y - IIf(dZoom > 1, 6 * (dZoom -
1), 0)) * PointsPerPixelY / dZoom - _
(.PlotArea.InsideTop +
.ChartArea.Top)) / .PlotArea.InsideHeight)
End With

Application.StatusBar = "(" & Application.Round(xVal, 2) & ", " &
Application.Round(yVal, 2) & ")"

End Sub

'The width of a pixel in Excel's userform coordinates
Public Property Get PointsPerPixelX() As Double
Dim hDC As Long

hDC = GetDC(0)

'A point is defined as 1/72 of an inch and LOGPIXELSX returns
'the number of pixels per logical inch, so divide them to give
'the width of a pixel in Excel's userform coordinates
PointsPerPixelX = 72 / GetDeviceCaps(hDC, LOGPIXELSX)

ReleaseDC 0, hDC

End Property

'The width of a pixel in Excel's userform coordinates
Public Property Get PointsPerPixelY() As Double
Dim hDC As Long

hDC = GetDC(0)

'A point is defined as 1/72 of an inch and LOGPIXELSX returns
'the number of pixels per logical inch, so divide them to give
'the width of a pixel in Excel's userform coordinates
PointsPerPixelY = 72 / GetDeviceCaps(hDC, LOGPIXELSY)

ReleaseDC 0, hDC

End Property

John Chauvin

unread,
Jul 20, 2001, 11:01:29 AM7/20/01
to
Excellent Job! The only problem I have noticed is the Y coordinate becomes
extremely large if the chart is partially scrolled out of view. I do have a
few questions:

How did you come up with the constants LOGPIXELSX and LOGPIXELSY?
Can you explain exactly what the theory is behind the equations for
xVal and yVal?

Thanks again for your help.

John Chauvin

In article <VA.0000086...@bmsltd.ie>,

Stephen Bullen

unread,
Jul 20, 2001, 2:12:22 PM7/20/01
to
Hi John,

> The only problem I have noticed is the Y coordinate becomes
> extremely large if the chart is partially scrolled out of view.

Left, right, top or bottom?

> I do have a
> few questions:
>
> How did you come up with the constants LOGPIXELSX and LOGPIXELSY?

They're defined in the 'Windows API Viewer' tool that comes with the
Developer editions of Office and VB etc.

> Can you explain exactly what the theory is behind the equations for
> xVal and yVal?

Sure:

The X and Y values coming in to the event are pixel coordinates, with an
origin at the top-left of the ChartArea.

The data plotted on that chart are in coordinates defined by the Category and
Value axes (assuming an XY chart), where the bit displayed on the chart is
the area between the axes minimum and maximum values and where the origin is
the bottom-left corner of the inside of the plot area (unless the 'values in
reverse order' check box is ticked on either axis, in which the origin could
be in any corner - but I ignored that complexity!)

To convert from one coordinate system (pixels on the screen) to another (data
in the chart), we first need to decide on a common measurement system. I
chose to use Points, as that is the measurement system used by the chart
objects (ChartArea, PlotArea) etc.

So, the conversion goes something like this:
1. We're given the cursor position in pixels, X
2. Convert that to points, using the PointsPerPixel functions, adjusting for
different display Zoom factors, (X * PointerPerPixelX / dZoom)
3. At >100% zoom, the result seemed to drift a little, so I added an
adjustment to counteract that, IIf(dZoom > 1, 6 * (dZoom - 1)) *
PointsPerPixel / dZoom
NB. This may not be completely accurate, but seems OK in testing
4. I now have the cursor position in points.
5. Subtract the PlotArea's InsideLeft amount and the ChartArea's Left amount
to find the gap between the left of the inside plot area and the cursor
6. Take the ratio of that gap to the PlotArea's InsideWidth and apply it to
the visible range of the axes scaling.
7. That gives me the data-coordinate value for the cursor's position.

John Chauvin

unread,
Jul 20, 2001, 2:49:16 PM7/20/01
to

When I scrolled the chart up (i.e the top half of the chart is
is off the top of the screen), the Y coordinate becomes
extremely large. I will post the specific steps to reproduce the
problem when I get back to my PC.

John Chauvin

S...@internet.org

unread,
Jul 20, 2001, 3:13:31 PM7/20/01
to

|"Stephen Bullen" <Ste...@BMSLtd.ie> wrote

|Hi John,
|
|> The only problem I have noticed is the Y coordinate becomes
|> extremely large if the chart is partially scrolled out of view.
|
|Left, right, top or bottom?

Initialize the chart, scroll the embedded chart so that the top is
not visible in on the Excel desktop. Select the chart, moving the
mouse shows a large Y coordinate in the status bar display.
A similar phenomenon occurs if the left side of the chart is
scrolled off resulting in a large negative X coordinate value. Both
are of the form 114532####.## on a 1024x768 display XL2000,
on Win98SE.

The readings are normal when the right and/or the bottom of the
chart is not visible due to scrolling.

-- Sam

Stephen Bullen

unread,
Jul 20, 2001, 4:14:24 PM7/20/01
to
> A similar phenomenon occurs if the left side of the chart is
> scrolled off resulting in a large negative X coordinate value. Both
> are of the form 114532####.## on a 1024x768 display XL2000,

Thanks

It looks like there's a bug in .ChartArea.Left and .ChartArea.Top -
they're probably using unsigned longs behind the scenes. We just need
to detect it and change it back (hope the word-wrap's OK):

Private Sub oChart_MouseMove(ByVal Button As Long, ByVal Shift As Long,
ByVal X As Long, ByVal Y As Long)

Dim dZoom As Double
Dim dMin As Double
Dim dMax As Double

Dim dChartLeft As Double
Dim dChartTop As Double



dZoom = ActiveWindow.Zoom / 100

With oChart
dChartLeft = .ChartArea.Left
If dChartLeft > 2 ^ 31 Then
dChartLeft = dChartLeft - 2 ^ 32
End If

dChartTop = .ChartArea.Top
If dChartTop > 2 ^ 31 Then
dChartTop = dChartTop - 2 ^ 32
End If



dMin = .Axes(xlCategory).MinimumScale
dMax = .Axes(xlCategory).MaximumScale
xVal = dMin + (dMax - dMin) * ((X - IIf(dZoom > 1, 6 * (dZoom -
1), 0)) * PointsPerPixelX / dZoom - _
(.PlotArea.InsideLeft +

dChartLeft)) / .PlotArea.InsideWidth

dMin = .Axes(xlValue).MinimumScale
dMax = .Axes(xlValue).MaximumScale
yVal = dMin + (dMax - dMin) * (1 - ((Y - IIf(dZoom > 1, 6 *
(dZoom - 1), 0)) * PointsPerPixelY / dZoom - _
(.PlotArea.InsideTop +

dChartTop)) / .PlotArea.InsideHeight)
End With

Application.StatusBar = "(" & Application.Round(xVal, 2) & ", " &
Application.Round(yVal, 2) & ")"

End Sub


S...@internet.org

unread,
Jul 21, 2001, 7:29:36 AM7/21/01
to
Thank you for the revision.

--Sam

"Stephen Bullen" <Ste...@BMSLtd.ie> wrote in message
news:VA.0000086...@bmsltd.ie...

John Chauvin

unread,
Jul 22, 2001, 6:25:02 PM7/22/01
to
Stephen,

Thanks again for your help. I have been scratching my head trying to
figure the flaw in my original logic. I traced it to a
misunderstanding on the difference between chart object and chart
area. I assume they were the same thing. Obviously, upon closer
examination, they are not.

One side comment for all you Excel authors out there, it would be very
helpful to include a detailed diagram of a sample chart with all the
various objects and dimensions. I am not talking just ChartArea and
PlotArea but all the various properties like insideWidth and
insideHeight. It is not always clear exactly what these properties
really mean.

Anyway,when I examined the ChartArea Top and Left, they had a small
but finite value. There small value indicates that they are not
measure from the top of row 1 on the worksheet which is what I think
the ChartObject top property refers. So that begs the question what
exact does the chartArea top refer to?

Here is what is confusing me. If I enable chart events, and examine
the client coordinates for a simple XY embedded chart by clicking on
the chart area border, I get X = 0 and Y = 0 so the client coordinates
are measured from the visible chart area border. So the gap in points
between the chart area and plot area should be insideTop/insideLeft.
Yet this does not work, for example, you have to take the sum of the
ChartTop plus PlotAreaInsideTop to get a compariable measure to that
represented by the client coordinates. Why

What am I missing?

Thanks,

John Chauvin

Stephen Bullen

unread,
Jul 22, 2001, 9:07:54 PM7/22/01
to
Hi John,

> Yet this does not work, for example, you have to take the sum of the
> ChartTop plus PlotAreaInsideTop to get a compariable measure to that
> represented by the client coordinates. Why

When you draw a chart on a worksheet, you get a ChartObject, which has
Top and Left properties based on the worksheet (0,0 is top-left of cell
A1).

Inside a ChartObject there is a small border, then the ChartArea, so
ChartArea.Top and .Left are 12 points or so - the size of that border.

Inside the ChartArea is the PlotArea (which includes the axis labels),
inside of which is the areae actually drawn on. 0,0 of the InsideLeft
and InsideTop is the top-left of the ChartArea, while 0,0 of the X and
Y values given in the charts mouse events is the top-left of the
ChartObject (view in a fixed-width font):

1------------------------------------------+
|ChartObject |
| 2--------------------------------------+ |
| |ChartArea | |
| | | |
| | +--------------------------------+ | |
| | |PlotArea | | |
| | | 20 +-----------------------+| | |
| | | | 'Inside' dimensions || | |
| | | 10 | || | |
| | | | || | |
| | | 0 +-----------------------+| | |
| | +--------------------------------+ | |
| +--------------------------------------+ |
+------------------------------------------+

Point 1 is the origin for X and Y values passed to chart mouse events.
Point 2 is the original for the PlotArea InsideLeft and InsideTop.
The difference is the ChartArea.Left and ChartArea.Top

John Chauvin

unread,
Jul 23, 2001, 10:07:02 AM7/23/01
to

Thanks again for the explanation.

So when you create a standard XY chart, what object is enclosed by the
outside border...the chart area or chart object? Again using the Chart
MouseDown event and GetChartElement, it appears that the visible object
is the chart area (i.e. if I click one pixel below the border I get
xlChartArea.). But that cannot be true since the client coordinates
returned by the MouseDown event is measured from the Chart Object and
when I click on the chart border I get X=0, Y=0.

John Chauvin


In article <VA.0000087...@bmsltd.ie>,

David Lee

unread,
Jul 24, 2001, 6:35:42 AM7/24/01
to
Stephen

Excellent! Thanks very much for your solution.

Is your adjustment IIf(dZoom > 1, 6 * (dZoom - 1)) * PointsPerPixel / dZoom
based on trial and error or some calculation? On my machine (running
Office 97 under NT4 SP6) the accuracy is not quite as good as you found.
Using the Accessibility Options to nudge a cross hairs cursor I find that
the values returned can be off by up to 4 mouse increments and I wonder if
fine tuning may further improve this? Even so the accuracy and stability
are very much better than I was getting using my solution (using
GetClientRect to calibrate the x,y coordinates).

Now you've shown us what to look for I've come across a demo at
http://www.mvps.org/vbnet/index.html?code/screen/displaysettings.htm
that includes a listing of the values of the constants used in
GetDeviceCaps. Could be helpful if anyone wants to experiment further.

Many thanks for your time.

David

Stephen Bullen

unread,
Jul 24, 2001, 4:12:20 PM7/24/01
to
Hi David,

> Is your adjustment IIf(dZoom > 1, 6 * (dZoom - 1)) * PointsPerPixel / dZoom
> based on trial and error or some calculation?

100% Trial and error, and not too much of it either <g>

0 new messages