|
分類:[Microsoft Office 全般]
No65664の質問に続くのですが、一応動作するコードは出来たのですが、イマイチスッキリしない部分があるのでお知恵を拝借できれば。
☆やりたいこと
ExcelVBAのユーザ定義型で、byte配列のフィールドを持ちたい
☆問題
・一応動作はしています。がスッキリしない。
・COPYDATASTRUCTのlpDataに、さらにStringのポインタを入れても対処してくれないので固定長で苦肉の策
☆環境
・Win7 x64
・Excel 2007
・VS 2012
☆注意点
・unsafe初めて使いました。MarshalかC/C++でWrapper作成で今までは済んでいたので。
☆C#
...
// public const int STRUCT_STRING_MAXLENGTH = 1024;
public unsafe struct ReserveStruct
{
public enumReserveCategory Category;
public Int32 No;
public fixed byte Name[common.STRUCT_STRING_MAXLENGTH];
public fixed byte Comment[common.STRUCT_STRING_MAXLENGTH];
}
...
Encoding enc = Encoding.Unicode;
ReserveStruct Reserve = default(ReserveStruct);
Reserve.Category = Category;
Reserve.No = No;
unsafe
{
byte[] Name_buf = enc.GetBytes(Name);
byte* pName = Reserve.Name;
for (int i = 0; i < Name_buf.Length; i++)
{
if (!(i < STRUCT_STRING_MAXLENGTH)) break;
*pName = Name_buf[i];
pName++;
}
byte[] Comment_buf = enc.GetBytes(Comment);
byte* pComment = Reserve.Comment;
for (int i = 0; i < Comment_buf.Length; i++)
{
if (!(i < STRUCT_STRING_MAXLENGTH)) break;
*pComment = Comment_buf[i];
pComment++;
}
}
COPYDATASTRUCT data = new COPYDATASTRUCT();
data.dwData = new IntPtr(common.DW_RESERVE);
data.cbData = (uint)Marshal.SizeOf(Reserve);
data.lpData = Marshal.AllocHGlobal(Marshal.SizeOf(Reserve));
Marshal.StructureToPtr(Reserve, data.lpData, false);
try
{
IntPtr pData = Marshal.AllocHGlobal(Marshal.SizeOf(data));
Marshal.StructureToPtr(data, pData, false);
try
{
common.SendMessage(hWnd, common.WM_COPYDATA, IntPtr.Zero, pData);
}
finally
{
Marshal.FreeHGlobal(pData);
}
}
finally
{
Marshal.FreeHGlobal(data.lpData);
}
...
☆ExcelVBA
...
Public Const STRUCT_STRING_MAXLENGTH As Integer = (1024 / 2) ' 1024バイトでもUnicodeだから512文字だから一応動くケド...
Public Type ReserveStructAPI
Category As Long
No As Long
Name As String * STRUCT_STRING_MAXLENGTH ' Name(STRUCT_STRING_MAXLENGTH) As Byte みたいに出来ないか?
Comment As String * STRUCT_STRING_MAXLENGTH '
End Type
Public Type ReserveStruct
Category As enumReserveCategory
No As Long
Name As String
Comment As String
End Type
...
Private Function ReserveProc(ByRef data As COPYDATASTRUCT) As ReserveStruct
Dim Reserve As ReserveStructAPI
CopyMemory VarPtr(Reserve), data.lpData, data.cbData
ReserveProc.Category = Reserve.Category
ReserveProc.No = Reserve.No
ReserveProc.Name = Left$(Reserve.Name, InStr(Reserve.Name, Chr$(0)) - 1)
ReserveProc.Comment = Left$(Reserve.Comment, InStr(Reserve.Comment, Chr$(0)) - 1)
End Function
...
☆
googleで検索しても、VBA VB6 VB(.NET)の情報が混在して探しにくいですね。
VBFixedArray属性付けたい。
|