// ref: http://uchukamen.spaces.live.com/blog/cns!7CB203A44BF94940!298.entry
// 上記からそのまま。元は下記。
// ref: http://www.microsoft.com/japan/msdn/net/compactframework/netcfadvinterop.aspx
class Memory
{
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalAlloc(int uFlags, uint uByte);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalReAlloc(IntPtr hMem, uint uBytes, uint fuFlags);
private const int LMEM_FIXED = 0;
private const int LMEM_MOVEABLE = 2;
private const int LMEM_ZEROINIT = 0x40;
private const int LPTR = LMEM_FIXED | LMEM_ZEROINIT;
// LocalAlloc を使用して、メモリ ブロックを割り当てます。
public static IntPtr AllocHLocal(uint cb)
{
return LocalAlloc(LPTR, cb);
}
// AllocHLocal で割り当てられたメモリを解放します。
public static void FreeHLocal(IntPtr hlocal)
{
if (!hlocal.Equals(IntPtr.Zero))
{
if (!IntPtr.Zero.Equals(LocalFree(hlocal)))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
hlocal = IntPtr.Zero;
}
}
// 以前に AllocHLocal で割り当てられたメモリ ブロックのサイズを変更します。
public static IntPtr ReAllocHLocal(IntPtr pv, uint cb)
{
IntPtr newMem = LocalReAlloc(pv, cb, LMEM_MOVEABLE);
if (newMem.Equals(IntPtr.Zero))
{
throw new OutOfMemoryException();
}
return newMem;
}
// マネージ文字列の内容をアンマネージ メモリにコピーします。
public static IntPtr StringToHLocalUni(string s)
{
if (s == null)
return IntPtr.Zero;
else
{
uint nc = (uint)s.Length;
uint len = 2 * (1 + nc);
IntPtr hLocal = AllocHLocal(len);
if (hLocal.Equals(IntPtr.Zero))
throw new OutOfMemoryException();
else
{
Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length);
return hLocal;
}
}
}
}
// ref: http://www.microsoft.com/japan/msdn/net/compactframework/netcfadvinterop.aspx
// 上記をC#に。ちょっと修正
public struct StringPtr
{
private IntPtr stringPtr;
public void New(string str)
{
Free();
stringPtr = Memory.StringToHLocalUni(str);
}
public uint New(uint size)
{
Free();
stringPtr = Memory.StringToHLocalUni(new string('\0', (int)size));
return size;
}
public override string ToString()
{
return Marshal.PtrToStringUni(stringPtr);
}
public void Free()
{
if (IntPtr.Zero != stringPtr)
Memory.FreeHLocal(stringPtr);
}
}
// OPENFILENAMEラッパ
public class OPENFILENAME : IDisposable
{
private uint lStructSize;
private IntPtr hwndOwner;
private IntPtr hInstance = IntPtr.Zero;
private StringPtr lpstrFilter;
private StringPtr lpstrCustomFilter;
private uint nMaxCustFilter = 0;
private uint nFilterIndex;
private StringPtr lpstrFile;
private uint nMaxFile;
private StringPtr lpstrFileTitle;
private uint nMaxFileTitle;
private StringPtr lpstrInitialDir;
private StringPtr lpstrTitle;
private uint Flags;
private ushort nFileOffset = 0;
private ushort nFileExtension = 0;
private StringPtr lpstrDefExt;
private uint lCustData = 0;
private IntPtr lpfnHook = IntPtr.Zero;
private IntPtr lpTemplateName = IntPtr.Zero;
public OPENFILENAME()
{
lStructSize = (uint)Marshal.SizeOf(typeof(OPENFILENAME));
SetFilePathSize(512);
}
public void SetHandle(IntPtr handle) { hwndOwner = handle; }
public void SetFilter(string filter) { lpstrFilter.New(filter); }
public void SetFilter(string filter, uint index) { SetFilter(filter); nFilterIndex = index; }
public void SetFilePathSize(uint filePathSize) { nMaxFile = lpstrFile.New(filePathSize); }
public void SetFileTitleSize(uint fileTitleSize) { nMaxFileTitle = lpstrFileTitle.New(fileTitleSize); }
public void SetInitialDirectory(string initialDirectory) { lpstrInitialDir.New(initialDirectory); }
public void SetTitle(string title) { lpstrTitle.New(title); }
public void SetAllowMultiSelect() { Flags |= 0x200; }
public void SetCreatePrompt() { Flags |= 0x2000; }
public void SetOverWritePrompt() { Flags |= 0x2; }
public void SetPathMustExist() { Flags |= 0x800; }
public void SetFileMustExist() { Flags |= 0x1000; }
public void SetDefaultExtension(string defaultExtension) { lpstrDefExt.New(defaultExtension); }
public string GetPath() { return lpstrFile.ToString(); }
public void Dispose()
{
lpstrFilter.Free();
lpstrCustomFilter.Free();
lpstrFile.Free();
lpstrFileTitle.Free();
lpstrInitialDir.Free();
lpstrTitle.Free();
lpstrDefExt.Free();
}
}
//gsGetSaveFileName
[DllImport("gsgetfile.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "gsGetSaveFileName")]
private static extern bool gsGetSaveFileName([In, Out] OPENFILENAME ofn);
//filePathButtonという名前の参照ボタンとfilePathTextBoxというテキストボックスがある。
private void filePathButton_Click(object sender, EventArgs e)
{
//gsGetFileを使おうとしてみる。
OPENFILENAME ofn = new OPENFILENAME();
using (ofn)
{
try
{
if (gsGetSaveFileName(ofn))
filePathTextBox.Text = ofn.GetPath();
return;
}
catch (MissingMethodException) { }
}
//無理なら標準の使う。
saveFileDialog1.FileName = filePathTextBox.Text;
if (DialogResult.OK == saveFileDialog1.ShowDialog())
filePathTextBox.Text = saveFileDialog1.FileName;
}