Win32程序内部运行基本原理

来源:互联网 发布:淘宝hd登录接口不存在 编辑:程序博客网 时间:2024/04/30 03:07

/*

很到位的一篇总结,所以忍不住就转载过来保存学习了。

转载于:http://www.cnblogs.com/sqzxcv/archive/2009/11/28/1612439.html

*/

申明:本文是我看了孙鑫老师的VC++视频教程后的总结,相当于学习笔记吧,纯粹是为了方便自己。同时也希望能对大家学习vc++有所帮助。至于文中的内容如果有什么错误或不妥,欢迎指出。欢迎加我的QQ:124561376进行讨论,共同学习。

下面介绍了在使用WIN32 SDK 进行程序开发中,程序运行流程。

  1.Windows程序的入口函数为:WinMain();函数的原型为:

代码
1int WINAPI WinMain(
2  HINSTANCE hInstance,      // handle to current instance
3  HINSTANCE hPrevInstance,  // handle to previous instance
4  LPSTR lpCmdLine,          // command line
5  int nCmdShow              // show state
6);
7
复制代码

  他也是MFC程序的入口函数,只不过在MFC中微软把这个函数隐藏了。

WinMain参数介绍:

  HINSTANCE hInstance:当前应用程序的句柄,是系统对当前应用程序运行后的 实例 的唯一标示,我感觉句柄就类型指针。指向当前应用程序的实例。

  HINSTANCE hPrevInstance:字面意思是前面的一个程序的句柄,实际意义是:当 当前程序运行两个实例后,对于第二个实例的hPrevInstace参数就是就是第一个实例的hInstance。

  LPSTR lpCmdLine:是传入的命令行字符串。

    int nCmdShow:显示窗口的状态,如最大化、最小化等显示。

  由于这个函数是有系统调用的,所以这些参数的值都由系统传进来。我们可根据需要,进行调用就行了。

2.构建一个win32应用程序的步骤是:

  a.设计窗口类:WNDCLASS

  b.注册窗口类:RegisterClass

  c.创建窗口类:CreateWindow

  d.显示窗口类:ShowWindow

  e.更新窗口类:UpdateWindow

  f.消息循环:......

  

3.对于详细的信息可查看MSDN,这些函数都是系统API函数。下面重点说明一下WNDCLASS的结构:

代码
 1typedef struct _WNDCLASS 
 2    UINT       style; 
 3    WNDPROC    lpfnWndProc; 
 4    int        cbClsExtra; 
 5    int        cbWndExtra; 
 6    HINSTANCE  hInstance; 
 7    HICON      hIcon; 
 8    HCURSOR    hCursor; 
 9    HBRUSH     hbrBackground; 
10    LPCTSTR    lpszMenuName; 
11    LPCTSTR    lpszClassName; 
12}
 WNDCLASS, *PWNDCLASS; 
复制代码

  WNDCLASS其实就是一个结构体.里面有一个成员WNDPROC lpfnWndProc,他是一个窗口过程,是一个回调函数(有操作系统调用),事实上,他就是一个函数指针。我们在程序中定义一个函数,在里面写上我们希望的Code就行了,然后我们将这个函数名(函数名也就是一个函数指针,他是一个常量)赋给 lpfnWndProc 就行了。

  问:系统什么时候调用 窗口过程WNDPROC lpfnWndProc 调用

  答:当系统获取到由API函数DispatchMessage(LRESULT DispatchMessage(CONST MSG *lpmsg   /* message information*/);了)传进来的消息时,系统为了响应这个消息,会调用这个窗口过程(一个函数指针),至于这个窗口过程执行什么样的功能。就看你在赋给这个窗口过程的函数内部的CODE怎么写了。

赋给窗口过程WNDPROC lpfnWndProc 的函数指针所指的函数形式必须为:

代码
1LRESULT CALLBACK WindowProc(
2  HWND hwnd,      // handle to window
3  UINT uMsg,      // message identifier
4  WPARAM wParam,  // first message parameter
5  LPARAM lParam   // second message parameter
6);
复制代码

   对于WNDCLASS里面的其他一些成员都有什么意义,可以查看MSDN。

4.

在消息循环中使用了两个API函数

  a.TranslateMessage:转换消息对。如将WM_KEYDOWN和WM_KEYUP转化成WM_CHAR。

  b.DispatchMessage:将指定的消息发送给操作系统,由操作系统调用WNDCLASS中的窗口过程,实现消息响应。

 

5.注意:

  a. BeginPaint和EndPain两个API只能在WM_PAINT中使用。

  GetDC,ReleaseDC一般用在其他地方。

  b.DestroyWindow:只能销毁窗体,并不能退出程序,当调用这个函数后,会想当前应用程序的消息队列发送消息WM_DESTROY

  PostQuitMessage:是用于退出程序的API函数,他会想消息队列发送消息:WM_QUIT_

   c.GetMessage:每调用一次这个函数,就从当前应用程序的消息队列中取出一条消息,进行相应处理,当取出的消息为WM_QUIT时,GetMessage返回0,否则返回非零。 

 

6.自己发现的问题:同一个WNDCLASS类可以同时和多个窗口句柄HWND关联在一起,但一个HWND句柄只能和一个WNDCLASS进行关联。当一个WNDCLASS类同时和两个窗口句柄关联在一起时,一个句柄显示一个窗体,他们像是公用同一个消息循环。

 窗口类WNDCLASS和窗口句柄HWND是靠WNDCLASS中成员的窗口类名字LPCTSTR    lpszClassName字符串关联的

 

相应程序的Code如下:

代码
 1#include<Windows.h>;
 2#include<iostream>;
 3#include<tchar.h>;
 4#include<assert.h>;
 5using namespace std;
 6
 7LRESULT CALLBACK sqWndProc(
 8  HWND hwnd,      // handle to window
 9  UINT uMsg,      // message identifier
10  WPARAM wParam,  // first message parameter
11  LPARAM lParam   // second message parameter
12  );
13
14int WINAPI WinMain(
15                   HINSTANCE hInstance,      // handle to current instance
16                   HINSTANCE hPrevInstance,  // handle to previous instance
17                   LPSTR lpCmdLine,          // command line
18                   int nCmdShow              // show state
19                   )
20{
21    //set the class of windows,初始化一个窗口类
22    WNDCLASS WndClass;
23    WndClass.cbClsExtra=0;
24    WndClass.cbWndExtra=0;
25    WndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
26    WndClass.hCursor=LoadCursor(hInstance,IDC_APPSTARTING);
27    WndClass.hIcon=LoadIcon(NULL,IDI_ERROR);
28    WndClass.hInstance=hInstance;
29    WndClass.lpfnWndProc=sqWndProc;
30    WndClass.lpszClassName=_T("sqzxcv");
31    WndClass.lpszMenuName=NULL;
32    WndClass.style=CS_BYTEALIGNCLIENT|CS_HREDRAW|CS_VREDRAW;
33    
34    //注册窗口类    
35    assert(RegisterClass(&WndClass));
36    
37    //创建窗口CreateWindow
38    HWND hWnd=CreateWindow(_T("sqzxcv"),_T("小强测试用例"),WS_OVERLAPPEDWINDOW,50,50,600,600,NULL,NULL,hInstance,NULL);
39    assert(hWnd);
40
41    //显示窗口
42    ShowWindow(hWnd,nCmdShow);
43    UpdateWindow(hWnd);
44    
45    //消息
46    MSG msg;
47
48    //处理消息,进行消息循环
49    while(GetMessage(&msg,NULL,0,0))
50    {
51        TranslateMessage(&msg);
52        DispatchMessage(&msg);
53    }

54    return 0;
55}

56
57LRESULT CALLBACK sqWndProc(
58                       HWND hwnd,      // handle to window
59                           UINT uMsg,      // message identifier
60                           WPARAM wParam,  // first message parameter
61                           LPARAM lParam   // second message parameter
62                           )
63{
64    switch(uMsg)
65    {
66    case WM_CHAR:
67        char szChar[20];
68        sprintf(szChar,"char is %d",wParam);
69        MessageBox(hwnd,szChar,"!-_-木糖-_-!",0);
70        break;
71    case WM_LBUTTONDOWN:
72        MessageBox(hwnd,"mouse clicked","木糖",0);
73        HDC hdc;
74        hdc=GetDC(hwnd);
75        TextOut(hdc,0,50,"!-_-木糖-_-!",strlen("!-_-木糖-_-!"));
76        ReleaseDC(hwnd,hdc);
77        break;
78    case WM_PAINT:
79        HDC hDC;
80        PAINTSTRUCT ps;
81        hDC=BeginPaint(hwnd,&ps);
82        TextOut(hDC,0,0,"!-_-木糖-_-!",strlen("!-_-木糖-_-!"));
83        EndPaint(hwnd,&ps);
84        break;
85    case WM_CLOSE:
86        if(IDYES==MessageBox(hwnd,"是否真的结束?","!-_-木糖-_-!",MB_YESNO))
87        {
88            DestroyWindow(hwnd);
89        }

90        break;
91    case WM_DESTROY:
92        PostQuitMessage(0);
93        break;
94    default:
95        return DefWindowProc(hwnd,uMsg,wParam,lParam);
96    }

97    return 0;
98}


 

原创粉丝点击