c语言怎样实现键盘操作?

kuaidi.ping-jia.net  作者:佚名   更新日期:2024-07-04
如何用c语言实现控制键盘?

用bioskey()可以检测到按键的扫描码,扫描码是两个字节,低字节就是ASCLL码,高字节是功能码等

主要就是按键检测,防抖呗。
首先给出检测按键代码:(我这个事4*4键盘。具体你要根据实际情况编写)
uchar TestKey()
{
uchar cord_h,cord_l;
P6=0x0f;
cord_h=P6&0x0f;
if(cord_h!=0x0f)
{
Delay_Xms(1);
if(cord_h!=0x0f)
{
cord_h=P6&0x0f;
P6=cord_h|0xf0;
cord_l=P6&0xf0;
return(cord_h+cord_l);
}
}return(0xff);
}

--------------------------------------
然后你在Main函数里编写循环,检测按键然后做你想做的事情。。。
while(1)
{
key=TestKey();//调用键盘扫描,
switch(key)
{
case 0x7e:P4=0xa1;break;//0 按下相应的键显示相对应的码值
case 0x7d:Show1Menu();break;//1
case 0x7b:P4=0x83;break;//2
case 0x77:P4=0x88;break;//3
case 0xbe:P4=0x99;break;//4
case 0xbd:P4=0x90;break;//5
case 0xbb:P4=0x82;break;//6
case 0xb7:P4=0xb0;break;//7
case 0xde:P4=0xc0;break;//8
case 0xdd:P4=0x80;break;//9
case 0xdb:P4=0x92;break;//a
case 0xd7:P4=0xa4;break;//b
case 0xee:P4=0xc6;break;//c
case 0xed:P4=0xf8;break;//d
case 0xeb:P4=0x99;break;//e
case 0xe7:P4=0xf9;break;//f
}
}

在你的基础上改的
#include<stdio.h>
#include<stdlib.h>

#define LISTSIZE 100
#define ADD 10
typedef struct {
int *elem;
int length;
int listsize;
}List;//定义线性表的结构体
void SqList(List &L)
{

//int i;//C++中C程序的变量定义放在开始

L.elem=(int *)malloc(LISTSIZE*sizeof(int));
if(!L.elem) exit(0);
L.listsize=LISTSIZE;
//printf("请输入线性表长度:");
//scanf("%d",&L.length);
//printf("为线性表赋值:");
//for(i=0;i<=L.length-1;i++)
//scanf("%5d",&L.elem[i]);
L.length =0;//如果是初始化,那么长度就是0
}//初始化线性表

int InsertSq(List &L,int i,int e)
{
int *p=NULL, *q=NULL;//所有变量的定义都必须置前
if(i<0||i>L.length+1) return 0;
if(L.length>=L.listsize)
{
int *newbase;
newbase=(int *)realloc(L.elem,(L.listsize+ADD)*sizeof(int));
if(!newbase) exit(0);
L.elem=newbase;
L.listsize+=ADD;
}

q=&L.elem[i-1];
for(p=&L.elem[L.length-1];p>=q;--p)
*(p+1)=*p;
*q=e;
L.length++;
return 1;
}//在线性表的第i个元素之前插入元素e

void PrintList(List L)
{
printf("顺序表中的元素:\n");
for(int k=0;k<=L.length-1;k++)
printf("%5d",L.elem[k]);
printf("\n");
}

void main()
{

//void SqList(List &L);
//int InsertSq(List &L,int i,int e);使用之前已经定义了,可以不用函数说明
List L;
int i,e; //函数调用前,变量必须定义

SqList(L);
printf("输入顺序表中元素的个数:");
scanf("%d",&i);

printf("请输入元素:");
for(int j=1;j<=i;j++)
{
scanf("%d",&e);
InsertSq(L,j,e);
}

PrintList(L);
printf("输入插入的元素及其位置:");
scanf("%5d%5d",&e,&i);
InsertSq(L,i,e);
PrintList(L);
}


1.在Microsoft Windows 中,键盘和鼠标是两个标准的用户输入源,在一些交叠的操作中通常相互补充使用。当然,鼠标在今天的应用程序中比10年前使用得更为广泛。甚至在一些应用程序中,我们更习惯于使用鼠标,例如在游戏、画图程序、音乐程序,以及Web创览器等程序中就是这样。然而,我们可以不使用鼠标,但绝对不能从一般的PC中拆掉键盘。
  Windows程序获得键盘输入的方式:键盘输入以消息的形式传递给程序的窗口过程。实际上,第一次学习消息时,键盘就是一个明显的例子:消息应该传递给应用程序的信息类型。
  Windows用8种不同的消息来传递不同的键盘事件。这好像太多了,但是(就像我们所看到的一样)程序可以忽略其中至少一半的消息而不会有任何问题。并且,在大多数情况下,这些消息中包含的键盘信息会多于程序所需要的。处理键盘的部分工作就是识别出哪些消息是重要的,哪些是不重要的。
2.键盘基础知识
  虽然应用程序在很多情况下可以通过鼠标实现信息的输入,但到现在为止键盘仍然是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;
}

都不用按键盘了,那直接把1这个参数写在代码里不就行了...

  • 在C语言中如何实现用键盘输入一个字符串,并打印出来?
    答:在C语言中实现用键盘输入一个字符串,并打印出来的解决方法如下:1、首先定义一个字符串数组,如你可以给字符串100个数组空间。如图括号内数字即为你定义的数组大小。2、gets()函数用来获取键盘输入的字符串,括号内的s即为字符串变量。3、接着用puts()函数输出之前我们从键盘读取的字符串。括号内为...
  • C语言从键盘输入字符串的步骤有哪些?
    答:c语言从键盘输入字符串的步骤如下:1.首先我们新建一个dev C++的项目。2.接下来在项目中新建C语言程序文件。3.然后在C语言文件中声明一个字节数组。4.接下来我们通过printf函数提示用户输入字符串,通过scanf接收用户输入的字符串。5.接着在通过printf函数输出用户输入的内容。6.最后运行C语言程序,我们...
  • 在C语言中如何实现用键盘输入一个字符串,并打印出来?
    答:1.首先需要先定义一个存放字符串的数组空间,如给字符串100个数组空间。2.接着使用gets()函数来获取键盘输入的字符串。一般格式为gets(定义的字符数组名)。3.然后再使用puts()函数来输出之前输入的字符串内容。一般格式puts(定义的字符数组名)。4.最终运行程序,即可成功实现输入字符串,然后原样在屏...
  • 用c语言编写程序,如何实现获取键盘按下的字符?
    答:int main(void){ char ch;int index;ch = getchar(); //读入一个字符存入ch ch = tolower(ch); //转换为小写字母 index = ch - 'a' + 1; //计算序号 printf("%d\n", index);return 0;}
  • 求教C语言的键盘操作
    答:利用key.h实现,你利用键盘输入,接受到的键盘数据用switch就可以实现了,调用相应的操作函数就可以了,例子很多的,你可以看一下那些贪食蛇,俄罗斯方块了等代码,推荐你先看贪食蛇,比较简单,不会就自己查百度,因为书上一般情况下不给你讲这些,应该用tc吧,支持图形 ...
  • c语言 怎样模拟鼠标键盘操作?
    答:bVk:键名,例如: VK_NUMPAD7,VK_BACK, VK_TAB,VK_SHIFT,VK_F1,。。。keybd_event(VK_MENU,0xb8,0 , 0); -- 按下Alt 键 keybd_event(VK_MENU,0xb8,KEYEVENTF_KEYUP,0); -- 放开 Alt 键 (复位,弹上来)=== 下面程序模拟按 notepad 编辑器。等于C语言 system("notepad")...
  • c语言实现从键盘上输入10个数,并输出。
    答:用选择排序法编写c语言,实现从键盘上输入10个数,按从大到小的顺序排序输出。代码如下:include<stdio.h> int main(){ int i,j,a[10],t;printf("输入数");for (i = 0; i < 10; i++)scanf("%d",&a[i]);for (i = 0; i < 10; i++){ for (j = i + 1; j < 10;j...
  • C语言编程中怎么添加键盘操作
    答:用getch函数,方向键有两个字节,第一个字节是-32,所以判断是-32后再取一次,上左右下72,75,77,80 include <conio.h> include <stdio.h> int main(){ printf("请输入:");char ch;ch = getch();if(ch == -32)while(1){ ch = getch();switch(ch){ case 27:{printf("Esc");...
  • c语言怎样实现键盘操作?
    答://int i;//C++中C程序的变量定义放在开始 L.elem=(int *)malloc(LISTSIZE*sizeof(int));if(!L.elem) exit(0);L.listsize=LISTSIZE;//printf("请输入线性表长度:");//scanf("%d",&L.length);//printf("为线性表赋值:");//for(i=0;i<=L.length-1;i++)//scanf("%5d",&...
  • 怎么用c语言写一个 程序。实现从键盘输入字符并写入一个文件。_百度知...
    答:文件操作函数一般以f+单词的形式来命名(f是file的简写),其声明位于stdio.h头文件当中。例如:fopen、fclose函数用于文件打开与关闭;fscanf、fgets函数用于文件读取;fprintf、fputs函数用于文件写入;ftell、fseek函数用于文件操作位置的获取与设置。一般的C语言教程都有文件操作一章,可以找本教材进一步学习。