win32_API里的WM_KEYDOWN和WM_KEYUP

为什么按住一个键不放,貌似会持续产生这两个消息,我把SetTimer放在WM_KEYDOWN里面,KillTimer放在WM_KEYUP里面,但系统成对产生这两个消息的话... 为什么按住一个键不放,貌似会持续产生这两个消息,我把SetTimer放在WM_KEYDOWN里面,KillTimer放在WM_KEYUP里面,但系统成对产生这两个消息的话,按键激活SetTimer,松键中断SetTimer目的就无法达到,我该怎么解决,请高手指点一下啊,我是初学者...o(0.0)o 展开
 我来答
飘渺世间天
2007-08-28 · TA获得超过2650个赞
知道大有可为答主
回答量:843
采纳率:0%
帮助的人:1103万
展开全部
持续按住一个键不放是产生多个WM_KEYDOWN,最后只产生一个WM_KEYUP,你的timer无法被处理是因为WM_TIMER在消息队列中的优先级别很低,你按下键的时候在不断地向窗口发送WM_KEYDOWN消息,所以timer的消息处理不到,解决方法是在消息循环里做手脚,如果按下了一个键而没有弹起的话,就忽略之后的按键消息,这样就能腾出时间来处理timer了:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
WNDCLASS ws;

ws.style = CS_HREDRAW | CS_VREDRAW;
ws.lpfnWndProc = WndProc;
ws.cbClsExtra = 0;
ws.cbWndExtra = 0;
ws.hInstance = hInstance;
ws.hIcon = LoadIcon(NULL, IDI_APPLICATION);
ws.hCursor = LoadCursor(NULL, IDC_ARROW);
ws.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
ws.lpszMenuName = NULL;
ws.lpszClassName = "Timer";

if(!RegisterClass(&ws))
return 0;

HWND hwnd = CreateWindow("Timer",
NULL,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);

MSG msg;
bool hold = false;

while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
if(msg.message == WM_KEYDOWN && !hold)
{
hold = true;
DispatchMessage(&msg);
}
else if(msg.message == WM_KEYDOWN)
; // 忽略多余的按键
else if(msg.message == WM_KEYUP)
{
hold = false;
DispatchMessage(&msg);
}
else
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static TCHAR szBuf[32];
HDC hdc;
TEXTMETRIC tm;
static UINT key;
static int cyChar, i = 1;

switch(message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
return 0;

case WM_KEYDOWN:
key = wParam;
SetTimer(hwnd, 1, 1000, NULL);
InvalidateRect(hwnd, NULL, TRUE);
return 0;

case WM_TIMER:
hdc = GetDC(hwnd);
TextOut(hdc, 0, 0, szBuf, wsprintf(szBuf, "Key: '%c' %d sec", key, i++));
ReleaseDC(hwnd, hdc);
return 0;

case WM_KEYUP:
hdc = GetDC(hwnd);
i = 1;
TextOut(hdc, 0, cyChar, szBuf, wsprintf(szBuf, "Done!"));
ReleaseDC(hwnd, hdc);
KillTimer(hwnd, 1);
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
邱茗蒋和豫
2019-09-05 · TA获得超过3732个赞
知道大有可为答主
回答量:3137
采纳率:29%
帮助的人:227万
展开全部
持续按住一个键不放是产生多个WM_KEYDOWN,最后只产生一个WM_KEYUP,你的timer无法被处理是因为WM_TIMER在消息队列中的优先级别很低,你按下键的时候在不断地向窗口发送WM_KEYDOWN消息,所以timer的消息处理不到,解决方法是在消息循环里做手脚,如果按下了一个键而没有弹起的话,就忽略之后的按键消息,这样就能腾出时间来处理timer了:
#include
<windows.h>
LRESULT
CALLBACK
WndProc(HWND,
UINT,
WPARAM,
LPARAM);
int
WINAPI
WinMain(HINSTANCE
hInstance,
HINSTANCE
hPrevInstance,
PSTR
szCmdLine,
int
iCmdShow)
{
WNDCLASS
ws;
ws.style
=
CS_HREDRAW
|
CS_VREDRAW;
ws.lpfnWndProc
=
WndProc;
ws.cbClsExtra
=
0;
ws.cbWndExtra
=
0;
ws.hInstance
=
hInstance;
ws.hIcon
=
LoadIcon(NULL,
IDI_APPLICATION);
ws.hCursor
=
LoadCursor(NULL,
IDC_ARROW);
ws.hbrBackground
=
(HBRUSH)GetStockObject(WHITE_BRUSH);
ws.lpszMenuName
=
NULL;
ws.lpszClassName
=
"Timer";
if(!RegisterClass(&ws))
return
0;
HWND
hwnd
=
CreateWindow("Timer",
NULL,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd,
iCmdShow);
UpdateWindow(hwnd);
MSG
msg;
bool
hold
=
false;
while(GetMessage(&msg,
NULL,
0,
0))
{
TranslateMessage(&msg);
if(msg.message
==
WM_KEYDOWN
&&
!hold)
{
hold
=
true;
DispatchMessage(&msg);
}
else
if(msg.message
==
WM_KEYDOWN)
;
//
忽略多余的按键
else
if(msg.message
==
WM_KEYUP)
{
hold
=
false;
DispatchMessage(&msg);
}
else
DispatchMessage(&msg);
}
return
msg.wParam;
}
LRESULT
CALLBACK
WndProc(HWND
hwnd,
UINT
message,
WPARAM
wParam,
LPARAM
lParam)
{
static
TCHAR
szBuf[32];
HDC
hdc;
TEXTMETRIC
tm;
static
UINT
key;
static
int
cyChar,
i
=
1;
switch(message)
{
case
WM_CREATE:
hdc
=
GetDC
(hwnd)
;
GetTextMetrics
(hdc,
&tm)
;
cyChar
=
tm.tmHeight
+
tm.tmExternalLeading
;
ReleaseDC
(hwnd,
hdc)
;
return
0;
case
WM_KEYDOWN:
key
=
wParam;
SetTimer(hwnd,
1,
1000,
NULL);
InvalidateRect(hwnd,
NULL,
TRUE);
return
0;
case
WM_TIMER:
hdc
=
GetDC(hwnd);
TextOut(hdc,
0,
0,
szBuf,
wsprintf(szBuf,
"Key:
'%c'
%d
sec",
key,
i++));
ReleaseDC(hwnd,
hdc);
return
0;
case
WM_KEYUP:
hdc
=
GetDC(hwnd);
i
=
1;
TextOut(hdc,
0,
cyChar,
szBuf,
wsprintf(szBuf,
"Done!"));
ReleaseDC(hwnd,
hdc);
KillTimer(hwnd,
1);
return
0;
case
WM_DESTROY:
PostQuitMessage(0);
return
0;
}
return
DefWindowProc(hwnd,
message,
wParam,
lParam);
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式