当前位置:C++技术网 > 精选软件 > 键盘状态灯(大小写状态灯、数字键盘锁灯)的状态检测标准实现

键盘状态灯(大小写状态灯、数字键盘锁灯)的状态检测标准实现

更新时间:2016-01-07 14:14:54浏览次数:1+次

    在文章《win32检测键盘的大小写状态并实时显示编辑的大小写状态》中,我们已经用自己的方法实现了大小写状态检测。同理,我们也可以实现插入状态和覆盖状态的切换,还可以检测数字键盘锁灯的切换。都是利用布尔变量值的切换实现。
    然而上述实现方法存在一个缺陷。因为我们是假设一个初始的状态的,即假设初始状态为小写。然后再对表示状态的布尔变量进行检测和改变,来显示当前的状态。然而,大小写锁定和数字键盘锁两个状态,并不会在你程序运行时有一个固定的初始状态。这两个状态是全局的,由键盘本身存储着。你的程序启动时,既可能是大写,也可能是小写。所以,基于上述的检测实现,是不准确的。只是在一些场合提供一个实现方法,比如你能确定初始的状态是固定的,就可以使用我们之前实现的大小写状态切换的方法。此方法适用于文本编辑的插入模式和覆盖模式的检测。因为这种状态是程序定义的,并不是键盘相关的。还有很多你要自己定义的状态,都可以使用固定初始值,然后来检测和改变状态值。
    然而,大小写状态灯和数字键盘锁灯的两个键盘状态,则是与键盘相关的。键盘硬件本身会记录这个状态,然后根据这状态来执行输入。所以,这两个状态与编辑文字时的插入覆盖模式完全不是一回事。
    所以,对于检测与键盘硬件相关的状态(大小写状态灯、数字键盘锁灯)时,我们就不能使用布尔变量值,而是获取键盘状态值。我们要得到状态值,就要从键盘消息获取。要改变状态值,就要通过点击按键来改变。而且,既然我们是检测硬件的状态,就要依赖于硬件,这样也就是最准确的。
    当按键按下时,就产生WM_KEYDOWN或WM_SYSKEYDOWN消息。在这个消息产生时,我们就可以使用一个函数来得到当前的状态灯的状态。这个函数就是GetKeyState,它只需要传入一个待检测的虚拟键码即可。返回值的低位为1就表示状态灯是亮的,否则状态灯是熄灭的。
    下面是实现的检测键盘大小写状态灯的状态的代码:
int iState = GetKeyState(VK_CAPITAL);
wsprintf(tip,_T("%s"),iState&0x0001?_T("大写"):_T("小写"));
    将返回的状态值iState与0x0001执行位与操作,就可以得到这个位的状态,然后判断大小写状态灯的状态。最后可以将字符数组tip输出显示。
    同理,实现检测数字键盘锁灯的代码如下:
int iState = GetKeyState(VK_NUMLOCK);
wsprintf(tip,_T("%s"),iState&0x0001?_T("数字键盘有效"):_T("数字键盘无效"));
    这两种状态的检测使用GetKeyState检测是最合适的,其他的检测如编辑的插入模式和覆盖模式这类程序自定义的状态,则使用文中开头提到的文章里的方法实现。
    需要注意的是,GetKeyState只能在键盘消息处理代码中调用。对于GetKeyState函数的使用,将会在一篇文章详细说明。
    下面是本文的检测大小写状态灯、数字键盘锁灯程序完整代码:
#include "windows.h"
#include <tchar.h>
#define MAX 100
TCHAR tip[MAX]=_T("");

// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    switch (message)
    {
        case WM_PAINT:
            hdc = BeginPaint(hwnd,&ps);
            TextOut(hdc,0,0,tip,lstrlen(tip));
            EndPaint(hwnd,&ps);
            return 0;
        case WM_KEYDOWN:
            {
                //int iState = GetKeyState(VK_CAPITAL);
                //wsprintf(tip,_T("%s"),iState&0x0001?_T("大写"):_T("小写"));

                int iState = GetKeyState(VK_NUMLOCK);
                wsprintf(tip,_T("%s"),iState&0x0001?_T("数字键盘有效"):_T("数字键盘无效"));
                InvalidateRect(hwnd,NULL,TRUE);
                return 0;
            }
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
        break;//跳出到默认处理
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
    TCHAR ClassName[] = _T("MyClass");
    TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
    WNDCLASS wndClass;
    wndClass.cbClsExtra=0;
    wndClass.cbWndExtra=0;
    wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.hCursor=LoadCursor(NULL,IDC_HAND);
    wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndClass.hInstance = hInstance;
    wndClass.lpfnWndProc = WinProc;
    wndClass.lpszClassName = ClassName;
    wndClass.lpszMenuName=NULL;
    wndClass.style=CS_HREDRAW|CS_VREDRAW;

    if(!RegisterClass(&wndClass))return 0;
    HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,650,400,NULL,NULL,hInstance,NULL);
    ShowWindow(hwnd,SW_SHOWNORMAL);

    MSG msg;
    while (GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}