�������� Linux Tags

7. ����

��������һ���������Ķ�λ�豸����ȻҲ����ʹ�����紥������͹��֮��������豸������ֻ�л����Լ�������ϥ���͵����ϵĹ켣��Ȳ�����͸��PC�г���Ψһ�����豸��

�������������ˡ���Ȼ��Windows�����ڿ�����Ա��Ϊ���Dz�Ӧ��Ҫ��ʹ����Ϊ��ִ�����Ʒ��������ֻ������ˣ����ǽ�������Ϊһ��ѡ���Եĸ����豸����ΪWindows�е����в����Լ�applet�ṩһ�ּ��̽��棨���磬�鿴WindowsС���̳�ʽ������˵����Ѷ�����Կ���ÿ����ť���ṩ��һ��ͬ�ȹ�Ч�ļ��̲�����ʽ�������������巢չ��Աʹ�ü��̽������ṩ�뻬�������ͬ�Ĺ��ܣ��Ȿ����ǰ�İ汾Ҳ����ô���ġ�

��������˵�����ڵ�Windows��Ҫ�������٣�һЩѶϢ�������������ġ���Ȼ����Ҳ���԰��»��󣬶���Windows��Ȼ����ִ�����ã�ֻ��ѶϢ�������ʾ��û�����ӻ��󣩡���ͼ���û�����ʹ��Windows�����ý�ֺ��������һ���������������һ��ʱ��������������������Ȼ����������������Ϊ��ˣ��һ���ϲ��Ϊ�������ṩ���̲���������Ա����ϲ�������ǵ��ֱ����ڼ����ϣ���������Ϊÿ���˶��������ҵ������Ҳ������󣬻��߻����ƶ��������ľ��顣ʹ�ü���ͨ������Ҫ���Ѹ���ľ�����Ŭ��������Ϊϲ��ʹ�ü��̵����ṩ����Ĺ��ܡ�

����ͨ����Ϊ�����̱������Ͳ����������ϣ����������춻�ͼ�Ͳ���ͼ�������ʵ���ϣ����´�����ķ�����ʽ������һЩͼ�Σ������õ��������ڵ�������ѧ����֪ʶ��

�������
��

Windows 98��֧Ԯ������˫��������������Ҳ����ʹ��ҡ�˻��߹����ģ�ⵥ���������ڣ��������ʹ���߶��е�����������WindowsӦ�ó�ʽ���DZ���ʹ��˫�����������󡣲��������˫�������Ѿ���Ϊ��ʵ�ϵı�׼����˲�ʹ�õڶ������Ĵ�ͳ�Ѿ����ٺ����ˡ���Ȼ���ڶ������󰴼����������һ�������Թ��ܱ������༴��������ͨ���ܱ���֮����Ӵ��й��ܱ�����������������ҷ��������ҷ����������Խ��ͣ���Ȼ������ʽ��������˫������

�����ϣ������������ǵ�������GetSystemMetrics��ʽ��ȷ�ϻ����Ƿ���ڣ�

fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ;

����Ѿ���װ�˻���fMouse������TRUE����0�������û�а�װ���򴫻�0��Ȼ������Windows 98�У����ۻ����Ƿ�װ���˺�ʽ��������TRUE ����Microsoft Windows NT�У�����������������

Ҫȷ������װ�������ϰ����ĸ�������ʹ��

cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ;

���û�а�װ������ô��ʽ������0��Ȼ������Windows 98�£����û�а�װ���󣬴˺�ʽ������2��

ϰ�������ֵ�ʹ���߿���ʹ��Windows�ġ�����̨�����л����󰴼�����ȻӦ�ó�ʽ����ͨ����GetSystemMetrics��ʹ��SM_SWAPBUTTON������ȷ���Ƿ�����������л�����ͨ��û�������Ҫ����ʳָ�����ļ�����Ϊ���������ʹ��ʵ����λ춻�����ұߡ���������һ������ѵ����ʽ�У�����������өĻ�ϻ�һ����������������£���������֪�����󰴼��Ƿ��л����ˡ�

�������ڡ�����̨�����趨�������������������˫���ٶȡ���WindowsӦ�ó�ʽ��ͨ��ʹ��SystemParametersInfo��ʽ�����趨���ô�����Ѷ��

һЩ�򵥵Ķ���
��

��Windowsʹ�����ƶ�����ʱ��Windows����ʾ�����ƶ�һ����Ϊ�������α꡹��С����ͼ�������α���һ��ָ����ʾ���Ͼ�ȷλ�õĵ�ͼ�ء��ȵ㡹�������ᵽ�����α���өĻ�ϵ�λ��ʱ��ָ�����ȵ��λ�á�

Windows֧Ԯ����Ԥ�ȶ���Ļ����α꣬��ʽ����ʹ����Щ�αꡣ������dz�ΪIDC_ARROW��б��ͷ����WINUSER.H�ж��壩���ȵ��ڼ�ͷ�Ķ��ˡ�IDC_CROSS�α꣨�ڱ��������BLOKOUT��ʽ�����õ������ȵ���ʮ�ֽ����ߵ����ġ� IDC_WAIT�α���һ��ɳ©��ͨ�����ָʾ��ʽ����ִ�С���ʽд����Ҳ��������Լ����αꡣ���ǽ��ڵ�ʮ��ѧϰ��Ʒ������ڶ����Ӵ����ṹʱָ���ض��Ӵ����ڶ��α꣬���磺

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

������һЩ�������󰴼����������

  •  Clicking ï¿½ï¿½ï¿½Â²ï¿½ï¿½Å¿ï¿½Ò»ï¿½ï¿½ï¿½ï¿½ï¿½ó°´¼ï¿½ï¿½ï¿½
    ��
  •  Double-clicking ï¿½ï¿½ï¿½Ù°ï¿½ï¿½Â²ï¿½ï¿½Å¿ï¿½ï¿½ï¿½ï¿½ó°´¼ï¿½ï¿½ï¿½ï¿½Î¡ï¿½
    ��
  •  Dragging ï¿½ï¿½×¡ï¿½ï¿½ï¿½ó°´¼ï¿½ï¿½ï¿½ï¿½Æ¶ï¿½ï¿½ï¿½ï¿½ï¿½
    ��

������������˵���������ֱ��Ϊ������м����Ҽ�����Windows��ͷ�����ж�����뻬���йص�ʶ����ʹ����дLBUTTON��MBUTTON��RBUTTON��˫������ֻ��������Ҽ�����������ֻ��һ�������

����(Mouse)�ĸ���
��

���ڣ�Ϊ��չ���ҵ��������ҽ��������װ�����ѱ�����ۻ��⣺ʲô�ǡ�mouse���ĸ�������Ȼÿ���˶�֪����ֻ���ݶ����Ϊmice���ƺ�û���˶Ը���γƺ��������װ��������Ĵ𰸡����ܡ�mice����mouse�������������Ծ����ҹ߳��ο��ġ�American Heritage Dictionary of the English Language����������ֻ��δ�ᡣ

��Wired style��Principles of English Usage in the Digital Age����HardWired, 1996��ָ����mouse���ȽϺã��Ա��������ݶ����졣��1964���������Doug Engelbart�Դ�����Ҳ�ﲻ��æ���������ʹ���mouse�ĸ�����ʲô����˵�Ҳ�֪����

���ᣬ��Ȩ����Microsoft Manual of Style for Technical Publications�������ǡ�����ʹ�ø���mice������������ᵽ��ֻmouse��ʹ��mouse devices�������������������ӱ����⣬����һ�������������Ծ�ʱ����ȷʵ�Ǹ����ǵ��Ҹ��ˡ���ʵ�ϣ��󲿷���Ҫmouse�����ľ��Ӷ��������޸����ܿ������磬����˵"People use the almost as much as keyboard"��������"Pople use mice almost as much as keyboards"��

��ʾ������ѶϢ
��

��ǰһ�������Ѿ�������Windowsֻ�Ѽ���ѶϢ���͸�ӵ�����뽹����Ӵ�������ѶϢ��˲�ͬ��ֻҪ�����Խ�Ӵ�������ij�Ӵ��а��»��󰴼�����ô�Ӵ�ѶϢ������ʽ�ͻ��յ�����ѶϢ�������ܸ��Ӵ��Ƿ������Ƿ�ӵ�����뽹�㡣WindowsΪ��������21��ѶϢ��������������11��ѶϢ����ʾ�����޹أ������֮Ϊ������ʾ����ѶϢ����Windows��ʽ����������ЩѶϢ��

�������ƹ��Ӵ�����ʾ����ʱ���Ӵ�ѶϢ������ʽ�յ�WM_MOUSEMOVEѶϢ�������Ӵ�����ʾ�����а��»����ͷ�һ�����󰴼�ʱ���Ӵ�ѶϢ������ʽ����յ�������ЩѶϢ��

��7-1
�� ���� �ͷ� ����(˫��)
�� WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK
�� WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK
�� WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK

ֻ�ж����������Ӵ�ѶϢ������ʽ�Ż��յ�MBUTTONѶϢ��ֻ�ж�˫�������������󣬲Ż���յ�RBUTTONѶϢ��ֻ�е�������Ӵ�����ܽ���DBLCLK��˫����ѶϢ���Ӵ�ѶϢ������ʽ���ܽ��յ���ЩѶϢ����μ������С�˫�����󰴼���һ�ڣ���

���������ЩѶϢ��˵����lParamֵ�����л����λ�ã�������Ϊx���꣬������Ϊy���꣬�����������������Ӵ���ʾ�������Ͻǵ�λ�á���������LOWORD��HIWORD�޼�����ȡ��Щֵ��

x = LOWORD (lParam) ;
y = HIWORD (lParam) ;

wParam��ֵָʾ���󰴼��Լ�Shift��Ctrl����״̬��������ʹ�ñ�ͷ����WINUSER.H�ж����λԪ����������wParam��MK���״��������󰴼�����

MK_LBUTTON �������
MK_MBUTTON �����м�
MK_RBUTTON �����Ҽ�
MK_SHIFT ����Shift��
MK_CONTROL ����Ctrl��

���磬����յ���WM_LBUTTONDOWNѶϢ������ֵ

wparam & MK_SHIFT

��TRUE����0��������֪�����������ʱҲ������Shift����

�����ѻ����ƹ��Ӵ�����ʾ����ʱ��Windows����Ϊ�����ÿ�����ܵ�ͼ��λ�ö�����һ��WM_MOUSEMOVEѶϢ�����ij�ʽ���յ�WM_MOUSEMOVEѶϢ�Ĵ���������춻���Ӳ�壬�Լ������Ӵ�ѶϢ������ʽ�ڴ��������ƶ�ѶϢʱ���ٶȡ����仰˵��Windows������δ������WM_MOUSEMOVEѶϢ������ѶϢ���С�����ִ�����潫������CONNECT��ʽʱ����������˽�WM_MOUSEMOVEѶϢ���������ʡ�

������ڷǻ�Ӵ�����ʾ�����а��»��������Windows���ѻ�Ӵ���Ϊ�����а��»��󰴼����Ӵ���Ȼ���WM_LBUTTONDOWNѶϢ�͵����Ӵ�ѶϢ������ʽ�����Ӵ�ѶϢ������ʽ�õ�WM_LBUTTONDOWNѶϢʱ�����ij�ʽ�Ϳ��԰�ȫ�ؼٶ����Ӵ��ǻ�����ˡ������������Ӵ�ѶϢ������ʽ������δ���յ�WM_LBUTTONDOWNѶϢ��������Ƚ��յ���WM_LBUTTONUP��ѶϢ�������һ���Ӵ��а��»��󰴼���Ȼ���ƶ���ʹ�����Ӵ��ͷ������ͻ����������������Ƶ�����������󰴼�����һ���Ӵ��б��ͷ�ʱ���Ӵ�ѶϢ������ʽֻ�ܽ��յ�WM_LBUTTONDOWNѶϢ����û����Ӧ��WM_LBUTTONUPѶϢ��

��Щ�������������⣺

  • �Ӵ�ѶϢ������ʽ���ԡ����ػ��󡹲��������ؽ��ջ���ѶϢ����ʹ��ʱ�����ڸ��Ӵ���ʾ����֮�⡣�����ڱ��µ�����ѧϰ������ػ���
    ��
  • ���������ʾһ��ϵͳģ̬ѶϢ�������ϵͳģ̬�Ի����飬��ô������ʽ�Ͳ��ܽ��ջ���ѶϢ����ϵͳģ̬ѶϢ������߶Ի�����ʱ����ֹ�л��������Ӵ����߳�ʽ��һ����ʾϵͳģ̬ѶϢ��������ӣ��ǵ����ر�Windowsʱ��
    ��

�򵥵Ļ�������һ������
��

��ʽ7-1����ʾ��CONNECT��ʽ����һЩ�򵥵Ļ�������ʹ����Windows��������ij�ʽ���ͻ���ѶϢ��һЩ��ᡣ

 ï¿½ï¿½Ê½7-1  CONNECT
CONNECT.C
/*--------------------------------------------------------------------------
	CONNECT.C -- Connect-the-Dots Mouse Demo Program
 					(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>
#define MAXPOINTS 1000
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
						PSTR szCmdLine, int iCmdShow)
{
	static TCHAR	szAppName[] = TEXT ("Connect") ;
	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 ("Program requires Windows NT!"), 
							szAppName, MB_ICONERROR) ;
		return 0 ;
	}
     
	hwnd = CreateWindow (	szAppName, TEXT ("Connect-the-Points Mouse Demo"),
								WS_OVERLAPPEDWINDOW,
								CW_USEDEFAULT, CW_USEDEFAULT,
								CW_USEDEFAULT, CW_USEDEFAULT,
								NULL, NULL, hInstance, NULL) ;
     
	ShowWindow (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 POINT pt[MAXPOINTS] ;
	static int 		iCount ;
	HDC				hdc ;
	in				i, j ;
	PAINTSTRUCT  ps ;
	switch (message)
     {
	case	WM_LBUTTONDOWN:
		iCount = 0 ;
		InvalidateRect (hwnd, NULL, TRUE) ;
		return 0 ;
          
	case	WM_MOUSEMOVE:
		if (wParam & MK_LBUTTON && iCount < 1000)
		{
				pt[iCount  ].x = LOWORD (lParam) ;
				pt[iCount++].y = HIWORD (lParam) ;
               
				hdc = GetDC (hwnd) ;
				SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0) ;
				ReleaseDC (hwnd, hdc) ;
		}
          				return 0 ;
          
     	case 	WM_LBUTTONUP:
          		InvalidateRect (hwnd, NULL, FALSE) ;
          		return 0 ;
          
     	case 	WM_PAINT:
          		hdc = BeginPaint (hwnd, &ps) ;
          
          		SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          		ShowCursor (TRUE) ;
          
          		for (i = 0 ; i < iCount - 1 ; i++)
               				for (j = i + 1 ; j < iCount ; j++)
               				{
                    			MoveToEx (hdc, pt[i].x, pt[i].y, NULL) ;
                    			LineTo   (hdc, pt[j].x, pt[j].y) ;
               }

          		ShowCursor (FALSE) ;
          		SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
          		EndPaint (hwnd, &ps) ;
          		return 0 ;
               
     	case 	WM_DESTROY:
          		PostQuitMessage (0) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

CONNECT������������ѶϢ��

  •  WM_LBUTTONDOWN CONNECT�������ʾ����
    ��
  •  WM_MOUSEMOVE ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Ã´CONNECT������ʾ�����еĻ���λ�ô�����һ���ڵ㣬����������ꡣ
    ��
  •  WM_LBUTTONUP��CONNECT ï¿½ï¿½ï¿½ï¿½Ê¾ï¿½ï¿½ï¿½ï¿½ï¿½Ð»ï¿½ï¿½ÆµÄµï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Ã¿ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Ê±ï¿½ï¿½ï¿½ï¿½ï¿½Ò»ï¿½ï¿½Æ¯ï¿½ï¿½ï¿½ï¿½Í¼ï¿½Î£ï¿½ï¿½ï¿½Ê±ï¿½ï¿½ï¿½ï¿½Çºï¿½Ñ»Ñ»ï¿½ï¿½Ò»ï¿½ï¿½ï¿½ã£¨ï¿½ï¿½Í¼7-1����
    ��


��

ͼ7-1 CONNECT��өĻ��ʾ

CONNECT��ʹ�÷������ѻ����α��ƶ�����ʾ�����У�����������ƶ�һ��λ�ã��ͷ�������Լ����������ߵĵ㣬CONNECT�ܴ����úܺã������ǰ�ס����������ƶ����������Ϳ��Ի��Ƴ�������ͼ����

CONNECTʹ���������򵥵�ͼ��װ�ý���(GDI)��ʽ�����ڵ��������۹���Щ��ʽ���������������ʱ��SetPixelΪÿ��WM_MOUSEMOVEѶϢ����һ����ͼ�أ���춸߽����ȵ���ʾ����ͼ�ؼ���������������ֱ����ҪMoveToEx��LineTo��ʽ��

��������ͷŻ��󰴼�֮ǰ�ѻ����α��Ƶ���ʾ����֮�⣬��ôCONNECT�Ͳ���������Щ�㣬��Ϊ��û���յ�WM_LBUTTONUPѶϢ��������ѻ����ƻ���ʾ�����ڲ������������ôCONNECT�������ʾ�������������ʾ�������ͷ�����ỹ�������л�ͼ����ô��������ʾ�����ⰴ�»������ƻ���ʾ�����С�

CONNECT�����Ա���1000���㡣�����ΪP����CONNECT���������͵��P �� (P - 1) / 2�������1000���㣬��Ҫ����50����ֱ�ߣ���Լ��Ҫ�����Ӳ��ܻ��꣨ʱ��ij���ȡ�������Ӳ���豸�������Windows 98��һ������Ȩʽ�๤�������������������һ��ʱ���л�����ij�ʽ�С����ǣ�����ʽ����æ��ʱ�������޷���CONNECT��ʽ���κ��£������ƶ��������ŵȣ����ڵڶ�ʮ���У����ǽ����۽����һ����ķ�����

��ΪCONNECT���ܻỨһЩʱ��������ֱ�ߣ�����ڴ���WM_PAINTѶϢʱ�����л���ɳ©�α꣬Ȼ���ٻָ�ԭ״����Ҫ��ʹ�����������α�������SetCursor��CONNECT����������ShowCursor��һ����TRUE��������һ����FALSE�������ҽ��ڱ��µ����棬��ʹ�ü���ģ�⻬��һ���и���ϸ��������Щ���С�

��ʱ������ʹ�á����١�����ʴ�����ʽ���������ƶ��ķ��������ǣ����ٲ�����ζ������ʽ���Ӵ�ѶϢ������ʽ�е�ij����Ȧ����ϸ��滬������ʾ���ϵ��˶���ʵ���ϣ��Ӵ�ѶϢ������ʽ����ÿ������ѶϢ��Ȼ��Ѹ���˳���

����Shift��
��

��CONNECT���յ�һ��WM_MOUSEMOVEѶϢʱ������wParam��MK_LBUTTON����λԪ�루AND�����㣬��ȷ���Ƿ����������wParamҲ�������ȷ��Shift����״̬�����磬����������������Shift��Ctrl����״̬����ô������ʹ��������ʾ�ķ�����

if (wParam & MK_SHIFT)
{
	if (wParam & MK_CONTROL) 
     	{
		//������Shift��Ctrl��
	}
	else
	{
				//������Shift��
		}
	{
	else
	{
		if (wParam & MK_CONTROL)
		{
				//������Ctrl�� 
		}
		else
		{
				//Shift��Ctrl�������
		}
}

��������ڳ�ʽ��ͬʱʹ�����Ҽ���ͬʱ�������ϣ��ֻ�е��������ʹ����Ҳ��ʹ�����ij�ʽ����ô������������д����ʽ��Shift����������ʹ�õ�Ч��Ҽ�������������£��Ի��󰴼��Ĵ������Բ���������ʾ�ķ�����

case	WM_LBUTTONDOWN:
	if (!(wParam & MK_SHIFT))
	{
				//�������
				return 0 ;
	}
				// Fall through
case WM_RBUTTONDOWN:
	//�����Ҽ�
	return 0 ;

Windows��ʽGetKeyState���ڵ������н��ܹ�������ʹ���������VK_LBUTTON��VK_RBUTTON��VK_MBUTTON��VK_SHIFT��VK_CONTROL�����ػ��󰴼���Shift����״̬�����GetKeyState���ظ�ֵ����˵���Ѱ����˻��󰴼�����Shift������ΪGetKeyState����Ŀǰ���ڴ����Ļ��󰴼�����Shift����״̬������ȫ��״̬��Ѷ����Ӧ��ѶϢ����ͬ���ġ����ǣ����粻�ܰ�GetKeyState�����δ���µļ�һ������Ҳ����Ϊ��δ���µĻ��󰴼�����GetKeyState���벻Ҫ��������

while (GetKeyState (VK_LBUTTON) >= 0) ;  // WRONG !!!

ֻ����������GetKeyState�ڼ䴦��ѶϢʱ��������Ѿ����£��Żᱨ����Ѿ����µ�ѶϢ��

˫�����󰴼�
��

˫�����󰴼���ָ�ڶ�ʱ���ڵ������Ρ�Ҫȷ��Ϊ˫�����������ε������뷢����������ʵ��λ��ʮ�ֽӽ���״���£��ڶ���Χ��һ��ƽ��ϵͳ������Ԫ�Ŀ��������Ԫ�ĸߣ������ҷ�����ָ����ʱ��������Ϊ��˫���ٶȡ����ڡ��������ڡ�����̨���иı�ʱ������

���ϣ�������Ӵ�ѶϢ������ʽ�ܹ��յ�˫�����Ļ���ѶϢ����ô�ں���RegisterClass��ʼ���Ӵ����ṹʱ���������Ӵ�����а���CS_DBLCLKSʶ���֣�

wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;

������Ӵ������δ����CS_DBLCLKS����ʹ�����ڶ�ʱ����˫���˻��󰴼�����ô�Ӵ�ѶϢ������ʽ����յ�������ЩѶϢ��

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDOWN

WM_LBUTTONUP

�Ӵ�ѶϢ������ʽ��������Щ����ѶϢ֮ǰ���յ�������ѶϢ���������ʵ���Լ���˫����������ô������ʹ��Windows��ʽGetMessageTimeȡ��WM_LBUTTONDOWNѶϢ֮������ʱ�䡣�ڰ��½�����ϸ�����������ʽ��

��������Ӵ�������а�����CS_DBLCLKS����ô˫��ʱ�Ӵ�ѶϢ������ʽ���յ�����ѶϢ��

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDBLCLK

WM_LBUTTONUP

WM_LBUTTONDBLCLKѶϢ�򵥵��滻�˵ڶ���WM_LBUTTONDOWNѶϢ��

���˫���еĵ�һ�μ�������ɵ����Ĺ��ܣ���ô˫����һѶϢ�Ǻ����״����ġ��ڶ��ΰ�����WM_LBUTTONDBLCLKѶϢ������ɵ�һ�ΰ�����������顣���磬����Windows Explorer��������û��������������б��ġ���һ�μ���ѡ�е�����Windows Explorer�÷�����ʾ��ָ����ѡ�񵵰���λ�á�˫����ʵ���������ܣ���һ���ǵ����Ǹ�ѡ�е������ڶ�����ָ��Windows Explorer�Դ򿪸õ�����ִ�з�ʽ�൱�򵥣����˫���еĵ�һ�ΰ�����ִ�е������ܣ���ô��������ʽ���÷dz����ӡ�

����ʾ������ѶϢ
��

���Ӵ�����ʾ�������ƶ����»��󰴼�ʱ��������10��ѶϢ������������Ӵ�����ʾ����֮�⵫�����Ӵ��ڣ�Windows�͸��Ӵ�ѶϢ������ʽ����һ��������ʾ���򡹻���ѶϢ���Ӵ�����ʾ������������С����ܱ����Ӵ������С�

ͨ����������Ҫ��������ʾ������ѶϢ�����ǽ���ЩѶϢ����DefWindowProc���Ӷ�ʹWindowsִ��ϵͳ���ܡ����ⷽ����˵������ʾ������ѶϢ�����ϵͳ����ѶϢWM_SYSKEYDOWN��WM_SYSKEYUP��WM_SYSCHAR��

����ʾ������ѶϢ������ȫ����ʾ������ѶϢ���Ӧ��ѶϢ�к�����ĸ��NC���Ա�ʾ�Ƿ���ʾ����ѶϢ������������Ӵ��ķ���ʾ�������ƶ�����ô�Ӵ�ѶϢ������ʽ����յ�WM_NCMOUSEMOVEѶϢ�����󰴼��������7-2��ʾ��ѶϢ��

��7-2
�� ���� �ͷ� ���£�˫����
�� WM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
�� WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
�� WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

�Է���ʾ������ѶϢ��wParam��lParam��������ʾ������ѶϢ��wParam��lParam������ͬ��wParam����ָ���ƶ����߰����󰴼��ķ���ʾ�������趨ΪWINUSER.H�ж������HT��ͷ��ʶ����֮һ��HT��ʾ�����в��ԡ�����

lParam�����ĵ�λԪwordΪx���꣬��λԪwordΪy���꣬���ǣ�������өĻ���꣬����������ʾ������ѶϢ����ָ������ʾ�������ꡣ��өĻ���꣬��ʾ�����Ͻǵ�x��y��ֵΪ0����������ʱx��ֵ���ӣ�������ʱy��ֵ���ӣ���ͼ7-2����

������������Windows��ʽ��өĻ����ת��Ϊ��ʾ����������߷�֮��

ScreenToClient (hwnd, &pt) ;
ClientToScreen (hwnd, &pt) ;

����pt��POINT�ṹ����������ʽת���˱����ڽṹ�е�ֵ������û�б�����ǰ��ֵ��ע�⣬���өĻ��������Ӵ���ʾ��������������ߣ���ʾ��������x��yֵ���Ǹ�ֵ��


��

ͼ7-2 өĻ������ͻ���ʾ��������

���в���ѶϢ
��

�������һ�£��Ϳ���֪�������Ѿ�������21������ѶϢ�е�20��������һ��ѶϢ��WM_NCHITTEST��������������ʾ�������в��ԡ�����ѶϢ�����������������ʾ����ͷ���ʾ������ѶϢ��lParam�������л���λ�õ�x��yөĻ���꣬wParam����û���á�

WindowsӦ�ó�ʽͨ�������ѶϢ���͸�DefWindowProc��Ȼ��Windows��WM_NCHITTESTѶϢ�����뻬��λ����ص�������������ѶϢ����춷���ʾ������ѶϢ���ڴ���WM_NCHITTESTʱ����DefWindowProc���ص�ֵ����Ϊ����ѶϢ�е�wParam���������ֵ�������������ʾ������ѶϢ��wParamֵ�ټ����������ݣ�

HTCLIENT

HTNOWHERE

HTTRANSPARENT

HTERROR

��ʾ����

�����Ӵ���

�Ӵ�����һ���Ӵ�����

ʹDefWindowProc������ʾ�õ�����

���DefWindowProc���䴦��WM_NCHITTESTѶϢ�ᴫ��HTCLIENT����ôWindows����өĻ����ת��Ϊ��ʾ�������겢������ʾ������ѶϢ��

��������ǵ��������ͨ������WM_SYSKEYDOWNѶϢ��ͣ�����е�ϵͳ���̹��ܣ���ô�����ܻ������ǿɷ�ͨ�����ػ���ѶϢ������Ƶ����顣��ȫ���ԣ�ֻҪ�����Ӵ�ѶϢ������ʽ�а������¼���������

case WM_NCHITTEST:
   	return (LRESULT) HTNOWHERE ;

�Ϳ�����Ч�ؽ������Ӵ��е�������ʾ����ͷ���ʾ������ѶϢ������һ�����������������Ӵ�������ϵͳ���ܱ�ͼʾ�����Ű�ť�Լ��رհ�ť����ʱ�����󰴼�����ʧЧ��

��ѶϢ����ѶϢ
��

Windows��WM_NCHITTESTѶϢ����������������ѶϢ��������ѶϢ��������ѶϢ���뷨��Windows���Ǻ��ձ�ġ����������ٸ����ӡ���֪�����������һ��Windows��ʽ��ϵͳ���ܱ�ͼʾ��˫��һ�£���ô��ʽ������ֹ��˫������һϵ�е�WM_NCHITTESTѶϢ����춻���λ��ϵͳ���ܱ�ͼʾ�ϣ����DefWindowProc������HTSYSMENU��ֵ������Windows��wParam���HTSYSMENU��WM_NCLBUTTONDBLCLKѶϢ����ѶϢ�����С�

�Ӵ�ѶϢ������ʽͨ���ѻ���ѶϢ���ݸ�DefWindowProc����DefWindowProc���յ�wParam�������HTSYSMENU��WM_NCLBUTTONDBLCLKѶϢʱ�����Ͱ�wParam�������SC_CLOSE��WM_SYSCOMMANDѶϢ����ѶϢ�����У����WM_SYSCOMMANDѶϢ����ʹ���ߴ�ϵͳ���ܱ���ѡ��Close��ʱ�����ģ���ͬ���أ��Ӵ�ѶϢ������ʽҲ�����ѶϢ����DefWindowProc��DefWindowProcͨ�����Ӵ�ѶϢ������ʽ����WM_CLOSEѶϢ��������ѶϢ��

���һ����ʽ����ֹ֮ǰҪ������ʹ���ߵ�ȷ�ϣ���ô�Ӵ�ѶϢ������ʽ����Ҫ����WM_CLOSE������DefWindowProc����DestroyWindow��ʽ������WM_CLOSE����������������DestroyWindow�����Ӵ�ѶϢ������ʽ����һ��WM_DESTROYѶϢ���Ӵ�ѶϢ������ʽͨ�������г�ʽ��������WM_DESTROYѶϢ��

case	WM_DESTROY:
	PostQuitMessage (0) ;
	return 0 ;

PostQuitMessageʹ��Windows��WM_QUITѶϢ����ѶϢ�����У���ѶϢ��Զ���ᵽ���Ӵ�ѶϢ������ʽ����Ϊ��ʹGetMessage����0������ֹѶϢ��Ȧ���Ӷ�Ҳ��ֹ�˳�ʽ��

��ʽ�е����в���
��

����ǰ��������Windows Explorer��λ�Ӧ����ĵ�����˫������Ȼ����ʽ�����߸���ȷ��˵����ͬWindows Explorer��ʹ��list view control������ȷ��ʹ���߻�����ָ�������һ��������

����������в��ԡ�������DefWindowProc�ڴ���WM_NCHITTESTѶϢʱ��һЩ���в���һ�����Ӵ�ѶϢ������ʽ������������ʾ�����н���һЩ���в��ԡ�һ����˵�����в����л�ʹ��x��y����ֵ�������ɴ����Ӵ�ѶϢ������ʽ�Ļ���ѶϢ��lParam����������

һ�����������
��

������һ�����ӡ��������ij�ʽ��Ҫ��ʾ���а���ĸ���еĵ�����ͨ����������ʹ��list view control������������Ҫ��ȫ�������в��Թ����������Ǽ��������ij��ԭ�������ʹ�ã���ʱ����Ҫ�Լ������ˡ������Ǽٶ������������ڳ�ΪszFileNames���������ִ�ָ�������С�

������Ҳ�ٶ������б���ʼ���ʾ����Ķ��ˣ���ʾ����ΪcxClientͼ�ؿ��� cyClientͼ�ظߣ�ÿ��ΪcxColWidthͼ�ؿ���ÿ����Ԫ�߶�ΪcyCharͼ�ظߡ���ôÿ��������ĵ��������ǣ�

iNumInCol = cyClient / cyChar ;

���յ�һ�����󵥻�ѶϢ�ᣬ�����ܴ�lParam���cxMouse��cyMouse���ꡣȻ�����������Ĺ�ʽ������ʹ������ָ������һ�еĵ�������

iColumn = cxMouse / cxColWidth ;

�����ж��˵ĵ�����λ��Ϊ��

iFromTop = cyMouse / cyChar ;

�������Ϳ��Լ���szFileNames���е��±꣺

iIndex = iColumn * iNumInCol + iFromTop ;

���iIndex�����������еĵ����������ʾʹ����������ʾ���Ŀհ������ڰ����󰴼���

����������£����в���Ҫ�ȱ������Ӹ��ӡ�����ʾһ����������Сͼ�ε�ͼ��ʱ�����������Ҫ��ʾ��ÿ��Сͼ�ε����ꡣ�����м����У�������������ҵ���������⽫��ʹ�ò�ȷ�������С���ִ�����ʽ�б�÷dz����ң���Ϊ�������ҵ���Ԫ���ִ��е�λ�á�

������ʽ
��

��ʽ7-2��ʾ��CHECKER1��ʽչʾ��һЩ�򵥵����в��ԣ��˳�ʽ����ʾ�����Ϊ5��5��25�����Ρ��������ij�������а��»��󰴼�����ô�ڸþ����н�����һ����X����������ٰ�һ�Σ���ô��X������ɾ����

 ï¿½ï¿½Ê½7-2  CHECKER1
CHECKER1.C
/*-------------------------------------------------------------------------
   	CHECKER1.C --	 	Mouse Hit-Test Demo Program No. 1
                 						(c) Charles Petzold, 1998
--------------------------------------------------------------------------*/

#include <windows.h>
#define DIVISIONS 5
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR  szCmdLine, int iCmdShow)
{	    static TCHAR	szAppName[] = TEXT ("Checker1") ;
     	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 ("Program requires Windows NT!"), 
                      							szAppName, MB_ICONERROR) ;
          		return 0 ;
     	}
     	hwnd = CreateWindow (	szAppName, TEXT ("Checker1 Mouse Hit-Test Demo"),
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL) ;
     
  	ShowWindow (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,LPARAMlParam)
{
     	static BOOL 	fState[DIVISIONS][DIVISIONS] ;
     	static int  		cxBlock, cyBlock ;
     	HDC         				hdc ;
     	int         				x, y ;
     	PAINTSTRUCT 		ps ;
     	RECT        				rect ;
     
     	switch (message)
     {
     	case 	WM_SIZE :
          		cxBlock = LOWORD (lParam) / DIVISIONS ;
          		cyBlock = HIWORD (lParam) / DIVISIONS ;
          		return 0 ;
          
     	case WM_LBUTTONDOWN :
          		x = LOWORD (lParam) / cxBlock ;
          		y = HIWORD (lParam) / cyBlock ;
          
          		if (x < DIVISIONS && y < DIVISIONS)
          		{
               				fState [x][y] ^= 1 ;
               				rect.left 			= x * cxBlock ;
               				rect.top 			= y * cyBlock ;
               				rect.right 			= (x + 1) * cxBlock ;
               				rect.bottom 		= (y + 1) * cyBlock ;
               
               				InvalidateRect (hwnd, &rect, FALSE) ;
          		}
          		else
               				MessageBeep (0) ;
       		return 0 ;
          
     	case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;
          
          		for (x = 0 ; x < DIVISIONS ; x++)
          		for (y = 0 ; y < DIVISIONS ; y++)
          		{
               			Rectangle (hdc, x * cxBlock, y * cyBlock,
                         		(x + 1) * cxBlock, (y + 1) * cyBlock) ;
                    
               		if (fState [x][y])
               		{
                    		MoveToEx	(hdc, x * cxBlock,  y * cyBlock, NULL) ;
                    		LineTo	(hdc, (x+1) * cxBlock, (y+1) * cyBlock) ;
			MoveToEx (hdc, x * cxBlock, (y+1) * cyBlock, NULL) ;
			LineTo 	(hdc, (x+1) * cxBlock, y  * cyBlock) ;
               			}
          		}
          		EndPaint (hwnd,&ps);	
		return 0 ;
               
     	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

ͼ7-3��CHECKER1����ʾ����ʽ����25�����εĿ��Ⱥ͸߶Ⱦ���ͬ����Щ���Ⱥ͸߶ȱ�����cxBlock��cyBlock�У�����ʾ�����С�����ı�ʱ�������¶���Щֵ���м��㡣WM_LBUTTONDOWN��������ʹ�û���������ȷ�����ĸ������а����˼�������fState�����б�־Ŀǰ���ε�״̬����ʹ�þ�������ʧЧ���Ӷ�����WM_PAINTѶϢ��


��

ͼ7-3 CHECKER1��өĻ��ʾ

�����ʾ����Ŀ��Ⱥ͸߶Ȳ��ܱ�5��������ô����ʾ�������ߺ��±߽���һС�������ܱ����������ǡ���춴��������CHECKER1ͨ������MessageBeep��Ӧ�������еĻ��󰴼�������

��CHECKER1�յ�WM_PAINTѶϢʱ����ͨ��GDI��Rectangle��ʽ�����»�����ʾ��������趨��fStateֵ����ôCHECKER1��ʹ��MoveToEx��LineTo��ʽ����������ֱ�ߡ��ڴ���WM_PAINT�ڼ䣬CHECKER1�����»���֮ǰ�������ÿ�������������Ч�ԣ������������������������Ч�Ե�һ�ַ������ڻ�Ȧ��Ϊÿ�����ο齨��RECT�ṹ��ʹ����WM_LBUTTONDOWN������ʽ����ͬ�Ĺ�ʽ������ʹ��IntersectRect��ʽ������Ƿ�����Ч���Σ�ps.rcPaint���ཻ��

ʹ�ü���ģ�⻬��
��

CHECKER1ֻ����װ�л�������²ſ�ִ�С����������ڳ�ʽ�м�����̽��棬����ͬ�������ж�SYSMETS��ʽ��������������������ʹ��һ��ʹ�û����α���Ϊָ����;�ij�ʽ�м�����̽��棬���ǻ��DZ��봦�������α���ƶ�����ʾ���⡣

��ʹû�а�װ����Windows��Ȼ������ʾһ�������αꡣWindowsΪ����α걣����һ������ʾ�������������װ�˻�����ʾ�����ᱻ��ʼ��Ϊ0��������ʾ�����ᱻ��ʼ��Ϊ-1��ֻ������ʾ�����Ǹ�ʱ����ʾ�����αꡣҪ������ʾ�����������Ժ��У�

ShowCursor (TRUE) ;

Ҫ������ʾ���������Ժ��У�

ShowCursor (FALSE) ;

����ʹ��ShowCursor֮ǰ������Ҫȷ���Ƿ�װ�˻������������ʾ�����α꣬�����ܻ�����������ôֻ�����ShowCursor��������ʾ����������һ����ʾ����֮�ᣬ���û�а�װ������������������α꣬�����װ�˻�����������ʾ��

��ʹû�а�װ����WindowsҲ�����˻���Ŀǰ��λ�á����û�а�װ���󣬶�������ʾ�����α꣬�α�Ϳ��ܳ�������ʾ��������λ�ã�ֱ����ȷʵ�ƶ�������Ҫ����α��λ�ã����Ժ��У�

GetCursorPos (&pt) ;

����pt��POINT�ṹ����ʽʹ�û����x��y����������POINT��λ��Ҫ�趨�α�λ�ã�����ʹ�ã�

SetCursorPos (x, y) ;

������������£�x��y����өĻ���꣬��������ʾ�������꣨���Ǻ����Եģ���Ϊ��Щ��ʽû��Ҫ��hwnd��������ǰ���Ѿ��ᵽ��������ScreenToClient��ClientToScreen��������өĻ������ͻ�������໥ת����

������ڴ�������ѶϢ��ת����ʾ��������ʱ����GetCursorPos ����Щ��������뻬��ѶϢ��lParam�����е�������΢��Щ��ͬ����GetCursorPos���ص������ʾ����Ŀǰ��λ�á�lParam�е��������Dz���ѶϢʱ�����λ�á�

��������дһ�����̴�����ʽ��ʹ�ü��̷�������ƶ������α꣬ʹ��Spacebar��Enter����ģ�⻬�󰴼������϶���ϣ��ÿ�ΰ���ֻ�ǽ������α��ƶ�һ��ͼ�أ��������������Ҫ�ѻ����α����ʾ����һ���ƶ�����һ��ʱ����ʹ�����ںܳ�һ��ʱ���ڶ�Ҫ��סͬһ���������

�������Ҫʵ�������α�ļ��̽��棬�������α�ľ�ȷ��λ��������ô�����Բ�������ķ�ʽ����������ѶϢ�������·����ʱ��һ��ʼ�����α��ƶ��������������ӿ졣��Ҳ�����ǵ�WM_KEYDOWNѶϢ�е�lParam������־������ѶϢ�Ƿ����ظ���Ľ��������Ǵ˲�����һ����ҪӦ�á�

��CHECKER�м�����̽���
��

��ʽ7-3��ʾ��CHECKER2��ʽ�����˰������̽����⣬��CHECKER1��һ���ģ�������ʹ�����ҡ��Ϻ��·������25������֮���ƶ��αꡣHome�����α��ƶ������ε����Ͻǣ� End�����α��ƶ������ε����½ǡ�Spacebar��Enter�������л�X��ǡ�

 ï¿½ï¿½Ê½7-3  CHECKER2
CHECKER2.C
/*----------------------------------------------------------------------------
   CHECKER2.C --	Mouse Hit-Test Demo Program No. 2
						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>

#define DIVISIONS 5

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
						PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR szAppName[] = TEXT ("Checker2") ;
     	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 ("Program requires Windows NT!"), 
							szAppName, MB_ICONERROR) ;
          		return 0 ;
     	}
     	hwnd = CreateWindow (	szAppName, TEXT ("Checker2 Mouse Hit-Test Demo"),
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (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 BOOL	fState[DIVISIONS][DIVISIONS] ;
     	static int 		cxBlock, cyBlock ;
     	HDC         				hdc ;
     	int         				x, y ;
     	PAINTSTRUCT 		          ps ;
     	POINT       				point ;
     	RECT        				rect ;
     
     	switch (message)
     	{
     	case 	WM_SIZE :
          		cxBlock = LOWORD (lParam) / DIVISIONS ;
          		cyBlock = HIWORD (lParam) / DIVISIONS ;
          		return 0 ;
          
     	case 	WM_SETFOCUS :
          		ShowCursor (TRUE) ;
          		return 0 ;
          
     	case 	WM_KILLFOCUS :
          		ShowCursor (FALSE) ;
          		return 0 ;
          
     	case 	WM_KEYDOWN :
          		GetCursorPos (&point) ;
          		ScreenToClient (hwnd, &point) ;
          		x = max (0, min (DIVISIONS - 1, point.x / cxBlock)) ;
          		y = max (0, min (DIVISIONS - 1, point.y / cyBlock)) ;
          
          		switch (wParam)
          		{
          			case VK_UP :
               					y-- ;
               					break ;
               
          			case 	VK_DOWN :
               					y++ ;
               					break ;
               
          			case 	VK_LEFT :
               					x-- ;
               					break ;
               
          			case 	VK_RIGHT :
               					x++ ;
               					break ;
               
          			case 	VK_HOME :
               					x = y = 0 ;
               					break ;
               
          			case 	VK_END :
               					x = y = DIVISIONS - 1 ;
               					break ;
               
          			case 	VK_RETURN :
          			case 	VK_SPACE :
               					SendMessage (hwnd, WM_LBUTTONDOWN, MK_LBUTTON,
                            	MAKELONG (x * cxBlock, y * cyBlock)) ;
               					break ;
          		}
			x = (x + DIVISIONS) % DIVISIONS ;
          			y = (y + DIVISIONS) % DIVISIONS ;
          
          			point.x = x * cxBlock + cxBlock / 2 ;
          			point.y = y * cyBlock + cyBlock / 2 ;
          
          			ClientToScreen (hwnd, &point) ;
          			SetCursorPos (point.x, point.y) ;
      			return 0 ;
     	case	WM_LBUTTONDOWN :
		x = LOWORD (lParam) / cxBlock ;
		y = HIWORD (lParam) / cyBlock ;
          
		if (x < DIVISIONS && y < DIVISIONS)
          		{
               					fState[x][y] ^= 1 ;
               
               					rect.left     = x * cxBlock ;
               					rect.top      = y * cyBlock ;
               					rect.right    = (x + 1) * cxBlock ;
               					rect.bottom   = (y + 1) * cyBlock ;
               
               					InvalidateRect (hwnd, &rect, FALSE) ;
          }
          		else
               					MessageBeep (0) ;
          		return 0 ;
     	case 	WM_PAINT :
		hdc = BeginPaint (hwnd, &ps) ;
          
         		for (x = 0 ; x < DIVISIONS ; x++)
          		for (y = 0 ; y < DIVISIONS ; y++)
          		{
               			Rectangle (hdc, x * cxBlock, y * cyBlock,
                          		(x + 1) * cxBlock, (y + 1) * cyBlock) ;
                    
               			if (fState [x][y])
               			{
                    MoveToEx (hdc,  x   *cxBlock,  y   *cyBlock, NULL) ;
					LineTo   (hdc, (x+1)*cxBlock, (y+1)*cyBlock) ;
					MoveToEx (hdc,  x   *cxBlock, (y+1)*cyBlock, NULL) ;
                    LineTo   (hdc, (x+1)*cxBlock,  y   *cyBlock) ;
               			}
          		}
          		EndPaint (hwnd, &ps) ;
          		return 0 ;
               
	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
  	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

CHECKER2�е�WM_KEYDOWN�Ĵ�����ʽ�����α��λ�ã���GetCursorPos������өĻ����ת��Ϊ��ʾ�������꣨��ScreenToClient�������þ��η���Ŀ��Ⱥ͸߶�����������ꡣ������ָʾ����λ�õ�x��yֵ��5��5���У���������һ����ʱ�������α�����ڻ�����ʾ�����У�����x��y���뾭��min��max�޼������Ա�֤���ǵķ�Χ��0��4֮�䡣

�Է������CHECKER2���Ƶ����ӻ����x��y�������Enter����Spacebar������ôCHECKER2ʹ��SendMessage��WM_LBUTTONDOWNѶϢ���͸������������ּ����������ڵ�����SYSMETS��ʽ�аѼ��̽���ӵ��Ӵ�������ʱ��ʹ�õķ�����WM_KEYDOWN�Ĵ�����ʽ��ͨ������ָ��������ĵ���ʾ�������꣬����ClientToScreenת����өĻ���꣬Ȼ����SetCursorPos�趨�α�λ����ʵ���ġ�

�����Ӵ�������в���
��

��Щ��ʽ�����磬Windows�ġ���ͼ����ʽ��������ʾ���򻮷�Ϊ����С���߼����򡣡���ͼ����ʽ���������һ����ͼʾ��ɵĹ��߹��ܱ������ڵײ�����ɫ���ܱ��������������������в��Ե�ʱ�򣬡���ͼ��������ʹ����ѡ�й��ܱ���֮ǰ��ס���ܱ���λ�á�

������Ҳ���ܲ���Ҫ��ô����ʵ���ϣ����羭��ʹ�����Ӵ����˹��ܱ��Ļ��ƺ����в��ԡ����Ӵ��������������򻮷�Ϊ������С�ľ�������ÿ�����Ӵ����Լ����Ӵ����š��Ӵ�ѶϢ������ʽ����ʾ����ÿ���Ӵ�ѶϢ������ʽ����ֻ������������Ӵ��Ļ���ѶϢ������ѶϢ�е�lParam���������൱춸����Ӵ���ʾ�������Ͻǵ����꣬�������丸�Ӵ������ǡ���ͼ������Ӧ�ó�ʽ�Ӵ�����ʾ�������Ͻǵ����ꡣ

�����ַ�ʽʹ�����Ӵ�����춳�ʽ�Ľṹ����ģ�黯��������Ӵ�ʹ�ò�ͬ���Ӵ������ôÿ�����Ӵ��������Լ����Ӵ�ѶϢ������ʽ����ͬ���Ӵ�Ҳ���Զ��岻ͬ�ı�����ɫ�Ͳ�ͬ���ڶ��αꡣ�ڵھ����У��ҽ����������Ӵ�������������С���ť�ͱ༭�����Ԥ�ȶ�������Ӵ������ڣ�����˵����CHECKER��ʽ�������ʹ�����Ӵ��ġ�

CHECKER�е����Ӵ�
��

��ʽ7-4��ʾ��CHECKER3��ʽ����һ�汾������25���������󵥻������Ӵ�����û�м��̽��棬���ǿ��԰����������CHECKER4��ʽ�����ķ������ӡ�

 ï¿½ï¿½Ê½7-4  CHECKER3
CHECKER3.C
/*---------------------------------------------------------------------------
   CHECKER3.C --	Mouse Hit-Test Demo Program No. 3
          						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>

#define DIVISIONS 5

LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szChildClass[] 					= TEXT ("Checker3_Child") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    						PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR	szAppName[]	= TEXT ("Checker3") ;
     	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 ("Program requires Windows NT!"), 
                      							szAppName, MB_ICONERROR) ;
  		return 0 ;
     	}
     
	wndclass.lpfnWndProc   			= ChildWndProc ;
     	wndclass.cbWndExtra    		= sizeof (long) ;
     	wndclass.hIcon         		= NULL ;
     	wndclass.lpszClassName 		= szChildClass ;

     	RegisterClass (&wndclass) ;
     	hwnd = CreateWindow (	szAppName, TEXT ("Checker3 Mouse Hit-Test Demo"),
                         WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (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 HWND 	hwndChild[DIVISIONS][DIVISIONS] ;
     	int    				cxBlock, cyBlock, x, y ;
     
     	switch (message)
     {
     	case 	WM_CREATE :
          		for (x = 0 ; x < DIVISIONS ; x++)
               		for (y = 0 ; y < DIVISIONS ; y++)
                    hwndChild[x][y] = CreateWindow (szChildClass, NULL,
                    WS_CHILDWINDOW | WS_VISIBLE,
                    0, 0, 0, 0,
         	        hwnd, (HMENU) (y << 8 | x),
                    (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              								NULL) ;
          		return 0 ;
               
     	case 	WM_SIZE :
          		cxBlock = LOWORD (lParam) / DIVISIONS ;
          		cyBlock = HIWORD (lParam) / DIVISIONS ;
          		for (x = 0 ; x < DIVISIONS ; x++)
                				for (y = 0 ; y < DIVISIONS ; y++)
                    						MoveWindow (	hwndChild[x][y],
                                			x * cxBlock, y * cyBlock,
                                			    cxBlock, cyBlock, TRUE) ;
          		return 0 ;

     	case 	WM_LBUTTONDOWN :
          		MessageBeep (0) ;
          		return 0 ;
          
     	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message, 
                WPARAM wParam, LPARAM lParam)
{
     	HDC         					hdc ;
     	PAINTSTRUCT 			        ps ;
     	RECT        					rect ;
     
     	switch (message)
     	{
     	case 	WM_CREATE :
          		SetWindowLong (hwnd, 0, 0) ;       // on/off flag
          		return 0 ;
          
     	case 	WM_LBUTTONDOWN :
          		SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
          		InvalidateRect (hwnd, NULL, FALSE) ;
          		return 0 ;
          
     	case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;
          
          		GetClientRect (hwnd, &rect) ;
          		Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
          
          		if (GetWindowLong (hwnd, 0))
          		{
               				MoveToEx (hdc, 0,          0, NULL) ;
               				LineTo   (hdc, rect.right, rect.bottom) ;
               				MoveToEx (hdc, 0,          rect.bottom, NULL) ;
               				LineTo   (hdc, rect.right, 0) ;
      		}
          
          		EndPaint (hwnd, &ps) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

CHECKER3�������Ӵ�ѶϢ������ʽWndProc��ChildWndProc��WndProc���������򸸣��Ӵ����Ӵ�ѶϢ������ʽ��ChildWndProc�����25�����Ӵ����Ӵ�ѶϢ������ʽ���������Ӵ�ѶϢ������ʽ�����붨��ΪCALLBACK��ʽ��

��Ϊ�Ӵ�ѶϢ������ʽ���ض����Ӵ����ṹ����������Ӵ����ṹ��Windows����RegisterClass��ʽ��ע�ᣬCHECKER3��Ҫ�����Ӵ���𡣵�һ���Ӵ����������Ӵ�����Ϊ��Checker3�����ڶ����Ӵ������Ϊ��Checker3_Child������Ȼ��������ѡ������������������֡�

CHECKER3��WinMain��ʽ��ע�����������Ӵ����ע���곣����Ӵ����֮�ᣬCHECKER3ֻ�Ǽ򵥵�����ʹ��wndclass�ṹ�еĴ��������λ��ע��Checker3_Child���������Σ����ĸ���λ�������Ӵ������趨Ϊ��ͬ��ֵ��

  • pfnWndProc��λ�趨ΪChildWndProc�����Ӵ������Ӵ�ѶϢ������ʽ��
    ��
  • cbWndExtra��λ�趨Ϊ4λԪ�飬���߸�ȷ�е���sizeof (long)���������Windows����Ϊ���ݴ��Ӵ������Ӵ��������ڲ��ṹ�У�Ԥ����4λԪ�����Ŀռ䡣����ʹ�ô˿ռ�������ÿ���Ӵ��Ŀ���������ͬ����Ѷ��
    ��
  • ����CHECKER3�е����Ӵ�����Ҫͼʾ������hIcon��λ�趨ΪNULL ��
    ��
  • pszClassName��λ�趨Ϊ��Checker3_Child�������������ơ�
    ��

ͨ������WinMain�У�CreateWindow���н�������Checker3�������Ӵ���Ȼ������WndProc�յ�WM_CREATEѶϢ�ᣬ������CreateWindow 25���Խ���25��Checker3_Child�������Ӵ�����7-3����WinMain��CreateWindow���еIJ��������ڽ���25�����Ӵ���WndProc��CreateWindow���еIJ�����ıȽϡ�

��7-3
���� ���Ӵ� ���Ӵ�
�Ӵ���� ��Checker3�� ��Checker3_Child��
�Ӵ����� ��Checker3...�� NULL
�Ӵ���ʽ WS_OVERLAPPEDWINDOW WS_CHILDWINDOW | WS_VISIBLE
ˮƽλ�� CW_USEDEFAULT 0
��ֱλ�� CW_USEDEFAULT 0
���� CW_USEDEFAULT 0
�߶� CW_USEDEFAULT 0
���Ӵ����� NULL hwnd
���ܱ�����/��ID NULL (HMENU) (y << 8 | x)
ִ��ʵ����� hInstance (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE)
������� NULL NULL

һ������£����Ӵ�Ҫ���й�λ�úʹ�С�IJ�����������CHECKER3�е����Ӵ���WndProcȷ��λ�úʹ�С��������Ӵ�����Ϊ���������Ǹ��Ӵ����������ĸ��Ӵ�������NULL����ʹ��CreateWindow����������һ�����Ӵ�ʱ������Ҫ���Ӵ������ˡ�

���Ӵ�û�й��ܱ�����˲�����NULL��������Ӵ�����ͬλ�õIJ�����Ϊ��ID�������Ӵ�ID��������Ψһ�������Ӵ������֡��������ڵ�ʮһ�½�������һ�����ڴ����Ի���������Ӵ�������ʱ����ID�Եø�Ϊ��Ҫ�����CHECKER3��˵����ֻ�Ǽ򵥵ؽ���ID�趨Ϊһ����ֵ������ֵ��ÿ�����Ӵ���5��5�����Ӵ��е�x��yλ�õ���ϡ�

CreateWindow��ʽ��Ҫһ��ִ��ʵ����š���WinMain�У�ִ��ʵ����ſ��Ժ����׵�ȡ�ã���Ϊ����WinMain��һ���������ڽ������Ӵ�ʱ�� CHECKER3������GetWindowLong����WindowsΪ�Ӵ������Ľṹ��ȡ��hInstanceֵ������GetWindowLong����Ҳ�ܽ�hInstance��ֵ���浽�����������ֱ��ʹ��������

ÿһ�����Ӵ�����hwndChild�����б����˲�ͬ���Ӵ����š���WndProc���յ�һ��WM_SIZEѶϢ�ᣬ����Ϊ��25�����Ӵ�����MoveWindow��MoveWindow�IJ�����ʾ���Ӵ����Ͻ����춸��Ӵ���ʾ��������ꡢ���Ӵ��Ŀ��Ⱥ͸߶��Լ����Ӵ��Ƿ���Ҫ�ػ���

���������ǿ�һ��ChildWndProc�����Ӵ�ѶϢ������ʽΪ������25�����Ӵ�����ѶϢ��ChildWndProc��hwnd���������Ӵ�����ѶϢ�Ĵ��š���ChildWndProc����WM_CREATEѶϢʱ����Ϊ��25�����Ӵ�������Ҫ����25�Σ�������SetWindowWord���Ӵ��ṹ�����Ķ��������д���һ��0ֵ��ͨ���ڶ����Ӵ����ʱʹ�õ�cbWndExtra�������Ŀռ䣩��ChildWndProc�ô�ֵ���ָ�Ŀǰ���ε�״̬����X��û��X���������Ӵ��е���ʱ��WM_LBUTTONDOWN������ʽ�򵥵��޸��������ֵ����0��1�����1��0������ʹ�������Ӵ���Ч���������DZ������ľ��Ρ�WM_PAINT�Ĵ����ܼ򵥣���Ϊ�������Ƶľ�������ʾ����һ����

��ΪCHECKER3��Cԭʼ�뵵����.EXE������CHECKER1�Ĵ󣨸�����˵��ʽ��˵���ˣ����Ҳ�������������˵CHECKER3��CHECKER1���򵥡�����ע�⣬����û�����κεĻ������в��ԣ�������Ҫ�ģ�����֪��CHECKER3���Ƿ��и����Ӵ��õ��������Ӵ���WM_LBUTTONDOWNѶϢ��

���Ӵ��ͼ���
��

ΪCHECKER3���Ӽ��̽������CHECKERϵ�й����е�����һ����������������ʱ�򣬿����и��ʵ�����������CHECKER2�У������α��λ�þ�������Spacebar��ʱ�ĸ����򽫻�ñ�Ƿ��š������Ǵ������Ӵ�ʱ�������ܴӶԻ����鹦���л����ʾ���ڶԻ������У�������˸�IJ�����Ż�㻮�ľ��ε����Ӵ���ʾ�������뽹�㣨��ȻҲ�����ü��̽��ж�λ����

���Dz���Ҫ��Windows�ڲ����еĶԻ����鴦����ʽ����д������ֻ��Ҫ������������Ӧ�������Ӧ�ó�ʽ��ģ��Ի����顣�о������У����ᷢ������һ���£����Ӵ������Ӵ�����Ҫ����ͬ����ѶϢ����������Spacebar����Enter��ʱ�����Ӵ���������ѡ��ǡ����·����ʱ�����Ӵ��������Ӵ�֮���ƶ����뽹�㡣ʵ���ϣ����������Ӵ��ϵ���ʱ���������Щ���ӣ���ʱ�Ǹ��Ӵ����������Ӵ�������뽹�㡣

CHECKER4.C���ʽ7-5��ʾ��

 ï¿½ï¿½Ê½7-5  CHECKER4
CHECKER4.C
/*---------------------------------------------------------------------------
   CHECKER4.C -- 	Mouse Hit-Test Demo Program No. 4
 						(c) Charles Petzold, 1998
---------------------------------------------------------------------------*/

#include <windows.h>
#define DIVISIONS 5

LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;
int   idFocus = 0 ;
TCHAR szChildClass[] = TEXT ("Checker4_Child") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    						PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR 	szAppName[] = TEXT ("Checker4") ;
     	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 ("Program requires Windows NT!"), 
                      							szAppName, MB_ICONERROR) ;
          		return 0 ;
     	}
     
     	wndclass.lpfnWndProc   				= ChildWndProc ;
     	wndclass.cbWndExtra    				= sizeof (long) ;
     	wndclass.hIcon         				= NULL ;
     	wndclass.lpszClassName 			= szChildClass ;
     
     	RegisterClass (&wndclass) ;
     	hwnd = CreateWindow (	szAppName, TEXT ("Checker4 Mouse Hit-Test Demo"),
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        NULL, NULL, hInstance, NULL) ;
     	ShowWindow (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 HWND 	hwndChild[DIVISIONS][DIVISIONS] ;
     	int    				cxBlock, cyBlock, x, y ;
     
     	switch (message)
     	{
     	case WM_CREATE :
          		for (x = 0 ; x < DIVISIONS ; x++)
               				for (y = 0 ; y < DIVISIONS ; y++)
              hwndChild[x][y] = CreateWindow (szChildClass, NULL,
                          WS_CHILDWINDOW | WS_VISIBLE,
                          0, 0, 0, 0,
                          hwnd, (HMENU) (y << 8 | x),
                          HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              			NULL) ;
          		return 0 ;
     	case 	WM_SIZE :
          		cxBlock = LOWORD (lParam) / DIVISIONS ;
          		cyBlock = HIWORD (lParam) / DIVISIONS ;
          
          		for (x = 0 ; x < DIVISIONS ; x++)
                				for (y = 0 ; y < DIVISIONS ; y++)
                    		MoveWindow (	hwndChild[x][y],
                             x * cxBlock, y * cyBlock,
                                 cxBlock, cyBlock, TRUE) ;
          		return 0 ;
                       
     	case 	WM_LBUTTONDOWN :
          		MessageBeep (0) ;
          		return 0 ;

          		// On set-focus message, set focus to child window
     	case 	WM_SETFOCUS:
          		SetFocus (GetDlgItem (hwnd, idFocus)) ;
          		return 0 ;

		// On key-down message, possibly change the focus window

     	case 	WM_KEYDOWN:
          		x = idFocus & 0xFF ;
          		y = idFocus >> 8 ;

         		switch (wParam)
          		{
        case VK_UP:             y-- ;  							break ;
		case VK_DOWN:  			y++ ;  							break ;
		case VK_LEFT:  			x-- ;       					break ;
        case VK_RIGHT: 		    x++ ;                    	    break ;
        case VK_HOME:  			x = y = 0 ;              		break ;
        case VK_END:   			x = y = DIVISIONS - 1 ;  	    break ;
          		default:     					return 0 ;
          		}

          		x = (x + DIVISIONS) % DIVISIONS ;
          		y = (y + DIVISIONS) % DIVISIONS ;

          		idFocus = y << 8 | x ;

          		SetFocus (GetDlgItem (hwnd, idFocus)) ;
          		return 0 ;

     	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message, 
                   WPARAM wParam, LPARAM lParam)
{
     	HDC         					hdc ;
     	PAINTSTRUCT 			        ps ;
     	RECT        					rect ;
     
 	switch (message)
     {
     	case 	WM_CREATE :
          		SetWindowLong (hwnd, 0, 0) ;       // on/off flag
          		return 0 ;

     	case 	WM_KEYDOWN:
               			// Send most key presses to the parent window
          
          		if (wParam != VK_RETURN && wParam != VK_SPACE)
          		{
               		SendMessage (GetParent (hwnd), message, wParam, lParam) ;
               		return 0 ;
          		}
               			// For Return and Space, fall through to toggle the square
          
     	case 	WM_LBUTTONDOWN :
          		SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
          		SetFocus (hwnd) ;
          		InvalidateRect (hwnd, NULL, FALSE) ;
          		return 0 ;

               	// For focus messages, invalidate the window for repaint
          
     	case 	WM_SETFOCUS:
          		idFocus = GetWindowLong (hwnd, GWL_ID) ;

               	// Fall through

     	case 	WM_KILLFOCUS:
          		InvalidateRect (hwnd, NULL, TRUE) ;
          		return 0 ;
          
	    case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;
          
          		GetClientRect (hwnd, &rect) ;
          		Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;

               			// Draw the "x" mark
          
          		if (GetWindowLong (hwnd, 0))
          		{
               			MoveToEx (hdc, 0,          0, NULL) ;
               			LineTo   (hdc, rect.right, rect.bottom) ;
               			MoveToEx (hdc, 0,          rect.bottom, NULL) ;
               			LineTo   (hdc, rect.right, 0) ;
          		}
               			// Draw the "focus" rectangle
          
          		if (hwnd == GetFocus ())
          		{
               			rect.left   += rect.right / 10 ;
               			rect.right  -= rect.left ;
               			rect.top    += rect.bottom / 10 ;
               			rect.bottom -= rect.top ;

               			SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
               			SelectObject (hdc, CreatePen (PS_DASH, 0, 0)) ;
               			Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
               			DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
          		}

          		EndPaint (hwnd, &ps) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

��Ӧ���ܻ�����ÿһ�����Ӵ���Ψһ�����Ӵ�ID����ID�ں���CreateWindow�����Ӵ�ʱ���塣��CHECKER3�У���ID�Ǿ��ε�x��yλ�õ���ϡ�һ����ʽ����ͨ������ĺ��������һ���ض����Ӵ������Ӵ�ID��

idChild = GetWindowLong (hwndChild, GWL_ID) ;

����ĺ�ʽҲ��ͬ���Ĺ��ܣ�

idChild = GetDlgCtrlID (hwndChild) ;

���纯ʽ��������ʾ�ģ�����Ҫ��춶Ի�����Ϳ����Ӵ��������֪�����Ӵ��Ĵ��ź����Ӵ�ID���˺�ʽҲ���Ի�����Ӵ��Ĵ��ţ�

hwndChild = GetDlgItem (hwndParent, idChild) ;

��CHECKER4�У��������idFocus��춱���Ŀǰ���뽹���Ӵ������Ӵ�ID������ǰ��˵�������������Ӵ����浥������ʱ�����Dz����Զ�������뽹�㡣��ˣ�CHECKER4�еĸ��Ӵ���ͨ����������ĺ�ʽ������WM_SETFOCUSѶϢ��

SetFocus (GetDlgItem (hwnd, idFocus)) ;

�����趨һ�����Ӵ�Ϊ���뽹�㡣

ChildWndProc����WM_SETFOCUS��WM_KILLFOCUSѶϢ�����WM_SETFOCUS�������������������idFocus�н������뽹������Ӵ�ID�����������ѶϢ���Ӵ�����Ч�ģ�������һ��WM_PAINTѶϢ�����WM_PAINTѶϢ�����������뽹������Ӵ�����������PS_DASH���ʵķ��һ�������Ա�ʾ���Ӵ������뽹�㡣

ChildWndProcҲ����WM_KEYDOWNѶϢ����춳���Spacebar��Enter�����������ѶϢ��WM_KEYDOWN���������Ӵ�����ѶϢ�����⣬�Ӵ�ѶϢ������ʽҲ��������WM_LBUTTONDOWNѶϢ��ѶϢ��

���������ƶ����Ǹ��Ӵ������顣�ڷ�����Ƶ�CHECKER2�У��˳�ʽ�ɻ�������뽹������Ӵ���x��y���꣬�����ݰ��µ��ض���������ı����ǡ�Ȼ��ͨ������SetFocus�����뽹���趨���µ����Ӵ���

���ػ���
��

һ���Ӵ�ѶϢ������ʽͨ��ֻ�ڻ����α�λ��Ӵ�����ʾ���򣬻����ʾ������ʱ�Ž��ջ���ѶϢ��һ����ʽҲ������Ҫ�ڻ���λ��Ӵ���ʱ���ջ���ѶϢ���������������ʽ�������С����ء����󡣱��£���ô��ûʲô���˵ġ�

��ƾ���
��

Ϊ��˵�����ػ���ı�Ҫ�ԣ��������ǿ�һ��BLOKOUT1��ʽ�����ʽ7-6��ʾ�����˳�ʽ�������ﵽ��һ���Ĺ��ܣ�����ȴ��ʮ�����ص�ȱ�ݡ�

 ï¿½ï¿½Ê½7-6  BLOKOUT1
BLOKOUT1.C
/*----------------------------------------------------------------------------
   BLOKOUT1.C -- 	Mouse Button Demo Program
 						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#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 ("BlokOut1") ;
     	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 ("Program requires Windows NT!"), 
                      							szAppName, MB_ICONERROR) ;
		return 0 ;
     	}
     
     	hwnd = CreateWindow (szAppName, TEXT ("Mouse Button Demo"),
                     WS_OVERLAPPEDWINDOW,
                     CW_USEDEFAULT, CW_USEDEFAULT,
                     CW_USEDEFAULT, CW_USEDEFAULT,
                     NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;
     
     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          		TranslateMessage (&msg) ;
          		DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

void DrawBoxOutline (HWND hwnd, POINT ptBeg, POINT ptEnd)
{
     	HDC hdc ;
     	hdc = GetDC (hwnd) ;
     	SetROP2 (hdc, R2_NOT) ;
     	SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
     	Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
     
     	ReleaseDC (hwnd, hdc) ;
}
LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static BOOL 	fBlocking, fValidBox ;
     	static POINT	ptBeg, ptEnd, ptBoxBeg, ptBoxEnd ;
     	HDC     				hdc ;
     	PAINTSTRUCT  ps ;
     	switch (message)
     	{
     	case 	WM_LBUTTONDOWN :
          		ptBeg.x = ptEnd.x = LOWORD (lParam) ;
          		ptBeg.y = ptEnd.y = HIWORD (lParam) ;
          
          		DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
          
          		SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
          
          		fBlocking = TRUE ;
          		return 0 ;

     	case 	WM_MOUSEMOVE :
          		if (fBlocking)
          		{
               			SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
               
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               
               			ptEnd.x = LOWORD (lParam) ;
               			ptEnd.y = HIWORD (lParam) ;
               
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
          		}
          		return 0 ;
          
     	case 	WM_LBUTTONUP :
          		if (fBlocking)
          		{
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               
               			ptBoxBeg   				= ptBeg ;
               			ptBoxEnd.x 				= LOWORD (lParam) ;
               			ptBoxEnd.y 				= HIWORD (lParam) ;
               
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
               			fBlocking 				= FALSE ;
               			fValidBox  				= TRUE ;
               
               			InvalidateRect (hwnd, NULL, TRUE) ;
          		}
          		return 0 ;
          
     	case 	WM_CHAR :
          		if (fBlocking & wParam == '\x1B')       // i.e., Escape
          		{
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
               
               			fBlocking = FALSE ;
          		}
          		return 0 ;

     	case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;

    		if (fValidBox)
          		{
               				SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
               				Rectangle 	(	hdc, ptBoxBeg.x, ptBoxBeg.y,
                    									ptBoxEnd.x, ptBoxEnd.y) ;
          		}
          
     		if (fBlocking)
          		{
               			SetROP2 (hdc, R2_NOT) ;
               			SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
               			Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
          		}
          
          		EndPaint (hwnd, &ps) ;
          		return 0 ;

     	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
     }
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

�˳�ʽչʾ��һЩ��������ʵ����Windows�ġ���ͼ����ʽ�еĶ������ɰ��»��������ʼȷ�����ε�һ�ǣ�Ȼ���϶����󡣳�ʽ����һ�����ε������������λ���ǻ���Ŀǰ��λ�á������ͷŻ����ᣬ��ʽ������������Ρ�ͼ7-4��ʾ��һ���Ѿ�����ľ��κ���һ�����ڻ��ľ��Ρ�


��

ͼ7-4 BLOKOUT1��өĻ��ʾ

��ô�������������أ�

����һ������IJ�������BLOKOUT1����ʾ�����»���������Ȼ�Ὣ�α��Ƴ��Ӵ�����ʽ��ֹͣ����WM_MOUSEMOVEѶϢ�������ͷŰ�ť��BLOKOUT1�����ٻ��WM_BUTTONUPѶϢ����Ϊ�α�����ʾ�������⡣Ȼ�Ὣ�α��ƻ�BLOKOUT1����ʾ�����Ӵ�ѶϢ������ʽ��Ȼ��Ϊ��ť��춰���״̬��

�����������ã���Ϊ��ʽ��֪��������ʲô���顣

���صĽ������
��

BLOKOUT1��ʾ��һЩ�����ij�ʽ���ܣ������ij�ʽ����Ȼ��ȱ�ݡ������������Ҫʹ�û����������Ը������ʹ����������ҷ������ô�������ʱ���ڱ��ϳ��Ӵ�ʱӦ��û��ʲô�����⣬��ʽӦ����Ȼ����������

���ػ���Ҫ�ȷ���һ�������������һЩ����ֻҪ���У�

SetCapture (hwnd) ;

�������ʽ����֮�ᣬWindows�����л���ѶϢ�����Ӵ�����Ϊhwnd���Ӵ�ѶϢ������ʽ��֮���յ�����ѶϢ��������ʾ����ѶϢ����̬���֣���ʹ���������Ӵ��ķ���ʾ����lParam������ָʾ��������ʾ���������е�λ�á�������������λ���ʾ�������߻����Ϸ�ʱ����Щx��y��������Ǹ��ġ��������ͷŻ���ʱ�����У�

ReleaseCapture () ;

�Ӷ�ʹ�����ָ�������

��32λԪ��Windows�У���������Ҫ������ǰ��Windows�汾���ж�һЩ���ơ��ر��ǣ�����������أ������󰴼�Ŀǰ��δ�����£����һ����α��Ƶ�����һ���Ӵ��ϣ���ô�����������ػ�����Ǹ��Ӵ����������α�������Ӵ������ջ���ѶϢ����춷�ֹһ����ʽ�����ػ���֮�᲻�ͷ�������������ϵͳ�Ļ��ң����DZ�Ҫ�ġ�

���仰˵��ֻ�е����󰴼���������ʾ�����б�����ʱ�����ػ��󣻵����󰴼����ͷ�ʱ�����ͷŻ������ء�

BLOKOUT2��ʽ
��

չʾ�������ص�BLOKOUT2��ʽ���ʽ7-7��ʾ��

 ï¿½ï¿½Ê½7-7  BLOKOUT2
BLOKOUT2.C
/*----------------------------------------------------------------------------
   	BLOKOUT2.C -- 		Mouse Button & Capture Demo Program
						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#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 ("BlokOut2") ;
     	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 ("Program requires Windows NT!"), 
							szAppName, MB_ICONERROR) ;
		return 0 ;
 	}

     	hwnd = CreateWindow (	szAppName, TEXT ("Mouse Button & Capture Demo"),
					WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    NULL, NULL, hInstance, NULL) ;
     
     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;
     
     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          				TranslateMessage (&msg) ;
          				DispatchMessage (&msg) ;
     	}
     	return msg.wParam ;
}

void DrawBoxOutline (HWND hwnd, POINT ptBeg, POINT ptEnd)
{
     	HDC hdc ;
     	hdc = GetDC (hwnd) ;
     	SetROP2 (hdc, R2_NOT) ;
     	SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
     	Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
     
     	ReleaseDC (hwnd, hdc) ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
     	static BOOL  fBlocking, fValidBox ;
     	static POINT ptBeg, ptEnd, ptBoxBeg, ptBoxEnd ;
     	HDC          hdc ;
     	PAINTSTRUCT  ps ;
     
     	switch (message)
     	{
     	case 	WM_LBUTTONDOWN :
          		ptBeg.x = ptEnd.x = LOWORD (lParam) ;
          		ptBeg.y = ptEnd.y = HIWORD (lParam) ;
          
          		DrawBoxOutline (hwnd, ptBeg, ptEnd) ;

          		SetCapture (hwnd) ;
          		SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
          
          		fBlocking = TRUE ;
          		return 0 ;
          
     	case 	WM_MOUSEMOVE :
          		if (fBlocking)
          		{
               			SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
               
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               
               			ptEnd.x = LOWORD (lParam) ;
               			ptEnd.y = HIWORD (lParam) ;
               
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
          		}
        		return 0 ;
          
     	case 	WM_LBUTTONUP :
          		if (fBlocking)
          		{
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               
               			ptBoxBeg   			= ptBeg ;
               			ptBoxEnd.x 			= LOWORD (lParam) ;
               			ptBoxEnd.y 			= HIWORD (lParam) ;
               
               			ReleaseCapture () ;
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
               
               			fBlocking 			= FALSE ;
               			fValidBox  			= TRUE ;
               
               			InvalidateRect (hwnd, NULL, TRUE) ;
          		}
          		return 0 ;
          
     	case 	WM_CHAR :
          		if (fBlocking & wParam == '\x1B')       // i.e., Escape
          		{
               			DrawBoxOutline (hwnd, ptBeg, ptEnd) ;
               			ReleaseCapture () ;
               			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               			fBlocking = FALSE ;
          		}
          		return 0 ;
          
     	case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;
          
          		if (fValidBox)
          {
               			SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
               			Rectangle (hdc, ptBoxBeg.x, ptBoxBeg.y,
                    			ptBoxEnd.x, ptBoxEnd.y) ;
          		}
          
          			if (fBlocking)
          		{
               			SetROP2 (hdc, R2_NOT) ;
               			SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
               			Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
          		}
          
          		EndPaint (hwnd, &ps) ;
          		return 0 ;
          
     	case 	WM_DESTROY :
          		PostQuitMessage (0) ;
          		return 0 ;
     	}
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BLOKOUT2��ʽ��BLOKOUT1��ʽһ����ֻ�Ƕ��������³�ʽ�룺��WM_LBUTTONDOWNѶϢ�����ڼ����SetCapture������WM_LBUTTONDOWN��WM_CHARѶϢ�����ڼ����ReleaseCapture����黭���Ӵ���ʹ�Ӵ�С�өĻ��С����ʼ����ʾ���򻭳�һ����Σ�Ȼ�Ὣ�����α��Ƴ���ʾ������ұ߻��±ߣ������ͷŻ��󰴼�����ʽ������������ε����ꡣ������Ҫ�����Ӵ����ܿ��������

���ػ��󲢷�ֻ�������Щ�Źֵ�Ӧ�ó�ʽ���������Ҫ���󰴼�����ʾ������ʱ���ܹ�׷��WM_MOUSEMOVEѶϢ����ֱ�����󰴼����ͷ�Ϊֹ����ô����Ӧ�����ػ��������������ij�ʽ��ͬʱ�ַ���ʹ���ߵ�������

������
��

�봫ͳ�Ļ�����ȣ�Microsoft IntelliMouse���ص�����������֮�����һ��С���֡������԰���������֣���ʱ���Ĺ����൱춻��󰴼����м���������Ҳ������ʳָ��ת������������һ�������ѶϢ������WM_MOUSEWHEEL��ʹ�û����ֵij�ʽͨ��������Ŵ��ļ�����Ӧ��ѶϢ���������������һ������Ҫ�����ػ��أ����ұ�����ϣ��Һܿ��ϰ���ʹ�û�����������Microsoft Word��Microsoft Internet Explorer�ˡ�

�Ҳ������ۻ����ֵ�����ʹ�÷�����ʵ���ϣ���ֻ�����������������еij�ʽ�������ʽSYSMETS4�������ӻ����ִ�����ʽ���Ա�����ʾ�����о������ϡ����յ�SYSMETS��ʽ���ʽ7-8��ʾ��

 ï¿½ï¿½Ê½7-8  SYSMETS4
SYSMETS.C
/*----------------------------------------------------------------------------
SYSMETS.C -- Final System Metrics Display Program 
					(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include <windows.h>
#include "sysmets.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    						PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR 	szAppName[] = TEXT ("SysMets") ;
     	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 ("Program requires Windows NT!"), 
                      							szAppName, MB_ICONERROR) ;
          		return 0 ;
     	}
     
	hwnd = CreateWindow (	szAppName, TEXT ("Get System Metrics"),
                          	WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
 		ShowWindow (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 	int	cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth ;
	static 		int		iDeltaPerLine, iAccumDelta ; 		// for mouse wheel logic
     		HDC         hdc ;
     		int         i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;
     		PAINTSTRUCT 		ps ;
     		SCROLLINFO  		si ;
     		TCHAR  				szBuffer[10] ;
     		TEXTMETRIC		tm ;
     		ULONG  				ulScrollLines ;   	// for mouse wheel logic
     	switch (message)
     	{
     	case 	WM_CREATE:
          		hdc = GetDC (hwnd) ;

          		GetTextMetrics (hdc, &tm) ;
          		cxChar 	= tm.tmAveCharWidth ;
          		cxCaps 	= (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
          		cyChar = tm.tmHeight + tm.tmExternalLeading ;
          
          		ReleaseDC (hwnd, hdc) ;

               					// Save the width of the three columns
          
       		iMaxWidth = 40 * cxChar + 22 * cxCaps ;

               					// Fall through for mouse wheel information

     	case 	WM_SETTINGCHANGE:
          		SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0) ;
          	
			// ulScrollLines usually equals 3 or 0 (for no scrolling)
			// WHEEL_DELTA equals 120, so iDeltaPerLine will be 40

          		if (ulScrollLines)
               				iDeltaPerLine = WHEEL_DELTA / ulScrollLines ;
          		else
               				iDeltaPerLine = 0 ;

		return 0 ;
          
     	case 	WM_SIZE:
          		cxClient = LOWORD (lParam) ;
   		cyClient = HIWORD (lParam) ;

               					// Set vertical scroll bar range and page size

          		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) ;

               					// Set horizontal scroll bar range and page size

          		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:
               					// Get all the vertical scroll bar information
          		si.cbSize = sizeof (si) ;
          		si.fMask  = SIF_ALL ;
          		GetScrollInfo (hwnd, SB_VERT, &si) ;

               					// Save the position for comparison later on
          		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 ;         
          		}
               				// Set the position and then retrieve it.  Due to adjustments
				//   by Windows it may not be the same as the value set.

          		si.fMask = SIF_POS ;
          		SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
          		GetScrollInfo (hwnd, SB_VERT, &si) ;

               				// If the position has changed, scroll the window and update it

          		if (si.nPos != iVertPos)
          		{                    
               			ScrollWindow (	hwnd, 0, cyChar * (iVertPos - si.nPos), 
                                   		NULL, NULL) ;
               			UpdateWindow (hwnd) ;
          		}
          		return 0 ;
          
     	case 	WM_HSCROLL:
               				// Get all the vertical scroll bar information

          		si.cbSize = sizeof (si) ;
          		si.fMask  = SIF_ALL ;

               				// Save the position for comparison later on

          		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 ;
          		}
               			// Set the position and then retrieve it.  Due to adjustments
			//   by Windows it may not be the same as the value set.

		si.fMask = SIF_POS ;
          		SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
          		GetScrollInfo (hwnd, SB_HORZ, &si) ;
          
               			// If the position has changed, scroll the window 

          		if (si.nPos != iHorzPos)
          		{
               				ScrollWindow (	hwnd, cxChar * (iHorzPos - si.nPos), 0, 
                             				NULL, NULL) ;
          		}
          		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_MOUSEWHEEL:
          		if (iDeltaPerLine == 0)
               				break ;

          		iAccumDelta += (short) HIWORD (wParam) ;     // 120 or -120

          		while (iAccumDelta >= iDeltaPerLine)
          		{               
               				SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;
               				iAccumDelta -= iDeltaPerLine ;
          		}

          		while (iAccumDelta <= -iDeltaPerLine)
          		{
               				SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;
               				iAccumDelta += iDeltaPerLine ;
          		}

          		return 0 ;

     	case 	WM_PAINT :
          		hdc = BeginPaint (hwnd, &ps) ;

               				// Get vertical scroll bar position

          			si.cbSize 		= sizeof (si) ;
          			si.fMask  			= SIF_POS ;
          			GetScrollInfo (hwnd, SB_VERT, &si) ;
          			iVertPos 			= si.nPos ;

               				// Get horizontal scroll bar position

          			GetScrollInfo (hwnd, SB_HORZ, &si) ;
          			iHorzPos = si.nPos ;

               				// Find painting limits

          			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) ;
}

ת�����ֻᵼ��Windows�������뽹����Ӵ������ǻ����α�������Ӵ�������WM_MOUSEWHEELѶϢ����ƽ��һ����lParam����û����λ�ã���Ȼ����������өĻ���Ͻǵģ���������ʾ����ġ����⣬wParam�ĵ��������һϵ�е���꣬��춱�ʾ���󰴼���Shift��Ctrl����״̬��

�µ���Ѷ������wParam�ĸ����顣������һ����delta��ֵ����ֵĿǰ������120��-120����ȡ��춻��ֵ���ǰת����Ҳ����˵�������ǰ�棬�����а�ť����µ�һ�ˣ���������ת����ֵ120��-120��ʾ�ļ����ֱ����ϻ����¾������С�����Ĺ����ǣ�����汾�Ļ��������б����ڵĻ����������ȷ���ƶ��ٶ���Ѷ��������deltaֵ������40��-40��������WM_MOUSEWHEELѶϢ����Щֵ��ʹ�ļ�ֻ���ϻ����¾���һ�С�

Ϊʹ��ʽ����һ�㻯����ִ�У�SYSMETS����WM_CREATE��WM_SETTINGCHANGEѶϢ����ʱ����SPI_GETWHEELSCROLLLINES��Ϊ����������SystemParametersInfo����ֵ˵��WHEEL_DELTA��deltaֵ�����������У�WHEEL_DELTA��WINUSER.H�ж��塣WHEEL_DELTA���120�����ң����ڶ������SystemParametersInfo����3����������һ������ϵ��deltaֵ����40��SYSMETS����ֵ������iDeltaPerLine��

��WM_MOUSEWHEELѶϢ�����ڼ䣬SYSMETS��deltaֵ����̬����iAccumDelta��Ȼ�ᣬ���iAccumDelta��춻���iDeltaPerLine��������С춻���-iDeltaPerLin����SYSMETS��SB_LINEUP��SB_LINEDOWNֵ����WM_VSCROLLѶϢ�����ÿһ��WM_VSCROLLѶϢ��iAccumDelta��iDeltaPerLine���ӣ�����٣����˴�������deltaֵ��춡�С춻��춹���һ������Ҫ��deltaֵ��

���滹��
��

����һ������עĿ�Ļ������⣺�����Զ������αꡣ�ҽ��ڵ�ʮ�£�������Windows��Դһ�����۴����⡣