views:

2143

answers:

3

I need to show a camera capture dialog in a compact framework 3.7 application by pinvoking SHCameraCapture from the dll Aygshell.dll. I cannont use the managed object CameraCaptureDialog because of limitations with the technology I'm working with. Instead, I need to access it by Pinvoking it.

See http://msdn.microsoft.com/en-us/library/aa454995.aspx for documentation on the function. The function takes in a struct that defines the parameters of the dialog. e.g. where to save the file, what resolution to use.

I would imaging that I would have to define a copy of the struct in C# and decorate the sturct with the attribute StructLayout. I also imagine that the code would involve [DllImport("aygshell.dll")]. Any sample code of how to call this would be much appreciated.

A: 

I've not been able to test this, but your struct/function should look something like this:

struct SHCAMERACAPTURE {
  public Int32 cbSize;
  public IntPtr hwndOwner;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]  
  public string szFile;

  [MarshalAs(UnmanagedType.LPStr)] 
  string pszInitialDir;

  [MarshalAs(UnmanagedType.LPStr)] 
  string pszDefaultFileName;

  [MarshalAs(UnmanagedType.LPStr)] 
  string pszTitle;

  Int32 StillQuality;
  Int32 VideoTypes;
  Int32 nResolutionWidth;
  Int32 nResolutionHeight;
  Int32 nVideoTimeLimit;
  Int32 Mode;
}

[DllImport("aygshell.dll")]
static extern int SHCameraCapture(ref SHCAMERACAPTURE pshcc);

AFAIK, you don't need to explicitly set StructLayout on SHCAMERCAPTURE as there's nothing unusual about its layout.

Once you get this working, you might want to post your findings to pinvoke.net for others to make use of!

Groky
+1  A: 

Groky, this is a good start... Thanks for getting this started. I tried wiring this up, but get a NotSupportedException.

I've pasted the text from my test app below. Note that I tried decorating the struct with [StructLayout(LayoutKind.Sequential)]. I've also made all members public to eliminate any issues with object accessability.

public partial class Form1 : Form
{
    [DllImport("aygshell.dll")]
    static extern int SHCameraCapture(ref SHCAMERACAPTURE pshcc);

    [StructLayout(LayoutKind.Sequential)]
    struct SHCAMERACAPTURE
    {
        public Int32 cbSize;
        public IntPtr hwndOwner;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szFile;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pszInitialDir;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pszDefaultFileName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pszTitle;
        public Int32 StillQuality;
        public Int32 VideoTypes;
        public Int32 nResolutionWidth;
        public Int32 nResolutionHeight;
        public Int32 nVideoTimeLimit;
        public Int32 Mode;
    }
    private void ShowCamera()
    {
        SHCAMERACAPTURE captureData = new SHCAMERACAPTURE
                                           {
                                               cbSize = sizeof (Int64),
                                               hwndOwner = (IntPtr)0,
                                               szFile = "\\My Documents",
                                               pszDefaultFileName = "picture.jpg",
                                               pszTitle = "Camera Demo",
                                               StillQuality = 0,
                                               VideoTypes = 1,
                                               nResolutionWidth = 480,
                                               nResolutionHeight = 640,
                                               nVideoTimeLimit = 0,
                                               Mode = 0
                                           };
        SHCameraCapture(ref captureData);
    }
    private void button1_Click(object sender, EventArgs e)
    {
        ShowCamera();
    }
Peter Walke
Hmm, I'm afraid I'm unable to try the code as I've not got the compact framework installed. However, "\\My Documents" is a shell folder, not a valid filesystem path. Try using a full filesystem path there. (Unless things work differently in the compact framework, in which case please disregard!)
Groky
@Groky: You're wrong, that is a path. Devices have no drive letters.
ctacke
+2  A: 

this code works....

#region Enumerations

public enum CAMERACAPTURE_STILLQUALITY
{
    CAMERACAPTURE_STILLQUALITY_DEFAULT = 0,
    CAMERACAPTURE_STILLQUALITY_LOW = 1,
    CAMERACAPTURE_STILLQUALITY_NORMAL = 2,
    CAMERACAPTURE_STILLQUALITY_HIGH = 3
}
public enum CAMERACAPTURE_VIDEOTYPES
{
    CAMERACAPTURE_VIDEOTYPE_ALL = 0xFFFF,
    CAMERACAPTURE_VIDEOTYPE_STANDARD = 1,
    CAMERACAPTURE_VIDEOTYPE_MESSAGING = 2
}

public enum CAMERACAPTURE_MODE
{
    CAMERACAPTURE_MODE_STILL = 0,
    CAMERACAPTURE_MODE_VIDEOONLY = 1,
    CAMERACAPTURE_MODE_VIDEOWITHAUDIO = 2
}

#endregion //Enumerations

#region Structures

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
public struct struSHCAMERACAPTURE
{
    public uint cbSize;
    public IntPtr hwndOwner;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public String szFile;
    [MarshalAs(UnmanagedType.LPTStr)]
    public String pszInitialDir; //LPCTSTR
    [MarshalAs(UnmanagedType.LPTStr)]
    public String pszDefaultFileName; //LPCTSTR
    [MarshalAs(UnmanagedType.LPTStr)]
    public String pszTitle;  //LPCTSTR
    public CAMERACAPTURE_STILLQUALITY StillQuality;
    public CAMERACAPTURE_VIDEOTYPES VideoTypes;
    public uint nResolutionWidth;
    public uint nResolutionHeight;
    public uint nVideoTimeLimit;
    public CAMERACAPTURE_MODE Mode;
}
#endregion //Structures

#region API
[DllImport("Aygshell.dll", SetLastError = true,CharSet=CharSet.Unicode)]
public static extern int SHCameraCapture
(
    ref struSHCAMERACAPTURE pshCamCapture
);

private string StartImager(String strImgDir, String strImgFile, uint uintImgHeight,
                            uint uintImgWidth)

try
{
  struSHCAMERACAPTURE shCamCapture = new struSHCAMERACAPTURE();

  shCamCapture.cbSize = (uint)Marshal.SizeOf(shCamCapture);
  shCamCapture.hwndOwner = IntPtr.Zero;
  shCamCapture.szFile = "\\" + strImgFile;  //strImgDir + "\\" + strImgFile;
  shCamCapture.pszInitialDir = "\\"; // strImgDir;
  shCamCapture.pszDefaultFileName = strImgFile;
  shCamCapture.pszTitle = "PTT Image Capture";
  shCamCapture.StillQuality = 0; // CAMERACAPTURE_STILLQUALITY.CAMERACAPTURE_STILLQUALITY_NORMAL;
  shCamCapture.VideoTypes = CAMERACAPTURE_VIDEOTYPES.CAMERACAPTURE_VIDEOTYPE_STANDARD;
  shCamCapture.nResolutionHeight = 0; // uintImgHeight;
  shCamCapture.nResolutionWidth = 0; // uintImgWidth;
  shCamCapture.nVideoTimeLimit = 10;
  shCamCapture.Mode = 0; // CAMERACAPTURE_MODE.CAMERACAPTURE_MODE_STILL;

  //IntPtr intptrCamCaptr = IntPtr.Zero;

  //Marshal.StructureToPtr(shCamCapture, intptrCamCaptr, true);

  int intResult = SHCameraCapture(ref shCamCapture);
  if (intResult != 0)
  {
      Win32Exception Win32 = new Win32Exception(intResult);
      MessageBox.Show("Error: " + Win32.Message);
  }             

  return strCaptrErr;
}

catch (Exception ex)
{
    MessageBox.Show("Error StartImager : " + ex.ToString() + " - " + strCaptrErr
                    , "Nomad Imager Test");
    return "";
}