Hook Volume Keys in .NET - General Questions and Answers

Hi,
I try to install a Keyboard Hook to get volume key presses in .NET 3.5.
But it fails. Does someone know how to do it?
This is my VB .NET code:
Code:
Imports System.Runtime.InteropServices
Public Delegate Function HookCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As intptr) As Integer
Public Class Form1
<MarshalAs(UnmanagedType.FunctionPtr)> _
Private callbackKeyboard As HookCallback
Private Shared hHookKeyboard As Integer = 0
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If hHookKeyboard.Equals(0) Then
callbackKeyboard = New HookCallback(AddressOf KeyboardHookProc)
hHookKeyboard = WinApi.SetWindowsHookEx(WinApi.WH_KEYBOARD_LL, callbackKeyboard, WinApi.GetModuleHandle(Nothing), 0)
If hHookKeyboard.Equals(0) Then
MessageBox.Show("Keyboard Hook Failed:" & vbCrLf & hHookKeyboard.ToString() & vbCrLf & Marshal.GetLastWin32Error(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1)
End If
End If
End Sub
End Class
'API Functions
Public Class WinApi
Public Const WH_KEYBOARD_LL As Integer = 13
Public Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
<DllImport("coredll.dll")> _
Public Shared Function SetWindowsHookEx( _
ByVal idHook As Integer, ByVal HookProc As HookCallback, _
ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
End Function
<DllImport("coredll.dll")> _
Public Shared Function GetModuleHandle(ByVal mod2 As String) As IntPtr
End Function
<DllImport("coredll.dll")> _
Public Shared Function CallNextHookEx( _
ByVal idHook As Integer, ByVal nCode As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
End Class

glad to claim not vb knowlege at all but I can advice you to search
for c# solutions as everything which can be don in c# can be don as
far as I know in vb.net even if the syntes is horrid
thing is most people who you want to get advice from would never
use vb but if you read their stuff you can with a bit of skill convert it
from c# to vb.net even if it makes baby jesus cry

Well, this Code is inspired by C# code from here.
I know that most .NET developers use C# and not VB so I searched for C# code too. I've already used keyboard hooks in desktop apps but this does not work for .NET CF.

Very strange, I tried the same code in C# and it worked!
So I'll write my app in C#

Whatever language you have written the code in should not make any difference. Take the C# generated .EXE file or .DLL that works, and load it into RED GATE's .NET Reflector.
http://www.red-gate.com/products/reflector/
A freeware download, just agree to the disclaimer etc.
Load your program in it and navigate down until the code appears in the main window. It will show you the C# code that was used to create it. It won't know the variable names but it will replace them with int1,int2,string1,float1 etc.
Here's the clever bit, use the drop down box to switch the language to VB, and it will display the VB code to do the same job. You should be able to spot the difference in the code compared to your own VB original.

Related

All About Gigabyte GSmart i120

Hi there!
Does anyone here uses the GSmart i120 from Gigabyte?
If so, I've got alot of questions about it.
I'm so used to using a phone with a numeric keypad, Like Nokia to compose SMS using one hand.
Now that I have this GSmart i120, I thought it works the same as a Nokia when typing SMS using the keypad..But I was wrong.
It has this input thing called "Smart Keypad" which is not so Smart as I find it really dumb and stupid.
It lets you type in the text or characters using the keypad alright, but it has this lag or wait time that is really slow that you have to wait maybe 1.5 seconds just to be able to type-in the next character. and if you press another key, then it will type-in the letter or character of that key.
I've found this CAB file for the Phone Pad from another PPC-Phone device (i forgot where it was extracted from) and it sort of works like a Nokia keypad when typing SMS. but it uses the touch-screen LCD. what I'd like to do is maybe modify that CAB file so that it will instead MAP the numeric keypad of my device.
So, my question is can anyone help me in finding a solution to this?
I Have here the code to MAP the hardware keypad, but i don't know how to do it and integrate it with the Phone Pad.
Paste the following code into a module, and call in in the form_load as follows:-
Dim messageWindow As Hwbuttons.hwMessageWindow
Me.messageWindow = New Hwbuttons.hwMessageWindow(Me)
RegisterHKeys.RegisterRecordKey(Me.messageWindow.H wnd)
Imports Microsoft.WindowsCE.Forms
Imports System.Runtime.InteropServices
Public Enum KeyModifiers As Integer
None = 0
Alt = 1
Control = 2
Shift = 4
Windows = 8
Modkeyup = &H1000
End Enum
Public Enum KeysHardware As Integer
Hardware1 = 193
Hardware2 = 194
Hardware3 = 195
Hardware4 = 196
Hardware5 = 202
End Enum
Public Module RegisterHKeys
<DllImport("coredll.dll", Entrypoint:="RegisterHotKey", setLastError:=True)> _
Public Function RegisterHotKey( _
ByVal hWnd As IntPtr, _
ByVal id As Integer, _
ByVal Modifiers As KeyModifiers, _
ByVal key As Integer) As Boolean
End Function
<DllImport("coredll.dll")> _
Private Function UnregisterFunc1( _
ByVal modifiers As KeyModifiers, _
ByVal keyID As Integer) As Boolean
End Function
Public Sub RegisterRecordKey(ByVal hWnd As IntPtr)
UnregisterFunc1(KeyModifiers.Windows, CType(KeysHardware.Hardware1, Integer))
RegisterHotKey(hWnd, CType(KeysHardware.Hardware1, Integer), KeyModifiers.Windows, CType(KeysHardware.Hardware1, Integer))
UnregisterFunc1(KeyModifiers.Windows, CType(KeysHardware.Hardware2, Integer))
RegisterHotKey(hWnd, CType(KeysHardware.Hardware2, Integer), KeyModifiers.Windows, CType(KeysHardware.Hardware2, Integer))
UnregisterFunc1(KeyModifiers.Windows, CType(KeysHardware.Hardware3, Integer))
RegisterHotKey(hWnd, CType(KeysHardware.Hardware3, Integer), KeyModifiers.Windows, CType(KeysHardware.Hardware3, Integer))
UnregisterFunc1(KeyModifiers.Windows, CType(KeysHardware.Hardware4, Integer))
RegisterHotKey(hWnd, CType(KeysHardware.Hardware4, Integer), KeyModifiers.Windows, CType(KeysHardware.Hardware4, Integer))
UnregisterFunc1(KeyModifiers.Windows, CType(KeysHardware.Hardware5, Integer))
RegisterHotKey(hWnd, CType(KeysHardware.Hardware5, Integer), KeyModifiers.Windows, CType(KeysHardware.Hardware5, Integer))
End Sub
Public Class Hwbuttons
Inherits System.Windows.Forms.Form
Public Shared messageWindow As hwMessageWindow
Public Class hwMessageWindow
Inherits messageWindow
Public Const WM_HOTKEY = &H312
Dim example As frmComms
Public Sub New(ByVal example As frmComms)
Me.example = example
End Sub
Protected Overrides Sub WndProc(ByRef msg As Message)
Select Case msg.Msg
Case WM_HOTKEY
'ButtonPressed(msg.WParam.ToInt32())
Return
End Select
MyBase.WndProc(msg)
End Sub
Public Sub ButtonPressed(ByVal button As Integer)
Select Case button
Case KeysHardware.Hardware1
MessageBox.Show("Button 1 pressed!")
Exit Sub
Case KeysHardware.Hardware2
MessageBox.Show("Button 2 pressed!")
Exit Sub
Case KeysHardware.Hardware3
MessageBox.Show("Button 3 pressed!")
Exit Sub
Case KeysHardware.Hardware4
MessageBox.Show("Button 4 pressed!")
Exit Sub
Case KeysHardware.Hardware5
MessageBox.Show("Button 5 pressed!")
Exit Sub
End Select
End Sub
End Class
End Class
End Module
Also, the phone has a TV-recording function, but it records only in 3GP instead of the more decent Mpeg format. Can anyone also help me out with this? I'd sure appreciate it! Thanks.
And also, I think the device doesn't support or doesn't have the AVRCP Bluetooth profile, is there a Hack or a CAB file that I can download so I can have AVRCP support on the GSmart i120?
hello !!
i also use i120 ! can you find a solution for it???

Problem in message handling VC++

Hello friends,
First off, please check below code. Well, I am developing printing functionality from the windows mobile device using vc++. (I am novice to the vc++ ). For printing, we are using third party DLLs. Below are important snippet required to explain the complete picture. Currently, the problem I am more concerning is printing multiple pages. For this, we have API and everything. While printing using “mpPreviewDialog” API (provided by third party in form of DLL) and when it recognize more than one pages required, it raises/passes “MP_EVENT_REQ_NEW_PAGE” message from printing library, ie mpPreviewDialog itself, to the handle hWnd of “mpPreviewDialog(hWnd,__)”. Now, to handle this message, we have put all logic portion in one class which is inherited from CWnd so that we can override “DefWindowProc” function to achieve our goal. But while I run the application and command print for multiple page, it only prints the first page perfectly and then just get hanged. Thus, it fails to handle the “MP_EVENT_REQ_NEW_PAGE” message of “DefWindowProc” function. What all I need is to handle this message and execute the case MP_EVENT_REQ_NEW_PAGE: while printing and multiple page required. Because in this case it issues the message but appropriate case never get executed. I hope you got my point. Please let me know how to solve this. Am I missing something? Thank you very much for your time in advance.
class CFxPrinterWnd : public CWnd
{
DECLARE_DYNCREATE(CFxPrinterWnd)
public:
CFxPrinterWnd(); // protected constructor used by dynamic creation
virtual ~CFxPrinterWnd();
public:
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
public:
int PrintReport(HWND hwnd, int flg);
protected:
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};
Int CFxPrinterWnd:rintReport (HWND hWnd, int flg)
{
_______
This contains “mpPreviewDialog” API call which starts printing and issue “MP_EVENT_REQ_NEW_PAGE” message if more than one page required.
}
LRESULT CFxPrinterWnd:efWindowProc(___,___,___)
{
Switch (message)
{
___
Case MP_EVENT_REQ_NEW_PAGE: //This debug point never get focused while printing and new page required.
___This point is never get executed
___
}
}
Button1 Click Event
{
hWnd = ::FindWindow(NULL, _T(“del”));
CFxPrinterWnd wnd;
Wnd.Create(_______________________);
Ret = wnd.PrintReport(hWnd, 0);
___
___
mpPreviewDialog (hWnd____); //This is the printing API where MP_EVENT_REQ_NEW_PAGE message get raised while printing if new page
//required.
wnd.DestroyWindow();
}
---
Kind Regards,
Sachin Patel

Help hiding window in VB.NET

I'm trying to hide the incoming call window, but it's not working.
I declare the functions
Public Declare Function ShowWindow Lib "Coredll" (ByVal hWnd As IntPtr, ByVal iVisible As Integer) As Boolean
Public Declare Function FindWindow Lib "Coredll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Then call
ShowWindow(FindWindow("", "Phone - Incoming"), 0)
But the window is still there. And yes the window title is correct. I've been trying to debug for over an hour. I don't get any errors it just doesn't work. Any help is greatly appreciated.

Modem Communication in .NET

I've been looking through the vast amount of info on gaining access to the chipset for sending AT commands. What I'm attempting to do is make this easy within a visual studio .NET project.
My Test device is a HTC touch pro2 running WM6.1
I have translated most of a post from this forum into VB.net. see attached ril.zip for the c code I'm trying to translate. see attached smartdeviceapplication1.zip for my attempt at translation.
My code is attached. I cannot work out the DeviceIoControl function (even after following the MSDN documentation) and the EscapeCommFunction wont work.
I need some help with what I'm doing wrong here. I'm basically trying to translate the c++ code to vb.net code.. (I know, VB.net is for loosers. but with all the people on the internet asking for this, it seems it might be usefull for someone other than just me)
The goal is to make a class to provide direct access to the com ports with .NET.
Let me know if someone has already done this. My searching on the internet only comes up with variants of c code.
Thanks
my code for gretting the DeviceIoControl
<DllImport("coredll.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Public Shared Function DeviceIoControl _
(<[In]()> ByVal hDevice As IntPtr, _
<[In]()> ByVal dwIoControlCode As Int32, _
<[In]()> ByVal lpInputBuffer As IntPtr, _
<[In]()> ByVal nInBufferSize As Integer, _
<Out()> ByVal lpOutBuffer As IntPtr, _
<[In]()> ByVal nOutBufferSize As Integer, _
<Out()> ByRef lpBytesReturned As Integer, _
<[In]()> ByVal lpOverlapped As IntPtr) As Integer
End Function
Ok.. I just realised I needed to initialise the ril and get a new com handle. it then creates com 9 which is the port to use..... It helps when you read the MSDN docs!

[GUIDE] Marshalling data in Compact Framework

Author: Apriorit (Device Team)
Permanent link: apriorit(dot)com/our-company/dev-blog/62-marshalling-data-in-cf
In many situations when we create applications for different embedded systems or mobile platforms we can’t develop all parts of the product using managed code only.
For example we need several modules written in native language which perform some low level operations or we already have these libraries written on C++. So we have to use more than one programming language in our product and also use data marshaling in it.
In this article we will review some aspects of using data types and ways of using them during marshalling data to and from unmanaged code.
Making your interop calls more efficient
Marshaling is the act of taking data from one environment to another. In the context of .NET marshalling refers to transferring data from the app-domain you are in to somewhere else, outside.
You should remember that such Platform Invoke calls are slower than direct native calls and than regular managed calls. The speed depends on types marshaled between managed and native code, but nevertheless you should avoid using Platform Invoke calls if you have a chance to do this. Also it is recommended to use calls with some amount of transferred data than several “small” Platform Invoke calls.
Bitable types
It is recommended to use simple data types (int, byte, boolean, characters and strings). It makes the call more efficient and helps to avoid any convertions and copying. These blittable types have identical representation in both managed and unmanaged memory. But you should remember that in Compact Framework during marshaling boolean type is represented as 1-byte integer value (instead of 4-byte integer value in the full .NET Framework), character type (char) is always represented as 2-bytes Unicode character and String type is always treated as a Unicode array (in full .NET Framework it may be treated as a Unicode or ANSI array, or a BSTR).
Method Inlining
The JIT compiler can inline some methods in order to make the calls more efficient. You can not force a method to be inlined by the compiler, but you can make it NOT to be inlined. In order to avoid inlining you can:
• make the method virtual;
• add branching to the method’s body;
• define local variables in the method;
• use 2-bit floating point arguments (or return value).
Disabling method inlining can help to detect a problem during Platform Invoke calls.
Sequential layout
In the Compact Framework all structures and classes always have sequential layout (the managed value type has the same memory layout as the unmanaged structure). This behavior can be specified by setting attribute LayoutKind.Sequential. You don’t need to specify this attribute in Compact Framework, but if you use these pieces of code in both full .NET Framework and Compact Framework you have to set it to avoid different behavior on two platforms.
The following sample shows how to send some pointers from C# code for storing them in the native module.
Code C#:
Code:
[StructLayout(LayoutKind.Sequential)]
public class BasePointers // you can use the struct too
{
public IntPtr pointer1;
public IntPtr pointer2;
}
[DllImport("NativeDLL.dll", CallingConvention = CallingConvention.Winapi)]
// Cdecl
public static extern int TransferStruct(BasePointers pointers);
Code C++:
Code:
struct BasePointers
{
unsigned int pointer1;
unsigned int pointer2;
}
extern "C" __declspec(dllexport) int CDECL TransferArray(BasePointers*
pointers);
One Calling Convention
The Calling Convention determines the order in which parameters are passed to the function, and who is responsible for the stack cleaning. The .NET Compact Framework supports only the Winapi value (Cdecl on this platform) of Calling Convention. It defines the calling convention for C and C++ (instead of the full .NET Framework which supports three different calling conventions). To avoid crashes of your application you should make sure that your calling conventions in both managed and native declarations are same.
If you specify the attribute to preserve signature of functions ([PreserveSig]) then the returned value will contain 32-bit HRESULT value that will give you more data to analyze errors during the native function execution. The Calling Convention can be specified by adding the attribute CallingConvention to the declaration of your function. As it was mentioned the .NET Compact Framework supports only “Winapi” Calling Convention that corresponds to Cdecl:
Code C#:
Code:
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int ProgressEventHandler(int progressValue);
Code C++:
Code:
typedef void (CDECL *ProgressEventHandler)(int progressValue);
Data Alignment
In some situations we need to transfer data between the managed and unmanaged code in the structures. As it’s written above all structures have sequential layout in the Compact Framework, but you should remember about representation of structs in the managed in unmanaged code. The way of packing structures depends on a platform and on a way how the members of structure are aligned. On ARM platform this value for alignment is four (all values in structures are aligned to 4 bytes).
Code:
typedef struct OurStruct
{
unsigned char valueChar;
usingned int valueInt;
} ourStruct_;
This structure could be perfectly acceptable in desktop code, but if you use such structure on the Windows Mobile platform then you might receive valueInt at the offset 4. If you use such structures in both desktop and device's side code you have to use them carefully during marshaling.
During marshaling data you might receive such errors as “Datatype misalignment” (0x80000002) or “Access violation” (0x80000005). It indicates that you are using wrong pointers or try to access to the wrong offset of data. For example, you transfer array of bytes from C# code to the native module and define you functions as:
C# code:
Code:
[DllImport("NativeDLL.dll", CallingConvention = CallingConvention.Winapi)]
// Cdecl
public static extern int TransferArray(IntPtr src, int srcSize);
C++ Native Module code:
extern "C" __declspec(dllexport) int CDECL TransferArray(byte* srcArr,
int srcSize);
If you try to use the pointer “srcArr” as the pointer on integer (int*) and then try to use the corresponding value you will receive an error :
Code:
int value = *(int*)srcArr; // Datatype misalignment
The simple way to avoid this problem is to change declaration of C++ function and change the pointer on array of bytes to the pointer on array of integer and use it without any problems:
Code:
extern "C" __declspec(dllexport) int CDECL TransferArray(int* srcArr,
int srcSize);
Marshal class
You can use methods in the class Marshal to manually convert managed objects and perform conversions between IntPtrs. These methods are PtrToStructure, GetComInterfaceForObject, PtrToStringBSTR, GetFunctionPointerForDelegate and others. It allows you to control marshaling. These methods are also useful for debugging issues with marshaling parameters where the runtime is not able to convert a particular argument.
You cannot pass delegate directly to the native module as parameter of you function because the .NET Compact Framework does not support marshaling of delegates. Instead you should use method Marshal.GetFunctionPointerForDelegate for getting function pointer which you can pass to the native code and call it.
Code:
Code:
class MainClass
{
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int ProgressEventHandler(int progressValue);
...
void OnProgressChanged(int progressValue)
{
...
}
…
…
[DllImport("NativeDLL.dll", CallingConvention = CallingConvention.Winapi)]
// Cdecl
public static extern int SetCallbackFunction(IntPtr functionPointer);
}
// Passing function pointer
Delegate d = new ProgressEventHandler(OnProgressChanged);
IntPtr progressChanged = Marshal.GetFunctionPointerForDelegate(d);
int result = SetCallbackFunction(progressChanged);
But you should be aware of Garbage Collector (GC) in such situation. The GC might collect you delegates and your function pointers will become invalid. It may happen when you passed the function pointer to the native code as callback method in order to call it later - GC might think that there are no references to it in the managed code. To avoid this situation you should keep reference to this delegate. For example, you can store it in the classes variable or create some delegates pool, in which you can keep references to the several delegates.
GCHandle
Since we're passing a pointer to some data we need to allocate memory for that data and make sure that the GC will not remove that memory. One of the possible ways to manage this situation is to use GCHandle.
If you want to pass some class (or array of bytes) to the unmanaged code and you need to pin memory for the proper work with it in the unmanaged code you can write:
Code:
class SampleClass
{
...
}
SampleClass classSample = new SampleClass();
GCHandle classHandle = GCHandle.Alloc(classSample, GCHandleType.Pinned);
IntPtr ptrToClass = classHandle.AddrOfPinnedObject();
int result = PassPtrToUnmanagedCode(ptrToClass); // our function
You can also make an instance of GCHandle as a member of the class to avoid deleting them by GC. Also you should remember that the structure is value-type. And pinning it to the memory will cause a problem, because structure will be copied and GCHandle will handle a reference to created “boxed” copy of the object. It will be hard to find such problem in the future.
Conclusion
During marshaling data you may face with the problems described above. Very often you may get “NotSupportedException” and other exceptions. To find a problem you can enable logging of setting the registry keys. One of the logging components is “Interop ”. The log provides information about Platform Invoke calls and marshaling. You can read MSDN for more information about Creating Log Files.
With the .NET Compact Framework 2.0 you can use Platform Invoke calls in managed application, even though there are a few limitations. You should remember all differences and limitations between full .NET Framework and the Compact Framework to avoid problems in your applications.

Categories

Resources