初学windows API(实例分析)
这学期开了VC++可视化课程,今天亲自上手理解和修改了一个VC内置Demo程序,感觉还是很难上手的,尤其是
刚接触的时候,那么多生僻的函数名,方法名,结构名,类名,一点都没有学C++时的亲切感。有了Java jdk的使用基础,其
实与windows api的开发方式差不多,都是用到什么查什么。第一天的学习当中最生僻的概念无非就是句柄了,网上搜了点资料。
概念如下:
在Windows环境中,句柄是用来标识项目的,这些项目包括:模块(module)、任务(task)、实例 (instance)、文件(file)、
内存块(block of memory)、菜单(menu)、控制(control)、字体(font)、资源(resource),包括图标(icon),光标 (cursor),
字符串(string)等、GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),
区域 (region),以及设备描述表(device context)。或理解为WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数。
与指针的使用差不多,只不过是为了隐藏window 内核的数据结构,而为程序员提供的一套操作对象的标识。
-----------------------------------------------疑问-----------------------------------------------
那么接下来要问句柄如何与对象映射?
封装背后,必须有一个地方可以实现解码,以实现句柄和对象的相互转换。在
windows中,存在两种映射方式:
a. 全等映射。也即,句柄本身就是一个指针。映射在这里只是类型转换而已。
这种情况有,进程实例句柄或模块句柄,以及资源句柄等等。
b. 基于表格的映射。这是对象指针与句柄之间最普通的映射机制。操作系统创
建表格,并保存所有要考虑的对象。需要创建新对象时,要先在表格中找到空入口
,然后把表示对象的数据添入其中。当对象被删除时,它的数据成员和其在表中的
入口被释放。
----------------------------了解了这个概念,可以为我的学习提供了帮助-----------------------------
下面就开源我分析的内置示例源码,实现功能很简单,只不过是显示一个带菜单的窗体,显示一段文字。毕竟初学,如果
有那里说明有问题,还请指教,课本现在还没买,照着Api理解的。
//
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前句柄
TCHAR szTitle[MAX_LOADSTRING]; // 标题
TCHAR szWindowClass[MAX_LOADSTRING]; // 类名
// 提出声明的功能包括在这个代码模块:
//注册类
ATOM MyRegisterClass(HINSTANCE hInstance);
//初始化句柄
BOOL InitInstance(HINSTANCE, int);
//消息处理回调函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//该函数被系统调用,作为一个32位应用程序的入口点。
//HINSTANCE hInstance 应用程序当前事例的句柄
//HINSTANCE hPrevInstance 应用程序的前事例的句柄。对于一个32的位程序,该参数总为NULL。
//LPSTR lpCmdLine 指向应用程序命令行的空字符串的指针
//int nCmdShow 指明窗口如何显示
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//消息
MSG msg;
//加速键表
HACCEL hAccelTable;
// 初始化全局字符串
//装载字符串表资源
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_FIRSTVIEW, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用初始化:初始化失败返回false
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
//LoadAccelerators调入加速键表
//hInstance模块的一个事例的句柄
//(LPCTSTR)IDC_FIRSTVIEW指向一个以空结尾的字符串的指针,
//该字符串包含了即将调入的加速键表的名字
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FIRSTVIEW);
// 主要消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
//TranslateAccelerator 翻译加速键表。该函数处理菜单
//命令中的加速键。如果失败,执行TranslateMessage,DispatchMessage方法
//msg.hwnd 窗口句柄,该窗口的消息将被翻译。
//hAccelTable 加速键表句柄。
//&msg MSG结构指针
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
//函数:MyRegisterClass()。
//寄存器窗口类。
//如果你想这段代码
//是兼容与Win32系统前RegisterClassEx
//函数被加到Windows 95。它是重要的,调用这个函数
//使应用程序将得到“格式良好的“小图标
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;//指向一个WNDCLASSEX结构的指针
wcex.cbSize = sizeof(WNDCLASSEX);
//定义INPUT结构的大小。若cbSize不是INPUT结构的大小,则函数调用失败。
wcex.style = CS_HREDRAW | CS_VREDRAW;
//此风格中可使用DKGRAY_BRUSH、GRAY_BRUSH和LTGRAY_BRUSH对象。
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;//句柄赋值
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_FIRSTVIEW);//图标句柄
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //光标句柄
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //背景句柄
wcex.lpszMenuName = (LPCSTR)IDC_FIRSTVIEW;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
//返回函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类。
return RegisterClassEx(&wcex);
}
//
//函数:InitInstance(int)处理
//节省处理和创造主窗口的实例
//这个功能的时候,我们保存情况处理在一个全局变量、
//创造、显示的主程序的窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;//窗口句柄
hInst = hInstance; //全局变量处理
//创建窗口
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//显示窗口
ShowWindow(hWnd, nCmdShow);
//重绘窗口
UpdateWindow(hWnd);
return TRUE;
}
//
//函数:WndProc(HWND, unsigned, WORD, LONG)
//目的:过程信息的主窗口
//WM_COMMAND -应用程序的菜单
//WM_PAINT -主窗口
//WM_DESTROY -显示退出信息并返回
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc; //指向目标设备环境的句柄
TCHAR szHello[MAX_LOADSTRING]; //100个单位长度字符串
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); //装载字符串表资源
switch (message)
{
//应用程序的菜单
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单:
switch (wmId)
{
case IDM_ABOUT:
//根据对话框模板资源创建一个模态的对话框
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
//关闭窗口
DestroyWindow(hWnd);
break;
default:
//调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
//主窗口
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT rt;//指向RECT结构的指针
//该函数获取窗口客户区的坐标
GetClientRect(hWnd, &rt);
//该函数在指定的矩形里写入格式化文本
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
//绘制结束
EndPaint(hWnd, &ps);
break;
//显示退出信息并返回
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//信息处理器.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
相比于,Java的GUI技术,我觉得这个实现代码还是比较麻烦的,毕竟更底层一些,也许是生疏的原因吧。
也希望一些前辈可以推荐几本好书。
作者:Steven(Steven's Think out)
出处:http://shiyangxt.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。