移植VBA代码到C#:如何将&HFFFFFFF0转换为uint?
Hey there, let's sort out that conversion problem you're stuck on when porting your VBA code to C#. The root issue boils down to how VBA handles hex literals versus C# rules, plus signed vs. unsigned integer behavior differences.
Why Your Current Code Fails
In VBA, &HFFFFFFF0 is a signed 32-bit long integer (equivalent to C# int) that evaluates to -16. When you try to convert this via Convert.ToUInt32("&HFFFFFFF0", 16), two problems crop up:
- C#'s
Convert.ToUInt32doesn't recognize the VBA-style&Hprefix in the input string. - Even if you stripped the
&H, converting the signed value-16(which is0xFFFFFFF0in two's complement) to an unsigneduintwould throw an overflow exception by default—C# enforces overflow checks in safe contexts.
The Fix: Use Proper C# Hex Literals or Unchecked Conversion
That hex value corresponds to OBJID_NATIVEOM (a standard constant for retrieving a window's native object model), so you can handle it in a couple of clean, reliable ways:
Option 1: Use an Unsigned Hex Literal
C# lets you define unsigned hex literals with the U suffix. Replace your problematic conversion line with this direct value:
0xFFFFFFF0U
Option 2: Unchecked Conversion (For Explicit Casting)
If you prefer explicit casting without overflow checks, use the unchecked keyword to bypass C#'s default overflow protection:
unchecked((uint)0xFFFFFFF0)
Modified Working Code
Here's your updated method with the fix, plus added clarity via constants and required P/Invoke declarations:
// Define standard constants for readability private const uint OBJID_NATIVEOM = 0xFFFFFFF0U; private const int RETURN_OK = 0; // P/Invoke declarations required for Windows API calls [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("oleacc.dll")] private static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint dwObjectID, ref Guid riid, ref object ppvObject); public static bool GetReferenceToApplication(long hWndXL, out object oApplication) { oApplication = null; IntPtr hWinDesk = FindWindowEx(new IntPtr(hWndXL), IntPtr.Zero, "XLDESK", string.Empty); IntPtr hWin7 = FindWindowEx(hWinDesk, IntPtr.Zero, "EXCEL7", string.Empty); Guid iidIDispatch = new Guid("00020400-0000-0000-C000-000000000046"); object obj = null; if (AccessibleObjectFromWindow(hWin7, OBJID_NATIVEOM, ref iidIDispatch, ref obj) == RETURN_OK) { oApplication = obj; return true; } return false; }
Key Notes
- I added the missing
DllImportdeclarations—these are mandatory for calling Windows API functions likeFindWindowExandAccessibleObjectFromWindowin C#. - Renamed the guid variable to
iidIDispatchto make its purpose clearer (it's the interface ID for the COMIDispatchinterface, which Excel's application object implements). - Using the
OBJID_NATIVEOMconstant eliminates "magic numbers" and makes your code easier to maintain.
内容的提问来源于stack exchange,提问作者JasonG

