How do I set the class cursor to null? - pinvoke

Sorry about the long post! I have some explaining to do, I'm afraid... I have an application (in Unity3d, but for windows) that doesn't use WinForms, so I cannot use the Cursor class which is part of System.Windows.Forms namespace. But all the same, I'd like to be able to set the current shape of the cursor.
After much research and much googling, I've found that this is possible using P/Invoke calls to certain methods in user32.dll. I got it (sort of) working by:
Find a handle to the window using:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
And supply null for the classname and the title of the window for the windowname. Then use the returned IntPtr to call this:
[DllImport("user32.dll")]
public static extern IntPtr SetClassLong(IntPtr hwnd, int index, IntPtr dwNewLong);
And supply "-4" for the index in order to target the pointer to the WindowProc that handles all the lowlevel window messages, and then use:
System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate()
To generate a native pointer to a new WndProc delegate which I implement in my managed code. Its signature looks like this:
public long WndProc(IntPtr hwnd, uint msg, uint wparam, int lparam);
In summary, I'm basically overriding the native window procedure with a managed callback, and it then becomes my responsibility to handle all the window messages. But I'm not interested in rewriting the entire implementation for the standard window proc, I just want to be able to control the way it draws its mouse cursor shape when the cursor is over the window. So, to do so, I can call the default window proc with this function:
[DllImport("user32.dll")]
public static extern long DefWindowProc(IntPtr hwnd, uint msg, uint wparam, int lparam);
And then immediately afterwards, set the cursor to something else using:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr SetCursor(IntPtr hCursor);
This sort of works. :) I say "sort of", because I'm seeing a bit of flickering that occurs because the default window proc first sets the cursor to the class cursor, and then immediately afterwards, my implementation sets it to the custom cursor I want using SetCursor. This situation can be remedied by setting the class cursor to null. Doing so causes the system to not draw the cursor and expect the application to set the cursor for every window message instead, and that's exactly what I'm doing, so it would stop them fighting over the who gets to set the cursor and eliminate the flickering. This is documented on MSDN at:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648393%28v=vs.85%29.aspx
Where they explain that one must set the class cursor to null. But that's where my knowledge falls short. :( The class cursor is set with SetClassLong as explained in the article above.
But the datatype for the new value of the cursor is IntPtr. This datatype is not nullable, the compiler complains if I pass in null, and passing in IntPtr.zero doesn't work. So how do I accomplish what the article advices? How do I set the class cursor to null using P/Invoke?

Related

How to properly store an HWND in a ref class?

I'm working on a C++/CLI library to be used with C#. I have a ref class (for use directly within managed code, so it has to be compatible) that stores an HWND, but I don't think I'm doing it right:
public ref class MyClass {
protected:
HWND hWnd;
}
Should I be using a native pointer like that inside a ref class? Or should I use something like ptr<T>?
A handle is not a pointer, HWND is fine. If you want C# code to derive from your class and access the handle then you need to expose it as an IntPtr. Which is compatible with a handle, it is 4 bytes in 32-bit mode and 8 bytes in 64-bit mode, just like a handle.
Best to wrap it with a property to hide the conversion:
protected:
property IntPtr Handle {
IntPtr get() { return IntPtr(hwnd); }
void set(IntPtr h) { hwnd = (HWND)h.ToPointer(); }
}
private:
HWND hWnd;
A SafeHandle might be useful, the lifetime of a HWND is however not typically under your control.
Native pointers/handles are completely safe inside ref classes. (They're just ints after all.) However, it would be more idiomatic to store them in the IntPtr class. (This is how WinForms stores them.)

Why do libgit2 methods using kernel32.dll's GetProcAddress always return 0?

I have the need to manually handle the loading / unloading of the actual git2.dll, instead of using [DllImport("git2")] in C#. I seem to have issues with creating an IntPtr for reference to the address of methods stored in libgit2.
Here're the good bits from my PluginManager class which are supposed to help facilitate manually loading, marshal/delegate (whenever I get this kink fixed), and unloading libraries.
public class PluginManager {
public const string LIB = "Assets\\Plugins\\git2.dll";
[DllImport( "kernel32.dll", CharSet = CharSet.Ansi )]
public static extern IntPtr LoadLibrary( [In, MarshalAs( UnmanagedType.LPStr )] string lib );
[DllImport( "kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true )]
public static extern IntPtr GetProcAddress( [In] IntPtr reference, [In, MarshalAs( UnmanagedType.LPStr )] string method );
[DllImport( "kernel32.dll" )]
public static extern bool FreeLibrary( [In] IntPtr reference );
}
Here's where I attempt to use them:
//# Working; always non-zero.
IntPtr reference = PluginManager.LoadLibrary( PluginManager.LIB );
//# Should be valid -- LibGit2Sharp.Core.NativeMethods.cs calls this method, too.
//# Always returns IntPtr.Zero.
IntPtr methodReference = PluginManager.GetProcAddress( reference, "git_repository_open" );
Is the library not exposed to this type of loading? I've tried all kinds of methods present in the LibGit2Sharp native hooks, but they always return zero.
It seems that git2.dll has mangled export names, so git_repository_open is actually _git_repository_open#4. After researching some more on why this is happening, it seems that, according to This Post, and several others that I've run into while looking for a fix, that the functions may not be exported using extern "C" or may not be using a .def file.
I did look through some of the libgit2 code, and I saw extern used on a couple functions, but on others I saw no export keyword at all, but they're still being accessed externally from LigGit2Sharp's NativeMethods.cs class.
While all of that is foreign to me, I did find a very useful post about a tool shipped with Visual Studio that allows you to see all exported items, and their names: Dumpbin. With this, I was able to determine the exported names, and used the /OUT:filename flag to save them to a file: PasteBin
With all of the exported names at my disposal, I just have to follow function calls, that I'm actually using, and replace the the methods in NativeMethods.cs to look something like this: LibGit2Sharp Issue #341.

Unable to find an entry point

I import two WinApi functions and use them in my class
using namespace System::Runtime::InteropServices;
[DllImport("user32",ExactSpelling = true)]
extern bool CloseWindow(int hwnd);
[DllImport("user32",ExactSpelling = true)]
extern int FindWindow(String^ classname,String^ windowname);
public ref class WinApiInvoke
{
public:
bool CloseWindowCall(String^ title)
{
int pointer = FindWindow(nullptr,title);
return CloseWindow(pointer);
}
};
Then I create object in main program and call CloseWindowCall method
Console::WriteLine("Window's title");
String ^s = Console::ReadLine();
WinApiInvoke^ obj = gcnew WinApiInvoke();
if (obj->CloseWindowCall(s))
Console::WriteLine("Window successfully closed!");
else Console::WriteLine("Some error occured!");
When I write in console for example Chess Titans to close I've got an error
Unable to find an entry point named 'FindWindow' in DLL 'user32'
What entry point?
You are using the ExactSpelling property inappropriately. There is no FindWindow function in user32.dll, just like the exception message says. There is FindWindowA and FindWindowW. The first one handles legacy 8-bit character strings, the second uses Unicode strings. Any Windows api function that accepts strings has two versions, you don't see this in C or C++ code because the UNICODE macro selects between the two.
Avoid ExactSpelling on winapi functions, the pinvoke marshaller knows how to deal with this. You have some other mistakes, the proper declaration is:
[DllImport("user32.dll", CharSet = CharSet::Auto, SetLastError = true)]
static IntPtr FindWindow(String^ classname, String^ windowname);

Turning off screen echo in VB.NET

In Microsoft Access there was an easy method to turn off screen updates by setting Echo = False. Is there an equivalent in VB.NET for WinForms? I've got a situation where I'm trying to prevent users from seeing controls flickering while they're being updated. I could probably solve the problem by coding it differently, but would rather avoid it if I can.
What you're looking to do is suspend and resume the redrawing of your form. There isn't a managed API for this, but it's a fairly trivial P/Invoke to do it. I don't remember the VB.NET syntax for declaring external functions right off the top of my head, but this C# example should give you the information that you need to know.
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
public static void SuspendDrawing(Control target)
{
SendMessage(target.Handle, WM_SETREDRAW, false, 0);
}
public static void ResumeDrawing(Control target)
{
SendMessage(target.Handle, WM_SETREDRAW, true, 0);
target.Refresh();
}
In C# (where this represents your form):
this.SuspendLayout();
// Make your changes
this.ResumeLayout(false);

Run-Time Check Failure #0 vb.net callback from C dll

I'm writing Add-inn Application A in VB.Net and DLL B in C language.
Application A pass callback method to dll B.
When certain event occur the dll invoke the callback from A.
Whole works fine on my PC but when I move it to Notebook I get an error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
This is part of C code:
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3){
switch (dwMessage)
{
case LINE_CALLSTATE:
switch (dwParam1)
{
case LINECALLSTATE_OFFERING:
if(dwInstance!=NULL)
{
try
{
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
}
catch(...)
{
MessageBox (NULL, L"( (OFFICE_PTR)dwInstance )(&sCallNr)",L"ERROR",MB_OK);
}
}
break;
};
break;
}
}
Where dwInstance is a address of application A callback method
This is part of VB.Net code:
Public Class TapiPlugin
Public Delegate Sub P_Fun()
Private Declare Function startSpy _
Lib "TAPIClient.dll" _
(ByVal pFun As P_Fun) As IntPtr
Public Shared Sub simpleTest()
MsgBox("Plugin sub simpleTest")
End Sub
Public Sub onStart()
Dim pBSTR As IntPtr
pBSTR = startSpy(AddressOf simpleTest)
MsgBox(Marshal.PtrToStringAuto(pBSTR))
Marshal.FreeBSTR(pBSTR)
End Sub
End Class
The Error occur when I try call 'vbFunc( )'. I would be grateful for any help. :D
If the calling convention is cdecl, then you need to declare your delegate like this:
<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Sub P_Fun()
You can only do this in .NET 2.0 and after, as the attribute was not introduced before then (and the interop layer was not changed to acknowledge it before that).
If the calling convention is indeed stdcall then the delegate can remain as is. You said it is stdcall, but I have doubts, since the exception is explicitly telling you that there might be a mismatch in calling conventions.
Do the two computers have different pointer sizes perhaps? Maybe one is a 64 bit machine and the other only 32?
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
...){
...
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
The DWORD type is not really valid for passing pointer types. You should be using INT_PTR I guess.
I thing it is not a reason to check it out I passed the callback as global pointer of type OFFICE_PTR and i get the same result. On PC it work fine on Notebook it crash :(
A have to apologies for a mistake I wrote that the def look like:
typedef void (__cdecl * OFFICE_PTR)();
but for real it looks like
typedef void (__stdcall * OFFICE_PTR)();