You might check out e.g.

[link:stackoverflow.com]

as well as just do a web search for "F# DllImport" to find other examples.

By on 4/11/2010 11:33 AM ()

Well my current work is like the following.

VIRTUALKEYF.fs
namespace User32type VIRTUALKEYF =| LBUTTON = 0x01| RBUTTON = 0x02| CANCEL = 0x03| MBUTTON = 0x04 // NOT contiguous with L & RBUTTON
| XBUTTON1 = 0x05 // NOT contiguous with L & RBUTTON| XBUTTON2 = 0x06 // NOT contiguous with L & RBUTTON
// 0x07 : unassigned
| BACK = 0x08| TAB = 0x09
// 0x0A - 0x0B : reserved
| CLEAR = 0x0C| RETURN = 0x0D
| SHIFT = 0x10| CONTROL = 0x11| MENU = 0x12| PAUSE = 0x13| CAPITAL = 0x14
| KANA = 0x15| HANGEUL = 0x15 // old name - should be here for compatibility| HANGUL = 0x15| JUNJA = 0x17| FINAL = 0x18| HANJA = 0x19| KANJI = 0x19
| ESCAPE = 0x1B
| CONVERT = 0x1C| NONCONVERT = 0x1D| ACCEPT = 0x1E| MODECHANGE = 0x1F
| SPACE = 0x20| PRIOR = 0x21| NEXT = 0x22| END = 0x23| HOME = 0x24| LEFT = 0x25| UP = 0x26| RIGHT = 0x27| DOWN = 0x28| SELECT = 0x29| PRINT = 0x2A| EXECUTE = 0x2B| SNAPSHOT = 0x2C| INSERT = 0x2D| DELETE = 0x2E| HELP = 0x2F
//// VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)// 0x40 : unassigned// VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)//
| LWIN = 0x5B| RWIN = 0x5C| APPS = 0x5D
//// 0x5E : reserved//
| SLEEP = 0x5F
| NUMPAD0 = 0x60| NUMPAD1 = 0x61| NUMPAD2 = 0x62| NUMPAD3 = 0x63| NUMPAD4 = 0x64| NUMPAD5 = 0x65| NUMPAD6 = 0x66| NUMPAD7 = 0x67| NUMPAD8 = 0x68| NUMPAD9 = 0x69| MULTIPLY = 0x6A| ADD = 0x6B| SEPARATOR = 0x6C| SUBTRACT = 0x6D| DECIMAL = 0x6E| DIVIDE = 0x6F| F1 = 0x70| F2 = 0x71| F3 = 0x72| F4 = 0x73| F5 = 0x74| F6 = 0x75| F7 = 0x76| F8 = 0x77| F9 = 0x78| F10 = 0x79| F11 = 0x7A| F12 = 0x7B| F13 = 0x7C| F14 = 0x7D| F15 = 0x7E| F16 = 0x7F| F17 = 0x80| F18 = 0x81| F19 = 0x82| F20 = 0x83| F21 = 0x84| F22 = 0x85| F23 = 0x86| F24 = 0x87
//// 0x88 - 0x8F : unassigned//
| NUMLOCK = 0x90| SCROLL = 0x91
//// VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.// Used only as parameters to GetAsyncKeyState() and GetKeyState().// No other API or message will distinguish left and right keys in this way.//| LSHIFT = 0xA0| RSHIFT = 0xA1| LCONTROL = 0xA2| RCONTROL = 0xA3| LMENU = 0xA4| RMENU = 0xA5
| BROWSER_BACK = 0xA6| BROWSER_FORWARD = 0xA7| BROWSER_REFRESH = 0xA8| BROWSER_STOP = 0xA9| BROWSER_SEARCH = 0xAA| BROWSER_FAVORITES = 0xAB| BROWSER_HOME = 0xAC
| VOLUME_MUTE = 0xAD| VOLUME_DOWN = 0xAE| VOLUME_UP = 0xAF| MEDIA_NEXT_TRACK = 0xB0| MEDIA_PREV_TRACK = 0xB1| MEDIA_STOP = 0xB2| MEDIA_PLAY_PAUSE = 0xB3| LAUNCH_MAIL = 0xB4| LAUNCH_MEDIA_SELECT = 0xB5| LAUNCH_APP1 = 0xB6| LAUNCH_APP2 = 0xB7
//// 0xB8 - 0xB9 : reserved//
| OEM_1 = 0xBA // ';:' for US| OEM_PLUS = 0xBB // '+' any country| OEM_COMMA = 0xBC // ',' any country| OEM_MINUS = 0xBD // '-' any country| OEM_PERIOD = 0xBE // '.' any country| OEM_2 = 0xBF // '/?' for US| OEM_3 = 0xC0 // '`~' for US
//// 0xC1 - 0xD7 : reserved//
//// 0xD8 - 0xDA : unassigned//
| OEM_4 = 0xDB // '[{' for US| OEM_5 = 0xDC // '\|' for US| OEM_6 = 0xDD // ']}' for US| OEM_7 = 0xDE // ''"' for US| OEM_8 = 0xDF
//// 0xE0 : reserved//Api.fs:
module User32.Apiopen Systemopen System.Runtime.InteropServices
type INPUTF = | MOUSE | KEYBOARD | HARDWARE[<Flags>] type KEYEVENTF = | EXTENDEDKEY=1 | KEYUP=2 | UNICODE=4 | SCANCODE=8[<Flags>] type MOUSEEVENTF = | MOVE | LEFTDOWN | LEFTUP | RIGHTDOWN | RIGHTUP | MIDDLEDOWN | MIDDLEUP | XDOWN | XUP | UNDEFINED | UNDEFINED2 | WHEEL | HWHEEL | NOCOALESCE | VIRTUALDESK | ABSOLUTE
//typedef struct tagMOUSEINPUT { LONG dx; LONG dy; DWORD mouseData; DWORD dwFlags; DWORD time; ULONG_PTR dwExtraInfo; } MOUSEINPUT, *PMOUSEINPUT;type MOUSEINPUT = struct val dx:int val dy:int val mouseData:int val dwFlags:MOUSEEVENTF val time:uint32 val dwExtraInfo:nativeint new(dx, dy, mouseData, dwFlags, time, dwExtraInfo) = { dx=dx; dy=dy; mouseData=mouseData; dwFlags=dwFlags; time=time; dwExtraInfo=dwExtraInfo } endtype KEYBDINPUT = struct val wVk:VIRTUALKEYF val wScan:uint16 val dwFlags:KEYEVENTF val time:uint32 val dwExtraInfo:nativeint new(wVk, wScan, dwFlags, time, dwExtraInfo) = {wVk=wVk; wScan=wScan; dwFlags=dwFlags; time=time; dwExtraInfo=dwExtraInfo} new(wVk, dwFlags) = new KEYBDINPUT(wVk, uint16 0x45, dwFlags, uint32 0, nativeint 0) endtype HARDWAREINPUT = struct val uMsg:uint32 val wParamL:uint16 val wParamH:uint16 new(uMsg, wParamL, wParamH) = { uMsg=uMsg; wParamL=wParamL;wParamH =wParamH } new(uMsg) = new HARDWAREINPUT(uMsg, uint16 0, uint16 0) endtype INPUT = struct val ``type``:INPUTF val mi:MOUSEINPUT val ki:KEYBDINPUT val hi:HARDWAREINPUT new(``type``, mi, ki, hi) = { ``type``=``type``; mi=mi; ki=ki; hi=hi } new(ki) = new INPUT(INPUTF.KEYBOARD, Unchecked.defaultof<MOUSEINPUT>, ki, Unchecked.defaultof<HARDWAREINPUT>) new(wVk, dwFlags) = new INPUT(new KEYBDINPUT(wVk, dwFlags)) end
// VOID keybd_event(__in BYTE bVk, BYTE bScan, __in DWORD dwFlags, __in PTR dwExtraInfo);[<DllImport("user32.dll")>] extern void keybd_event( byte bVk, byte bScan, int dwFlags, nativeint dwExtraInfo)
[<DllImport("user32.dll")>] extern unit SendInput(uint32 nInputs, INPUT pInputs, int cbSize)
[<DllImport("user32.dll")>] extern int MessageBox(int32 hWnd, string lpText, string lpCaption, uint32 uType)
//[<DllImport("User32.dll")>] let GetKeyState(key:int) : int16 = failwith ""[<DllImport("user32.dll")>] extern int GetKeyState(int nVirtKey)
[<Struct>] type LASTINPUTINFO = val cbSize : uint32 val dwTime : uint32
//[<DllImport("User32.dll")>] extern [<MarshalAs(UnmanagedType.Bool)>] bool GetLastInputInfo(LASTINPUTINFO* plii)[<DllImport("User32.dll")>] extern bool GetLastInputInfo(LASTINPUTINFO* plii)Keyboard.fs
module Keyboardopen Systemopen System.Runtime.InteropServicesopen User32open User32.Api
let GetState (key:VIRTUALKEYF) = (GetKeyState (int key) = 1)
let SetStateWithEvent key state = if state <> GetState key then keybd_event (byte key, byte 0x45, int KEYEVENTF.EXTENDEDKEY, nativeint 0) keybd_event (byte key, byte 0x45, int (KEYEVENTF.EXTENDEDKEY ||| KEYEVENTF.KEYUP), nativeint 0)
let SetStateWithSendInput key state = if state <> GetState key then SendInput(uint32 1, new INPUT(key, KEYEVENTF.EXTENDEDKEY), Marshal.SizeOf(typeof<INPUT>)) SendInput(uint32 1, new INPUT(key, KEYEVENTF.EXTENDEDKEY ||| KEYEVENTF.KEYUP), Marshal.SizeOf(typeof<INPUT>))
let switchNumLock = printfn "%s" (String.Format( "**BEFORE**\r\nCAP: {0}\r\nSCR: {1}\r\nNUM: {2}", (if GetState VIRTUALKEYF.CAPITAL then "ON" else "OFF"), (if GetState VIRTUALKEYF.SCROLL then "ON" else "OFF"), if GetState VIRTUALKEYF.NUMLOCK then "ON" else "OFF")) SetStateWithEvent VIRTUALKEYF.NUMLOCK (not <| GetState VIRTUALKEYF.NUMLOCK)// SetStateWithSendInput VIRTUALKEYF.NUMLOCK (not <| GetState VIRTUALKEYF.NUMLOCK) printfn "%s" (String.Format( "\r\n**AFTER**\r\nCAP: {0}\r\nSCR: {1}\r\nNUM: {2}", (if GetState VIRTUALKEYF.CAPITAL then "ON" else "OFF"), (if GetState VIRTUALKEYF.SCROLL then "ON" else "OFF"), if GetState VIRTUALKEYF.NUMLOCK then "ON" else "OFF"))during run the code it got the keyboard's NumLock switched, and if I comment the line
"SetStateWithEvent VIRTUALKEYF.NUMLOCK (not <| GetState VIRTUALKEYF.NUMLOCK)"
and uncomment the line
"SetStateWithSendInput VIRTUALKEYF.NUMLOCK (not <| GetState VIRTUALKEYF.NUMLOCK)"
then the code doesn't work, could somebody help me to find out my error please!

By on 4/11/2010 1:22 PM ()

In the debugger, I get a message saying the PInvoke signature is wrong.

SendInput needs INPUT as byref. You should change e.g.

type INPUTF = | MOUSE=0 | KEYBOARD=1 | HARDWARE=2
[<Flags>] type KEYEVENTF = | EXTENDEDKEY=1 | KEYUP=2 | UNICODE=4 | SCANCODE=8
[<Flags>] type MOUSEEVENTF = | MOVE=1 | LEFTDOWN=2 | LEFTUP=4 | RIGHTDOWN=8 | RIGHTUP=16 | MIDDLEDOWN=32 | MIDDLEUP=64 | XDOWN=128 | XUP=256 // etc

Make sure these have =value after each, so it is an integer enumeration, and not an F# discriminated union. Then change

[<DllImport("user32.dll")>] extern unit SendInput(uint32 nInputs, INPUT* pInputs, int cbSize)

and

let SetStateWithSendInput key state =
if state <> GetState key then
let mutable i1 = new INPUT(key, KEYEVENTF.EXTENDEDKEY)
let mutable i2 = new INPUT(key, KEYEVENTF.EXTENDEDKEY ||| KEYEVENTF.KEYUP)
SendInput(uint32 1, &&i1, Marshal.SizeOf(typeof<INPUT>))
SendInput(uint32 1, &&i2, Marshal.SizeOf(typeof<INPUT>))

This still doesn't change the program behavior to what you expect, I think, but it definitely fixes a problem with the PInvoke signature.

By on 4/11/2010 4:58 PM ()

Hello Brian!

The PInvoke signature error is not ever raise after I applied the change, but the code is still taking no effect for switching the numlock, and I'm now trying hard to find the error.

By on 4/11/2010 11:54 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper