vba 如何获取键盘消息

vba 如何获取键盘消息,第1张

获取键盘信息

2942 获取键盘信息

在VBA中,没有提供获取键盘状态函数。在程序中若需要查询键盘状态,可编写代码调用API函数节器完成。

1.GetKeyState函数

使用该函数可获取键盘锁定键的状态,函数原型如下:

Public Declare Function GetKeyState Lib

"user32" (ByVal nVirtKey As Long) As Integer

参数nVirtKey为需要获取状态的键常数,在VBA中,每个键都有一个对应的常数,例如,CapsLock键的常数为vbKeyCapital。

该函数返回值为一个整型值,如果最低位为1,则表示锁定键是打开的,因此可以使用以下代码来判断:

CBool(GetKeyState(vbKeyCapital) And 1)

将GetKeyState函数的返回值与整数1进行逻辑与运算,来取得返回值的最低位,然后通过CBool函数将其转换为逻辑值,即可得到指定锁定键的状态。

2.GetKeyboardState函数和SetKeyboardState函数

设置锁定键状态需使用GetKeyboardState和SetKeyboardState函数来 *** 作。这两个函数都用一个256字节缓冲区取得或设置256个键设置,在VBA中设置一个有256个元素的字节数组来作为缓冲区,这个数组记录着键盘状态,每个键在数组中的位置由VK_常数决定。

一旦用GetKeyboardState函数取得键盘各键状态并存储到缓冲区中后,即可修改特定的键设置,然后用SetKeyboardState函数存回设置,达到修改键设置的目的。

GetKeyboardState函数可取得键盘上每个虚拟键当前的状态,其函数原型如下:

Declare Function GetKeyboardState

Lib "user32" Alias "GetKeyboardState" _

(pbKeyState As Byte) As Long

参数pbKeyState为具有256个元素的字节数组的第一个项目。

如果函数返回非0表示成功,返回0则表示失败。

SetKeyboardState函数用来设置每个虚拟键当前在键盘上的状态,其声明格式如下:

Declare Function SetKeyboardState Lib

"user32" Alias "SetKeyboardState" _

(lppbKeyState As Byte) As Long

了解设置键盘状态的函数后,就可以在VBA中编写代码,用来设置锁定键的状态。具体步骤如下:

(1)在Excel中按快捷键Alt+F11进入VBE。

(2)单击菜单插入|模块命令,向工程中插入一个模块体。

(3)在模块的声明部分粘贴API函数的定义如下:

Public Declare Function GetKeyState Lib

"user32" (ByVal nVirtKey As Long) As Integer

Public Declare Function GetKeyboardState

Lib "user32" (pbKeyState As Byte) As Long

Public Declare Function SetKeyboardState

Lib "user32" (lppbKeyState As Byte) As Long

(4)编写修改锁定键状态的通用子过程,具体代码如下:

Sub SetKeyState(intVKey As Integer, bState As Boolean) '修改键盘状态

Dim aBuffer(0 To 255) As Byte '定义数组作为缓冲区

GetKeyboardState aBuffer(0) '获取键盘状态放入缓冲区

aBuffer(intVKey) = CByte(Abs(bState)) '在缓冲区修改指定键的状态

SetKeyboardState aBuffer(0) '使用缓冲区修改键的状态

End Sub

程序中使用数组的第一个元素作为参数传递给两个API函数,由于数组在VBA中是连续存放的,所以API函数通过第一个元素的地址就可访问到后面的所有元素。

(5)有了通用函数SetKeyState,就可以很方便地编写修改锁定键状态的代码了。例如,以下代码可修改CapsLock键的状态(在大小写之间相互切换):

Sub ModiCapsLock() '大写锁定

If CBool(GetKeyState(vbKeyCapital) And 1)

Then '获取CapsLock原来的状态

SetKeyState vbKeyCapital, False '关闭

Else

SetKeyState vbKeyCapital, True '打开

End If

End Sub

程序首先使用GetKeyState函数查询CapsLock原来的状态,再将其状态进行切换(即如果原来是打开的,就将其关闭;如果原来是关闭的,就将其打开)。

C# 获取键盘输入数字的值

C# 代码如下:

/// <summary>

        /// 重载ProcessCmdKey事件

        /// </summary>

        /// <param name="msg"></param>

        /// <param name="keyData"></param>

        /// <returns></returns>

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

        {

            int index = dgvBasesListCurrentCellRowIndex;

            string text = ClipboardGetText();

            EventArgs e = new EventArgs();

            if (keyData == KeysEnter)

            {

                thisbtnOK_Click(this, e);

            }

            else if (keyData == KeysDown)

            {

                if (index < dgvBasesListRowsCount - 1)

                {

                    // dgvBasesListRows[index + 1]Selected =true ;

                    dgvBasesListCurrentCell = dgvBasesList[0, index + 1];

                    txtNoText = (dgvBasesListCurrentRowIndex + 1)ToString();

                }

            }

            else if (keyData == KeysUp)

            {

                if (index > 0)

                {

                    dgvBasesListCurrentCell = dgvBasesList[0, index - 1];

                    txtNoText = (dgvBasesListCurrentRowIndex + 1)ToString();

                }

            }

            else if ((keyData >= KeysD0 && keyData <= KeysD9) || (keyData >= KeysNumPad0 && keyData <= KeysNumPad9))

            {

                string num = KeyCodeToStr(keyData);

                string num1 = num;

                int no = Int32Parse(txtNoTextToString() + num);

                if (no > dgvBasesListRowsCount - 1)

                {

                    if (Int32Parse(num) > dgvBasesListRowsCount)

                    {

                        dgvBasesListCurrentCell = dgvBasesList[0, dgvBasesListRowsCount - 1];

                        txtNoText = (dgvBasesListRowsCount - 1)ToString();

                    }

                    else if (Int32Parse(num) > 0)

                    {

                        dgvBasesListCurrentCell = dgvBasesList[0, Int32Parse(num) - 1];

                        txtNoText = numToString();

                    }

                }

                else

                {

                    dgvBasesListCurrentCell = dgvBasesList[0, no - 1];

                    txtNoText = noToString();

                }

            }

            return true;

}

        [DllImport("user32dll")]

        static extern int MapVirtualKey(uint uCode, uint uMapType);

private static char KeyCodeToChar(Keys k)

        {

            int nonVirtualKey = MapVirtualKey((uint)k, 2);

            char mappedChar = ConvertToChar(nonVirtualKey);

            return mappedChar;

        }

        public static string KeyCodeToStr(Keys k)

        {

            char mappedChar = KeyCodeToChar(k);

            string str = mappedCharToString();

            if (CharIsWhiteSpace(mappedChar) || stringIsNullOrEmpty(str) || mappedChar == '\r' || mappedChar == '\n' || mappedChar == KeyCodeToChar(KeysF1))

            {

                return kToString();

            }

            else

            {

                return str + "";

            }

        }

可以用全局快捷键

这个需要用到windows api,添加引用,并导入api方法:

using SystemRuntimeInteropServices;

[DllImport("user32dll")]

private static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);

[DllImport("user32dll")]

private static extern int UnregisterHotKey(IntPtr hwnd, int id);

注册快捷键方法:

/// <summary>

/// 注册热键

/// </summary>

/// <param name="hwnd">窗口句柄</param>

/// <param name="hotKey_id">热键ID</param>

/// <param name="fsModifiers">组合键(没有为0)</param>

/// <param name="vk">热键</param>

public bool RegKey(IntPtr hwnd, int hotKey_id, int fsModifiers, int vk)

{

bool result;

if (RegisterHotKey(hwnd, hotKey_id, fsModifiers, vk) == 0)

{

result = false;

}

else

{

result = true;

}

return result;

}

注销热键:

/// <summary>

/// 注销热键

/// </summary>

/// <param name="hwnd">窗口句柄</param>

/// <param name="hotKey_id">热键ID</param>

public void UnRegKey(IntPtr hwnd, int hotKey_id)

{

UnregisterHotKey(hwnd, hotKey_id);

}

热键编号vk楼主可以去网上查下,因为有很多,就不在这里贴了,贴几个楼主提问中的编号:

VK_ESCAPE = 27;//esc

VK_UP = 38;//↑

VK_DOWN = 40;//↓

VK_LEFT = 37;//←

VK_RIGHT = 39;//→

在程序中注册时,调用RegKey方法,第一个参数可传Handle(窗口类中有这个属性);第二个是快捷键ID,必须唯一,可传热键编号;第三个是组合键码,如果不需要可以传0;第四个就是热键编码了,就是上面我举例的几个编号。

重写WndProc方法,响应windows消息:

protected override void WndProc(ref Message m)

{

switch (mMsg)

{

case 0x312: //窗口消息-热键

switch (mWParamToInt32())

{

case VK_ESCAPE: //热键ID

//按了esc键,做相应处理

break;

}

break;

default:

break;

}

baseWndProc(ref m);//将其余不关心的消息调用基类方法做默认处理

}

在程序退出时,别忘了调用UnRegKey注销。

组合键码:

private const int MOD_ALT = 0x1; //ALT

private const int MOD_CONTROL = 0x2; //CTRL

private const int MOD_SHIFT = 0x4; //SHIFT

private const int MOD_WIN = 0x8;//windows

有点麻烦。

第一,你要会写DLL,检查,键盘过滤函数 WH_KEYBOARD,用SetWindowsHookEx()将其挂接在函数链首,用CallNextHookEx()把消息传给下一个函数。

键盘挂钩函数:

int FAR PASCAL KeyboardProc( int nCode,WORD wParam,DWORD lParam) {}

KeyboardProc--挂接函数名,该函数必须在模块定义文件中利用EXPORTS命令进行说明;

nCode决定挂接函数是否对当前消息进行处理;wParam和lParam为具体的消息内容。

第二,你要会写程序,调用那个钩子DLL

第三,你要让程序在背景运行。

楼上这些说的都是当前程序获取到焦点的时候取的方法。。。LZ的意思是要程序只要运行起然后就算没有获取焦点没被激活也能获取系统中的所有键盘和鼠标按键值,,,,这个可以用WINDOWS的API来实现用钩子就可以取到当前计算机的键盘和鼠标的信息。如果你想弄可以加我QQ 我给你代码

私以为有点理解LZ的意思了,LZ想要制作实时交互的游戏程序对么?

那么LZ是想要编写DOS游戏么?我没啥实践能力,只是自学了一些WINAPI的东西,贪吃蛇这种东西用windows还是不难做的,大概可以对LZ说一点东西。

想要实现贪吃蛇这种程度的交互,那么stdio是绝对满足不了你的。如果你真的是想要做游戏,那么建议LZ学习windows编程,这样至少可以对游戏编程有个了解。

向LZ推荐两本书

《WINDOWS游戏编程大师技巧》 AndrèLaMothe

这本书的前两节是关于windows编程的一些概述,但是后来就是directX了,不过思想是最重要的。不建议一开始就勉强通读,后面绝对要迷茫的。。。

《windows程序设计》 charles petzold

这本书是系统地讲述WINAPI的,虽然很多东西现在都不再用API,而是可能选择MFC之类来做,但是API的思想是通用的,有了API,就可以比较顺利地学习MFC之类。

虽然C语言还有一些可以直接读取键盘讯息的库,但是我猜想LZ需要的是迈向windows应用程序编程吧 所以范例我也就不必写了,实现方法不一样。

以上就是关于vba 如何获取键盘消息全部的内容,包括:vba 如何获取键盘消息、C#如何获取键盘的输入啊、C# API 获取键盘等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10638417.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存