windows程序运行机制
来源:互联网 发布:深圳玛歌品牌淘宝有吗 编辑:程序博客网 时间:2024/06/16 05:06
一.字符集的编码
对字符集的编码可以使用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>//编写兼容两种字符的winMainLRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); //编写兼容两种字符的winMainint WINAPI _tWinMain( HINSTANCE hInstance, // handle to current instanceHINSTANCE hPrevInstance, // handle to previous instanceLPTSTR lpCmdLine, // command lineint 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); //默认的窗口过程}
- Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- WINDOWS程序内部运行机制
- Windows程序运行机制
- Windows程序内部运行机制
- windows程序运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- windows程序内部运行机制
- Windows 程序内部运行机制
- Lesson1:Windows程序内部运行机制
- 一.Windows程序内部运行机制
- (1)Windows程序内部运行机制
- 第一章,Windows程序内部运行机制
- Windows程序内部运行机制学习
- 第一章:Windows程序内部运行机制
- 转载 -- lvs、haproxy、nginx 负载均衡的比较分析
- QT实现窗口透明的方法
- Android -- 小问题 InputStream的read方法读取字节不完全的问题
- Android Loader加载器使用详解
- css兼容性坑记录
- windows程序运行机制
- jquery获得select option的值 和对select option的操作
- Lucene学习总结之一:全文检索的基本原理
- Neutron网络入门
- hdu 3499 Flight(spfa+反向图)
- VIM
- 黑马程序员--正则表达式
- timer和timertask
- int,int32_t,int64_t