windows程序运行机制

一.字符集的编码

对字符集的编码可以使用8位和16位进行编码,ASCII编码使用了一个字节进行编码,Unicode用两个字节进行编码,最多可以表示65536个字符;ASCII码当初的设计只是针对美国英语设计的。对于其他国家而言,一个字节最多只能够256个字符,对于汉字,最常用的汉字就多大6000多个。显然用一个字节并不能够完全表示所有的汉字;因此,16位编码可以表示多国言语,对于国际语言的转换变得方便。

宽字符集:使用两个字节对字符进行编码,计算机判断宽字符集的字符串是否结束,通过连续两个‘\0’进行识别,即当出现两个连续的字符'\0'时就认为此字符串结束;unicode属于宽字符集。

多字节字符集:一个字节或者两个字节,当遇到‘\0’就判定是字符串结尾。

    因此,使用前必须确定使用的字符集,不然会带来一些不必要的麻烦;windows程序是如何兼容两种字符集的,在tchar.h头文件中有如下的宏定义

 

#ifdef  _UNICODE

  #define _tcslen    wcslen
  #deine  TCHAR  wchar_t
  #define LPTSTR wchar_t *
  #define _T(x)   L##x
#else
  #define _tcslen    strlen
  #deine  TCHAR  char
  #define LPTSTR char *
  #define _T(x)   x
#endif
这里只列出部分宏定义,因此我们可以通过宏定义实现两种编码的兼容;幸运地是,这些微软已经帮我们做好了,我们只要会用就行了。


二.预备知识

(1)句柄(HANDLE):句柄是windows中一个必要重要的概念,是windows程序中的一种资源标识符,通过句柄可以区分不同的资源,从而可以方便我们管理资源。windows中有很多资源,包括窗口(HWND)、光标(HCURSOR)、图标(HICON)、画刷(HBRUSH)等。

(2)窗口(window):窗口分为客户区和非客户区;非客户无包括标题栏、菜单栏、工具栏和窗口边框,客户区是用来与客户打交道的区域

(3)消息:windows程序设计是一种事件驱动的方式,基于消息的;操作系统感知特定窗口的事件,并把它打包成消息,放到应用程序的消息队列中,然后应用程序从消息队列中取出消息并对此进行响应。当应用程序需要响应某一个消息时,从消息队列中取出消息,并把此消息分发给操作系统,由操作系统完成对应用程序的消息处理函数的调用。

进队消息:进入消息队列。

不进队消息:系统调用窗口过程时直接发送给窗口。

(4)winmain():winmain函数是windows程序的入口点函数,声明形式如下:

int WINAPI WinMain(  HINSTANCE hInstance,      // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state);

第一个参数:应用程序的实例句柄,用于标识不同的应用程序

第二个参数:当前实例的前一个实例的句柄

第三个参数:命令行参数;如一个文本应用程序,当文本应用程序打开一个文本文档时,需要把文本文档的路径传给文本应用程序

第四个参数:指定程序的窗口应该如何显示,最大化、最小化、隐藏等。


三.windows内部程序内部运行机制

    一般windows程序要经过以下流程,注册窗口、创建窗口、显示和更新窗口、进入消息循环、消息处理!

1.注册窗口类

WNDCLASSEX结构体:

typedef struct _WNDCLASSEX { 
    UINT       cbSize; 
    UINT       style; 
    WNDPROC    lpfnWndProc; 
    int        cbClsExtra; 
    int        cbWndExtra; 
    HINSTANCE  hInstance; 
    HICON      hIcon; 
    HCURSOR    hCursor; 
    HBRUSH     hbrBackground; 
    LPCTSTR    lpszMenuName; 
    LPCTSTR    lpszClassName; 
    HICON      hIconSm; 
} WNDCLASSEX, *PWNDCLASSEX; 

总共有12个属性:以EX为后缀的函数,代表是原先函数的扩展版本

cbSize:WNDCALSSEX结构体类型的大小  sizeof(WNDCLASSEX)

style:窗口的样式 ;一般有CS_VERDRAW,CS_HREDRAW,

cbWndEXtra: 指定窗口附加内存,一般为0

cbClsEXtra:指定窗口类型额外的内存,一般为0

lpfnWndProc:窗口回调函数

hInstance:窗口实例句柄

hIcon:窗口类的图标句柄 LoadIcon();函数装载

hCursor:窗口类光标句柄LoadCursor()函数装载

hbrBackground:背景颜色,一般用HGDIOBJ GetStockObject(int);获取标准画刷;

lpzsMenuName:菜单资源的名字,菜单资源的ID号,一般需要用MAKEINTERSOURCE宏进行类型转换;

lpszClassName:窗口类的名字

hIconSm:

 然后调用ATOM RegisterClassEx( CONST WNDCLASSEX *)对窗口进行注册;

const TCHAR * lpszClassName= _T("MyWinows");
	WNDCLASSEX wndcls;
	wndcls.cbClsExtra=0;
	wndcls.cbWndExtra=0;
	wndcls.cbSize=sizeof(WNDCLASSEX);
	wndcls.hbrBackground=(HBRUSH)COLOR_GRAYTEXT;
	wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
	wndcls.hIcon=LoadIcon(NULL,IDI_QUESTION);
	wndcls.hIconSm=NULL;
	wndcls.hInstance=hInstance;
	wndcls.lpfnWndProc=WindowProc;
	wndcls.lpszClassName = lpszClassName;
	wndcls.lpszMenuName=NULL;
	wndcls.style=CS_VREDRAW | CS_HREDRAW;
	//12条属性
	bool nRet=::RegisterClassEx(&wndcls);
		if (!nRet)
		{
			::MessageBox(NULL,_T("注册窗口类失败"),_T("注册窗口"),MB_OK);
			return FALSE;
		}


2.创建窗口

HWND CreateWindowEx(  DWORD dwExStyle,      // extended window style
  LPCTSTR lpClassName,  // registered class name
  LPCTSTR lpWindowName, // window name  
  DWORD dwStyle,        // window style
  int x,                // horizontal position of window
  int y,                // vertical position of window
  int nWidth,           // window width  
  int nHeight,          // window height
  HWND hWndParent,      // handle to parent or owner window
  HMENU hMenu,          // menu handle or child identifier
  HINSTANCE hInstance,  // handle to application instance
  LPVOID lpParam        // window-creation data);

 窗口风格dwStyle是以WS_开始的宏,在window.h文件中;(x,y)窗口左上角的坐标,nWidth,nHeight分别是窗口的宽度和高度;

lpParam:作为WM_CREATE消息的附加参数lpParam传入的数据指针;

	HWND hWnd=::CreateWindowEx(0,lpszClassName,_T("时间的流逝"),
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,NULL,hInstance,NULL);
	if (NULL==hWnd)
	{
		::MessageBox(NULL,_T("创建窗口失败"),_T("创建窗口"),MB_OK);
		return FALSE;
	}


3.显示和更新窗口

::ShowWindow(hWnd,SW_SHOW);
::UpdateWindow(hWnd);
窗口的显示状态:SW_开头的宏;

4.消息循环

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

当GetMessage接收到除WM_QUIT消息之外都返回非零值,即一直在消息循环;

TranslateMessage();用于虚拟键转换成字符消息,比如可以把WM_KEYDOWN和WM_KEYUP转换成WM_CHAR消息,然后投递到消息队列中。

DispatchMessage()把消息分发给窗口过程,由窗口过程函数对消息进行处理,实际上把消息回传给操作系统;

windows消息处理机制:

(1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条条的消息。取出后,以对消息进行一些预处理,如放弃对某些消息的响应,或者调用TranslateMessage产生新的消息
3)应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。

4)系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。

5.消息处理

LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 
	LPARAM lParam )
{
	switch (uMsg)
	{
	case WM_CLOSE:
		::DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
	case WM_PAINT:
		HDC hdc;
		RECT clientRect;
		GetClientRect(hWnd,&clientRect);
		PAINTSTRUCT ps;
		 hdc=BeginPaint(hWnd,&ps);  //获取设备描述表
		//DrawText(hdc,_T("www.lppmww.com"),_tcslen(_T("www.lppmww.com")),&clientRect,DT_SINGLELINE|DT_BOTTOM);
		 TextOut(hdc,100,0,_T("www.lppmww.com"),_tcslen(_T("www.lppmww.com")));
		EndPaint(hWnd,&ps);
		break;
	default:
		break;
	}

	return ::DefWindowProc(hWnd,uMsg,wParam,lParam);  //默认的窗口过程
}

系统是通过窗口过程函数的地址来调用窗口过程函数的;beginPaint和endPaint只能在WM_PAINT消息的响应函数中;

windows绘图:

一般我们生活中要完成绘图过程,需要以下几个元素:画家、画图工具、画图技巧;windows程序与之相对应的是

画家:设备描述表

画图工具:画笔、画刷、位图等

画图技巧:windows提供的API函数,画点、划线函数;

在windows中,我们要想绘图,

首先应该获取设备描述表,把绘图工具选入设备描述表,然后调用windows提供的API函数;

获取设备描述表的方法:

(1)beginPaint()和EndPaint(),在WM_PAINT消息响应函数里面用

(2)GetDC()和ReleaseDC(),在客户区绘图

(3)GetWindowDC()和ReleaseDC()  在非客户区绘图


代码:

#include <tchar.h>
#include <Windows.h>
//编写兼容两种字符的winMain
LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 
	LPARAM lParam ); 
//编写兼容两种字符的winMain
int WINAPI _tWinMain(  HINSTANCE hInstance,      // handle to current instance
	HINSTANCE hPrevInstance,  // handle to previous instance
	LPTSTR lpCmdLine,          // command line
	int nCmdShow              // show state
	)
{  
	const TCHAR * lpszClassName= _T("MyWinows");
	WNDCLASSEX wndcls;
	wndcls.cbClsExtra=0;
	wndcls.cbWndExtra=0;
	wndcls.cbSize=sizeof(WNDCLASSEX);
	wndcls.hbrBackground=(HBRUSH)COLOR_GRAYTEXT;
	wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
	wndcls.hIcon=LoadIcon(NULL,IDI_QUESTION);
	wndcls.hIconSm=NULL;
	wndcls.hInstance=hInstance;
	wndcls.lpfnWndProc=WindowProc;
	wndcls.lpszClassName = lpszClassName;
	wndcls.lpszMenuName=NULL;
	wndcls.style=CS_VREDRAW | CS_HREDRAW;
	//12条属性
	bool nRet=::RegisterClassEx(&wndcls);
		if (!nRet)
		{
			::MessageBox(NULL,_T("注册窗口类失败"),_T("注册窗口"),MB_OK);
			return FALSE;
		}
	HWND hWnd=::CreateWindowEx(0,lpszClassName,_T("时间的流逝"),
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,NULL,hInstance,NULL);
	if (NULL==hWnd)
	{
		::MessageBox(NULL,_T("创建窗口失败"),_T("创建窗口"),MB_OK);
		return FALSE;
	}
	::ShowWindow(hWnd,SW_SHOW);
	::UpdateWindow(hWnd);

	MSG msg;
	while (::GetMessage(&msg,NULL,NULL,NULL))
	{
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}
}
LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 
	LPARAM lParam )
{
	switch (uMsg)
	{
	case WM_CLOSE:
		::DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
	case WM_PAINT:
		HDC hdc;
		RECT clientRect;
		GetClientRect(hWnd,&clientRect);
		PAINTSTRUCT ps;
		 hdc=BeginPaint(hWnd,&ps);  //获取设备描述表
		//DrawText(hdc,_T("www.lppmww.com"),_tcslen(_T("www.lppmww.com")),&clientRect,DT_SINGLELINE|DT_BOTTOM);
		 TextOut(hdc,100,0,_T("www.lppmww.com"),_tcslen(_T("www.lppmww.com")));
		EndPaint(hWnd,&ps);
		break;
	default:
		break;
	}

	return ::DefWindowProc(hWnd,uMsg,wParam,lParam);  //默认的窗口过程
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值