黄色伧理_ 装饰门户网
淘宝减肥药排行榜十强
只推淘宝安全有效的减肥药

当前位置:黄色伧理 > 减肥产品

黄色伧理

时间:2020-05-19 17:21  编辑:wendj

Windows API 一日一练(1)第一个应用程序 --------------------------------------------------------------- 3 Windows API 一日一练(2)使用应用程序句柄 ------------------------------------------------------------ 4 Windows API 一日一练(3)使用命令行参数 --------------------------------------------------------------- 6 Windows API 一日一练(4)MessageBox 函数 -------------------------------------------------------- 9 Windows API 一日一练(5)RegisterClass 和RegisterClassEx 函数--------------- 11 Windows API 一日一练(6)CreateWindow 函数 ------------------------------------------------- 14 Windows API 一日一练(7)ShowWindow 函数 --------------------------------------------------- 17 Windows API 一日一练(8)UpdateWindow 函数 ------------------------------------------------ 18 Windows API 一日一练(9)WindowProc 和DefWindowProc 函数----------------- 20 Windows API 一日一练(10)LoadAccelerators 函数------------------------------------------ 22 Windows API 一日一练(11)GetMessage 函数 ---------------------------------------------------- 24 Windows API 一日一练(12)TranslateAccelerator 函数----------------------------------- 26 Windows API 一日一练(13)TranslateMessage 函数 ---------------------------------------- 28 Windows API 一日一练(14)DispatchMessage 函数------------------------------------------ 30 Windows API 一日一练(15)PostQuitMessage 函数 ------------------------------------------ 32 Windows API 一日一练(16)BeginPaint 和EndPaint 函数 ------------------------------- 34 Windows API 一日一练(17)DialogBox 和DialogBoxParam 函数 ------------------ 36 Windows API 一日一练(18)EndDialog 函数 -------------------------------------------------------- 39 Windows API 一日一练(19)DestroyWindow 函数 -------------------------------------------- 40 Windows API 一日一练(20)LoadString 、LoadIcon 和LoadCursor 函数----- 42 Windows API 一日一练(21)SetWindowLongPtr 和GetWindowLongPtr 函数-------------------------------------------------------------------------------------------------------------------------------------- 45 Windows API 一日一练(23)SetTextColor 函数 -------------------------------------------------- 50 Windows API 一日一练(24)DrawText 函数--------------------------------------------------------- 52 Windows API 一日一练(25)CreateSolidBrush 函数------------------------------------------ 54 Windows API 一日一练(27)SetBkMode 函数------------------------------------------------------ 56 Windows API 一日一练(28)CreateFont 函数 ------------------------------------------------------ 59 Windows API 一日一练(29)SelectObject 和DeleteObject 函数 -------------------- 61 Windows API 一日一练(30)GetTextMetrics 函数 ---------------------------------------------- 63 Windows API 一日一练(31)MoveToEx 和LineTo 函数 ------------------------------------- 66 Windows API 一日一练(32)CreatePen 函数 ------------------------------------------------------- 66 Windows API 一日一练(33)ExtCreatePen 函数 ------------------------------------------------- 68 Windows API 一日一练(34)GetSysColor 函数---------------------------------------------------- 70 Windows API 一日一练(36)SetWindowText 函数--------------------------------------------- 72 Windows API 一日一练(37)MoveWindow 函数 ------------------------------------------------- 73 Windows API 一日一练(38)SetWindowPos 函数 ---------------------------------------------- 75 Windows API 一日一练(39)AnimateWindow 函数 ------------------------------------------- 77 Windows API 一日一练(40)CreateRectRgn 和CombineRgn 函数 ---------------- 79 Windows API 一日一练(41)FindWindowEx 函数----------------------------------------------- 80 Windows API 一日一练(42)CreateThread 函数 ------------------------------------------------- 82 Windows API 一日一练(43)WaitForSingleObject 函数 ----------------------------------- 84 Windows API 一日一练(44)wsprintf 函数 ----------------------------------------------------------- 87 Windows API 一日一练(45)CreateEvent 和SetEvent 函数 ----------------------------- 90 Windows API 一日一练(46)EnterCriticalSection 和LeaveCriticalSection 函

数 ---------------------------------------------------------------------------------------------------------------------------------- 94 Windows API 一日一练(47)CreateSemaphore 和ReleaseSemaphore 函数-------------------------------------------------------------------------------------------------------------------------------------- 96 Windows API 一日一练(48)PostThreadMessage 函数 ------------------------------------ 99 Windows API 一日一练(49)SetThreadPriority 和GetThreadPriority 函数-------------------------------------------------------------------------------------------------------------------------------------102 Windows API 一日一练(50)SuspendThread 和ResumeThread 函数 ---------103 Windows API 一日一练(51)CreateDirectory 和RemoveDirectory 函数 ----104 Windows API 一日一练(52)GetCurrentDirectory 和SetCurrentDirectory 函数 ---------------------------------------------------------------------------------------------------------------------------------106 Windows API 一日一练(53)CreateFile 函数-------------------------------------------------------107 Windows API 一日一练(54)WriteFile 和ReadFile 函数-----------------------------------109 Windows API 一日一练(55)FlushFileBuffers 和SetFilePointer 函数 ----------112 Windows API 一日一练(56)SetEndOfFile 和GetFileSizeEx 函数------------------114 Windows API 一日一练(57)CopyFile 和MoveFile 函数 -----------------------------------117 Windows API 一日一练(58)FindFirstFile 和FindNextFile 函数 --------------------119 Windows API 一日一练(59)CreateFileMapping 和MapViewOfFile 函数----122 Windows API 一日一练(60)CreateIoCompletionPort 和GetQueuedCompletionStatus 函数 --------------------------------------------------------------------124 Windows API 一日一练(61)GetDriveType 函数 ------------------------------------------------129 Windows API 一日一练(62)GetDiskFreeSpaceEx 函数 ----------------------------------131 Windows API 一日一练(63)RegOpenKeyEx 和RegCreateKeyEx 函数 -------132 Windows API 一日一练(64) RegSetValueEx 和RegDeleteValue 函数 -------135 Windows API 一日一练(65)RegQueryValueEx 函数 ---------------------------------------139 Windows API 一日一练(66)CreateWaitableTimer 和SetWaitableTimer 函数-------------------------------------------------------------------------------------------------------------------------------------141 Windows API 一日一练(67)SetTimer 和KillTimer 函数 ----------------------------------143 Windows API 一日一练(68)QueryPerformanceCounter 函数 ----------------------144 Windows API 一日一练(69)GetTickCount 函数 ------------------------------------------------146 Windows API 一日一练(70)GetSystemTime 和GetLocalTime 函数 ------------147 Windows API 一日一练(71)GetComputerName 函数 -------------------------------------148 Windows API 一日一练(72)GetUserName 函数------------------------------------------------150 Windows API 一日一练(73)GetVersionEx 函数 ------------------------------------------------151

Windows API 一日一练(1)第一个应用程序

要跟计算机进行交互,就需要计算机显示信息给人看到,或者发出声音给人听到,

然后人看到或听到相应的信息后,再输入其它信息给计算机,这样就可以让计算机进行数据处理,把结果显示给我们。现在就来编写一个最简单的Windows 应用程序,让它提示一行文字给我们看到,这就是简单的目标。 它实现的源程序和界面如下:

上面这个图,是从VC++ 2005里截出来的。这样可以看到源程序和显示的界面,很清楚地知道那些内容在那里显示,显示窗口里的标题是例子,就是MessageBox 里的字符串“例子”的显示。“第一个应用程序”也是那样显示出来的。第一个应用程序是非常简单的,下面再来详细地解说每行程序的作用。 源程序如下:

#001 // First.cpp : 应用程序入口文件 #002 // #003

#004 #include "stdafx.h" #005 #include "First.h" #006

#007 //

#008 //第一个例子。

#009 //蔡军生 2007/07/02

#010 //

#011 int APIENTRY _tWinMain(HINSTANCE hInstance, #012 HINSTANCE hPrevInstance, #013 LPTSTR lpCmdLine, #014 int nCmdShow) #015 {

#016 UNREFERENCED_PARAMETER(hPrevInstance); #017 UNREFERENCED_PARAMETER(lpCmdLine); #018 UNREFERENCED_PARAMETER(hInstance); #019 UNREFERENCED_PARAMETER(nCmdShow); #020

#021 //获取桌面的句柄。

#022 HWND hWnd = GetDesktopWindow();

#023

#024 //显示一行消息。

#025 ::MessageBox(hWnd, _T("第一个应用程序"), _T("例子"), MB_OK);

#026 #027 //

#028 return 0; #029 }

第4行是包含Windows 的API 头文件。在这个文件里包含一些系统的定义等。 第5行是包行C ++的头文件。

第11行是定义WinMain 的入口。

第16行到第19行是指明不生产这些参数不使用的警告。 第22行是获取桌面的句柄。 第25行是显示一个窗口提示信息。 第28行是返回程序出错码。

Windows API 一日一练(2)使用应用程序句柄

从上面这段程序就可以看到,_tWinMain 是应用程序的入口函数,这里是使用它的宏,定义在tchar.h 头文件里,为什么要这样作宏定义的呢?由于Windows 的应用程序要适应UNICODE 和以前单字符的应用程序,由于Windows 这两个API 的定义是不一样的,如下:

UNICODE 的定义:

#define _tWinMain wWinMain 单字符的定义:

#define _tWinMain WinMain

只要经过这样的宏定义后,就可以适应不同字符宽度的函数接口了。由于我是采用UNICODE 编译的,所以这里使用wWinMain 函数定义,下面再把它的定义找出来,如下: int

WINAPI wWinMain(

HINSTANCE hInstance,

HINSTANCE hPrevInstance, LPWSTR lpCmdLine,

int nShowCmd

);

这里要详细地解释一下函数wWinMain 的参数,它有四个参数。

hInstance 是当前应用程序的实例句柄,一般用来区分不同的资源使用。

hPrevInstance 是以前Win98使用的句柄,在Win2000以后的操作系统里都是空值NULL 。

lpCmdLine 是命令行参数,比如你在Windows 开始菜单里运行一个程序,并添加参数在后面,就会传递给应用程序,后面再详细讨论。

nShowCmd 是窗口的显示方式,比如最大化显示,最小化显示,还是正常显示。

Windows 运行程序时,是通过运行库里的启动代码来调用wWinMain 函数,它是在启动文件里如下调用:

#ifdef WPRFLAG

mainret = wWinMain( #else /* WPRFLAG */ mainret = WinMain( #endif /* WPRFLAG */

(HINSTANCE)&__ImageBase, NULL,

lpszCommandLine,

StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow

: SW_SHOWDEFAULT );

这就是操作系统传递给应用程序的值,现在就来演示使用第一个参数hInstance 。 请看下面的例子:

#001 #include "stdafx.h" #002 #include "First.h" #003

#004 //

#005 //第一个例子。

#006 //蔡军生 2007/07/03

#007 //

#008 int APIENTRY _tWinMain(HINSTANCE hInstance, #009 HINSTANCE hPrevInstance, #010 LPTSTR lpCmdLine, #011 int nCmdShow) #012 {

#013 UNREFERENCED_PARAMETER(hPrevInstance); #014 UNREFERENCED_PARAMETER(lpCmdLine); #015 UNREFERENCED_PARAMETER(nCmdShow); #016

#017 //使用应用程序句柄

#018 const int MAXSIZE_APPBUF = 256;

#019 TCHAR wAppTile[MAXSIZE_APPBUF];

#020 LoadString(hInstance,IDS_APP_TITLE,wAppTile,MAXSIZE_APPBUF);

#021

#022 //获取桌面的句柄。

#023 HWND hWnd = GetDesktopWindow(); #024

#025 //显示一行消息。

#026 MessageBox(hWnd, _T("第一个应用程序"), wAppTile, MB_OK); #027

#028 //

#029 return 0; #030 }

这个例子是在前面的基础上修改的,主要添加了使用应用程序实例句柄。在第19行里定义了一个保存应用程序标题的缓冲区,然后在第20行里调用函数LoadString 从应用程序的资源里加载字符串,它的第一个参数就使用到hInstance 句柄。因此应用程序句柄是表示程序在资源上唯一的标识符。

Windows API 一日一练(3)使用命令行参数

下面再接着练习使用命令行参数,先在VC2005调试设置里设置输入参数,如下图:

7

可以看到在Command Arguments里输入给程序传送的命令行参数(cmd1 cmd2 命

令行参数)。

接着修改原来的程序如下:

#001 int APIENTRY _tWinMain(HINSTANCE hInstance,

#002 HINSTANCE hPrevInstance,

#003 LPTSTR lpCmdLine,

#004 int nCmdShow)

#005 {

#006 UNREFERENCED_PARAMETER(hPrevInstance);

#007 UNREFERENCED_PARAMETER(nCmdShow);

#008

#009 //使用应用程序句柄

#010 const int MAXSIZE_APPBUF = 256;

#011 TCHAR wAppTile[MAXSIZE_APPBUF];

#012 ::LoadString(hInstance,IDS_APP_TITLE,wAppTile,MAXSIZE_APPB

UF);

#013

#014 //获取桌面的句柄。

#015 HWND hWnd = ::GetDesktopWindow(); #016

#017 //显示命令行参数。

#018 ::MessageBox(hWnd, lpCmdLine, wAppTile, MB_OK); #019

#020

#021 //显示一行消息。

#022 ::MessageBox(hWnd, _T("第一个应用程序"), wAppTile, MB_OK); #023 #024 // #025 return 0;

#026 } #027

在上面的程序里添加了第18行的代码,用来显示程序命令行的参数。它的显示结果如下:

这样就可以看到WinMain 两个参数的使用了。现在就使用了第一个API 函数WinMain 了,就是这么简单地就学会了使用第一个API 函数。

Windows API 一日一练(4)MessageBox 函数

为了显示提示信息给用户,Windows 是提供了一个非常方便的API 函数MessageBox 给用户使用,使用这个API 函数可以显示简单的文字信息出来,提醒或提示用户进行下一步操作。

函数声明如下: WINUSERAPI int

WINAPI

MessageBoxA(

__in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType); WINUSERAPI int

WINAPI

MessageBoxW(

__in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType);

#ifdef UNICODE

#define MessageBox MessageBoxW #else

#define MessageBox MessageBoxA #endif // !UNICODE

从上面可以看出,Windows 的API 是两种声明,一种是使用到ANSI 编码,一种是使用到UNICODE 编码的API 函数。通过宏定义把这两种API 名称统一到MessageBox 的声明。这是一种使用选择不同API 的技术,在今后的编程里,大多数都需要使用UNICODE 编码了,因为可以适应不同国家的语言显示,可以国际化编程,特别对于中文支持更加需要UNICODE 编程。

下面来解释一下参数的定义:

hWnd 是指向父窗口的句柄,如果没有父窗口,可以把这个参数设置为NULL 。

lpText 是需要显示的文字。显示字符串的起始地址。 lpCaption 是在窗口上标题显示。

uType 是窗口组合按钮和显示图标的类型。后面再详细说明。

返回值是一个整数,如果有取消按钮,并且按下ESC 键就返回IDCANCEL 。如果有其它按钮,并且按下,就返回相应的值。主要的值如下:

IDABORT 放弃按钮

IDCANCEL 取消按钮 IDCONTINUE 继续按钮 IDIGNORE 忽略按钮 IDNO 否按钮

10

IDOK 确定按钮

IDRETRY 重试按钮

IDTRYAGAIN 重试按钮

IDYES 是按钮

演示例子如下:

上面显示的代码是:

#001 //MB_DEFBUTTON4

#002 int CMsgBox::Show_MB_DEFBUTTON4(void)

#003 {

#004 //显示MB_DEFBUTTON4。

#005 r eturn ::MessageBox(NULL, _T("MB_YESNOCAN CEL|MB_DEFBUTTON4|MB_HELP"),

#006 _T("第一个应用程序"), MB_YESNOCAN CEL|MB_DEFBUTTON4|MB_HELP|MB_ICON QUESTION); #007 }

uType常用的选择值如下:

按钮类型:

MB_ABORTRETRYIGNORE MB_CANCELTRYCONTINUE MB_HELP MB_OK

MB_OKCANCEL MB_RETRYCANCEL MB_YESNO

MB_YESNOCANCEL

图标类型:

MB_ICONEXCLAMATION MB_ICONWARNING

MB_ICONINFORMATION MB_ICONASTERISK MB_ICONQUESTION MB_ICONSTOP MB_ICONERROR MB_ICONHAND

设置缺省按钮值: MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 MB_DEFBUTTON4

修改显示信息窗口的属性: MB_APPLMODAL MB_SYSTEMMODAL MB_TASKMODAL MB_RIGHT MB_RTLREADING MB_SETFOREGROUND MB_TOPMOST

MB_SERVICE_NOTIFICATION

Windows API 一日一练(5)RegisterClass 和RegisterClassEx 函数

为了可以创建自己的窗口,就需要向Windows 操作系统注册窗口类型,以便后面创建窗口时调用。当然,如果使用Windows 预先注册的窗口是不需要注册的。

函数声明如下:

#if(WINVER >= 0x0400)

WINUSERAPI

ATOM WINAPI

RegisterClassExA(

__in CONST WNDCLASSEXA *); WINUSERAPI ATOM

WINAPI

RegisterClassExW(

__in CONST WNDCLASSEXW *); #ifdef UNICODE

#define RegisterClassEx RegisterClassExW #else

#define RegisterClassEx RegisterClassExA #endif // !UNICODE

函数的输入参数是一个WNDCLASSEXA 或WNDCLASSEXW 的指针。这里主要介绍UNICODE 版本的函数定义,WNDCLASSEXW 的结构定义如下: typedef struct tagWNDCLASSEXW { UINT cbSize; /* Win 3.x */ UINT style;

WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon;

HCURSOR hCursor;

HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; /* Win 4.0 */

HICON hIconSm;

} WNDCLASSEXW, *PWNDCLASSEXW, NEAR *NPWNDCLASSEXW, FAR *LPWNDCLASSEXW;

cbSize 是本结构的字节大小,一般设置为sizeof(WNDCLASSEXW); style 是窗口类型。

lpfnWndProc 是窗口处理消息的回调函数。 cbClsExtra 是窗口类型的扩展。 cbWndExtra 是窗口实例的扩展。 hInstance 是窗口实例句柄。 hIcon 是窗口图标。

hCursor 是窗口的光标。

hbrBackground 是窗口背景颜色。 lpszMenuName 是窗口菜单名称。 lpszClassName 是窗口类型的名称。 hIconSm 是窗口小图标。

调用这个函数的实例如下:

#001 //

#002 // 函数: MyRegisterClass() #003 //

#004 // 目的: 注册一个窗口类型. #005 //

#006 // 蔡军生 2007/07/12

#007 //

#008 ATOM MyRegisterClass(HINSTANCE hInstance) #009 {

#010 WNDCLASSEX wcex;

#011

#012 wcex.cbSize = sizeof(WNDCLASSEX); #013

#014 wcex.style = CS_HREDRAW | CS_VREDRAW; #015 wcex.lpfnWndProc = WndProc; #016 wcex.cbClsExtra = 0;

#017 wcex.cbWndExtra = 0;

#018 wcex.hInstance = hInstance;

#019 wcex.hIcon = LoadIcon(hInstance,

MAKEINTRESOURCE(IDI_TESTWIN));

#020 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

#021 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

#022 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TESTWIN); #023 wcex.lpszClassName = szWindowClass;

#024 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); #025

#026 return RegisterClassEx(&wcex); #027 }

第10行定义一个窗口结构的对象wcex 。 第12行设置窗口结构的大小。 第14行设置窗口类型。

第15行设置窗口消息处理函数WndProc 。 第16行设置窗口类型的扩展为空。 第17行设置窗口实例的扩展为空。

第18行设置窗口当前实例句柄hInstance 。 第19行设置窗口图标。

第20行设置光标为箭头。

第21行设置窗口背景颜色为白色。 第22行设置窗口菜单。

第23行设置窗口类型名称。 第24行设置窗口小图标。

第26行是调用函数RegisterClassEx 注册这个窗口类型。

如果注册成功,返回这个窗口类型的标识号,可以用标识号进行创建窗口,查找窗口和注销窗口类型等等。如果失败返回的值是空,因此可以通过检查返回值为判断是否调用成功。

Windows API 一日一练(6)CreateWindow 函数

一个窗口要显示,先要把它创建出来。那就需要调用API 函数CreateWindow 了,所以在注册窗口后的第二步,就需要调用创建窗口函数。

函数声明如下: WINUSERAPI HWND WINAPI

CreateWindowExA(

__in DWORD dwExStyle,

__in_opt LPCSTR lpClassName, __in_opt LPCSTR lpWindowName, __in DWORD dwStyle, __in int X, __in int Y, __in int nWidth, __in int nHeight,

__in_opt HWND hWndParent, __in_opt HMENU hMenu,

__in_opt HINSTANCE hInstance, __in_opt LPVOID lpParam); WINUSERAPI HWND WINAPI

CreateWindowExW(

__in DWORD dwExStyle,

__in_opt LPCWSTR lpClassName, __in_opt LPCWSTR lpWindowName, __in DWORD dwStyle, __in int X, __in int Y,

__in int nWidth,

__in int nHeight,

__in_opt HWND hWndParent, __in_opt HMENU hMenu,

__in_opt HINSTANCE hInstance, __in_opt LPVOID lpParam); #ifdef UNICODE

#define CreateWindowEx CreateWindowExW #else

#define CreateWindowEx CreateWindowExA #endif // !UNICODE

#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\ nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\

CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y,\ nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)

#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\ nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\

CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y,\ nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) #ifdef UNICODE

#define CreateWindow CreateWindowW #else

#define CreateWindow CreateWindowA #endif // !UNICODE

dwExStyle 是扩展的窗口类型。

lpClassName 是注册的窗口类型名称。 lpWindowName 是窗口名称。 dwStyle 是窗口类型。 X 是窗口左上角位置。 Y 是窗口左上角位置。 nWidth 是窗口的宽度。 nHeight 是窗口的高度。 hWndParent 是父窗口。

hMenu 是主菜单。

hInstance 是应用程序实例句柄。 lpParam 是传送给窗口的自定义参数。

调用这个函数的实例如下:

#001 //

#002 // 函数: InitInstance(HINSTANCE, int) #003 //

#004 // 目的: 保存程序实例句柄,并创建窗口显示。 #005 //

#006 // 蔡军生 2007/07/12

#007 //

#008 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) #009 {

#010 HWND hWnd;

#011

#012 hInst = hInstance; // 保存实例句柄到全局变量里。 #013

#014 hWnd = CreateWindow(szWindowClass, #015 szTitle,

#016 WS_OVERLAPPEDWINDOW, #017 CW_USEDEFAULT, #018 0,

#019 CW_USEDEFAULT, #020 0,

#021 NULL, #022 NULL,

#023 hInstance, #024 NULL); #025

#026 if (!hWnd) #027 {

#028 return FALSE; #029 } #030

#031 ShowWindow(hWnd, nCmdShow); #032 UpdateWindow(hWnd); #033

#034 return TRUE;

#035 }

第14行里就是调用创建窗口函数。szWindowClass 是窗口注册名称,前面已经介绍过注册的。

第15行的szTitle 是窗口显示的标题。 第16行是窗口显示类型。

第17行是缺省的左上角坐标。 第18行是窗口左上角坐标,由于X 坐标设置为缺省的坐标了,所以会忽略这里的所有设置的值。

第19行是设置窗口的宽度。使用缺省值。 第20行同样忽略窗口的高度。 第21行是没有父窗口。 第22行是没有主菜单。 第23行是窗口当前实例句柄。

第24行是传递给窗口的自定义参数为空。

如果窗口创建成功就会返回这个窗口的句柄,否则返回空值。

通过这样设置,就可以创建各种各样的窗口,只要你自己喜欢的,就可以改变它。

Windows API 一日一练(7)ShowWindow 函数

ShowWindow 的API 函数是显示窗口,但它在第一次调用和以后的调用是有区别的。第一次调用时,它的输入参数nCmdShow 是需要输入WinMain 函数里传入来的nCmdShow 参数,而不能是其它参数。

函数声明如下: WINUSERAPI BOOL

WINAPI

ShowWindow(

__in HWND hWnd, __in int nCmdShow); hWnd 是窗口的句柄。

nCmdShow 是窗口显示的状态。可能设置的值如下:

SW_FORCEMINIMIZE 是强制窗口最小化,主要使用在非窗口主线程的其它线程来操作。 SW_HIDE 是显示窗口为隐藏状态。 SW_MAXIMIZE 是显示窗口为最大化。 SW_MINIMIZE 是显示窗口为最小化。

SW_RESTORE 是从任务里恢复窗口显示。

SW_SHOW 是激活窗口为当前窗口,并且显示为当前的大小和位置。 SW_SHOWDEFAULT 是创建进程时显示窗口的值。

SW_SHOWMAXIMIZED 是激活窗口为当前窗口,并且显示最大化。 SW_SHOWMINIMIZED 是激活窗口为当前窗口,并且显示最小化。

SW_SHOWMINNOACTIVE 是显示窗口为最小化,但不激活它作为当前窗口。 SW_SHOWNA 是显示为当前的大小和位置,但不激活它作为当前窗口。

SW_SHOWNOACTIVATE 是显示当前窗口,但不激活它作为当前窗口。

SW_SHOWNORMAL 是显示当前窗口,但窗口是最小化或最大化时会恢复窗口为原来的大小和位置。

调用这个函数的实例如下:

#001 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) #002 {

#003 HWND hWnd; #004

#005 hInst = hInstance; // 保存实例句柄到全局变量里。 #006

#007 hWnd = CreateWindow(szWindowClass, #008 szTitle,

#009 WS_OVERLAPPEDWINDOW, #010 CW_USEDEFAULT,

#011 0,

#012 CW_USEDEFAULT, #013 0,

#014 NULL, #015 NULL, #016 hInstance, #017 NULL); #018

#019 if (!hWnd)

#020 {

#021 return FALSE; #022 }

#023

#024 ShowWindow(hWnd, nCmdShow); #025 UpdateWindow(hWnd); #026

#027 //

#028 //蔡军生 2007/07/14 #029 //显示窗口测试。

#030 MessageBox(NULL,_T("最大化"),_T("测试"),MB_OK); #031

#032 //显示窗口为最大化。

#033 ShowWindow(hWnd, SW_SHOWMAXIMIZED); #034 #035

#036 MessageBox(NULL,_T("原来位置"),_T("测试"),MB_OK); #037

#038 //显示窗口为原来位置。

#039 ShowWindow(hWnd, SW_SHOWNORMAL); #040 #041

#042 return TRUE; #043 }

在第24行里先调用这个函数显示创建进程的窗口状态。 第33行里显示窗口为最大化。 第39行里显示窗口为原来的状态。

这样就可以掌握了ShowWindow 函数的使用。

Windows API 一日一练(8)UpdateWindow 函数

UpdateWindow 函数是更新窗口的客户区,主要通过发送WM_PAINT 消息来实现的。

函数声明如下: WINUSERAPI BOOL WINAPI

UpdateWindow(

__in HWND hWnd);

hWnd 是要更新窗口客户区的窗口句柄。

调用这个函数的实例如下:

#001 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) #002 {

#003 HWND hWnd;

#004

#005 hInst = hInstance; // 保存实例句柄到全局变量里。 #006

#007 hWnd = CreateWindow(szWindowClass, #008 szTitle,

#009 WS_OVERLAPPEDWINDOW, #010 CW_USEDEFAULT, #011 0,

#012 CW_USEDEFAULT, #013 0,

#014 NULL, #015 NULL,

#016 hInstance, #017 NULL); #018

#019 if (!hWnd) #020 {

#021 return FALSE; #022 } #023

#024 ShowWindow(hWnd, nCmdShow); #025 UpdateWindow(hWnd);

#026 #027 //

#028 //蔡军生 2007/07/14 #029 //显示窗口测试。

#039 ShowWindow(hWnd, SW_SHOWNORMAL); #040 #041

#042 return TRUE;

#043 }

第25行就是调用UpdateWindow 函数来更新窗口的客户区。

一般创建窗口之后都需要调用UpdateWindow 函数来更新窗口客户区的显示,否则是乱糟糟。

Windows API 一日一练(9)WindowProc 和DefWindowProc 函数

在Windows 操作系统里,当窗口显示之后,它就可以接收到系统源源不断地发过来的消息,然后窗口就需要处理这些消息,因此就需要一个函数来处理这些消息。在API 里定义了一个函数为回调函数,当系统需要向窗口发送消息时,就会调用窗口给出的回调函数WindowProc ,如果WindowProc 函数不处理这个消息,就可以把它转向DefWindowProc 函数来处理,这是系统的默认消息处理函数。当你按下菜单,或者点击窗口时,窗口需要运行这个消息处理函数。 函数WindowProc 声明如下:

LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg,

WPARAM wParam, LPARAM lParam );

hwnd 是当前窗口的句柄。 uMsg 是系统发过来的消息。 wParam 是消息参数。 lParam 是消息参数。

这个函数一定是静态函数,也就是全局函数,在编译时已经确定了地址。由于它需要设置在注册的窗口类型里,如下:

#008 ATOM MyRegisterClass(HINSTANCE hInstance) #009 {

#010 WNDCLASSEX wcex; #011

#012 wcex.cbSize = sizeof(WNDCLASSEX); #013

#014 wcex.style = CS_HREDRAW | CS_VREDRAW; #015 wcex.lpfnWndProc = WndProc; 第15行就是设置窗口的消息处理函数。

函数DefWindowProc 声明如下:

LRESULT DefWindowProc( HWND hWnd, UINT Msg,

WPARAM wParam, LPARAM lParam

);

这个函数参数跟上面那个函数是一样的。 只不过,它是处理所有默认的消息。

调用这两个函数的实例如下:

#001 //

#002 // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) #003 //

#004 // 目的: 处理主窗口的消息. #005 //

#006 // 蔡军生 2007/07/12

#007 //

#008 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) #009 {

#010 int wmId, wmEvent; #011 PAINTSTRUCT ps; #012 HDC hdc; #013

#014 switch (message) #015 {

#016 case WM_COMMAND:

#017 wmId = LOWORD(wParam); #018 wmEvent = HIWORD(wParam); #019 // 菜单选项命令响应: #020 switch (wmId) #021 {

#022 case IDM_ABOUT:

#023 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

#024 break;

#025 case IDM_EXIT:

#026 DestroyWindow(hWnd); #027 break; #028 default:

#029 return DefWindowProc(hWnd, message, wParam, lParam); #030 }

#031 break;

#032 case WM_PAINT:

#033 hdc = BeginPaint(hWnd, &ps); #034 //

#035 EndPaint(hWnd, &ps); #036 break;

#037 case WM_DESTROY: #038 PostQuitMessage(0); #039 break;

#040 default:

#041 return DefWindowProc(hWnd, message, wParam, lParam); #042 }

#043 return 0;

#044 }

第8行定义消息处理函数

第14行开始根据不同的消息作处理。

第29行和第41行都是调用DefWindowProc 函数来处理未处理的消息。

有了窗口消息处理函数,就可以响应不同的消息,实现各种各样的功能。

Windows API 一日一练(10)LoadAccelerators 函数

当用户使用软件时,往往有些功能是最常用的功能。作为开发人员,就需要让用户感觉到这个软件好用,这样就需要把他们最常用的功能用起来最方便,最快捷,能提高生产效率。在这方面,微软是做到家了,比如在键盘上有一个Windows 键,Windows 很多功能都可以通过这个键与其它键来组合成快捷键,提高使用的方便性。现在就来介绍一下怎么样让你的程序也方便使用,就是使用快捷键。 函数LoadAccelerators 声明如下: WINUSERAPI HACCEL WINAPI

LoadAcceleratorsA(

__in_opt HINSTANCE hInstance, __in LPCSTR lpTableName); WINUSERAPI HACCEL

WINAPI

LoadAcceleratorsW(

__in_opt HINSTANCE hInstance, __in LPCWSTR lpTableName); #ifdef UNICODE

#define LoadAccelerators LoadAcceleratorsW #else

#define LoadAccelerators LoadAcceleratorsA #endif // !UNICODE

hInstance 是应用程序实例句柄,用来从程序的资源文件里查找到快捷键定义。 lpTableName 是快捷键的定义表格。

调用这个函数的实例如下: #001 //主程序入口

#002 //

#003 // 蔡军生 2007/07/12

#004 //

#005 int APIENTRY _tWinMain(HINSTANCE hInstance, #006 HINSTANCE hPrevInstance, #007 LPTSTR lpCmdLine, #008 int nCmdShow)

#009 {

#010 UNREFERENCED_PARAMETER(hPrevInstance); #011 UNREFERENCED_PARAMETER(lpCmdLine); #012

#013 //

#014 MSG msg;

#015 HACCEL hAccelTable; #016

#017 // 加载全局字符串。

#018 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); #019 LoadString(hInstance, IDC_TESTWIN, szWindowClass, MAX_LOADSTRING);

#020 MyRegisterClass(hInstance); #021

#022 // 应用程序初始化:

#023 if (!InitInstance (hInstance, nCmdShow)) #024 {

#025 return FALSE; #026 } #027

#028 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN)); #029

#030 // 消息循环:

#031 while (GetMessage(&msg, NULL, 0, 0)) #032 {

#033 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) #034 {

#035 TranslateMessage(&msg); #036 DispatchMessage(&msg); #037 } #038 }

#039

#040 return (int) msg.wParam; #041 }

第28行就是调用函数LoadAccelerators 从资源里加载快捷键。

到这里,就已经了解和使用LoadAccelerators 函数了。但还有一个问题,就是快捷键的资源是怎么样定义的呢?问得好,下面就带你看一下它的定义:

#001 ///////////////////////////////////////////////////////////////////////////// #002 //

#003 // Accelerator #004 //

#005

#006 IDC_TESTWIN ACCELERATORS

#007 BEGIN

#008 "?", IDM_ABOUT, ASCII, ALT #009 "/", IDM_ABOUT, ASCII, ALT #010 END #011

这是从资源文件TestWin.rc 里拷贝出来的。IDC_TESTWIN 是快捷键表的名称,ACCELERATORS 是快捷键定义的关键字,BEGIN 是表示快捷键的开始,END 是表示快捷键的结束。

下面快捷键定义语法:

acctablename ACCELERATORS [optional-statements] {event, idvalue, [type] [options]... }

[optional-statements]是可选的选项。

event 是必须有的内容,它是定义的键码,或者键的ASCII 码。 idvalue 是快捷键响应的ID 命令。

type 是类型选择。

上面第8行和第9行里就是设置ALT+…?‟或者ALT + …/‟作为快捷键,当用户按下ALT+…?‟或者ALT + …/‟时就会弹出关于对话框。

Windows API 一日一练(11)GetMessage 函数

应用程序为了获取源源不断的消息,就需要调用函数GetMessage 来实现,因为所有在窗口上的输入消息,都会放到应用程序的消息队列里,然后再发送给窗口回调函数处理。 函数GetMessage 声明如下: WINUSERAPI BOOL WINAPI

GetMessageA(

__out LPMSG lpMsg,

__in_opt HWND hWnd, __in UINT wMsgFilterMin, __in UINT wMsgFilterMax); WINUSERAPI BOOL WINAPI GetMessageW(

__out LPMSG lpMsg, __in_opt HWND hWnd, __in UINT wMsgFilterMin, __in UINT wMsgFilterMax); #ifdef UNICODE

#define GetMessage GetMessageW #else

#define GetMessage GetMessageA #endif // !UNICODE

lpMsg 是从线程消息队列里获取到的消息指针。

hWnd 是想获取那个窗口的消息,当设置为NULL 时是获取所有窗口的消息。 wMsgFilterMin 是获取消息的ID 编号最小值,如果小于这个值就不获取回来。 wMsgFilterMax 是获取消息的ID 编号最大值,如果大于这个值就不获取回来。 函数返回值可能是0,大于0,或者等于-1。如果成功获取一条非WM_QUIT 消息时,就返回大于0的值;如果获取WM_QUIT 消息时,就返回值0值。如果出错就返回-1的值。

调用这个函数的例子如下: #001 //主程序入口

#002 //

#003 // 蔡军生 2007/07/19 #004 // QQ: 9073204 #005 //

#006 int APIENTRY _tWinMain(HINSTANCE hInstance, #007 HINSTANCE hPrevInstance, #008 LPTSTR lpCmdLine, #009 int nCmdShow) #010 {

#011 UNREFERENCED_PARAMETER(hPrevInstance); #012 UNREFERENCED_PARAMETER(lpCmdLine); #013 #014 //

#015 MSG msg;

#016 HACCEL hAccelTable; #017

#018 // 加载全局字符串。

#019 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

#020 LoadString(hInstance, IDC_TESTWIN, szWindowClass, MAX_LOADSTRING);

#021 MyRegisterClass(hInstance); #022

#023 // 应用程序初始化:

#024 if (!InitInstance (hInstance, nCmdShow)) #025 {

#026 return FALSE; #027 }

#028

#029 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN)); #030

#031 // 消息循环:

#032 BOOL bRet;

#033 while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0) #034 {

#035 if (bRet == -1) #036 {

#037 //处理出错。 #038

#039 }

#040 else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) #041 {

#042 TranslateMessage(&msg); #043 DispatchMessage(&msg); #044 } #045 } #046

#047 return (int) msg.wParam; #048 } #049

第33行就是获取所有窗口的消息回来。

Windows API 一日一练(12)TranslateAccelerator 函数

当应用程序运行时,用户按下快捷键,这样就产生了一个按键消息,那么Windows 是怎么样把它转化为快捷键响应的消息呢?这就需要使用TranslateAccelerator 函数。

TranslateAccelerator 函数主要的作用就是把消息跟快捷键表里定义的按键进行比较,如果发现有快捷键,就会把这个按键消息转换为WM_COMMAND 或者WM_SYSCOMMAND 消息给窗口的消息处理函数发送过去。 函数TranslateAccelerator 声明如下: WINUSERAPI

int

WINAPI

TranslateAcceleratorA( __in HWND hWnd,

__in HACCEL hAccTable, __in LPMSG lpMsg); WINUSERAPI int

WINAPI

TranslateAcceleratorW( __in HWND hWnd, __in HACCEL hAccTable, __in LPMSG lpMsg); #ifdef UNICODE

#define TranslateAccelerator TranslateAcceleratorW #else

#define TranslateAccelerator TranslateAcceleratorA #endif // !UNICODE hWnd 是窗口句柄。

hAccTable 是快捷键定义表。 lpMsg 是当前消息。

如果函数调用成功就返回非0值。如果失败就返回0值。 #038

#039 }

#040 else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

#041 {

#042 TranslateMessage(&msg); #043 DispatchMessage(&msg); #044 } #045 }

#046

#047 return (int) msg.wParam; #048 } #049

第40行就是调用函数TranslateAccelerator 来处理快捷键,并转换为命令消息发送出去。

Windows API 一日一练(13)TranslateMessage 函数

TranslateMessage 是用来把虚拟键消息转换为字符消息。由于Windows 对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。

TranslateMessage 函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage 函数时被取出。当我们敲击键盘上的某个字符

键时,系统将产生WM_KEYDOWN 和WM_KEYUP 消息。这两个消息的附加参数(wParam 和lParam )包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII 码,TranslateMessage 这个函数就可以将WM_KEYDOWN 和WM_ KEYUP 消息的组合转换为一条WM_CHAR 消息(该消息的wParam 附加参数包含了字符的ASCII 码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage 函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。

也就是说TranslateMessage 会发现消息里是否有字符键的消息,如果有字符键的消息,就会产生WM_CHAR 消息,如果没有就会产生什么消息。

函数TranslateMessage 声明如下: WINUSERAPI BOOL

WINAPI

TranslateMessage(

__in CONST MSG *lpMsg); lpMsg 是检查需要转换的消息。

调用这个函数的例子如下: #001 //主程序入口

#002 //

#003 // 蔡军生 2007/07/19 #004 // QQ: 9073204

#005 //

#006 int APIENTRY _tWinMain(HINSTANCE hInstance, #007 HINSTANCE hPrevInstance, #008 LPTSTR lpCmdLine, #009 int nCmdShow)

#010 {

#011 UNREFERENCED_PARAMETER(hPrevInstance); #012 UNREFERENCED_PARAMETER(lpCmdLine); #013 #014 //

#015 MSG msg;

#016 HACCEL hAccelTable; #017

#018 // 加载全局字符串。

#019 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); #020 LoadString(hInstance, IDC_TESTWIN, szWindowClass, MAX_LOADSTRING);

#021 MyRegisterClass(hInstance); #022

#023 // 应用程序初始化:

#024 if (!InitInstance (hInstance, nCmdShow)) #025 {

#026 return FALSE;

#027 } #028

#029 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN)); #030

#031 // 消息循环:

#032 BOOL bRet;

#033 while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0) #034 {

#035 if (bRet == -1) #036 {

#037 //处理出错。 #038

#039 }

#040 else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) #041 {

#042 TranslateMessage(&msg); #043 DispatchMessage(&msg); #044 } #045 } #046

#047 return (int) msg.wParam; #048 } #049

第42行是调用函数TranslateMessage 作消息转换工作。

Windows API 一日一练(14)DispatchMessage 函数

前面已经介绍从系统队列里获取一条消息,然后经过快捷键的函数检查,又通过字符消息函数的转换,最后要做的事情就是调用DispatchMessage 函数,它的意思就是说要把这条消息发送到窗口里的消息处理函数WindowProc 。

函数DispatchMessage 声明如下: WINUSERAPI LRESULT WINAPI

DispatchMessageA(

__in CONST MSG *lpMsg); WINUSERAPI LRESULT WINAPI

DispatchMessageW(

__in CONST MSG *lpMsg); #ifdef UNICODE

#define DispatchMessage DispatchMessageW #else

#define DispatchMessage DispatchMessageA #endif // !UNICODE

lpMsg 是指向想向消息处理函数WindowProc 发送的消息。

调用这个函数的例子如下: #001 //主程序入口

#002 //

#003 // 蔡军生 2007/07/19 #004 // QQ: 9073204 #005 //

#006 int APIENTRY _tWinMain(HINSTANCE hInstance, #007 HINSTANCE hPrevInstance, #008 LPTSTR lpCmdLine, #009 int nCmdShow)

#010 {

#011 UNREFERENCED_PARAMETER(hPrevInstance); #012 UNREFERENCED_PARAMETER(lpCmdLine); #013 #014 //

#015 MSG msg;

#016 HACCEL hAccelTable; #017

#018 // 加载全局字符串。

#019 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); #020 LoadString(hInstance, IDC_TESTWIN, szWindowClass, MAX_LOADSTRING);

#021 MyRegisterClass(hInstance); #022

#023 // 应用程序初始化:

#024 if (!InitInstance (hInstance, nCmdShow)) #025 {

#026 return FALSE; #027 } #028

#029 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN)); #030

#031 // 消息循环:

#032 BOOL bRet;

#033 while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0) #034 {

#035 if (bRet == -1) #036 {

#037 //处理出错。 #038

#039 }

#040 else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) #041 {

#042 TranslateMessage(&msg); #043 DispatchMessage(&msg); #044 } #045 }

#046

#047 return (int) msg.wParam; #048 } #049

第43行就是调用函数DispatchMessage 发送消息。

Windows API 一日一练(15)PostQuitMessage 函数

自然界面里,各种生物都是有其生命周期的。程序也是有其生命周期的,创建时就是它出生了,当它运行工作中就是成年期,最后少不了要死亡的,那么程序的死亡是怎么样出现的呢?像以前介绍函数GetMessage 里是使用一个循环不断地检测消息,周止复始的,是不可能出现死亡的,但它会检测到消息WM_QUIT 就退出来。那现在问题是谁发送WM_QUIT 消息出来呢?这就是PostQuitMessage 函数所做的工作。当你点击窗口右上角的关闭时,Windows 就会把窗口从系统里删除,这时就会发出消息WM_DESTROY 给窗口消息处理函数WindowProc ,WindowProc 收到这条消息后,最需要做的一件事情就是调用PostQuitMessage 发出退出消息,让消息循环结束。

函数PostQuitMessage 声明如下: WINUSERAPI VOID

WINAPI

PostQuitMessage(

__in int nExitCode);

nExitCode 是退出标识码,它被放到WM_QUIT 消息的参数wParam 里。

调用这个函数的例子如下: #001 //

#002 // 目的: 处理主窗口的消息.

#003 //

#004 // 蔡军生 2007/07/12 QQ:9073204

#005 //

#006 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) #007 {

#008 int wmId, wmEvent; #009 PAINTSTRUCT ps; #010 HDC hdc;

#011

#012 switch (message) #013 {

#014 case WM_COMMAND:

#015 wmId = LOWORD(wParam); #016 wmEvent = HIWORD(wParam); #017 // 菜单选项命令响应:

#018 switch (wmId) #019 {

#020 case IDM_ABOUT:

#021 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

#022 break;

#023 case IDM_EXIT:

#024 DestroyWindow(hWnd); #025 break;

#026 default:

#027 return DefWindowProc(hWnd, message, wParam, lParam); #028 }

#029 break;

#030 case WM_PAINT:

#031 hdc = BeginPaint(hWnd, &ps); #032 //

#033 EndPaint(hWnd, &ps); #034 break;

#035 case WM_DESTROY:

#036 PostQuitMessage(0);

#037 break; #038 default:

#039 return DefWindowProc(hWnd, message, wParam, lParam); #040 }

#041 return 0; #042 }

第36行就是调用函数PostQuitMessage 来处理退出应用程序。

Windows API 一日一练(16)BeginPaint 和EndPaint 函数

当人们使用软件时,大多数是想看到自己所需要的结果,比如玩RPG 游戏,就是想看到自己所操作的主角做各种各样的事情。在2D 的RPG 游戏里,其实做的事情,就是不断地更新画面,也就是不断地显示BMP 的图片。在普通的程序里,大多也是显示各种文本和图片的,但是有一种类型的应用程序是不怎么显示结果的,那就是服务程序。不管怎么样,只要我们想看到程序所执行后的结果,就需要在程序里显示出来。也就是需要调用BeginPaint 和EndPaint 函数。BeginPaint 函数的作用是告诉Windows 系统,要开始向显示卡输出内容了,把这次显示的操作请求放到系统显示队列里。由于系统上的显示卡往往只有一个,那么这种资源是独占的,所以操作系统会让显示操作线性化,保证每个窗口的显示是独立进行的,而不是A 窗口显示一部份,或者B 窗口显示一部份,而是A 窗口显示完成后再让B 窗口显示。因此,BeginPaint 函数就是跟操作系统说,我需要显示了,你安排好吧。当BeginPaint 返回时,就获取到系统的显示资源句柄,这样就可以调GDI 一大堆函数来操作了。显示完成后,一定要记得调用函数EndPaint ,因为使用BeginPaint 函数请求了独占的显示资源后,如果不释放回去,就会让其它程序永远获取不到显示资源了,这样系统就死锁了。如果你有空仔细地查看一下Windows 源程序,就会发现BeginPaint 函数和

EndPaint 函数怎样构成的。比如在调用BeginPaint 函数时先把光标隐藏起来,接着再显示用户显示的东西,最后调用EndPaint 函数后,又把隐藏的光标显示出来。

函数BeginPaint 函数和EndPaint 函数声明如下: WINUSERAPI HDC WINAPI

BeginPaint(

__in HWND hWnd,

__out LPPAINTSTRUCT lpPaint);

WINUSERAPI BOOL WINAPI

EndPaint(

__in HWND hWnd,

__in CONST PAINTSTRUCT *lpPaint); hWnd 是窗口句柄。

lpPaint 是获取显示参数。它的结构定义如下: typedef struct tagPAINTSTRUCT { HDC hdc;

BOOL fErase; RECT rcPaint; BOOL fRestore;

BOOL fIncUpdate;

BYTE rgbReserved[32];

} PAINTSTRUCT, *PPAINTSTRUCT; hdc 是获取设备句柄。

fErase 是否擦新背景。

rcPaint 是显示的窗口大小。

fRestore 、fIncUpdate 、rgbReserved 是保留使用的参数。

BeginPaint 函数的返回值也是显示设备的句柄。

调用这个函数的例子如下: #001 //

#002 // 目的: 处理主窗口的消息.

#003 //

#004 // 蔡军生 2007/07/12 QQ:9073204 #005 //

#006 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) #007 {

#008 int wmId, wmEvent; #009 PAINTSTRUCT ps; #010 HDC hdc;

#011

#012 switch (message)

#013 {

#014 case WM_COMMAND:

#015 wmId = LOWORD(wParam); #016 wmEvent = HIWORD(wParam); #017 // 菜单选项命令响应: #018 switch (wmId) #019 {

#020 case IDM_ABOUT:

#021 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

#022 break;

#023 case IDM_EXIT:

#024 DestroyWindow(hWnd); #025 break;

#026 default:

#027 return DefWindowProc(hWnd, message, wParam, lParam); #028 }

#029 break; #030 case WM_PAINT:

#031 hdc = BeginPaint(hWnd, &ps); #032 //

#033 EndPaint(hWnd, &ps);

#034 break;

#035 case WM_DESTROY:

#036 PostQuitMessage(0); #037 break; #038 default:

#039 return DefWindowProc(hWnd, message, wParam, lParam); #040 }

#041 return 0; #042 }

第31行调用函数BeginPaint 。 第33行调用函数EndPaint 。

Windows API 一日一练(17)DialogBox 和DialogBoxParam 函数

对话框是比较常用的窗口,比如当你想让用户输入一些参数时就可以使用对话框。或者提示一些警告的信息,都是可以使用对话框的。比如当你拷贝文件时,Windows 就会提示一个拷贝文件的进度对话框。对话框的使用范围比较广,并且它在设计时就可以看到运行的结果模样,这样方便设计。但对话框又分为两类,一种对话框运行后,一定要用户关闭那个对话框后才能返回到父窗口;一种对话框是不需要关闭后就可以直接返回父窗口。因此,软件开发人员就要考虑这个对话框的结果是否会影响后面的操作,如果这个对话框的结果跟后面的操作没有因果关系的,可以设置为第二种对话框。像拷贝文件的对话框就是第二种的对话框,称作无模式的对话框。如果设置为第一类,非要等那里拷贝文件才可以去操作其它东西,那么Windows 就不方便使用了,这样会浪费大量的时间。让人等待,就是一个不好用的软件,所以软件开发人员设计软件时,要站在用户的立场思考问题,在保持软件正确的情况下,不要让人等待,任何让人等待超过20秒以上的软件,会让用户烦躁不安。如果非要等待的话,也要加入进度条对话框提示,这样可以有效地缓解用户烦躁不安的心情。这就跟你去银行排队时,可以坐在那里看着电视,感觉不到时间长的道理一样的。

函数DialogBox 函数和DialogBoxParam 函数声明如下:

#define DialogBoxA(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ DialogBoxParamA(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L)

#define DialogBoxW(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ DialogBoxParamW(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L)

#ifdef UNICODE

#define DialogBox DialogBoxW #else

#define DialogBox DialogBoxA #endif // !UNICODE

WINUSERAPI INT_PTR

WINAPI

DialogBoxParamA(

__in_opt HINSTANCE hInstance, __in LPCSTR lpTemplateName, __in_opt HWND hWndParent, __in_opt DLGPROC lpDialogFunc, __in LPARAM dwInitParam);

WINUSERAPI INT_PTR WINAPI

DialogBoxParamW(

__in_opt HINSTANCE hInstance, __in LPCWSTR lpTemplateName, __in_opt HWND hWndParent,

__in_opt DLGPROC lpDialogFunc, __in LPARAM dwInitParam);

#ifdef UNICODE

#define DialogBoxParam DialogBoxParamW #else

#define DialogBoxParam DialogBoxParamA #endif // !UNICODE

hInstance 是当前应用程序的实例句柄。 lpTemplateName 是对话框的资源模板。 hWndParent 是父窗口的句柄。

lpDialogFunc 是对话框的消息处理函数。

dwInitParam 是初始化参数,这里缺省设置为0。

调用这个函数的例子如下: #001 //

#002 // 目的: 处理主窗口的消息.

#003 //

#004 // 蔡军生 2007/07/12 QQ:9073204

#005 //

#006 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) #007 {

#008 int wmId, wmEvent; #009 PAINTSTRUCT ps; #010 HDC hdc; #011

#012 switch (message) #013 {

#014 case WM_COMMAND:

#015 wmId = LOWORD(wParam); #016 wmEvent = HIWORD(wParam); #017 // 菜单选项命令响应: #018 switch (wmId) #019 {

#020 case IDM_ABOUT:

#021 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

#022 break;

#023 case IDM_EXIT:

#024 DestroyWindow(hWnd); #025 break; #026 default:

#027 return DefWindowProc(hWnd, message, wParam, lParam); #028 }

#029 break;

#030 case WM_PAINT:

#031 hdc = BeginPaint(hWnd, &ps); #032 //

#033 EndPaint(hWnd, &ps); #034 break;

#035 case WM_DESTROY:

#036 PostQuitMessage(0); #037 break;

#038 default:

#039 return DefWindowProc(hWnd, message, wParam, lParam); #040 }

#041 return 0;

#042 }

第21行就是调用函数DialogBox 来显示对话框窗口。

对话框的模板如下:

///////////////////////////////////////////////////////////////////////////// //

// Dialog //

IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75

STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU CAPTION "关于"

FONT 9, "新宋体", 400, 0, 0x86

BEGIN

ICON IDI_TESTWIN,IDC_MYICON,14,9,21,21

LTEXT "TestWin Version

1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX

LTEXT "Copyright (C) 2007",IDC_STATIC,49,20,119,8 DEFPUSHBUTTON "确定",IDOK,185,51,38,16,WS_GROUP END

IDD_ABOUTBOX 是对话框模板的名称。 DIALOGEX 是对话框定义的关键字。

22, 17, 230, 75是对话框的坐标和大小。 STYLE 是设置对话框的显示类型。

CAPTION 是定义标题名称。这里是"关于"。 FONT 是定义对话的字体。 ICON 是定义一个图标显示。 LTEXT 是定义显示静态文本。

DEFPUSHBUTTON 是定义一个按钮。

Windows API 一日一练(18)EndDialog 函数

上一次介绍了怎么样显示对话框的函数,那么怎么样关闭对话框呢?这就需要使用到函数EndDialog 。这个函数只能在对话框的消息处理函数里使用,并且这个函数调用之后,没有立即就删除对话框的,而是设置了操作系统里的结束标志。当操作系统查检到有这个标志时,就去删除对话框的消息循环,同时也去释放对话框占用的资源。其实对话框的生命周期是这样的,先由函数DialogBox 创建对话框,这样函数DialogBox 完成创建对话框但还没有显示前会发出消息WM_INITDIALOG ,让对话框有机会初始化上面所有窗口或控件的显示,比如设置文本框的字符串等。最后当用户点出确定或者取消的按钮,就收到两个命令IDOK 或IDCANCEL ,这时就可以调用函数EndDialog 来结束对话框的生命。

函数EndDialog 声明如下: WINUSERAPI BOOL WINAPI

EndDialog(

__in HWND hDlg, __in INT_PTR nResult); hDlg 是对话框窗口的句柄。

nResult 是设置给函数DialogBox 的返回值。

调用这个函数的例子如下: #001 // 显示关于对话框。 #002 //

#003 // 蔡军生 2007/07/12 #004 //

#005 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) #006 {

#007 UNREFERENCED_PARAMETER(lParam); #008 switch (message) #009 {

#010 case WM_INITDIALOG: #011 return (INT_PTR)TRUE; #012

#013 case WM_COMMAND:

#014 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

#015 {

#016 EndDialog(hDlg, LOWORD(wParam)); #017 return (INT_PTR)TRUE; #018 }

#019 break; #020 }

#021 return (INT_PTR)FALSE; #022 }

第16行就是调用函数EndDialog 来关闭对话框。

Windows API 一日一练(19)DestroyWindow 函数

以前已经介绍过直接点击关闭按钮来关闭应用程序,但想删除一个窗口对象,需要用到什么函数的呢?比如创建了30个窗口,想把第12个窗口关闭删除掉,那就需要使用函数DestroyWindow 。当调用DestroyWindow 函数后,操作系统就会进行一系列的删除动作,先发送WM_DESTROY 消息,接着发送WM_NCDESTROY 消息。如果这个窗口还有子窗口或者是其它窗口的所有者,就需要给所有子窗口发送删除消息。

函数DestroyWindow 声明如下: WINUSERAPI BOOL

WINAPI

DestroyWindow(

__in HWND hWnd);

hWnd 是要删除的窗口句柄。

调用这个函数的例子如下:

#001 //

#002 // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) #003 //

#004 // 目的: 处理主窗口的消息.

。

猜你喜欢

最安全有效的减肥药

最安全有效的减肥药

编辑:小徐

现在的减肥药真的是真假难分,在选择减肥药的同时也应该更加小心,减肥药多种多样,那么如何才能选择最安全有效的减肥药,也成了很多小仙女的内心疑问,下面就跟着黄色伧理小编一起看一下,如何选择最安全有效的减肥药。 最安全有效的减肥药选购方法 1、首先需要观察产品的外包装,在包装中可以看到其配方是不是含有激素,含有激素的减肥药对身体的内..

吃减肥药失眠

吃减肥药失眠

编辑:小徐

随着现在流行以瘦为美,很多人会不顾身体的健康选择减肥药,达到快速减肥瘦身的效果,但是很多减肥药都是有副作用的,副作用比较轻的就是失眠现象,那么吃减肥药出现失眠是怎么回事儿?如果出现失眠后,我们应该怎样缓解? 吃减肥药失眠是怎么回事 减肥药中富含安非他命,所以减肥药服用了太多会有失眠现象,服用减肥药期间,身体会逐渐出现抗药性,身..

最新文章