初识Windows编程

本人为初学者,水平有限,写blog主要为了记录自己学习的轨迹,代码介绍参考msdn,如有错误或者疏漏敬请各位批评指正,感谢您的阅读!

1.对Windows编程的基本认识

最简单的Windows编程时调用一些windows中的用户态的API,大多是User32.dll GDI32.dll这两个库文件中的函数。

MFC是一个类库(class libraries),以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件组件的封装类。MFC是WINAPI与C++的结合,它不仅仅是一个页面开发系统,内含很多类的作用并不是一个界面类,不实现对一个窗口对象的控制,有一些是在windows内部处理的类。

2.对基本框架的理解过程

笔者在了解了基本的c语言知识之后,尝试阅读基本的框架代码。

每一个c语言的程序都有着自己的main函数,而based win32 的程序,有着WinMain function,作为程序的入口点,基本代码如下 

int CALLBACK WinMain(  
  _In_ HINSTANCE hInstance,  //handle to the current instance
  _In_ HINSTANCE hPrevInstance,  //handle to the previous instance
  _In_ LPSTR     lpCmdLine,  // command line of the application
  _In_ int       nCmdShow  // control how the window to be shown
);

在winmain里,创建WNDCLASSEX的struct,其包含了一个窗口的基本信息,基本代码如下

WNDCLASSEX wcex;  

wcex.cbSize = sizeof(WNDCLASSEX);  
wcex.style          = CS_HREDRAW | CS_VREDRAW;  
wcex.lpfnWndProc    = WndProc;  
wcex.cbClsExtra     = 0;  
wcex.cbWndExtra     = 0;  
wcex.hInstance      = hInstance;  
wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));  
wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);  
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  
wcex.lpszMenuName   = NULL;  
wcex.lpszClassName  = szWindowClass;  
wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

之后需要注册窗口(其意义有点类似于在主程序之前写函数定义),基本代码如下

if (!RegisterClassEx(&wcex))  
{  
    MessageBox(NULL,  
        _T("Call to RegisterClassEx failed!"),  
        _T("Win32 Guided Tour"),  
        NULL);  

    return 1;  
}

我们在注册窗口之后就可以创建窗口了,CREATEWINDOW返回值是一个HWND,handle to the window,用来跟踪窗口。

static TCHAR szWindowClass[] = _T("win32app");  
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");  

// The parameters to CreateWindow explained:  
// szWindowClass: the name of the application  
// szTitle: the text that appears in the title bar  
// WS_OVERLAPPEDWINDOW: the type of window to create  
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)  
// 500, 100: initial size (width, length)  
// NULL: the parent of this window  
// NULL: this application does not have a menu bar  
// hInstance: the first parameter from WinMain  
// NULL: not used in this application  
HWND hWnd = CreateWindow(  
    szWindowClass,  
    szTitle,  
    WS_OVERLAPPEDWINDOW,  
    CW_USEDEFAULT, CW_USEDEFAULT,  
    500, 100,  
    NULL,  
    NULL,  
    hInstance,  
    NULL  
);  
if (!hWnd)  
{  
    MessageBox(NULL,  
        _T("Call to CreateWindow failed!"),  
        _T("Win32 Guided Tour"),  
        NULL);  

    return 1;  
}

之后我们显示这个窗口,并让其可以update

// The parameters to ShowWindow explained:  
// hWnd: the value returned from CreateWindow  
// nCmdShow: the fourth parameter from WinMain  
ShowWindow(hWnd,  
    nCmdShow);  
UpdateWindow(hWnd);

接下来添加消息循环从消息队列里检索窗口相关的消息,接收到的消息送给WndProc处理

window application是基于消息的程序设计模式,用事件去驱动编程模式。所谓消息循环实际上就是从消息队列里接收消息,检索消息,发送给WndProc的程序循环。

MSG msg;  
while (GetMessage(&msg, NULL, 0, 0))  
{  
    TranslateMessage(&msg);  
    DispatchMessage(&msg);  
}  

return (int) msg.wParam;

除此之外,还需要一个windows procedure function ,我们习惯叫它WndProc,基本代码如下

LRESULT CALLBACK WndProc(  
  _In_ HWND   hwnd,  
  _In_ UINT   uMsg,  
  _In_ WPARAM wParam,  
  _In_ LPARAM lParam  
);

在windows程序内,事件发生,WinProc用来对事件作出处理响应(handle an event)。里面的pattern近似于一个switch 里面有多个case,根据收到的消息做出不同的响应。

示例如下:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_CREATE:
		// 初始化窗体
		InitGame(hWnd, wParam, lParam);
		break;
	case WM_KEYDOWN:
		// 键盘按下事件
		KeyDown(hWnd, wParam, lParam);
		break;
	case WM_KEYUP:
		// 键盘松开事件
		KeyUp(hWnd, wParam, lParam);
		break;
	case WM_MOUSEMOVE:
		// 鼠标移动事件
		MouseMove(hWnd, wParam, lParam);
		break;
	case WM_LBUTTONDOWN:
		// 鼠标左键按下事件
		LButtonDown(hWnd, wParam, lParam);
		break;
	case WM_LBUTTONUP:
		// 鼠标左键松开事件
		LButtonUp(hWnd, wParam, lParam);
		break;
	case WM_TIMER:
		// 定时器事件
		if (currentStage != NULL && currentStage->timerOn) TimerUpdate(hWnd, wParam, lParam);
		break;
	case WM_PAINT:
		// 绘图
		Paint(hWnd);
		break;
	case WM_DESTROY:
        //退出
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

3.little  pieces

(1)双缓冲绘图

笔者在学习中碰到的WndProc中WM_PAINT 函数,里面涉及到双缓冲绘图。

因为在WM_PAINT 中,进行图形的绘制时,程序的响应相当频繁,每一次执行OnEraseBKgnd的过程都要擦除原先屏幕上的图像,接着用背景色进行填充,最后再重新绘制。这不仅会引起绘制耗时太长的问题,也会导致绘图过程中屏幕上出现闪烁的现象。因此,我们想到,先将图片绘制到内存缓冲区当中,之后利用BitBlt,将其copy到屏幕上。BitBlt的执行速度很快,所以这很好的实现了将图片整体显示在屏幕上的效果。示例代码如下

void Paint(HWND hWnd)
{

	PAINTSTRUCT ps;
	HDC hdc_window = BeginPaint(hWnd, &ps);

	HDC hdc_memBuffer = CreateCompatibleDC(hdc_window);
	HDC hdc_loadBmp = CreateCompatibleDC(hdc_window);

	//初始化缓存
	HBITMAP	blankBmp = CreateCompatibleBitmap(hdc_window, WINDOW_WIDTH, WINDOW_HEIGHT);
	SelectObject(hdc_memBuffer, blankBmp);

	// 绘制背景到缓存
	SelectObject(hdc_loadBmp, bmp_Background);

	BitBlt(hdc_memBuffer, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hdc_loadBmp, 0, 0, SRCCOPY);
    
    //need to do


    // 最后将所有的信息绘制到屏幕上
	BitBlt(hdc_window, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hdc_memBuffer, 0, 0, SRCCOPY);

	// 回收资源所占的内存(非常重要)
	DeleteObject(blankBmp);
	DeleteDC(hdc_memBuffer);
	DeleteDC(hdc_loadBmp);

	// 结束绘制
	EndPaint(hWnd, &ps);
}

待更新......

                                            

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值