Convert c# windows panel to c HWND - c#

I have a dll which accepts HWND,
(code in the dll);
void VideoCapture::SetVideoWindow(HWND VidWind)
{
VideoWindow = VidWind;
}
i am calling the above dll in a sample c#.net application by adding the dll in references, in c#.net i have a form with Panel, is it possible to pass that panel to the dll?
i gave code as below in c#
VidCapWrapper.ManagedVideoCapture cc = new VidCapWrapper.ManagedVideoCapture();
cc.SetVideoWindow( panel1);
i am getting errors as below:
'Error 2 The best overloaded method match for 'VidCapWrapper.ManagedVideoCapture.SetVideoWindow(HWND__)' has some invalid arguments D:\DirectShow_Capture_GUI\DirectShow_Capture_GUI\Form1.cs 44 13 DirectShow_Capture_GUI
Error 3 Argument 1: cannot convert from 'System.Windows.Forms.Panel' to 'HWND__' D:\DirectShow_Capture_GUI\DirectShow_Capture_GUI\Form1.cs 44 32 DirectShow_Capture_GUI`
Can any one please tell me how to pass panel to dll, (any example will be good)?
(sorry i am very new to .net, but trying to create a sample app which shows available devices like integrated webcam... and then shows preview on c#.net form panel)
EDIT:
Thanks to Both #Blachshma and #Hans Passant, Now i am able to pass c# windows form's panel to my c++ dll.
I changed my func in dll as
void VideoCapture::SetVideoWindow(IntPtr windowHandle)
{
VideoWindow = (HWND)windowHandle.ToPointer();
}
and in c# i am calling it as
cc.SetVideoWindow(panel1.Handle);

You must be careful to not expose fundamentally unmanaged types like HWND to C# code. The C# compiler will not allow you to pass a value of such a type. The proper interop type here is IntPtr, it can store a handle value. So make your C++/CLI method look like this:
void VideoCapture::SetVideoWindow(IntPtr windowHandle)
{
VideoWindow = (HWND)windowHandle.ToPointer();
}
You can now simply pass panel1.Handle to the method, also of type IntPtr.

The panel has a Handle property you can use:
Panel p = new Panel();
IntPtr handle = p.Handle;
This should be enough if you set the SetVideoWindow signature to allow IntPtr i.e.
void VideoCapture::SetVideoWindow(IntPtr VidWind)
If you MUST use a HWND, you'll need to use an unsafe context, and cast it like this:
HWND hwnd=(HWND)this.Handle.ToPointer();
Here is an link with more information

Related

How to pass C# objects through to JNI method in Xamarin?

I'm using Xamarin and need to call through to two static java methods in a jar I've linked to. Here is the java class in the jar:
package com.test;
public class Car {
public static Car makeCar(String name);
public void drawCar(ImageView imageview);
}
I'm not sure how to pass in the parameters for the two methods to the JNI code. The JNIEnv.Call**Method() class takes a JValue[] array for parameters, I'm trying to use it to wrap a C# string and call it all like so:
// C#
string carName = "mustang";
JValue[] paramCarName = new JValue[] {
new JValue(JNIEnv.NewString(carName))
};
IntPtr theClass = JNIEnv.FindClass("com.test.Car");
IntPtr theMethod = JNIEnv.GetMethodID(theClass,
"makeCar", "()Ljava/lang/String;");
IntPtr resultCar = JNIEnv.CallStaticObjectMethod(
theClass, theMethod, paramCarName);
Is that correct usage? I'm having the same problem with calling the second method, which refers to a C# version of android's ImageView:
// C#
// Xamarin provides an ImageView wrapper class.
ImageView imageview = ...;
// Is it alright to use JNIEnv.ToJniHandle here to reference the imageview?
JValue[] paramCarName = new JValue[] {
new JValue (JNIEnv.ToJniHandle (imageview))
};
...
The above currently compiles ok, but I can't run it since I only have the free version. Any info on this would be great as I'm sure I'm misusing this.
Thanks
If you are having trouble getting a jar to bind you may be able to fix the errors with Transforms/Metadata.xml (documentation here). With that file you can suppress bindings for classes or entire packages that cause code generation issues.
If Metadata.xml cannot get the job done, another (less desirable) option is to create your own Java library that wraps the one that won't bind, and exposes only the methods you need to access from C#. Then bind that jar.
But, it sounds like you have the free version of Xamarin (probably why you are trying to avoid jar binding since that requires the paid version) so I'll attempt to fix your JNI code:
// C#
IntPtr classHandle;
IntPtr theClass = JNIEnv.FindClass("com/test/Car", classHandle);
IntPtr theMethod = JNIEnv.GetMethodID(theClass,
"makeCar", "(Ljava/lang/String;)V");
// Just create a new JValue with your C# Android object peer
JNIEnv.CallStaticObjectMethod(classRef, methodRef, new JValue[] {
new JValue(imageView)
});
My JNI is not super-advanced so take the above with some grains of salt. But according to code generated by Xamarin Studio for jar binding, the above should be (close to) correct.

how to pass window handle to c++ win32 dll from C#

I have one project which capture images from multiple cameras which is in C++ .I want to use that project in my new project which is in C#.I had made dll of that project.My question is ,how can i use that dll in my project.I know by passing window handle to C++ dll we can use it but i dont know how to do it and what changes should i make in dll.
Please forgive ,if it is foolish question.
I had the exact problem as you and this article helped me.
http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx
To pass the handle, you can add another function in C++ end. Something like,
(in the header)
extern "C" __declspec(dllexport) void SetParent(HWND hWnd);
To use the SetParent in C#
class Program
{
...
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SetParent(IntPtr hWnd);
public void testMethod()
{
...
IntPtr getAddress = NativeMethods.GetProcAddress(pDll, "SetParent");
...
SetParent setParent = (SetParent)Marshal.GetDelegateForFunctionPointer(getAddress, typeof(SetParent));
setParent(this.Handle);
...
}
}
If your C++ project is already in a DLL you can call any functions that it exports using P/Invoke. You will have to declare the method in your C# assembly as shown below, but then you can call it like a standard static method.
[DllImport("YourDllsName.dll")]
public static extern bool FunctionThatAWindowHandleAndReturnsBool(IntPtr hWnd);
Depending on the types of parameters that your C++ DLL's functions take the marshaling of the .Net datatypes to C data types can get complicated.

How do I pass the address of a c++ method in win32 app to a c# method with Action delegate parameter method

I have a win32 application using a C# library.
The C# library has a method where the Action<T> delegate is a parameter as shown:
public NetSocket(Action<int, int, string> action)
I have a ref class in the win32 application with a method that matches the Action delegates signature.
How exactly do I pass this method as the Action parameter in the NetSocket method listed above?
Ben your solution seem to work but there was a compile error on matching the System:Sting^ input parameter of the action delegate method in the win32 application to the String input parameter of Action delegate in the C# code. The Action delegate in the c# code uses a String as an input parameter and the Action delegate method in the win32 code tries match using a System::String^ to match it but that does not work.
// win 32 app - void ServerClass::ActionMethod(int iCommand, int iClientIndex, System::String^ message)
// win32 app -server = gcnew NetSockets::NetSocket(gcnew Action(this,&ServerClass::ActionMethod));
// csharp - public NetSocket(Action<int, int, string> action)
Is there some marshaling method I need to use to match System::String used in the win32 code to string used in the C# code? Am I passing the System::String wrong or is something else have to be done? What must I do to match the System::String^ message parameter to the string parameter?
Thanks
Been correction I tried your solution and it gave the following error:
1 error C3352: 'void ServerClass::ActionMethod(int,int,System::String ^)' : the specified function does not match the delegate type 'void (void)'
#Ben : Getting close. Now when I compile the code using you solution i get an internal compile error as shown:
error C1001: An internal error has occurred in the compiler.
c:\program files (x86)\microsoft visual studio 9.0\vc\include\msclr\marshal.h 49 1 win32project
The code is compiled in Visual Studio 10 where the Framework 3.5 is used and not 4.0
I checked the line where the internal compile occurs and the error happens here in
line 49 in the marshal.h file:
_size = ::WideCharToMultiByte(CP_THREAD_ACP, WC_NO_BEST_FIT_CHARS, _pinned_ptr, _str->Length, NULL, 0, NULL,NULL);
if (_size == 0 && _str->Length != 0)
{
throw gcnew System::ArgumentException(_EXCEPTION_WC2MB);
}
I guess the error happens because the String::String^ input parameter in the c++ code is not being marshaled probably to the c# code, or the other way around.
I'm not sure what I need to fix the c++ side of the code or the C# side of the code.
Any idea?
I guess could just make a c++ dll and have the c# library import the library and call a method in the c++ dll, and then have the win32 application load the c++ dll, but that would seem to be odd to have a library load a w++ dll when the c++ dll used the c# library as a reference.
I checked the line where the internal compile occurs and the error happens here
line 49 in the marshal.h file.
_size = ::WideCharToMultiByte(CP_THREAD_ACP,
WC_NO_BEST_FIT_CHARS,
_pinned_ptr,
_str->Length,
NULL, .
0,
NULL,
NULL);
if (_size == 0 && _str->Length != 0)
{
throw gcnew System::ArgumentException(_EXCEPTION_WC2MB);
}
I guess the error happen because the String::String^ input parameter in the c++ code is not being marshalled probably to the c# code, or the other way around.
Not sure id I need to fix the c++ isde of the code or the C# side of the code.
If it's a native C++ function, use Marshal.GetDelegateForFunctionPointer
If you're using C++/CLI, which it sounds like (and you should retag the question), you want something along the lines of:
NetSocket(gcnew Action<int,int,String^>(this, &ServerClass::ActionMethod))

InternetExplorer being set up as __ComObject instead of SHDocVw.InternetExplorer

I'm having a problem with the InternetExplorer in SHDocVw.dll. I also have mshtml.tlb referenced (while googling, I did read 1 comment that said I should have mshtml.dll referenced, but that this couldn't be done in Microsoft Visual Studio Express, I don't know how true this is though). Here's one small function in its most basic form that won't work for me:
public static HtmlElement GetDocumentControlByID(
ref SHDocVw.InternetExplorer IEObj,
string ControlID)
{
HtmlElement ReturnElement = IEObj.Document.GetElementById(ControlID);
return ReturnElement;
}
The problem is that when I create the IEObj instance, it is considered type System.__ComObject instead of SHDocVw.InternetExplorer, and all subparts are also of type System.__ComObject. When I try any of the following statements...
Document WebDoc = IEObj.Document;
HtmlElement ReturnElement = IEObj.Document.GetElementById(ControlID);
...I keep getting the same error message:
Cannot implicitly convert type 'System.__ComObject' to 'System.Windows.Forms.HtmlElement'
(obviously the convert-to type is different for the IEObj.Document).
I am new to c# (coming from VBA, so I am familiar with programming), but in VBA, the equivelant works perfectly without needing to convert it in any way.
Is it something I'm doing wrong? In case it's my creation of the object, the following is (roughly) the code I used to test the function:
public static void Main(String [] args)
{
SHDocVw.InternetExplorer IEObj = new SHDocVw.InternetExplorer();
IEObj.Navigate("http://sports.ladbrokes.com/");
while (IEObj.ReadyState != 4)
{
}
// There is a textbox that definitely exists
HtmlElement NetControl = GetDocumentControlByID(ref IEObj, "username");
// I was goint to manipulate it after this, but it crashes in the above function.
}
All I really want to do is latch onto various elements so that I can enter text into textboxes, click buttons etc. I would also need to be able to use the Document variables as well (like Document.Body.InnerHtml, etc). The whole project is to be a bunch of functions to be contained in a DLL to be referenced by other projects.
You're trying to use the WinForms HtmlElement class, which isn't a COM object.
You can't mix the native InternetExplorer COM object with the managed classes in WinForms.
You should use the WinForms classes (the WebBrowser control) instead.
In most cases, you don't need COM at all.

Open a dialog box from a DLL

I have a Visual Studio 2008 solution with two projects: a C# Windows Forms application and a C++ DLL. The DLL opens a custom CFileDialog. Here is a toy version that demonstrates the problem, where the C# app is just a button to launch the dialog and a label to show its result:
DialogApp.cs:
...
public partial class Form1 : Form {
...
[DllImport("DialogDll.dll")]
static extern int OpenDialog();
...
private void button1_Click(object sender, EventArgs e) {
int r = OpenDialog();
label1.Text = r.ToString();
}
}
DialogDll.h:
extern "C" {
__declspec(dllexport) int __cdecl OpenDialog();
}
DialogDll.cpp:
#include <afxdlgs.h>
#include "DialogDll.h"
extern int __cdecl OpenDialog() {
CFileDialog d(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All Files (*.*)|*.*||"), NULL);
if (d.DoModal() == IFOK) {
return 4;
} else {
return 9;
}
}
When I run this, I get an error about a debug assertion failing, asking to Abort|Retry|Ignore. The assertion is afxCurrentResourceHandle != NULL. How do I get rid of this problem? If I click Ignore, I get my dialog, and everything appears to work fine.
I've already tried following the instructions here:
http://msdn.microsoft.com/en-us/library/7a51wcfx.aspx
These directions say the problem is that a DLL doesn't have a CWinApp object, and I should add AFX_MANAGE_STATE(AfxGetStaticModuleState()) to the beginning of each function call. I did that, and had to resolve a linker issue by following the directions here, manually specifying the entry point for my DLL: http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/0b154e1c-141f-4567-bb24-1ac7c8ee2713/ (The parts about changing the order of the .libs didn't work for me.)
But now I'm getting another error:
LoaderLock was detected:
Attempting managed execution code inside OS Loader Lock. Do not attempt to run
managed code inside a DllMain or image initialization function since doing so
can cause the application to hang.
Good grief! Am I even going in the right direction? I've done years of programming, but I'm pretty new to the Windows platform. I think after all this work, my question is still pretty simple: How do I open a CFileDialog from my dll?
You are probably going in the right direction. I am assuming that you want/need to use MFC in your DLL.
The WinApp and MANAGE_STATE advice was good.
Are you throwing /clr or /clr:pure on any of your C++ source files? Why? Does your C++ DLL mix managed and native code together?
The fix for this trivial app is to not throw /clr. This will make all your C++ code native and ensure that you are not at risk of calling managed static initialisers from the loader lock.
Martyn
Please see comment above, but I would recommend as my answer:
Use System.Windows.Forms.OpenFileDialog instead OR
Use GetOpenFileName

Categories