c语言按键监听,c语言检测按键

本文目录一览:

c语言键盘监听问题

#include stdio.h

#include conio.h

void main() {

while(1) {

printf(“\r                   hello world!”);

if(_kbhit()) {

if(_getch() == ‘\r’)

break;

}

}

printf(“\n”);

}

c语言 如何一直监听某个键是否按下?

看这样能不能达到效果

while (1)

{

    Sleep(100);//防止CPU消耗太多,每100毫秒才检测一下

    while (kbhit()){

        char ch = getch();

        if (ch==你所说的键)

        {

        //…

        }

    }

}

要求Windows环境

要求#include conio.h

#include Windows.h

C语言控制台程序实时监听键盘按键事件

输入焦点不在控制台窗口上, 键盘消息不会被控制台窗口接收, 这种情况只有用全局键盘钩子或低级键盘钩子, 全局钩子要写在动态链接库中(DLL文件), 低级键盘钩子可写在本线程中.

c语言怎么监听键盘按键

在Microsoft Windows 中,键盘和鼠标是两个标准的用户输入源,在一些交叠的操作中通常相互补充使用。当然,鼠标在今天的应用程序中比10年前使用得更为广泛。甚至在一些应用程序中,我们更习惯于使用鼠标,例如在游戏、画图程序、音乐程序,以及Web创览器等程序中就是这样。然而,我们可以不使用鼠标,但绝对不能从一般的PC中拆掉键盘。

Windows程序获得键盘输入的方式:键盘输入以消息的形式传递给程序的窗口过程。实际上,第一次学习消息时,键盘就是一个明显的例子:消息应该传递给应用程序的信息类型。

Windows用8种不同的消息来传递不同的键盘事件。这好像太多了,但是(就像我们所看到的一样)程序可以忽略其中至少一半的消息而不会有任何问题。并且,在大多数情况下,这些消息中包含的键盘信息会多于程序所需要的。处理键盘的部分工作就是识别出哪些消息是重要的,哪些是不重要的。

键盘基础知识

虽然应用程序在很多情况下可以通过鼠标实现信息的输入,但到现在为止键盘仍然是PC机中不可替代的重要输入设备。

用键盘当作输入设备,每当用户按下或释放某一个键时,会产生一个中断,该中断激活键盘驱动程序KEYBOARD.DRV来对键盘中断进行处理。 KEYBOARD.DRV程序会根据用户的不同操作进行编码,然后调用Windows用户模块USER.EXE生成键盘消息,并将该消息发送到消息队列中等候处理。

1.扫描码和虚拟码

扫描码对应着键盘上的不同键,每一个键被按下或释放时,都会产生一个唯一的扫描码作为本身的标识。扫描码依赖于具体的硬件设备,即当相同的键被按下或释放时,在不同的机器上可能产生不同的扫描码。在程序中通常使用由Windows系统定义的与具体设备无关的虚拟码。在击键产生扫描码的同时,键盘驱动程序KEYBOARD.DRV截取键的扫描码,然后将其翻译成对应的虚拟码,再将扫描码和虚拟码一齐编码形成键盘消息。所以,最后发送到消息队列的键盘消息中,既包含了扫描码又包含了虚拟码。

经常使用的虚拟码在WINDOWS.H文件中定义,常用虚拟码的数值、常量符号和含义如表所示。

取值(16进制) 常量符号 含义

01 VK_LBUTTON 鼠标左键

02 VK_RBUTTON 鼠标右键

03 VK_CANCEL Break中断键

04 VK_MBUTTON 鼠标中键

05-07 — 未定义

08 VK_BACK (BackSpace)键

09 VK_TAB Tab键

0A-0B — 未定义

0C VK_CLEAR Clear键

0D VK_RETURN Enter键

0E-0F — 未定义

10 VK_SHIFT Shift键

11 VK_CONTROL Ctrl键

12 VK_MENU Alt键

13 VK_PAUSE Pause键

14 VK_CAPTIAL CapsLock键

15-19 — 汉字系统保留

1A — 未定义

1B VK_ESCAPE Esc键

1C-1F — 汉字系统保留

20 VK_SPACE 空格键

21 VK_PRIOR PageUp键

22 VK_NEXT PageDown键

23 VK_END End键

24 VK_HOME Home键

25 VK_LEFT ←(Left Arrow)键

26 VK_UP ↑(Up Arrow)键

27 VK_RIGHT →(Right Arrow)键

28 VK_DOWN ↓(Down Arrow)键

29 VK_SELECT Select键

2A — OEM保留

2B VK_EXECUTE Execute键

2C VK_SNAPSHOT Print Screen键

2D VK_INSERT Insert键

2E VK_DELETE Delete键

2F VK_HELP Help键

30-39 VK_0-VK_9 数字键0-9

3A-40 — 未定义

41-5A VK_A-VK_Z 字母键A-Z

5B-5F — 未定义

60-69 VK_NUMPAD0-VK_NUMPAD9 小键盘数字键0-9

6A VK_MULTIPLY *(乘号)键

6B VK_ADD +(加号)键

6C VK_SEPAPATOR 分隔符键

6E VK_SUBTRACT -(减号)键

6F VK_DECIMAL .(小数点)键

70-87 VK_DIVIDE /(除号)键

88-8F VK_F1-VK_F24 F1-F24功能键

90 VK_NUMBERLOCK Number lock键

91 VK_SCROLL Scroll lock键

92-B9 — 未定义

BA-C0 — OEM保留

C1-DA — 未定义

DB_E4 — OEM保留

E5 — 未定义

E6 — OEM保留

E7-E8 — 未定义

E9-F5 — OEM保留

F6-FE — 未定义

2.输入焦点

同一时刻,Windows中可能有多个不同的程序在运行,也就是说有多个窗口同时存在。这时,键盘由多个窗口共享,但只有一个窗口能够接收到键盘消息,这个能够接收键盘消息的窗口被称为拥有输入焦点的窗口。

拥有输入焦点的窗口应该是当前的活动窗口,或者是活动窗口的子窗口,其标题和边框会以高亮度显示,以区别于其他窗口。拥有输入焦点的也可以是图标而不是窗口,此时,Windows也将消息发送给图标,只是消息的格式略有不同。

窗口过程可以通过发送WM_SETFOCUS和 WM_KILLFOCUS消息使窗体获得或失去输入焦点。程序也可以通过捕获WM_SETFOCUS和WM_KILLFOCUS消息来判断窗体何时获得或失去输入焦点。其中WM_SETFOCUS消息表示窗口正获得输入焦点,WM_ KILLFOCUS消息表示窗口正失去输入焦点。

3.键盘消息

键盘消息分为系统键消息和非系统键消息。系统键消息是指由Aft键和其他键组合而产生的按键消息。当系统键被按下时产生WM_ SYSKEYDOWN消息,当系统键被释放时产生WM_SYSKEYUP消息。 Aft键与其他键形成的组合键通常用于对程序菜单和系统菜单进行选择,或用于在不同的程序之间进行切换。因此,系统键消息应该交由Windows进行处理,用户所编制的程序一般不处理系统键消息,而是将这些消息交由DefWindowProc函数进行处理。如果用户想对系统键消息进行处理,应该在处理完这些消息后,再将其发送给DefWindowProc函数,使得Windows系统能够正常工作。

某些击键消息可以被转换成字符消息,例如字母键、数字键等。而有些键只能产生按键消息而没有字符消息,例如 Shift键、Insert键等。消息循环中的 TranslateMessage函数可以实现从击键消息向字符消息的转化。当GetMessage函数捕获一个WM_SYSKEYDOWN消息或 WM_KEYDOWN消息后,TranslateMessage函数判断产生该消息的键是否能够被转换成字符消息,如果能,就将该消息转换成字符消息,再通过DispatchMessape函数将转换后的字符消息发送到消息队列中去。字符消息共有以下四种,如表所示。

字符 系统字符 非系统字符

普通字符 WM_SYSCHAR WM_CHAR

死字符 WM_SYSDEADCHAR WM_DEADCHAR

其中死字符是由某些特殊键盘上的按键所造成的,Windows一般忽略死字符所产生的消息。

Windows的消息一般是通过一个MSG结构体变量传送给消息处理函数的。对于键盘消息, MSG结构体变量的各个域中较重要的是lParam域和 wParam域。wParam域用于保存按键的虚拟键代码或字符的ASCII码。对于非字符消息,wParam域保存按键的虚拟健代码;对于字符消息, wParam域不保存字符的ASCII码。lParam域则用于保存击键时产生的附加信息,实际上一个32位的lParam变量被分为六部分,记录了以下相关信息:重复次数、OEM扫描码、扩展键标志、关联键标志、前一击键状态和转换状态。lParam域各位的含义如表所示。

位数 含义

0-15 击键重复次数累加

16-23 OEM扫描码

24 是否为扩展键

25-28 未定义

29 是否便用关联键,及Alt键是否同时按下。

30 前一次击键状态,0表示该键前一次状态为抬起,1表示前一次状态为按下

31 转换状态

按键的次序不同,产生的消息也不相同。例如,按下并释放1键,读过程依次产生如表所示三条消息。按下1键所产生的消息和wParam的取值

消息 wParam变量取值

WM_KEYDOWN 虚拟码1

WM_CHAR ASCII码“1”

WM_KEYUP 虚拟码1

如果按下Shift键后再按下1键并释放,则依次产生如表所示的消息。按下 Shift键后按 1健所产生的消息和 wParam的取值

消息 wParam变量取值

WM_KEYDOWN 虚拟码 VK_SHIFT

WM_KEYDOWN 虚拟码 VK_1

WM_CHAR ASCII码 “1”

WM_KEYUP 虚拟码 VK_1

WM_KEYUP 虚拟码 VK_SHIF

键盘应用实例

下面通过一个应用程序实例来说明在实际编程中如何处理键盘消息。

#include windows.h

#include stdio.h

// 全局变量

RECT rc; //记录滚屏的矩形区域

?

int xChar, yChar; //文本输入点坐标

WNDCLASSEX wnd; //窗口类结构变量

char szAppName[] = “键盘消息监视程序”; //窗口类名

//函数声明

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL MyRegisterClass(HINSTANCE hInstance);

BOOL InitInstance(HINSTANCE hInstance,int iCmdShow);

//函数:WinMain

//作用:入口函数

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)

{

MSG msg;

if(!MyRegisterClass(hInstance))

{

return FALSE;

}

 if(!InitInstance(hInstance,iCmdShow))

{

return FALSE;

}

while (GetMessage (msg, NULL, 0, 0))

{

TranslateMessage (msg);

DispatchMessage (msg);

}

return msg.wParam;

}

//函数:ShowKey

//作用:实现在窗口中显示按键信息

void ShowKey (HWND hwnd, int iType,char *szMessage,WPARAM wParam,LPARAM lParam)

{

static char *szFormat[2] ={“%-14s %3d %c %6u %4d %5s %5s %6s %6s”,

  “%-14s %3d %c %6u %4d %5s %5s %6s %6s” };

char szBuffer[80];

HDC hdc;

ScrollWindowEx(hwnd, 0, -yChar, rc,rc,NULL,NULL,SW_INVALIDATE);

hdc = GetDC (hwnd);

SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT));

TextOut (hdc,

 xChar,

 rc.bottom – yChar,

 szBuffer,

 wsprintf szBuffer,

 szFormat[iType],

 szMessage, //消息

 wParam, //虚拟键代码

 (BYTE) (iType ? wParam :‘ ’),//显示字符值

 LOWORD (lParam), // 重复次数

 HIWORD (lParam)  0xFF, // OEM键盘扫描码

 //判断是否为增强键盘的扩展键

 (PSTR) (0x01000000  lParam ? “是” : “否”),

 //判断是否同时使用了ALT键

 (PSTR) (0x20000000  lParam ? “是” : “否”),

 (PSTR) (0x40000000  lParam ? “按下” : “抬”),

 //判断前一次击键状

 (PSTR)(0x80000000  lParam ? “按下” : “抬起”))

 //判断转换状态?

 );

ReleaseDC (hwnd, hdc); ?

ValidateRect (hwnd, NULL); ?

}

//函数:WndProc

//作用:处理主窗口的消息

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

static char szTop[] =”消息键 字符 重复数 扫描码 扩展码 ALT 前一状态 转换状态”;

static char szUnd[] =”_______ __ ____ _____ ______ ______ ___ _______ ______”;

//在窗口中输出文字作为信息标题

HDC hdc;

PAINTSTRUCT ps;

TEXTMETRIC tm;

switch (iMsg)

{

case WM_CREATE://处理窗口创建的消息

hdc = GetDC (hwnd); //设定字体

SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)); //检取当前字体的度量数据

GetTextMetrics (hdc, tm);

xChar = tm.tmAveCharWidth;//保存字体平均宽度

yChar = tm.tmHeight; //保存字体高度

ReleaseDC (hwnd, hdc);

rc.top = 3 * yChar / 2;

return 0;

case WM_SIZE://处理窗口大小改变的消息

//窗体改变后保存新的滚屏区域右下角坐标

rc.right = LOWORD (lParam);

rc.bottom = HIWORD (lParam);

UpdateWindow (hwnd);

return 0;

case WM_PAINT: //处理窗口重绘消息

InvalidateRect (hwnd, NULL, TRUE);

hdc = BeginPaint (hwnd, ps);

SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;

SetBkMode (hdc, TRANSPARENT) ;

TextOut (hdc, xChar, yChar / 2, szTop, (sizeof szTop) – 1) ;

TextOut (hdc, xChar, yChar / 2, szUnd, (sizeof szUnd) – 1) ;

EndPaint (hwnd, ps);

return 0;

case WM_KEYDOWN:

//处理键盘上某一键按下的消息

ShowKey (hwnd, 0, “WM_KEYDOWN”,wParam, lParam);

return 0;

case WM_KEYUP:

//处理键盘上某一按下键被释放的消息

ShowKey (hwnd, 0, “WM_KEYUP”, wParam, lParam);

return 0;

case WM_CHAR:

//处理击键过程中产生的非系统键的可见字符消息

howKey (hwnd, 1, “WM_CHAR”, wParam, lParam);

return 0;

case WM_DEADCHAR:

//处理击键过程中产生的非系统键”死字符”消息

ShowKey (hwnd, 1, “WM_DEADCHAR”, wParam, lParam);

return 0;

case WM_SYSKEYDOWN:

//处理系统键按下的消息

ShowKey (hwnd, 0, “WM_SYSKEYDOWN”,wParam, lParam);

break;

case WM_SYSKEYUP:

//处理系统键抬起的消息

ShowKey (hwnd, 0, “WM_SYSKEYUP”, wParam, lParam);

break;

case WM_SYSCHAR://处理系统键可见字符消息

ShowKey (hwnd, 1, “WM_SYSCHAR”, wParam, lParam);

break;

case WM_SYSDEADCHAR://处理系统键”死字符”消息

ShowKey (hwnd, 1, “WM_SYSDEADCHAR”, wParam, lParam);

break;

case WM_DESTROY:

//处理结束应用程序的消息

PostQuitMessage (0);

return 0;

}

return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

//函数:MyRegisterClass

//作用:注册窗口类

BOOL MyRegisterClass(HINSTANCE hInstance)

{

wnd.cbSize= sizeof (wnd);

wnd.style = CS_HREDRAW | CS_VREDRAW;

wnd.lpfnWndProc = WndProc;

wnd.cbClsExtra = 0;

wnd.cbWndExtra = 0;

wnd.hInstance = hInstance;

wnd.hIcon = LoadIcon (NULL, IDI_APPLICATION);?

wnd.hCursor = LoadCursor (NULL, IDC_ARROW);

wnd.hbrBackground = (HBRUSH)

GetStockObject (WHITE_BRUSH);

wnd.lpszMenuName = NULL;

wnd.lpszClassName = szAppName;

wnd.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

return RegisterClassEx (wnd);

}

//函数:InitInstance

//作用:创建主窗口

BOOL InitInstance(HINSTANCE hInstance,int iCmdShow)

{

HWND hwnd;

hwnd = CreateWindow (szAppName,

 “键盘消息监视程序”,

 WS_OVERLAPPEDWINDOW,

 CW_USEDEFAULT,CW_USEDEFAULT,

 CW_USEDEFAULT,CW_USEDEFAULT,

 NULL,NULL,hInstance,NULL

 );

if(!hwnd)

{

return FALSE;

}

ShowWindow (hwnd, iCmdShow);

UpdateWindow (hwnd);

return TRUE;

}

c语言,监听虚拟键的方法为什么不直接用getchar接收,然后用==判断是不是某个键,这样不就好

getchar 会阻断线程.不方便.所谓监听.一般必须是挂在系统键盘消息的响应函数上.在系统分发KEYDOWN消息时,探测当前按下的key的code是不是自己想要的..

所以getchar肯定是不行了.

如何在linux下用c语言实现对键盘的监听

自己写函数

#include stdio.h  

#include termios.h  

  

static struct termios initial_settings, new_settings;  

static int peek_character = -1;  

void init_keyboard(void);  

void close_keyboard(void);  

int kbhit(void);  

int readch(void);   

void init_keyboard()  

{  

    tcgetattr(0,initial_settings);  

    new_settings = initial_settings;  

    new_settings.c_lflag |= ICANON;  

    new_settings.c_lflag |= ECHO;  

    new_settings.c_lflag |= ISIG;  

    new_settings.c_cc[VMIN] = 1;  

    new_settings.c_cc[VTIME] = 0;  

    tcsetattr(0, TCSANOW, new_settings);  

}  

  

void close_keyboard()  

{  

    tcsetattr(0, TCSANOW, initial_settings);  

}  

  

int kbhit()  

{  

    unsigned char ch;  

    int nread;  

  

    if (peek_character != -1) return 1;  

    new_settings.c_cc[VMIN]=0;  

    tcsetattr(0, TCSANOW, new_settings);  

    nread = read(0,ch,1);  

    new_settings.c_cc[VMIN]=1;  

    tcsetattr(0, TCSANOW, new_settings);  

    if(nread == 1)   

    {  

        peek_character = ch;  

        return 1;  

    }  

    return 0;  

}  

  

int readch()  

{  

    char ch;  

  

    if(peek_character != -1)   

    {  

        ch = peek_character;  

        peek_character = -1;  

        return ch;  

    }  

    read(0,ch,1);  

    return ch;  

}  

   

int main()  

{  

    init_keyboard();  

    while(1)  

    {  

        kbhit();  

        printf(“\n%d\n”, readch());  

    }  

    close_keyboard();  

    return 0;  

}

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/295848.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-27 12:57
下一篇 2024-12-27 12:57

相关推荐

  • AES加密解密算法的C语言实现

    AES(Advanced Encryption Standard)是一种对称加密算法,可用于对数据进行加密和解密。在本篇文章中,我们将介绍C语言中如何实现AES算法,并对实现过程进…

    编程 2025-04-29
  • 学习Python对学习C语言有帮助吗?

    Python和C语言是两种非常受欢迎的编程语言,在程序开发中都扮演着非常重要的角色。那么,学习Python对学习C语言有帮助吗?答案是肯定的。在本文中,我们将从多个角度探讨Pyth…

    编程 2025-04-29
  • Python被称为胶水语言

    Python作为一种跨平台的解释性高级语言,最大的特点是被称为”胶水语言”。 一、简单易学 Python的语法简单易学,更加人性化,这使得它成为了初学者的入…

    编程 2025-04-29
  • OpenJudge答案1.6的C语言实现

    本文将从多个方面详细阐述OpenJudge答案1.6在C语言中的实现方法,帮助初学者更好地学习和理解。 一、需求概述 OpenJudge答案1.6的要求是,输入两个整数a和b,输出…

    编程 2025-04-29
  • Python按位运算符和C语言

    本文将从多个方面详细阐述Python按位运算符和C语言的相关内容,并给出相应的代码示例。 一、概述 Python是一种动态的、面向对象的编程语言,其按位运算符是用于按位操作的运算符…

    编程 2025-04-29
  • Python语言由荷兰人为中心的全能编程开发工程师

    Python语言是一种高级语言,很多编程开发工程师都喜欢使用Python语言进行开发。Python语言的创始人是荷兰人Guido van Rossum,他在1989年圣诞节期间开始…

    编程 2025-04-28
  • Python语言设计基础第2版PDF

    Python语言设计基础第2版PDF是一本介绍Python编程语言的经典教材。本篇文章将从多个方面对该教材进行详细的阐述和介绍。 一、基础知识 本教材中介绍了Python编程语言的…

    编程 2025-04-28
  • Python语言实现人名最多数统计

    本文将从几个方面详细介绍Python语言实现人名最多数统计的方法和应用。 一、Python实现人名最多数统计的基础 1、首先,我们需要了解Python语言的一些基础知识,如列表、字…

    编程 2025-04-28
  • Python作为中心语言,在编程中取代C语言的优势和挑战

    Python一直以其简单易懂的语法和高效的编码环境而著名。然而,它最近的发展趋势表明Python的使用范围已经从脚本语言扩展到了从Web应用到机器学习等广泛的开发领域。与此同时,C…

    编程 2025-04-28
  • Python基础语言

    Python作为一种高级编程语言拥有简洁优雅的语法。在本文中,我们将从多个方面探究Python基础语言的特点以及使用技巧。 一、数据类型 Python基础数据类型包括整数、浮点数、…

    编程 2025-04-28

发表回复

登录后才能评论