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);  //默认的窗口过程}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 已经喂了猫一个多月的高钙奶怎么办 几个月宝宝胳膊起来红豆豆怎么办 一岁半宝宝只喝牛奶不吃饭怎么办 儿子一生下来脖子上有淋巴结怎么办 满月宝宝睡觉不踏实易惊醒怎么办 两个月宝宝从婴儿车上掉下来怎么办 兔子不吃兔粮不喝水不拉粑粑怎么办 兔子吃了带水的菜叶怎么办 七个月的宝宝晚上睡觉总醒怎么办 紫薯和番茄一起吃了怎么办 1当半宝宝喝温开水后打隔怎么办 婴儿屁股拉便便肛门有点烂了怎么办 婴儿便便之后肛门就红怎么办 50天的宝宝三天不拉大便怎么办 两个月宝宝不拉屎只放屁怎么办 两个月大宝宝两天没拉屎怎么办 两个月宝宝三天没拉大便怎么办 5个月宝宝3天没拉大便怎么办 4个月宝宝3天没拉大便怎么办 20个月的宝宝大便干燥怎么办 20个月宝宝大便间隔三天怎么办 两个多月的宝宝四天没大便怎么办 两个多月的宝宝几天没大便怎么办 2个月3天没大便怎么办 两个月大的宝宝发烧40度怎么办 两个月大的宝宝感冒了怎么办 四个月宝宝拉水样大便要怎么办 六个月的宝宝咳嗽有痰怎么办 未满月的宝宝大便脓状怎么办 五个月的宝宝总是吃手怎么办 小孩子学数字怎么也学不会怎么办 小孩学数字老是学不会该怎么办 只买了大人票忘买儿童的了怎么办 铝合金滑动门没轨道安纱门怎么办 移门衣柜门与柜体有冶缝隙怎么办 推拉门关门时撞门框声音大怎么办 两岁宝宝夏天不盖被子怎么办 家里有好多会爬的小黑虫怎么办 刚贴的壁纸怎么发霉了怎么办 晚上睡觉一熄灯有许多小虫子怎么办 一岁宝宝夏天爱哭不爱吃饭怎么办