Disabling CTRL-X shortcut in Visio 2003 Addon fails

J

Josef Meile

Hi,
I'm trying to disabling the "Cut" (CTRL-X) shortcut in a Visio 2003 addon
written in C#; however it doesn't works.

I rewrote this VBA Code:

Visio2000: How to Bind a Custom Accelerator Key for a Custom Menu to a
Specific Drawing Window
http://support.microsoft.com/?scid=kb;en-us;281504&x=7&y=17

into C#:

Visio.UIObject visioUI = null;
if (VisioDocument.CustomMenus == null)
visioUI = CExeAddon.VisioApp.BuiltInMenus;
else
visioUI = VisioDocument.CustomMenus;

Visio.AccelTableClass vsoAccelTable =
(Visio.AccelTableClass)visioUI.AccelTables.get_ItemAtID(drawingMenuId);
Visio.AccelItemsClass vsoAccelItems =
(Visio.AccelItemsClass)vsoAccelTable.AccelItems;
Visio.AccelItemClass vsoAccelItem;

//This fails
//IEnumerator AccelEnum = vsoAccelItems.GetEnumerator();

// GetEnumerator() has two overrides, so, I tried both of them:

//This fails
//IEnumerator AccelEnum = ((Visio.IVAccelItems)vsoAccelItems).GetEnumerator();

//And this as well
IEnumerator AccelEnum = ((IEnumerable)vsoAccelItems).GetEnumerator();

while (AccelEnum.MoveNext())
{
vsoAccelItem = (Visio.AccelItemClass)AccelEnum.Current;
if (vsoAccelItem.CmdNum == (short)Visio.VisUICmds.visCmdUFEditCut)
{
vsoAccelItem.Delete();
break;
}
}

VisioDocument.SetCustomMenus(visioUI);

It should work; however, I'm getting the following exception as soon as the
GetEnumerator() method is called:

System.InvalidCastException: QI for IEnumVARIANT failed on the unmanaged
server.
at
System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
at Microsoft.Office.Interop.Visio.AccelItemsClass.GetEnumerator()

How should I do this in C#?

Thanks in advanced.

Best regards
Josef
 
J

Josef Meile

Even replacing this lines:

IEnumerator AccelEnum = ((IEnumerable)vsoAccelItems).GetEnumerator();
while (AccelEnum.MoveNext())
{
//[...] Code goes here
}

by:
foreach (Visio.AccelItemClass vsoAccelItem in vsoAccelItems)
{
//[...] Code goes here
}

Produced the same exception.

I found some threads that mentioned that it could be related to this problem:

* FIX: Uninstall of Developer Causes Build Errors in Microsoft Visual Studio
..NET
http://support.installshield.com/kb/view.asp?articleid=q106194

However, I haven't used "InstallShield Developer" nor installing nor
uninstalling it, so, I don't think this is related to my problem. However, I
imported the registry keys, but the problem continues.
 
J

JuneTheSecond

It might be a matter to be done in operating system, did you try Windows API?
Though all operations might be refused in PC.
 
J

Josef Meile

It might be a matter to be done in operating system, did you try Windows API?
Though all operations might be refused in PC.
Well actually, I'm able to add a custom menu to visio with some options.
Just trying to iterating over the visio shortcuts seems to be broken; perhaps
a bug in the .net interop assemblies; is there anybody else experiencing this
kind of problems?

I haven't tried the Windows API because I thaught the .net interface of
Visio would work. Anyway, I will give a try to it.


Thanks,
Josef
 
J

Josef Meile

Hi,

Ok, I tried your suggestion with the Windows API; however, my KeyHandler
isn't set. Here is what I did:

//Delegate to set a keyboard or mouse hook
public delegate int HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);

//Collection containing the hook types
public enum HookType
{
WH_KEYBOARD = 2,
WH_MOUSE = 7
}

//Function to set the keyboard or mouse hook
[DllImport("user32.dll", CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(HookType idHook, HOOKPROC lpfn,
IntPtr hInstance, int threadId);

//Function to remove keyboard or mouse hook
[DllImport("user32.dll", CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);

//Function to call the default hook
[DllImport("user32.dll", CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr
wParam, IntPtr lParam);

Here is how I set it:

private void SetKeyHandler() {
//VisioApp is a Visio.Application object
mKeyHookHandle = SetWindowsHookEx(HookType.WH_KEYBOARD,
new HOOKPROC(KeyHookHandler),
(IntPtr)0,
VisioApp.ProcessID);

int errorCode = Marshal.GetLastWin32Error();
if (mKeyHookHandle == 0)
{
Win32Exception winException = new Win32Exception(errorCode);
MessageBox.Show("SetKeyHandler failed:\n" +
winException.Message + "\n " + winException.StackTrace);
}
}

private int KeyHookHandler(int nCode, IntPtr wParam, IntPtr lParam)
{
System.Diagnostics.Debug.WriteLine(wParam);
return CallNextHookEx(mKeyHookHandle,nCode,wParam,lParam);
}

However, the handler isn't set. mKeyHookHandle is always zero and
GetLastWin32Error always returns zero, so, I don't know why is this failing.

Have you or somebody else ever done something like this?

Best regards
Josef
 
J

Josef Meile

Ok, I tried your suggestion with the Windows API; however, my KeyHandler
isn't set. Here is what I did:

[...] Long code was droped

However, the handler isn't set. mKeyHookHandle is always zero and
GetLastWin32Error always returns zero, so, I don't know why is this failing.

Nevermind, I just figured out that I have to use WH_KEYBOARD_LL instead of
WH_KEYBOARD and instead of including the visio ProcessID like before:

mKeyHookHandle = SetWindowsHookEx(HookType.WH_KEYBOARD,
new HOOKPROC(KeyHookHandler),
(IntPtr)0,
VisioApp.ProcessID);

I have to use its window handler like this:

mKeyHookHandle = CSystemUtils.SetWindowsHookEx(
CSystemUtils.HookType.WH_KEYBOARD_LL,
new CSystemUtils.HOOKPROC(KeyHookHandler),
(IntPtr)VisioApp.InstanceHandle32,
0);

This is my keyboard handler:

private int KeyHookHandler(int nCode, IntPtr wParam, IntPtr lParam)
{
KeyboardHookStruct keyboardHookStruct = (KeyboardHookStruct)
Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
KeyEventArgs keyArgs = new KeyEventArgs((Keys)keyboardHookStruct.vkCode);
if (keyArgs.KeyCode == Keys.X)
{
System.Diagnostics.Debug.WriteLine("X");
return 1;
}
return CallNextHookEx(mKeyHookHandle,nCode,wParam,lParam);
}

At the moment it disables all the "X"; however I'm confident that it isn't
difficult to disable the CTRL+X key. There is a function called GetKeyState,
which may help there. You may also wondering what the KeyboardHookStruct is,
you can get its definition from here:

* Processing Global Mouse and Keyboard Hooks in C#
http://www.codeproject.com/csharp/globalhook.asp

Best regards
Josef
 

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