• Windows Mobile 5.0 ネイティブアプリ開発メモ
  • .Net Compact Framework 2.0メモ
  • GetOpenFileName
    • Smart-PDA.net 管理者の日記 - FileDialog.dll Ver.1.1.3 リリース
      • 複数選択ができないそうだ。
    • gsgetfile.dll version 0.05β
      • ネイティブDLL。
      • 複数選択可能
      • lpstrFileは全て0で初期化されている必要がある。
    • gsGetFile.dllをC#と.NET Compact Framework 2.0から使う
      // 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;
      }
      
  • P/Invoke