在本章中,我将介绍窗口过程和基本的正文输出,并对一些较高级的题材,如键盘和鼠标,作一个简洁的介绍。消息系统完美的风格使得你可以相对完全地、及时地对这两个硬件设备进行控制。
现在,你可以开始输入并运行程序清单 5.1 上的程序。
程序清单 5.1 KeyMouse 程序,用于追踪键盘和鼠标的输入
///////////////////////////////////////
// Program Name:KeyMouse.cpp
// Programer: skyline
// Description: Show how to trap keyboard and mouse input
///////////////////////////////////////
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <string.h>
#include <stdio.h>
#pragma warning (disable:4068)
#pragma warning (disable:4100)
//-----------------------------
// Interface
//-----------------------------
// Some variabls
static int Xval=10;
static int Yval=30;
static char szAppName[]="KeyMouse";
static HWND MainWindow;
// Some procs
LRESULT CALLBACK WndProc(HWND hwnd,UINT Message,
WPARAM wParam,LPARAM lParam);
BOOL Register(HINSTANCE hInst);
HWND Create(HINSTANCE hInst,int nCmdShow);
#define skyline_DefProc DefWindowProc
void skyline_OnDestroy(HWND hwnd);
void skyline_OnChar(HWND hwnd,UINT ch,int cRepeat);
void skyline_OnKey(HWND hwnd,UINT vk,BOOL fDown,
int cRepeat,UINT flags);
void skyline_OnLButtonDown(HWND hwnd,BOOL fDoubleCick,
int x,int y,UINT KeyFlags);
void skyline_OnLButtonUp(HWND hwnd,int x,int y,UINT KeyFlags);
void skyline_OnMouseMove(HWND hwnd,int x,int y,UINT KeyFlags);
void skyline_OnPaint(HWND hwnd);
void skyline_OnSysKey(HWND hwnd,UINT vk,BOOL fDown,
int cRepeat,UINT flags);
//-----------------------
// Initalization
//-----------------------
///////////////////////////
// Program entry point.
///////////////////////////
#pragma argsused
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,int nCmdShow)
{
MSG Msg;
if (! hPrevInstance)
if (! Register(hInst))
return FALSE;
MainWindow = Create(hInst,nCmdShow);
if(! MainWindow)
return FALSE;
while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
////////////////////////////////////
// Register the window
////////////////////////////////////
BOOL Register(HINSTANCE hInst)
{
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInst;
WndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
return RegisterClass(&WndClass);
}
////////////////////////////////////
// Create the Window
////////////////////////////////////
HWND Create(HINSTANCE hInstance,int nCmdShow)
{
HWND hwnd = CreateWindowEx (0,szAppName,szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
if(hwnd == NULL)
return hwnd;
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
return hwnd;
}
//----------------------------
// WndProc and Implementation
//----------------------------
//////////////////////////////////
// The WindowProcedured
//////////////////////////////////
LRESULT CALLBACK WndProc(HWND hwnd,UINT Message,
WPARAM wParam,LPARAM lParam)
{
switch(Message)
{
HANDLE_MSG(hwnd,WM_DESTROY,skyline_OnDestroy);
HANDLE_MSG(hwnd,WM_CHAR,skyline_OnChar);
HANDLE_MSG(hwnd,WM_KEYDOWN,skyline_OnKey);
HANDLE_MSG(hwnd,WM_KEYUP,skyline_OnKey);
HANDLE_MSG(hwnd,WM_MOUSEMOVE,skyline_OnMouseMove);
HANDLE_MSG(hwnd,WM_LBUTTONDBLCLK,skyline_OnLButtonDown);
HANDLE_MSG(hwnd,WM_LBUTTONDOWN,skyline_OnLButtonDown);
HANDLE_MSG(hwnd,WM_LBUTTONUP,skyline_OnLButtonUp);
HANDLE_MSG(hwnd,WM_PAINT,skyline_OnPaint);
HANDLE_MSG(hwnd,WM_SYSKEYUP,skyline_OnSysKey);
HANDLE_MSG(hwnd,WM_SYSKEYDOWN,skyline_OnSysKey);
default:
return skyline_DefProc(hwnd,Message,wParam,lParam);
}
}
///////////////////////////////////////
// Handle WM_DESTROY
///////////////////////////////////////
#pragma argsused
void skyline_OnDestroy(HWND hwnd)
{
PostQuitMessage(0);
}
///////////////////////////////////////
// Handle regular keyboard hits
// Use if you want to trap the letter keys or number keys.
///////////////////////////////////////
#pragma argsused
void skyline_OnChar(HWND hwnd,UINT ch,int cRepeat)
{
char S[100];
HDC DC = GetDC(hwnd);
sprintf(S,"WM_CHAR ==> Char = %c cRepeat = %d ",
ch,cRepeat);
TextOut(DC,Xval,Yval+20,S,strlen(S));
ReleaseDC(hwnd,DC);
}
///////////////////////////////////////
// Handle a key press
// Don't try to process letter keys or number keys here.
// Instead, ues WM_CHAR messages.
///////////////////////////////////////
#pragma argsused
void skyline_OnKey(HWND hwnd,UINT vk,BOOL fDown,
int cRepeat,UINT flags)
{
char S[100];
HDC DC = GetDC(hwnd);
if(fDown)
sprintf(S,"WM_KEYDOWN ==> VK = %d fDown = %d cRepeat = %d "
"Flags = %d ",vk,fDown,cRepeat,flags);
else
sprintf(S,"WM_KEYUP ==> VK = %d fDown = %d cRepeat = %d "
"Flags = %d ",vk,fDown,cRepeat,flags);
SetBkColor(DC,GetSysColor(COLOR_WINDOW));
TextOut(DC,Xval,Yval+40,S,strlen(S));
ReleaseDC(hwnd,DC);
}
///////////////////////////////////////
// This function is called when the left mouse button is
// click or when the user double-clicks the mouse
///////////////////////////////////////
#pragma argsused
void skyline_OnLButtonDown(HWND hwnd,BOOL fDoubleClick,
int x,int y,UINT KeyFlags)
{
char S[100];
HDC DC = GetDC(hwnd);
if(fDoubleClick)
sprintf(S,"WM_LBUTTONDBLCLK ==> DblClk = %d X = %d Y = %d "
"Flags = %d ",fDoubleClick,x,y,KeyFlags);
else
sprintf(S,"WM_LBUTTONDOWN ==> Down = %d X = %d Y = %d "
"Flags = %d ",fDoubleClick,x,y,KeyFlags);
SetBkColor(DC,GetSysColor(COLOR_WINDOW));
TextOut(DC,Xval,Yval+100,S,strlen(S));
ReleaseDC(hwnd,DC);
}
///////////////////////////////////////
// This function is called when the mouse button is released
///////////////////////////////////////
#pragma argsused
void skyline_OnLButtonUp(HWND hwnd,int x,int y,UINT KeyFlags)
{
char S[100];
HDC DC = GetDC(hwnd);
sprintf(S,"WM_LBUTTONUP ==> X = %d Y = %d "
"Flag = %d ",x,y,KeyFlags);
SetBkColor(DC,GetSysColor(COLOR_WINDOW));
TextOut(DC,Xval,Yval+120,S,strlen(S));
ReleaseDC(hwnd,DC);
}
///////////////////////////////////////
// This function is called whenever the mouse moves
///////////////////////////////////////
#pragma argsused
void skyline_OnMouseMove(HWND hwnd,int x,int y,UINT KeyFlags)
{
char S[100];
HDC DC = GetDC(hwnd);
sprintf(S,"WM_MOUSEMOVE ==> X = %d Y = %d "
"KeyFlags = %d ",x,y,KeyFlags);
if((KeyFlags & MK_CONTROL) == MK_CONTROL)
SetTextColor(DC,RGB(0,0,255));
if((KeyFlags & MK_LBUTTON) == MK_LBUTTON)
SetTextColor(DC,RGB(0,128,0));
if((KeyFlags & MK_RBUTTON) == MK_RBUTTON)
SetTextColor(DC,RGB(152,84,95));
if((KeyFlags & MK_SHIFT) == MK_SHIFT)
SetTextColor(DC,RGB(196,0,196));
SetBkColor(DC,GetSysColor(COLOR_WINDOW));
TextOut(DC,Xval,Yval+80,S,strlen(S));
ReleaseDC(hwnd,DC);
}
///////////////////////////////////////
// Handle WM_PAINT messages
///////////////////////////////////////
void skyline_OnPaint(HWND hwnd)
{
PAINTSTRUCT PaintStruct;
RECT Rect;
static char * Message[] =
{
"WM_CHAR",
"WM_KEY",
"WM_SYSKEY",
"WM_MOUSEMOVE",
"WM_MOUSEDOWN",
"WM_MOUSEUP"
};
HDC PaintDC = BeginPaint(hwnd,&PaintStruct);
SetBkColor(PaintDC,GetSysColor(COLOR_WINDOW));
HFONT OldFont = SelectFont(PaintDC,
GetStockObject(OEM_FIXED_FONT));
GetClientRect(hwnd,&Rect);
Rect.top = 5;
DrawText(PaintDC,"Mouse and Keyboard Demonstration",-1,
&Rect,DT_CENTER);
Rect.top = 20;
Rect.bottom = 40;
DrawText(PaintDC,"Try experimenting with mouse and keyboard.",-1,
&Rect,DT_CENTER);
SelectFont(PaintDC,OldFont);
for(int i=0;i<6;i++)
TextOut(PaintDC,Xval,Yval+(20*(i+1)),
Message[i],strlen(Message[i]));
EndPaint(hwnd,&PaintStruct);
}
///////////////////////////////////////
// This function is called whenever the ALT key is pressed.
///////////////////////////////////////
#pragma argsused
void skyline_OnSysKey(HWND hwnd,UINT vk,BOOL fDown,
int cRepeat,UINT flags)
{
char S[100];
HDC DC = GetDC(hwnd);
SetBkColor(DC,GetSysColor(COLOR_WINDOW));
if(fDown)
{
sprintf(S,"WM_SYSKEYDOWN ==> VK = %d fDown = %d "
"cRepeat = %d ",vk,fDown,cRepeat,flags);
TextOut(DC,Xval,Yval+60,S,strlen(S));
FORWARD_WM_SYSKEYUP(hwnd,vk,cRepeat,flags,skyline_DefProc);
}
else
{
sprintf(S,"WM_SYSKEYUP ==> VK = %d fDown = %d "
"cRepeat = %d ",vk,fDown,cRepeat,flags);
TextOut(DC,Xval,Yval+60,S,strlen(S));
FORWARD_WM_SYSKEYUP(hwnd,vk,cRepeat,flags,skyline_DefProc);
}
ReleaseDC(hwnd,DC);
}
KeyMouse 程序提供两种主要的服务:
·如何检测一个键被按下,并且显示按下键的键值以及一些相关的信息。
·如何检测鼠标的移动或鼠标是否被按下,并在屏幕上显示出鼠标的当前位置及状态。
你可以花几分钟运行一下这个程序。当你移动鼠标或者按下键盘时,注意屏幕窗口上的反应。还要记住,每当你按下 Alt 键时,位于标题栏左上方的系统菜单就会被激活。此时若按一般的键都不会使屏幕恢复原样,除非再次按下 Alt 键或者采取其他动作改变焦点(focus)。有关检测 Alt 键按下动作的讨论在论述 WM_SYSKEY 消息一节中进行。
附注:
在 Windows 程序设计中,焦点的概念是很重要的。只有被聚焦的窗口才会响应键盘和鼠标的输入,而没有被聚焦的窗口是不响应的。你经常可以知道哪一个特定程序处于焦点,只要检查一下它的标题栏是否为高亮度显示就可以了。
同样十分重要的是要理解一个时刻只有一个窗口处于聚焦状态。例如,如果你打开 File 菜单,那么这个新打开的菜单处于焦点位置,而程序的主窗口就处于非活动状态。同样,在 My Computer 窗口中,当从 View 菜单中弹出 Options 对话框时,这个对话框是焦点,而 My Computer 窗口的其它部分是不活动的。