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调用的下一条语句。
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{// cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度// 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth, iVscrollPos; HDC hdc;int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;PAINTSTRUCT ps;SCROLLINFO si;TCHAR szBuffer[10];TEXTMETRIC tm; switch (message){case WM_CREATE:hdc = GetDC(hwnd);GetTextMetrics(hdc, &tm); // 获取系统默认字体的尺寸cxChar = tm.tmAveCharWidth;// tmPitchAndFamily为1表示变宽字体,为0表示等宽字体cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;cyChar = tm.tmHeight + tm.tmExternalLeading;ReleaseDC(hwnd, hdc);iMaxWidth = 40*cxChar + 22*cxCaps;return 0;case WM_SIZE:cxClient = LOWORD(lParam);cyClient = HIWORD(lParam);si.cbSize = sizeof(si);si.fMask = SIF_RANGE | SIF_PAGE;si.nMin = 0;si.nMax = NUMLINES-1;si.nPage = cyClient / cyChar;SetScrollInfo(hwnd, SB_VERT, &si, TRUE);si.cbSize = sizeof(si);si.fMask = SIF_RANGE | SIF_PAGE;si.nMin = 0;si.nMax = 2 + iMaxWidth/cxChar;si.nPage = cxClient / cxChar;SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);return 0;case WM_VSCROLL:si.cbSize = sizeof(si);si.fMask = SIF_ALL;GetScrollInfo(hwnd, SB_VERT, &si);iVertPos = si.nPos;switch (LOWORD(wParam)){case SB_TOP:si.nPos = si.nMin;break;case SB_BOTTOM:si.nPos = si.nMax;break;case SB_LINEUP:si.nPos -= 1;break;case SB_LINEDOWN:si.nPos += 1;break;case SB_PAGEUP:si.nPos -= si.nPage;break;case SB_PAGEDOWN:si.nPos += si.nPage;break;case SB_THUMBTRACK:si.nPos = si.nTrackPos;break;default:break;}si.fMask = SIF_POS;SetScrollInfo(hwnd, SB_VERT, &si, TRUE);GetScrollInfo(hwnd, SB_VERT, &si);if (si.nPos != iVertPos){ScrollWindow(hwnd, 0, cyChar*(iVertPos-si.nPos), NULL, NULL);UpdateWindow(hwnd);}return 0;case WM_HSCROLL:si.cbSize = sizeof(si);si.fMask = SIF_ALL;GetScrollInfo(hwnd, SB_HORZ, &si);iHorzPos = si.nPos;switch (LOWORD(wParam)){case SB_LINELEFT:si.nPos -= 1;break;case SB_LINERIGHT:si.nPos += 1;break;case SB_PAGELEFT:si.nPos -= si.nPage;break;case SB_PAGERIGHT:si.nPos += si.nPage;break;case SB_THUMBPOSITION:si.nPos = si.nTrackPos;break;default:break;}si.fMask = SIF_POS;SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);GetScrollInfo(hwnd, SB_HORZ, &si);if (si.nPos != iHorzPos){ScrollWindow(hwnd, cxChar*(iHorzPos-si.nPos), 0, NULL, NULL);UpdateWindow(hwnd);}return 0;case WM_KEYDOWN:switch (wParam){case VK_HOME:SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0);break;case VK_END:SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);break;case VK_PRIOR:SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);break;case VK_NEXT:SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);break;case VK_UP:SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);break;case VK_DOWN:SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);break;case VK_LEFT:SendMessage(hwnd, WM_HSCROLL, SB_PAGEUP, 0);break;case VK_RIGHT:SendMessage(hwnd, WM_HSCROLL, SB_PAGEDOWN, 0);break;}return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);si.cbSize = sizeof(si);si.fMask = SIF_POS;GetScrollInfo(hwnd, SB_VERT, &si);iVertPos = si.nPos;GetScrollInfo(hwnd, SB_HORZ, &si);iHorzPos = si.nPos;iPaintBeg = max(0, iVertPos + ps.rcPaint.top/cyChar);iPaintEnd = min(NUMLINES-1, iVertPos + ps.rcPaint.bottom/cyChar);for (i = iPaintBeg; i <= iPaintEnd; i++){x = cxChar * (1-iHorzPos);y = cyChar * (i-iVertPos);TextOut(hdc, x, y, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel));TextOut(hdc, x + 22*cxCaps, y, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc));SetTextAlign(hdc, TA_RIGHT | TA_TOP);TextOut(hdc, x + 22*cxCaps + 40*cxChar, y, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex)));// 将对齐方式设回正常方式SetTextAlign(hdc, TA_LEFT | TA_TOP);}EndPaint(hwnd, &ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);
}
有键盘了,就差鼠标了~很快会有的。
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消息。
/*---------------------------------------------------------------------------keyView.cpp -- Displays keyboard and character messages
----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------------SysMets4.cpp -- System Metrics Display Program ver4 use keyboard*----------------------------------------------------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{static TCHAR szAppName[] = TEXT("KeyView1");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass(&wndclass)){MessageBox(NULL, TEXT("This program requires windows NT!"), szAppName, MB_ICONERROR);return 0;}hwnd = CreateWindow(szAppName, // window class nameTEXT("Keyboard Message Viewer #1"), // window captionWS_OVERLAPPEDWINDOW, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y positionCW_USEDEFAULT, // initial x sizeCW_USEDEFAULT, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{// cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度// 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍static int cxChar, cyChar, cxClient, cyClient, cxClientMax, cyClientMax;static int cLinesMax, cLines;static PMSG pmsg;static RECT rectScroll;static TCHAR szTop[] = TEXT ("Message Key Char ")TEXT ("Repeat Scan Ext ALT Prev Tran") ;static TCHAR szUnd[] = TEXT ("_______ ___ ____ ")TEXT ("______ ____ ___ ___ ____ ____") ;static TCHAR* szFormat[2] = {TEXT("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),TEXT("%-13s 0x%04X%1s%c %6u %4d %3s %3s %4s %4s") };static TCHAR* szYes = TEXT("Yes");static TCHAR* szNo = TEXT("No");static TCHAR* szDown = TEXT("Down");static TCHAR* szUp = TEXT("Up");static TCHAR* szMessage[] = {TEXT("WM_KEYDOWN"), TEXT("WM_KEYUP"),TEXT("WM_CHAR"), TEXT("WM_DEADCHAR"),TEXT("WM_SYSKEYDOWN"), TEXT("WM_SYSKEYUP"),TEXT("WM_SYSCHAR"), TEXT("WM_SYSDEADCHAR") };HDC hdc;int i, iType;PAINTSTRUCT ps;TCHAR szBuffer[128], szKeyName[32];TEXTMETRIC tm; switch (message){case WM_CREATE:case WM_DISPLAYCHANGE:cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);hdc = GetDC(hwnd);SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));GetTextMetrics(hdc, &tm); // 获取系统默认字体的尺寸cxChar = tm.tmAveCharWidth;cyChar = tm.tmHeight;ReleaseDC(hwnd, hdc);if (pmsg)free(pmsg);cLinesMax = cyClientMax / cyChar;pmsg = (PMSG)malloc(cLinesMax * sizeof(MSG));cLines = 0;//return 0;case WM_SIZE:if (message == WM_SIZE){cxClient = LOWORD(lParam);cyClient = HIWORD(lParam);}rectScroll.left = 0;rectScroll.right = cxClient;rectScroll.top = cyChar;rectScroll.bottom = cyChar * (cyClient / cyChar);InvalidateRect(hwnd, NULL, TRUE);return 0;case WM_KEYDOWN:case WM_KEYUP:case WM_CHAR:case WM_DEADCHAR:case WM_SYSKEYDOWN:case WM_SYSKEYUP:case WM_SYSCHAR:case WM_SYSDEADCHAR:for (i = cLinesMax-1; i > 0; i--){pmsg[i] = pmsg[i-1];}pmsg[0].hwnd = hwnd;pmsg[0].message = message;pmsg[0].wParam = wParam;pmsg[0].lParam = lParam;cLines = min(cLines + 1, cLinesMax);ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll);break;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));SetBkMode(hdc, TRANSPARENT);TextOut(hdc, 0, 0, szTop, lstrlen(szTop));TextOut(hdc, 0, 0, szUnd, lstrlen(szUnd));for (i = 0; i < min(cLines, cyClient / cyChar - 1); i++){iType = pmsg[i].message == WM_CHAR ||pmsg[i].message == WM_SYSCHAR ||pmsg[i].message == WM_DEADCHAR ||pmsg[i].message == WM_SYSDEADCHAR;GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));TextOut(hdc, 0, (cyClient/cyChar - 1 - i) * cyChar, szBuffer, wsprintf(szBuffer, szFormat[iType],szMessage[pmsg[i].message - WM_KEYFIRST],pmsg[i].wParam,(PTSTR)(iType ? TEXT(" ") : szKeyName),(TCHAR)(iType ? pmsg[i].wParam: ' '),LOWORD(pmsg[i].lParam),HIWORD(pmsg[i].lParam) & 0xFF,0x01000000 & pmsg[i].lParam ? szYes : szNo,0x20000000 & pmsg[i].lParam ? szYes : szNo,0x40000000 & pmsg[i].lParam ? szDown: szUp,0x80000000 & pmsg[i].lParam ? szUp : szDown));}EndPaint(hwnd, &ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);
}
7.插入符号(就是平时说的光标)
插入符号指明你输入的下一个字符将出现在屏幕上的位置。
相关函数:
CreateCaret:创建和窗口关联的插入符号
SetCaretPos:设置窗口内的插入符号的位置
ShowCaret:显式插入符号
HideCaret:隐藏插入符号
DestroyCaret:销毁插入符号
GetCaretPos:获取插入符号位置
GetCaretBlinkTime、SetCaretBlinkTime:获取、设置插入符号闪烁时间
使用插入符号主要规则:在窗口过程处理WM_SETFOCUS消息时调用CreateCaret,处理WM_KILLFOCUS消息时调用DestroyCaret函数。
创建的插入符号是隐藏的,必须调用ShowCaret使之可见。
要在窗口内绘制某些东西时,它必须调用HideCaret隐藏插入符号。结束绘制后,再调用ShowCaret显式插入符号。
HideCaret效果是叠加的。
一个简单的文本编辑器雏形:
/*----------------------------------------------------------------------------typer.cpp -- Typing Program
----------------------------------------------------------------------------*//*---------------------------------------------------------------------------keyView.cpp -- Displays keyboard and character messages
----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------------SysMets4.cpp -- System Metrics Display Program ver4 use keyboard*----------------------------------------------------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);#define BUFFER(x, y) *(pBuffer + y*cxBuffer + x)int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{static TCHAR szAppName[] = TEXT("Typer");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass(&wndclass)){MessageBox(NULL, TEXT("This program requires windows NT!"), szAppName, MB_ICONERROR);return 0;}hwnd = CreateWindow(szAppName, // window class nameTEXT("Typer"), // window captionWS_OVERLAPPEDWINDOW, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y positionCW_USEDEFAULT, // initial x sizeCW_USEDEFAULT, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{static DWORD dwCharSet = DEFAULT_CHARSET;static int cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer, xCaret, yCaret;static TCHAR* pBuffer = NULL;int x, y, i;HDC hdc;PAINTSTRUCT ps;TEXTMETRIC tm; switch (message){case WM_INPUTLANGCHANGE:dwCharSet = wParam;case WM_CREATE:hdc = GetDC(hwnd);SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));GetTextMetrics(hdc, &tm);cxChar = tm.tmAveCharWidth;cyChar = tm.tmHeight;DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));ReleaseDC(hwnd, hdc);case WM_SIZE:if (message == WM_SIZE){cxClient = LOWORD(lParam);cyClient = HIWORD(lParam);}cxBuffer = max(1, cxClient/cxChar);cyBuffer = max(1, cyClient/cyChar);if (pBuffer != NULL)free(pBuffer);pBuffer = (TCHAR *)malloc(sizeof(TCHAR) * cxBuffer * cyBuffer);for (y = 0; y < cyBuffer; y++)for (x = 0; x < cxBuffer; x++)BUFFER(x, y) = ' ';xCaret = 0;yCaret = 0;if (hwnd == GetFocus())SetCaretPos(xCaret * cxChar, yCaret * cyChar);InvalidateRect(hwnd, NULL, TRUE);return 0;case WM_SETFOCUS:CreateCaret(hwnd, NULL, cxChar, cyChar);SetCaretPos(xCaret*cxChar, yCaret*cyChar);ShowCaret(hwnd);return 0;case WM_KILLFOCUS:HideCaret(hwnd);DestroyCaret();return 0;case WM_KEYDOWN:switch (wParam){case VK_HOME:xCaret = 0;break;case VK_END:xCaret = cxBuffer - 1;break;case VK_PRIOR:yCaret = 0;break;case VK_NEXT:yCaret = cyBuffer - 1;break;case VK_LEFT:xCaret = max(xCaret-1, 0);break;case VK_RIGHT:xCaret = min(xCaret+1, cxBuffer-1);break;case VK_UP:yCaret = max(yCaret-1, 0);break;case VK_DOWN:yCaret = min(yCaret+1, cyBuffer-1);break;case VK_DELETE:for (x = xCaret; x < cxBuffer-1; x++)BUFFER(x, yCaret) = BUFFER(x+1, yCaret);BUFFER(cxBuffer-1, yCaret) = ' ';HideCaret(hwnd);hdc = GetDC(hwnd);SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));TextOut(hdc, xCaret*cxChar, yCaret*cyChar, &BUFFER(xCaret, yCaret), cxBuffer-xCaret);DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));ReleaseDC(hwnd, hdc);ShowCaret(hwnd);break;}SetCaretPos(xCaret*cxChar, yCaret*cyChar);return 0;case WM_CHAR:for (i = 0; i < (int)LOWORD(lParam); i++){switch (wParam){case '\b': // backspaceif (xCaret > 0){xCaret--;SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);}break;case '\t': // tabdo{SendMessage(hwnd, WM_CHAR, ' ', 1);}while (xCaret % 8 != 0);break;case '\n': // line feedif (++yCaret == cyBuffer)yCaret = 0;break;case '\r': // carriage returnxCaret = 0;if (++yCaret == cyBuffer)yCaret = 0;break;case '\x1B': // escapefor (y = 0; y < cyBuffer; y++)for (x = 0; x < cxBuffer; x++)BUFFER(x, y) = ' ';xCaret = 0;yCaret = 0;InvalidateRect(hwnd, NULL, FALSE);break;default: // character codesBUFFER(xCaret, yCaret) = (TCHAR)wParam;HideCaret(hwnd);hdc = GetDC(hwnd);SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));TextOut(hdc, xCaret*cxChar, yCaret*cyChar, &BUFFER(xCaret, yCaret), 1);DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));ReleaseDC(hwnd, hdc);ShowCaret(hwnd);if (++xCaret == cxBuffer){xCaret = 0;if (++yCaret == cyBuffer)yCaret = 0;}break;}}SetCaretPos(xCaret*cxChar, yCaret*cyChar);return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));for (y = 0; y < cyBuffer; y++)TextOut(hdc, 0, y*cyChar, &BUFFER(0, y), cxBuffer);DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));EndPaint(hwnd, &ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);
}
Win32 键盘事件 - 击键消息、字符消息、插入符号(光标)相关推荐
- java按键事件空格_java键盘事件 空格键
public void keyPressed(KeyEvent e) {//键盘按键按下事件 // TODO Auto-generated method stub switch(e.getKeyCod ...
- vue 绑定 keyup.enter 绑定回车键盘事件 enter键防止页面刷新
为祖国的复兴而读书!!! 一般方法,这样写: <div class="btn submit" @keyup.enter="submit" @click=& ...
- Windows程序设计--击键消息和字符消息
键盘消息分为击键消息和字符消息.而击键消息就是指当你按下一个键时它是哪个键. 一般有以下四个击键消息: WM_KEYDOWN.WM_SYSKEYDOWN.WM_KEYUP.WM_SYSKEYUP.这里 ...
- python绑定按键pageup键_键盘事件keydown、keypress、keyup随笔整理总结(摘抄)
原文1:http://www.cnblogs.com/silence516/archive/2013/01/25/2876611.html 原文2:http://www.cnblogs.com/leo ...
- keyup常用事件_键盘事件keydown、keypress、keyup随笔整理总结
键盘 英文输入法: 事件触发顺序:keydown - > keypress - > keyup 中文输入法: firfox:输入触发keydown,回车确认输入触发keyup chrome ...
- 键盘事件keydown、keypress、keyup随笔整理总结(摘抄)
原文1:http://www.cnblogs.com/silence516/archive/2013/01/25/2876611.html 原文2:http://www.cnblogs.com/leo ...
- java keydown_键盘事件keydown、keypress、keyup随笔整理总结
英文输入法: 事件触发顺序:keydown - > keypress - > keyup 中文输入法: firfox:输入触发keydown,回车确认输入触发keyup chrome:输入 ...
- 键盘事件keydown、keypress、keyup随笔整理总结
键盘事件keydown.keypress.keyup随笔整理总结 英文输入法: 事件触发顺序:keydown - > keypress - > keyup 中文输入法: firfox:输入 ...
- JQuery 键盘事件使用整理
1. Js 键盘事件 1.键盘按下,keydown,在键盘上按下某个键时触发.如果按住某个键,会不断触发该事件 2.键盘松开,keyup,该事件仅在松开键盘时触发一次,不是一个持续的响应状态. 3.字 ...
最新文章
- 【转载】Python对接六大主流数据库,只需三步
- JavaScript多浏览器兼容问题
- Shell的一些基本用法
- 设计模式之反射与配置文件
- QT4到QT5的变化!
- OpenCV中SurfDescriptorExtractor
- 泛函分析4——希尔伯特空间
- Javascript中的arguments数组对象
- c 设计计算机报告,C课程设计(计算器)报告
- 纷杂的Spring-boot-starter: 5 应用安全与spring-boot-starter-security
- c语言程序设计100题,编程题(c语言编程题库100题)
- matlab里面计算相关系系数的显著性,数学建模笔记——相关系数
- 工具分享: 一键保存网页为PDF文件
- 黄河金岸诗词大赛获奖作品选登(2:现代新诗)
- graphpad两组t检验_GraphPad prism -- t检验操作步骤解析~
- php怎么做网站?如何用PHP开发一个完整的网站?
- 【个人经验】关于BFM
- “和合信诺”获启赋资本数千万元Pre-A轮融资-专注监管科技、助力金融业落地监管合规最后一公里
- 产业分析:视频云服务行业
- (Java实现) 洛谷 P1200 你的飞碟在这儿