getRibbonButtonRectangle - in C#?

C

Colbert Zhou [MSFT]

Hello Dave,

The getRibbonButtonRectangle seems not an Office default Ribbon callback
function for button. So are you using any third party library? Or could you
please post the link or VBA codes here so that I can do some researches and
see if I can make a C# version for you.


Best regards,
Ji Zhou
Microsoft Online Community Support
 
D

David Thielen

Hi;

Please look at
http://groups.google.com/group/micr...ed+the+location+of+the+ribbon+button+pressed"

thanks - dave


Hello Dave,

The getRibbonButtonRectangle seems not an Office default Ribbon callback
function for button. So are you using any third party library? Or could you
please post the link or VBA codes here so that I can do some researches and
see if I can make a C# version for you.


Best regards,
Ji Zhou
Microsoft Online Community Support


david@[email protected]
Windward Reports -- http://www.WindwardReports.com
me -- http://dave.thielen.com

Cubicle Wars - http://www.windwardreports.com/film.htm
 
C

Colbert Zhou [MSFT]

Hello Dave,

Now I know what we are talking. The link you post is using Accessibilty API
to get an Accessible Automation object of Ribbon control. The Accessiblity
API is implemented in native dll. So from C#, we have to PInvoke to call
into oleacc.dll. It is not as easy as we do callback in C# Office COM AddIn.

I reference a codeproject article,
http://www.codeproject.com/KB/winsdk/MSAA_UI_Automation.aspx

and did a lot of debugging and test. At last I got the following codes work
to get the location of Ribbon button.

----------------native function declarations-----------------
[DllImport("oleacc.dll")]
internal static extern int AccessibleObjectFromWindow(
IntPtr hwnd,
uint id,
ref Guid iid,
[In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object
ppvObject);

[DllImport("oleacc.dll")]
public static extern int AccessibleChildren(IAccessible
paccContainer, int iChildStart, int cChildren,
[Out()]
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] object[]
rgvarChildren, ref int pcObtained);

[DllImport("oleacc.dll")]
public static extern uint GetRoleText(uint dwRole, [Out]
StringBuilder lpszRole, uint cchRoleMax);

[DllImport("oleacc.dll")]
public static extern uint GetStateText(uint dwStateBit, [Out]
StringBuilder lpszStateBit, uint cchStateBitMax);
-------------------------------------------------------------------------


-------------Help Functions--------------------------------------
public static string GetStateText(uint stateID)
{
uint maxLength = 1024;
var focusableStateText = new StringBuilder((int)maxLength);
var sizeableStateText = new StringBuilder((int)maxLength);
var moveableStateText = new StringBuilder((int)maxLength);
var invisibleStateText = new StringBuilder((int)maxLength);
var unavailableStateText = new StringBuilder((int)maxLength);
var hasPopupStateText = new StringBuilder((int)maxLength);
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_SIZEABLE
| MSAAStateConstants.STATE_SYSTEM_MOVEABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_SIZEABLE,
sizeableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_MOVEABLE,
moveableStateText, maxLength);
return focusableStateText + "," + sizeableStateText + "," +
moveableStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_INVISIBLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_INVISIBLE,
invisibleStateText, maxLength);

return focusableStateText + "," + invisibleStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE,
unavailableStateText, maxLength);

return focusableStateText + "," + unavailableStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_HASPOPUP
| MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_HASPOPUP,
hasPopupStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE,
unavailableStateText, maxLength);

return hasPopupStateText + "," + unavailableStateText;
}
var stateText = new StringBuilder((int)maxLength);
GetStateText(stateID, stateText, maxLength);
return stateText.ToString();
}

internal static string GetRoleText(uint roleId)
{
uint maxLength = 1024;
var roleText = new StringBuilder((int)maxLength);
GetRoleText(roleId, roleText, maxLength);
return roleText.ToString();
}

public static IAccessible GetObjectByName(IAccessible objParent,
Regex objName, bool ignoreInvisible)
{
IAccessible objToReturn = default(IAccessible);
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string childName = null;
string childState = string.Empty;

try
{
childName = child.get_accName(0);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
}
catch (Exception)
{
}
if (ignoreInvisible)
{
if (childName != null
&& objName.Match(childName).Success
&& !childState.Contains("invisible"))
{
return child;
}
}
else
{
if (childName != null
&& objName.Match(childName).Success)
{
return child;
}
}
if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
objToReturn = GetObjectByName(child, objName,
ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
else
{
objToReturn = GetObjectByName(child, objName,
ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
}
return objToReturn;
}

public static IAccessible[] GetAccessibleChildren(IAccessible
objAccessible)
{
int childCount = 0;
try
{
childCount = objAccessible.accChildCount;
}
catch (Exception ex)
{
childCount = 0;
}
var accObjects = new IAccessible[childCount];
int count = 0;
if (childCount != 0)
{
AccessibleChildren(objAccessible, 0, childCount,
accObjects, ref count);
}
return accObjects;
}

public static IAccessible GetObjectByNameAndRole(IAccessible
objParent, Regex objName, string roleText, bool ignoreInvisible)
{
IAccessible objToReturn = default(IAccessible);
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string childName = null;
string childState = string.Empty;
string childRole = string.Empty;
try
{
childName = child.get_accName(0);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
childRole =
GetRoleText(Convert.ToUInt32(child.get_accRole(0)));
}
catch (Exception)
{
}
if (ignoreInvisible)
{
if (!string.IsNullOrEmpty(childName)
&& objName.Match(childName).Success
&& childRole == roleText
&& !childState.Contains("invisible"))
{
return child;
}
}
else
{
if (!string.IsNullOrEmpty(childName)
&& objName.Match(childName).Success
&& childRole == roleText)
{
return child;
}
}
if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
objToReturn = GetObjectByNameAndRole(child,
objName, roleText, ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
else
{
objToReturn = GetObjectByNameAndRole(child,
objName, roleText, ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}

}
}
return objToReturn;
}

public static void GetAccessibleObjectListByRole(IAccessible
objParent, string roleText,
ref List<IAccessible>
accessibleObjList, bool ignoreInvisible)
{
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string roleTextInner = null;
string childState = string.Empty;

try
{
uint roleId =
Convert.ToUInt32(child.get_accRole(0));
roleTextInner = GetRoleText(roleId);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
}
catch (Exception)
{
}

if (ignoreInvisible)
{
if (roleTextInner == roleText &&
!childState.Contains("invisible"))
{
accessibleObjList.Add(child);
}
}
else
{
if (roleTextInner == roleText)
{
accessibleObjList.Add(child);
}
}

if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
GetAccessibleObjectListByRole(child, roleText,
ref accessibleObjList, ignoreInvisible);
}
}
else
{
GetAccessibleObjectListByRole(child, roleText, ref
accessibleObjList, ignoreInvisible);
}
}
}
}
-------------------------------------------------------------------------


------------Codes to get the location of a button--------
object accObject = new object();
var guidAccessible = new
Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
IAccessible objWindow = default(IAccessible);
AccessibleObjectFromWindow(
Process.GetCurrentProcess().MainWindowHandle, 0, ref
guidAccessible, ref accObject);
objWindow = (IAccessible)accObject;
Debug.Print(objWindow.accChildCount.ToString());
Debug.Print(objWindow.accName.ToString());

IAccessible Home = GetObjectByNameAndRole(objWindow, new
Regex("Home"),"property page", true);
IAccessible clipBoard = GetObjectByNameAndRole(Home, new
Regex("Clipboard"), "tool bar", true);
IAccessible Paste = GetObjectByNameAndRole(clipBoard, new
Regex("Paste"), "split button", true);
int pxLeft;
int pyTop;
int pcxWidth;
int pcyHeight;
Paste.accLocation(out pxLeft, out pyTop, out pcxWidth, out
pcyHeight, 0);
MessageBox.Show("Left:" + pxLeft + "\r\n" +
"Top:" + pyTop + "\r\n" +
"Width:" + pcxWidth + "\r\n" +
"Height:" + pcyHeight + "\r\n");
-------------------------------------------------------------------------


Hope this helps!


Best regards,
Ji Zhou
Microsoft Online Community Support
 
D

David Thielen

Hi;

I'm trying to build this but I can't find a definition for
MSAAStateConstants anywhere. What do I need to include to get those
constants?

thanks - dave


Hello Dave,

Now I know what we are talking. The link you post is using Accessibilty API
to get an Accessible Automation object of Ribbon control. The Accessiblity
API is implemented in native dll. So from C#, we have to PInvoke to call
into oleacc.dll. It is not as easy as we do callback in C# Office COM AddIn.

I reference a codeproject article,
http://www.codeproject.com/KB/winsdk/MSAA_UI_Automation.aspx

and did a lot of debugging and test. At last I got the following codes work
to get the location of Ribbon button.

----------------native function declarations-----------------
[DllImport("oleacc.dll")]
internal static extern int AccessibleObjectFromWindow(
IntPtr hwnd,
uint id,
ref Guid iid,
[In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object
ppvObject);

[DllImport("oleacc.dll")]
public static extern int AccessibleChildren(IAccessible
paccContainer, int iChildStart, int cChildren,
[Out()]
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] object[]
rgvarChildren, ref int pcObtained);

[DllImport("oleacc.dll")]
public static extern uint GetRoleText(uint dwRole, [Out]
StringBuilder lpszRole, uint cchRoleMax);

[DllImport("oleacc.dll")]
public static extern uint GetStateText(uint dwStateBit, [Out]
StringBuilder lpszStateBit, uint cchStateBitMax);
-------------------------------------------------------------------------


-------------Help Functions--------------------------------------
public static string GetStateText(uint stateID)
{
uint maxLength = 1024;
var focusableStateText = new StringBuilder((int)maxLength);
var sizeableStateText = new StringBuilder((int)maxLength);
var moveableStateText = new StringBuilder((int)maxLength);
var invisibleStateText = new StringBuilder((int)maxLength);
var unavailableStateText = new StringBuilder((int)maxLength);
var hasPopupStateText = new StringBuilder((int)maxLength);
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_SIZEABLE
| MSAAStateConstants.STATE_SYSTEM_MOVEABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_SIZEABLE,
sizeableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_MOVEABLE,
moveableStateText, maxLength);
return focusableStateText + "," + sizeableStateText + "," +
moveableStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_INVISIBLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_INVISIBLE,
invisibleStateText, maxLength);

return focusableStateText + "," + invisibleStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE
| MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_FOCUSABLE,
focusableStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE,
unavailableStateText, maxLength);

return focusableStateText + "," + unavailableStateText;
}
if (stateID ==
(MSAAStateConstants.STATE_SYSTEM_HASPOPUP
| MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE))
{
GetStateText(MSAAStateConstants.STATE_SYSTEM_HASPOPUP,
hasPopupStateText, maxLength);
GetStateText(MSAAStateConstants.STATE_SYSTEM_UNAVAILABLE,
unavailableStateText, maxLength);

return hasPopupStateText + "," + unavailableStateText;
}
var stateText = new StringBuilder((int)maxLength);
GetStateText(stateID, stateText, maxLength);
return stateText.ToString();
}

internal static string GetRoleText(uint roleId)
{
uint maxLength = 1024;
var roleText = new StringBuilder((int)maxLength);
GetRoleText(roleId, roleText, maxLength);
return roleText.ToString();
}

public static IAccessible GetObjectByName(IAccessible objParent,
Regex objName, bool ignoreInvisible)
{
IAccessible objToReturn = default(IAccessible);
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string childName = null;
string childState = string.Empty;

try
{
childName = child.get_accName(0);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
}
catch (Exception)
{
}
if (ignoreInvisible)
{
if (childName != null
&& objName.Match(childName).Success
&& !childState.Contains("invisible"))
{
return child;
}
}
else
{
if (childName != null
&& objName.Match(childName).Success)
{
return child;
}
}
if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
objToReturn = GetObjectByName(child, objName,
ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
else
{
objToReturn = GetObjectByName(child, objName,
ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
}
return objToReturn;
}

public static IAccessible[] GetAccessibleChildren(IAccessible
objAccessible)
{
int childCount = 0;
try
{
childCount = objAccessible.accChildCount;
}
catch (Exception ex)
{
childCount = 0;
}
var accObjects = new IAccessible[childCount];
int count = 0;
if (childCount != 0)
{
AccessibleChildren(objAccessible, 0, childCount,
accObjects, ref count);
}
return accObjects;
}

public static IAccessible GetObjectByNameAndRole(IAccessible
objParent, Regex objName, string roleText, bool ignoreInvisible)
{
IAccessible objToReturn = default(IAccessible);
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string childName = null;
string childState = string.Empty;
string childRole = string.Empty;
try
{
childName = child.get_accName(0);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
childRole =
GetRoleText(Convert.ToUInt32(child.get_accRole(0)));
}
catch (Exception)
{
}
if (ignoreInvisible)
{
if (!string.IsNullOrEmpty(childName)
&& objName.Match(childName).Success
&& childRole == roleText
&& !childState.Contains("invisible"))
{
return child;
}
}
else
{
if (!string.IsNullOrEmpty(childName)
&& objName.Match(childName).Success
&& childRole == roleText)
{
return child;
}
}
if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
objToReturn = GetObjectByNameAndRole(child,
objName, roleText, ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}
}
else
{
objToReturn = GetObjectByNameAndRole(child,
objName, roleText, ignoreInvisible);
if (objToReturn != default(IAccessible))
{
return objToReturn;
}
}

}
}
return objToReturn;
}

public static void GetAccessibleObjectListByRole(IAccessible
objParent, string roleText,
ref List<IAccessible>
accessibleObjList, bool ignoreInvisible)
{
if (objParent != null)
{
IAccessible[] children = GetAccessibleChildren(objParent);
foreach (IAccessible child in children)
{
string roleTextInner = null;
string childState = string.Empty;

try
{
uint roleId =
Convert.ToUInt32(child.get_accRole(0));
roleTextInner = GetRoleText(roleId);
childState =
GetStateText(Convert.ToUInt32(child.get_accState(0)));
}
catch (Exception)
{
}

if (ignoreInvisible)
{
if (roleTextInner == roleText &&
!childState.Contains("invisible"))
{
accessibleObjList.Add(child);
}
}
else
{
if (roleTextInner == roleText)
{
accessibleObjList.Add(child);
}
}

if (ignoreInvisible)
{
if (!childState.Contains("invisible"))
{
GetAccessibleObjectListByRole(child, roleText,
ref accessibleObjList, ignoreInvisible);
}
}
else
{
GetAccessibleObjectListByRole(child, roleText, ref
accessibleObjList, ignoreInvisible);
}
}
}
}
-------------------------------------------------------------------------


------------Codes to get the location of a button--------
object accObject = new object();
var guidAccessible = new
Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
IAccessible objWindow = default(IAccessible);
AccessibleObjectFromWindow(
Process.GetCurrentProcess().MainWindowHandle, 0, ref
guidAccessible, ref accObject);
objWindow = (IAccessible)accObject;
Debug.Print(objWindow.accChildCount.ToString());
Debug.Print(objWindow.accName.ToString());

IAccessible Home = GetObjectByNameAndRole(objWindow, new
Regex("Home"),"property page", true);
IAccessible clipBoard = GetObjectByNameAndRole(Home, new
Regex("Clipboard"), "tool bar", true);
IAccessible Paste = GetObjectByNameAndRole(clipBoard, new
Regex("Paste"), "split button", true);
int pxLeft;
int pyTop;
int pcxWidth;
int pcyHeight;
Paste.accLocation(out pxLeft, out pyTop, out pcxWidth, out
pcyHeight, 0);
MessageBox.Show("Left:" + pxLeft + "\r\n" +
"Top:" + pyTop + "\r\n" +
"Width:" + pcxWidth + "\r\n" +
"Height:" + pcyHeight + "\r\n");
-------------------------------------------------------------------------


Hope this helps!


Best regards,
Ji Zhou
Microsoft Online Community Support


david@[email protected]
Windward Reports -- http://www.WindwardReports.com
me -- http://dave.thielen.com

Cubicle Wars - http://www.windwardreports.com/film.htm
 
D

David Thielen

Hi;

Ok I got this to compile (pulled the MSAAStateConstants from the
CodeProject sources). And I'm getting an exception.

IAccessible Home = GetObjectByNameAndRole(objWindow, new
Regex("Home"), "property page", true);

is getting a list of 7 children. For children[1] it has the values:
childName null string
childState "focusable" string
childRole "title bar" string

and recursively calls GetObjectByNameAndRole(). In the recursive call
it gets 5 children and on children[0] the call to
child.get_accName(0); throws the exception:
- $exception {"Entry point was not found.":""}
System.Exception {System.EntryPointNotFoundException}

child does not appear to be a COM object and while ti has a type of
Microsoft.Office.Core.IAccessible {int} - it has a value of 1 and
appears to just be an int.

Any ideas?

thanks - dave

david@[email protected]
Windward Reports -- http://www.WindwardReports.com
me -- http://dave.thielen.com

Cubicle Wars - http://www.windwardreports.com/film.htm
 
C

Colbert Zhou [MSFT]

OK. I am trying to get a complete workable C# sample and will send to your
mailbox. :)


Best regards,
Ji Zhou
Microsoft Online Community Support
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top