zoukankan      html  css  js  c++  java
  • Win32 键盘事件

    注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!

    以下内容主要来自《Windows 程序设计》

    1.焦点

    程序用于从消息队列中读取消息的MSG结构中包含一个hwnd字段。此字段指出了接收消息的窗口句柄。消息循环中的DispatchMessage函数传送消息给需要该消息的窗口过程。

    接收到这个键盘事件的窗口称为有输入焦点的窗口。

    有时没有窗口具有输入焦点。这种情况发生在所以程序都最小化时。

    窗口过程通过捕获WM_SETFOCUS和WM_KILLFOCUS消息来确定自己的窗口是否具有输入焦点。

    2.队列和同步

    当用户按下和释放键盘上的一个键时,Windows和键盘设备驱动程序将硬件扫描码转换为格式化后的消息。但是这些消息并不立即被放入应用程序消息队列,而是由Windows把这些消息存储在系统消息队列中。系统消息队列是一个单独的消息队列,它被Windows用来初步存储用户从键盘和鼠标输入的消息。仅当Windows应用程序完成了对当前一个用户输入消息的处理后,Windows才从系统消息队列中取出下一条消息,并把它放入应用程序消息队列。

    3.击键消息

    当用户按下一个键时,Windows将WM_KEYDOWN或WM_SYSKEYDOWN消息放入具有输入焦点的消息队列中。当该键被释放时,Windows把WM_KEYUP或WM_SYSKEYUP消息放入相应的消息队列中。其中SYS代表系统,它表明该击键对Windows比对应用程序更加重要。

    虚拟键代码存储在WM_KEYDOWN等消息的wParam参数中,确定哪个键被按下或被释放。

    当处理击键消息时,可能需要知道是否有转义键(Shift、Ctrl和Alt)或切换键(Caps Lock、Num Lock和Scroll Lock)键被按下。

    可以用如下方式:

    iState = GetKeyState(VK_SHIFT);

    给前面的SYSMETS代码(http://blog.csdn.net/guzhou_diaoke/article/details/8155740   7.滚动条)中添加键盘处理功能:

    简单方法:为窗口过程增加WM_KEYDOWN逻辑

    更好的方法:把每一个WM_KEYDOWN消息转换为等同的WM_VSCROLL或WM_HSCROLL消息。可以使用:

    SendMessage(hwnd, message, wParam, lParam);

    当你调用SendMessage函数时,Windows调用窗口句柄hwnd的窗口过程,同时把四个函数变量传递给他。当窗口过程处理完此消息,Windows把控制权还给紧跟着SendMessage调用的下一条语句。

    [cpp] view plain copy
     
     print?
    1. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
    2. {  
    3.     // cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度  
    4.     // 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍  
    5.     static int  cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth, iVscrollPos;   
    6.     HDC         hdc;  
    7.     int         i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;  
    8.     PAINTSTRUCT ps;  
    9.     SCROLLINFO  si;  
    10.     TCHAR       szBuffer[10];  
    11.     TEXTMETRIC  tm;   
    12.   
    13.     switch (message)  
    14.     {  
    15.     case WM_CREATE:  
    16.         hdc = GetDC(hwnd);  
    17.           
    18.         GetTextMetrics(hdc, &tm);       // 获取系统默认字体的尺寸  
    19.         cxChar = tm.tmAveCharWidth;  
    20.         // tmPitchAndFamily为1表示变宽字体,为0表示等宽字体  
    21.         cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;  
    22.         cyChar = tm.tmHeight + tm.tmExternalLeading;  
    23.   
    24.         ReleaseDC(hwnd, hdc);  
    25.   
    26.         iMaxWidth = 40*cxChar + 22*cxCaps;  
    27.         return 0;  
    28.   
    29.     case WM_SIZE:  
    30.         cxClient = LOWORD(lParam);  
    31.         cyClient = HIWORD(lParam);  
    32.           
    33.         si.cbSize   = sizeof(si);  
    34.         si.fMask    = SIF_RANGE | SIF_PAGE;  
    35.   
    36.         si.nMin     = 0;  
    37.         si.nMax     = NUMLINES-1;  
    38.         si.nPage    = cyClient / cyChar;  
    39.         SetScrollInfo(hwnd, SB_VERT, &si, TRUE);  
    40.   
    41.         si.cbSize   = sizeof(si);  
    42.         si.fMask    = SIF_RANGE | SIF_PAGE;  
    43.   
    44.         si.nMin     = 0;  
    45.         si.nMax     = 2 + iMaxWidth/cxChar;  
    46.         si.nPage    = cxClient / cxChar;  
    47.         SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);  
    48.   
    49.         return 0;  
    50.           
    51.     case WM_VSCROLL:  
    52.         si.cbSize   = sizeof(si);  
    53.         si.fMask    = SIF_ALL;  
    54.   
    55.         GetScrollInfo(hwnd, SB_VERT, &si);  
    56.         iVertPos = si.nPos;  
    57.   
    58.         switch (LOWORD(wParam))  
    59.         {  
    60.         case SB_TOP:  
    61.             si.nPos = si.nMin;  
    62.             break;  
    63.   
    64.         case SB_BOTTOM:  
    65.             si.nPos = si.nMax;  
    66.             break;  
    67.   
    68.         case SB_LINEUP:  
    69.             si.nPos -= 1;  
    70.             break;  
    71.   
    72.         case SB_LINEDOWN:  
    73.             si.nPos += 1;  
    74.             break;  
    75.   
    76.         case SB_PAGEUP:  
    77.             si.nPos -= si.nPage;  
    78.             break;  
    79.   
    80.         case SB_PAGEDOWN:  
    81.             si.nPos += si.nPage;  
    82.             break;  
    83.   
    84.         case SB_THUMBTRACK:  
    85.             si.nPos = si.nTrackPos;  
    86.             break;  
    87.   
    88.         default:  
    89.             break;  
    90.         }  
    91.   
    92.         si.fMask = SIF_POS;  
    93.         SetScrollInfo(hwnd, SB_VERT, &si, TRUE);  
    94.         GetScrollInfo(hwnd, SB_VERT, &si);  
    95.   
    96.         if (si.nPos != iVertPos)  
    97.         {  
    98.             ScrollWindow(hwnd, 0, cyChar*(iVertPos-si.nPos), NULL, NULL);  
    99.             UpdateWindow(hwnd);  
    100.         }  
    101.         return 0;  
    102.   
    103.     case WM_HSCROLL:  
    104.         si.cbSize   = sizeof(si);  
    105.         si.fMask    = SIF_ALL;  
    106.   
    107.         GetScrollInfo(hwnd, SB_HORZ, &si);  
    108.         iHorzPos = si.nPos;  
    109.   
    110.         switch (LOWORD(wParam))  
    111.         {  
    112.         case SB_LINELEFT:  
    113.             si.nPos -= 1;  
    114.             break;  
    115.   
    116.         case SB_LINERIGHT:  
    117.             si.nPos += 1;  
    118.             break;  
    119.   
    120.         case SB_PAGELEFT:  
    121.             si.nPos -= si.nPage;  
    122.             break;  
    123.   
    124.         case SB_PAGERIGHT:  
    125.             si.nPos += si.nPage;  
    126.             break;  
    127.   
    128.         case SB_THUMBPOSITION:  
    129.             si.nPos = si.nTrackPos;  
    130.             break;  
    131.   
    132.         default:  
    133.             break;  
    134.         }  
    135.   
    136.         si.fMask = SIF_POS;  
    137.         SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);  
    138.         GetScrollInfo(hwnd, SB_HORZ, &si);  
    139.   
    140.         if (si.nPos != iHorzPos)  
    141.         {  
    142.             ScrollWindow(hwnd, cxChar*(iHorzPos-si.nPos), 0, NULL, NULL);  
    143.             UpdateWindow(hwnd);  
    144.         }  
    145.         return 0;  
    146.   
    147.     case WM_KEYDOWN:  
    148.         switch (wParam)  
    149.         {  
    150.         case VK_HOME:  
    151.             SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0);  
    152.             break;  
    153.   
    154.         case VK_END:  
    155.             SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);  
    156.             break;  
    157.   
    158.         case VK_PRIOR:  
    159.             SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);  
    160.             break;  
    161.   
    162.         case VK_NEXT:  
    163.             SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);  
    164.             break;  
    165.   
    166.         case VK_UP:  
    167.             SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);  
    168.             break;  
    169.   
    170.         case VK_DOWN:  
    171.             SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);  
    172.             break;  
    173.   
    174.         case VK_LEFT:  
    175.             SendMessage(hwnd, WM_HSCROLL, SB_PAGEUP, 0);  
    176.             break;  
    177.   
    178.         case VK_RIGHT:  
    179.             SendMessage(hwnd, WM_HSCROLL, SB_PAGEDOWN, 0);  
    180.             break;  
    181.         }  
    182.         return 0;  
    183.   
    184.     case WM_PAINT:  
    185.         hdc = BeginPaint(hwnd, &ps);  
    186.   
    187.         si.cbSize = sizeof(si);  
    188.         si.fMask = SIF_POS;  
    189.           
    190.         GetScrollInfo(hwnd, SB_VERT, &si);  
    191.         iVertPos = si.nPos;  
    192.   
    193.         GetScrollInfo(hwnd, SB_HORZ, &si);  
    194.         iHorzPos = si.nPos;  
    195.   
    196.         iPaintBeg = max(0, iVertPos + ps.rcPaint.top/cyChar);  
    197.         iPaintEnd = min(NUMLINES-1, iVertPos + ps.rcPaint.bottom/cyChar);  
    198.   
    199.         for (i = iPaintBeg; i <= iPaintEnd; i++)  
    200.         {  
    201.             x = cxChar * (1-iHorzPos);  
    202.             y = cyChar * (i-iVertPos);  
    203.   
    204.             TextOut(hdc, x, y, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel));  
    205.   
    206.             TextOut(hdc, x + 22*cxCaps, y, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc));  
    207.   
    208.             SetTextAlign(hdc, TA_RIGHT | TA_TOP);  
    209.   
    210.             TextOut(hdc, x + 22*cxCaps + 40*cxChar, y, szBuffer, wsprintf(szBuffer, TEXT("%5d"),   
    211.                 GetSystemMetrics(sysmetrics[i].iIndex)));  
    212.   
    213.             // 将对齐方式设回正常方式  
    214.             SetTextAlign(hdc, TA_LEFT | TA_TOP);  
    215.         }  
    216.   
    217.         EndPaint(hwnd, &ps);  
    218.         return 0;  
    219.   
    220.     case WM_DESTROY:  
    221.         PostQuitMessage(0);  
    222.         return 0;  
    223.     }  
    224.   
    225.     return DefWindowProc(hwnd, message, wParam, lParam);  
    226. }  

    有键盘了,就差鼠标了~很快会有的。

    4.字符消息

    通过转义状态信息可把击键消息转换为字符消息。

    GetMessage从消息队列中取出下一条消息;

    TranslateMessage负责把击键消息转换为字符消息;

    DispatchMessage调用此消息的窗口过程。

    5.消息排序

    假如Caps Lock没有锁定,按下再释放A,相应窗口过程会接收:

    1)WM_KEYDOWN:’A‘ 的虚拟键代码(0x41)

    2)WM_CHAR:  'a'的字符编码(0x61)

    3)WM_KEYUP: 'A' 的虚拟键代码(0x41)

    按下Shift+A,释放A,再释放Shift:

    1)WM_KEYDOWN:虚拟键代码VK_SHIFT(0x10)

    2)WM_KEYDOWN:’A‘ 的虚拟键代码(0x41)

    3)WM_CHAR:  'A' 的字符编码(0x41)

    4)WM_KEYUP: 'A' 的虚拟键代码(0x41)

    5)WM_UP:虚拟键代码VK_SHIFT(0x10)

    连续按住A:

    1)WM_KEYDOWN:’A‘ 的虚拟键代码(0x41)

    2)WM_CHAR:  'a'的字符编码(0x61)

    3)WM_KEYDOWN:’A‘ 的虚拟键代码(0x41)

    4)WM_CHAR:  'a'的字符编码(0x61)

    ……

    n)WM_KEYUP: 'A' 的虚拟键代码(0x41)


    6.控制字符的处理

    按照以下基本规则来处理击键和字符消息:如果你需要读取输入到窗口中的键盘字符,就处理WM_CHAR消息;如果你需要读取光标键、功能键、Delete键、Insert键、Shift键、Ctrl键和Alt键,则处理WM_KEYDOWN消息。

    [cpp] view plain copy
     
     print?
    1. /*--------------------------------------------------------------------------- 
    2.     keyView.cpp -- Displays keyboard and character messages 
    3. ----------------------------------------------------------------------------*/  
    4.   
    5. /*----------------------------------------------------------------------------------- 
    6.     SysMets4.cpp -- System Metrics Display Program ver4 use keyboard 
    7.  *----------------------------------------------------------------------------------*/  
    8.   
    9. #include <windows.h>  
    10.   
    11. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  
    12.   
    13. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
    14. {  
    15.     static TCHAR    szAppName[] = TEXT("KeyView1");  
    16.     HWND            hwnd;  
    17.     MSG             msg;  
    18.     WNDCLASS        wndclass;  
    19.   
    20.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
    21.     wndclass.lpfnWndProc    = WndProc;  
    22.     wndclass.cbClsExtra     = 0;  
    23.     wndclass.cbWndExtra     = 0;  
    24.     wndclass.hInstance      = hInstance;  
    25.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
    26.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
    27.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
    28.     wndclass.lpszMenuName   = NULL;  
    29.     wndclass.lpszClassName  = szAppName;  
    30.   
    31.     if (!RegisterClass(&wndclass))  
    32.     {  
    33.         MessageBox(NULL, TEXT("This program requires windows NT!"), szAppName, MB_ICONERROR);  
    34.         return 0;  
    35.     }  
    36.   
    37.     hwnd = CreateWindow(szAppName,                                      // window class name  
    38.                         TEXT("Keyboard Message Viewer #1"),             // window caption  
    39.                         WS_OVERLAPPEDWINDOW,                            // window style  
    40.                         CW_USEDEFAULT,                                  // initial x position  
    41.                         CW_USEDEFAULT,                                  // initial y position  
    42.                         CW_USEDEFAULT,                                  // initial x size  
    43.                         CW_USEDEFAULT,                                  // initial y size  
    44.                         NULL,                                           // parent window handle  
    45.                         NULL,                                           // window menu handle  
    46.                         hInstance,                                      // program instance handle  
    47.                         NULL);                                          // creation parameters  
    48.   
    49.     ShowWindow(hwnd, iCmdShow);  
    50.     UpdateWindow(hwnd);  
    51.   
    52.     while (GetMessage(&msg, NULL, 0, 0))  
    53.     {  
    54.         TranslateMessage(&msg);  
    55.         DispatchMessage(&msg);  
    56.     }  
    57.   
    58.     return msg.wParam;  
    59. }  
    60.   
    61. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
    62. {  
    63.     // cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度  
    64.     // 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍  
    65.     static int      cxChar, cyChar, cxClient, cyClient, cxClientMax, cyClientMax;  
    66.     static int      cLinesMax, cLines;  
    67.     static PMSG     pmsg;  
    68.     static RECT     rectScroll;  
    69.     static TCHAR szTop[] = TEXT ("Message        Key       Char     ")  
    70.                             TEXT ("Repeat Scan Ext ALT Prev Tran") ;  
    71.      static TCHAR szUnd[] = TEXT ("_______        ___       ____     ")  
    72.                             TEXT ("______ ____ ___ ___ ____ ____") ;  
    73.   
    74.     static TCHAR*   szFormat[2] = {  
    75.         TEXT("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),  
    76.         TEXT("%-13s            0x%04X%1s%c %6u %4d %3s %3s %4s %4s") };  
    77.     static TCHAR*   szYes   = TEXT("Yes");  
    78.     static TCHAR*   szNo    = TEXT("No");  
    79.     static TCHAR*   szDown  = TEXT("Down");  
    80.     static TCHAR*   szUp    = TEXT("Up");  
    81.   
    82.     static TCHAR*   szMessage[] = {  
    83.         TEXT("WM_KEYDOWN"),     TEXT("WM_KEYUP"),  
    84.         TEXT("WM_CHAR"),        TEXT("WM_DEADCHAR"),  
    85.         TEXT("WM_SYSKEYDOWN"),  TEXT("WM_SYSKEYUP"),  
    86.         TEXT("WM_SYSCHAR"),     TEXT("WM_SYSDEADCHAR") };  
    87.   
    88.     HDC         hdc;  
    89.     int         i, iType;  
    90.     PAINTSTRUCT ps;  
    91.     TCHAR       szBuffer[128], szKeyName[32];  
    92.     TEXTMETRIC  tm;   
    93.   
    94.     switch (message)  
    95.     {  
    96.     case WM_CREATE:  
    97.     case WM_DISPLAYCHANGE:  
    98.         cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);  
    99.         cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);  
    100.   
    101.         hdc = GetDC(hwnd);  
    102.           
    103.         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));  
    104.         GetTextMetrics(hdc, &tm);       // 获取系统默认字体的尺寸  
    105.         cxChar = tm.tmAveCharWidth;  
    106.         cyChar = tm.tmHeight;  
    107.   
    108.         ReleaseDC(hwnd, hdc);  
    109.   
    110.         if (pmsg)  
    111.             free(pmsg);  
    112.   
    113.         cLinesMax = cyClientMax / cyChar;  
    114.         pmsg = (PMSG)malloc(cLinesMax * sizeof(MSG));  
    115.         cLines = 0;  
    116.   
    117.         //return 0;  
    118.   
    119.     case WM_SIZE:  
    120.         if (message == WM_SIZE)  
    121.         {  
    122.             cxClient = LOWORD(lParam);  
    123.             cyClient = HIWORD(lParam);  
    124.         }  
    125.           
    126.         rectScroll.left     = 0;  
    127.         rectScroll.right    = cxClient;  
    128.         rectScroll.top      = cyChar;  
    129.         rectScroll.bottom   = cyChar * (cyClient / cyChar);  
    130.   
    131.         InvalidateRect(hwnd, NULL, TRUE);  
    132.   
    133.         return 0;  
    134.           
    135.     case WM_KEYDOWN:  
    136.     case WM_KEYUP:  
    137.     case WM_CHAR:  
    138.     case WM_DEADCHAR:  
    139.     case WM_SYSKEYDOWN:  
    140.     case WM_SYSKEYUP:  
    141.     case WM_SYSCHAR:  
    142.     case WM_SYSDEADCHAR:  
    143.         for (i = cLinesMax-1; i > 0; i--)  
    144.         {  
    145.             pmsg[i] = pmsg[i-1];  
    146.         }  
    147.   
    148.         pmsg[0].hwnd    = hwnd;  
    149.         pmsg[0].message = message;  
    150.         pmsg[0].wParam  = wParam;  
    151.         pmsg[0].lParam  = lParam;  
    152.   
    153.         cLines = min(cLines + 1, cLinesMax);  
    154.   
    155.         ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll);  
    156.         break;  
    157.       
    158.   
    159.     case WM_PAINT:  
    160.         hdc = BeginPaint(hwnd, &ps);  
    161.   
    162.         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));  
    163.         SetBkMode(hdc, TRANSPARENT);  
    164.         TextOut(hdc, 0, 0, szTop, lstrlen(szTop));  
    165.         TextOut(hdc, 0, 0, szUnd, lstrlen(szUnd));  
    166.   
    167.         for (i = 0; i < min(cLines, cyClient / cyChar - 1); i++)  
    168.         {  
    169.             iType = pmsg[i].message == WM_CHAR ||  
    170.                     pmsg[i].message == WM_SYSCHAR ||  
    171.                     pmsg[i].message == WM_DEADCHAR ||  
    172.                     pmsg[i].message == WM_SYSDEADCHAR;  
    173.   
    174.             GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));  
    175.   
    176.             TextOut(hdc, 0, (cyClient/cyChar - 1 - i) * cyChar, szBuffer,   
    177.                 wsprintf(szBuffer, szFormat[iType],  
    178.                     szMessage[pmsg[i].message - WM_KEYFIRST],  
    179.                     pmsg[i].wParam,  
    180.                     (PTSTR)(iType ? TEXT(" ") : szKeyName),  
    181.                     (TCHAR)(iType ? pmsg[i].wParam: ' '),  
    182.                     LOWORD(pmsg[i].lParam),  
    183.                     HIWORD(pmsg[i].lParam) & 0xFF,  
    184.                     0x01000000 & pmsg[i].lParam ? szYes : szNo,  
    185.                     0x20000000 & pmsg[i].lParam ? szYes : szNo,  
    186.                     0x40000000 & pmsg[i].lParam ? szDown: szUp,  
    187.                     0x80000000 & pmsg[i].lParam ? szUp  : szDown));  
    188.         }  
    189.   
    190.         EndPaint(hwnd, &ps);  
    191.         return 0;  
    192.   
    193.     case WM_DESTROY:  
    194.         PostQuitMessage(0);  
    195.         return 0;  
    196.     }  
    197.   
    198.     return DefWindowProc(hwnd, message, wParam, lParam);  
    199. }  


    7.插入符号(就是平时说的光标)

    插入符号指明你输入的下一个字符将出现在屏幕上的位置。

    相关函数:

    CreateCaret:创建和窗口关联的插入符号

    SetCaretPos:设置窗口内的插入符号的位置

    ShowCaret:显式插入符号

    HideCaret:隐藏插入符号

    DestroyCaret:销毁插入符号

    GetCaretPos:获取插入符号位置

    GetCaretBlinkTime、SetCaretBlinkTime:获取、设置插入符号闪烁时间

    使用插入符号主要规则:在窗口过程处理WM_SETFOCUS消息时调用CreateCaret,处理WM_KILLFOCUS消息时调用DestroyCaret函数。

    创建的插入符号是隐藏的,必须调用ShowCaret使之可见。

    要在窗口内绘制某些东西时,它必须调用HideCaret隐藏插入符号。结束绘制后,再调用ShowCaret显式插入符号。

    HideCaret效果是叠加的。

    一个简单的文本编辑器雏形:

    [cpp] view plain copy
     
     print?
    1. /*---------------------------------------------------------------------------- 
    2.     typer.cpp -- Typing Program 
    3. ----------------------------------------------------------------------------*/  
    4.   
    5. /*--------------------------------------------------------------------------- 
    6.     keyView.cpp -- Displays keyboard and character messages 
    7. ----------------------------------------------------------------------------*/  
    8.   
    9. /*----------------------------------------------------------------------------------- 
    10.     SysMets4.cpp -- System Metrics Display Program ver4 use keyboard 
    11.  *----------------------------------------------------------------------------------*/  
    12.   
    13. #include <windows.h>  
    14.   
    15. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  
    16.   
    17. #define BUFFER(x, y)    *(pBuffer + y*cxBuffer + x)  
    18.   
    19. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
    20. {  
    21.     static TCHAR    szAppName[] = TEXT("Typer");  
    22.     HWND            hwnd;  
    23.     MSG             msg;  
    24.     WNDCLASS        wndclass;  
    25.   
    26.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
    27.     wndclass.lpfnWndProc    = WndProc;  
    28.     wndclass.cbClsExtra     = 0;  
    29.     wndclass.cbWndExtra     = 0;  
    30.     wndclass.hInstance      = hInstance;  
    31.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
    32.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
    33.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
    34.     wndclass.lpszMenuName   = NULL;  
    35.     wndclass.lpszClassName  = szAppName;  
    36.   
    37.     if (!RegisterClass(&wndclass))  
    38.     {  
    39.         MessageBox(NULL, TEXT("This program requires windows NT!"), szAppName, MB_ICONERROR);  
    40.         return 0;  
    41.     }  
    42.   
    43.     hwnd = CreateWindow(szAppName,                                      // window class name  
    44.                         TEXT("Typer"),                                  // window caption  
    45.                         WS_OVERLAPPEDWINDOW,                            // window style  
    46.                         CW_USEDEFAULT,                                  // initial x position  
    47.                         CW_USEDEFAULT,                                  // initial y position  
    48.                         CW_USEDEFAULT,                                  // initial x size  
    49.                         CW_USEDEFAULT,                                  // initial y size  
    50.                         NULL,                                           // parent window handle  
    51.                         NULL,                                           // window menu handle  
    52.                         hInstance,                                      // program instance handle  
    53.                         NULL);                                          // creation parameters  
    54.   
    55.     ShowWindow(hwnd, iCmdShow);  
    56.     UpdateWindow(hwnd);  
    57.   
    58.     while (GetMessage(&msg, NULL, 0, 0))  
    59.     {  
    60.         TranslateMessage(&msg);  
    61.         DispatchMessage(&msg);  
    62.     }  
    63.   
    64.     return msg.wParam;  
    65. }  
    66.   
    67. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
    68. {  
    69.     static DWORD    dwCharSet = DEFAULT_CHARSET;  
    70.     static int      cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer, xCaret, yCaret;  
    71.     static TCHAR*   pBuffer = NULL;  
    72.   
    73.     int             x, y, i;  
    74.     HDC             hdc;  
    75.     PAINTSTRUCT     ps;  
    76.     TEXTMETRIC      tm;   
    77.   
    78.     switch (message)  
    79.     {  
    80.     case WM_INPUTLANGCHANGE:  
    81.         dwCharSet = wParam;  
    82.   
    83.     case WM_CREATE:  
    84.         hdc = GetDC(hwnd);  
    85.           
    86.         SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));  
    87.         GetTextMetrics(hdc, &tm);  
    88.         cxChar = tm.tmAveCharWidth;  
    89.         cyChar = tm.tmHeight;  
    90.           
    91.         DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));  
    92.         ReleaseDC(hwnd, hdc);  
    93.   
    94.     case WM_SIZE:  
    95.         if (message == WM_SIZE)  
    96.         {  
    97.             cxClient = LOWORD(lParam);  
    98.             cyClient = HIWORD(lParam);  
    99.         }  
    100.           
    101.         cxBuffer = max(1, cxClient/cxChar);  
    102.         cyBuffer = max(1, cyClient/cyChar);  
    103.   
    104.         if (pBuffer != NULL)  
    105.             free(pBuffer);  
    106.   
    107.         pBuffer = (TCHAR *)malloc(sizeof(TCHAR) * cxBuffer * cyBuffer);  
    108.   
    109.         for (y = 0; y < cyBuffer; y++)  
    110.             for (x = 0; x < cxBuffer; x++)  
    111.                 BUFFER(x, y) = ' ';  
    112.   
    113.         xCaret = 0;  
    114.         yCaret = 0;  
    115.   
    116.         if (hwnd == GetFocus())  
    117.             SetCaretPos(xCaret * cxChar, yCaret * cyChar);  
    118.   
    119.         InvalidateRect(hwnd, NULL, TRUE);  
    120.         return 0;  
    121.   
    122.     case WM_SETFOCUS:  
    123.         CreateCaret(hwnd, NULL, cxChar, cyChar);  
    124.         SetCaretPos(xCaret*cxChar, yCaret*cyChar);  
    125.         ShowCaret(hwnd);  
    126.         return 0;  
    127.   
    128.     case WM_KILLFOCUS:  
    129.         HideCaret(hwnd);  
    130.         DestroyCaret();  
    131.         return 0;  
    132.           
    133.     case WM_KEYDOWN:  
    134.         switch (wParam)  
    135.         {  
    136.         case VK_HOME:  
    137.             xCaret = 0;  
    138.             break;  
    139.   
    140.         case VK_END:  
    141.             xCaret = cxBuffer - 1;  
    142.             break;  
    143.   
    144.         case VK_PRIOR:  
    145.             yCaret = 0;  
    146.             break;  
    147.   
    148.         case VK_NEXT:  
    149.             yCaret = cyBuffer - 1;  
    150.             break;  
    151.   
    152.         case VK_LEFT:  
    153.             xCaret = max(xCaret-1, 0);  
    154.             break;  
    155.   
    156.         case VK_RIGHT:  
    157.             xCaret = min(xCaret+1, cxBuffer-1);  
    158.             break;  
    159.   
    160.         case VK_UP:  
    161.             yCaret = max(yCaret-1, 0);  
    162.             break;  
    163.   
    164.         case VK_DOWN:  
    165.             yCaret = min(yCaret+1, cyBuffer-1);  
    166.             break;  
    167.   
    168.         case VK_DELETE:  
    169.             for (x = xCaret; x < cxBuffer-1; x++)  
    170.                 BUFFER(x, yCaret) = BUFFER(x+1, yCaret);  
    171.             BUFFER(cxBuffer-1, yCaret) = ' ';  
    172.   
    173.             HideCaret(hwnd);  
    174.   
    175.             hdc = GetDC(hwnd);  
    176.   
    177.             SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));  
    178.   
    179.             TextOut(hdc, xCaret*cxChar, yCaret*cyChar, &BUFFER(xCaret, yCaret), cxBuffer-xCaret);  
    180.   
    181.             DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));  
    182.             ReleaseDC(hwnd, hdc);  
    183.             ShowCaret(hwnd);  
    184.             break;  
    185.         }  
    186.         SetCaretPos(xCaret*cxChar, yCaret*cyChar);  
    187.         return 0;  
    188.   
    189.     case WM_CHAR:  
    190.         for (i = 0; i < (int)LOWORD(lParam); i++)  
    191.         {  
    192.             switch (wParam)  
    193.             {  
    194.             case '':          // backspace  
    195.                 if (xCaret > 0)  
    196.                 {  
    197.                     xCaret--;  
    198.                     SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);  
    199.                 }  
    200.                 break;  
    201.   
    202.             case ' ':          // tab  
    203.                 do  
    204.                 {  
    205.                     SendMessage(hwnd, WM_CHAR, ' ', 1);  
    206.                 }  
    207.                 while (xCaret % 8 != 0);  
    208.                 break;  
    209.   
    210.             case ' ':          // line feed  
    211.                 if (++yCaret == cyBuffer)  
    212.                     yCaret = 0;  
    213.                 break;  
    214.   
    215.             case ' ':          // carriage return  
    216.                 xCaret = 0;  
    217.                 if (++yCaret == cyBuffer)  
    218.                     yCaret = 0;  
    219.                 break;  
    220.   
    221.             case 'x1B':        // escape  
    222.                 for (y = 0; y < cyBuffer; y++)  
    223.                     for (x = 0; x < cxBuffer; x++)  
    224.                         BUFFER(x, y) = ' ';  
    225.   
    226.                 xCaret = 0;  
    227.                 yCaret = 0;  
    228.   
    229.                 InvalidateRect(hwnd, NULL, FALSE);  
    230.                 break;  
    231.   
    232.             default:            // character codes  
    233.                 BUFFER(xCaret, yCaret) = (TCHAR)wParam;  
    234.   
    235.                 HideCaret(hwnd);  
    236.                 hdc = GetDC(hwnd);  
    237.                 SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));  
    238.   
    239.                 TextOut(hdc, xCaret*cxChar, yCaret*cyChar, &BUFFER(xCaret, yCaret), 1);  
    240.   
    241.                 DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));  
    242.                 ReleaseDC(hwnd, hdc);  
    243.                 ShowCaret(hwnd);  
    244.   
    245.                 if (++xCaret == cxBuffer)  
    246.                 {  
    247.                     xCaret = 0;  
    248.                     if (++yCaret == cyBuffer)  
    249.                         yCaret = 0;  
    250.                 }  
    251.                 break;  
    252.             }  
    253.         }  
    254.   
    255.         SetCaretPos(xCaret*cxChar, yCaret*cyChar);  
    256.         return 0;  
    257.   
    258.     case WM_PAINT:  
    259.         hdc = BeginPaint(hwnd, &ps);  
    260.   
    261.         SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));  
    262.           
    263.         for (y = 0; y < cyBuffer; y++)  
    264.             TextOut(hdc, 0, y*cyChar, &BUFFER(0, y), cxBuffer);  
    265.   
    266.         DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));  
    267.   
    268.         EndPaint(hwnd, &ps);  
    269.         return 0;  
    270.   
    271.     case WM_DESTROY:  
    272.         PostQuitMessage(0);  
    273.         return 0;  
    274.     }  
    275.   
    276.     return DefWindowProc(hwnd, message, wParam, lParam);  
    277. }  


     
    http://blog.csdn.net/guzhou_diaoke/article/details/8170366
  • 相关阅读:
    leetcode 86. Partition List
    leetcode 303. Range Sum Query
    leetcode 1310. XOR Queries of a Subarray
    leetcode 1309. Decrypt String from Alphabet to Integer Mapping
    leetcode 215. Kth Largest Element in an Array
    将numpy.ndarray写入excel
    leetcode 1021 Remove Outermost Parentheses
    leetcode 1306. Jump Game III
    leetcode 1305. All Elements in Two Binary Search Trees
    ICCV2019 oral:Wavelet Domain Style Transfer for an Effective Perception-distortion Tradeoff in Single Image Super-Resolution
  • 原文地址:https://www.cnblogs.com/findumars/p/7475433.html
Copyright © 2011-2022 走看看