孙鑫VC视频教程笔记之第一课“Windows程序的内部运行原理”

时间:2021-11-13 20:13:51

1.      操作系统和应用程序之间的关系:
应用程序到操作系统表示应用程序可以通知操作系统执行某个具体的动作
操作系统到应用程序表示操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何作出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件作出反应。

 

2.      windows程序设计是种事件驱动方式的程序设计,主要基于消息的。当用户需要完成某种功能时,需要调用OS某种支持,然后OS将用户的需要包装成消息,并投入到消息队列中,最后应用程序从消息队列中取走消息并进行响应。
每个应用程序OS都为它建立一个消息队列,消息队列是个先进先出的缓冲区,其中每个元素都是一个消息,OS将生成的每个消息按先后顺序放进消息队列中,应用程序总是取走当前消息队列中的第一条消息,应用程序取走消息后便知道用户的操作和程序的状态,然后对其处理即消息响应,消息响应通过编码实现。

 

3.      创建一个完整的窗口需要经过下面四个操作步骤

1)       设计一个窗口类。如:WNDCLASS wndcls

2)       注册窗口类。如:RegisterClass(&wndcls)

3)       创建窗口。如:CreateWindow(),CreateWindowEX();

4)       显示及更新窗口。如:ShowWindow(),UpdateWindow();

 

4.      消息的结构:

typedef struct tagMSG {   

    HWND   hwnd;     //接收消息的窗口句柄,和哪个窗口相关联。

    UINT   message;  //消息标识,消息本身是什么,如WM_CHAR

    WPARAM wParam;   //消息的附加信息,具体取决于消息本身。 

    LPARAM lParam;

    DWORD  time;     //消息投递时间。

    POINT  pt;       //消息投递时,光标在屏幕上的位置。

} MSG;

 

5.      WinMain函数结构:

int WINAPI WinMain(

  HINSTANCE hInstance,  // 当前实例句柄。

  HINSTANCE hPrevInstance,  //上一个该程序的实例句柄,32位系统中此值都为NULL

  LPSTR lpCmdLine,      // 命令行指针

  int nCmdShow          // (窗口)显示的状态

);

要带参调用WinMain类似于命令行的功能,在Project->setting->Debug->Program arguments项填写参数

 

6.      窗口类WNDClass

typedef struct _WNDCLASS {

    UINT    style;        //窗口的类型

    WNDPROC lpfnWndProc;  //窗口过程函数指针(回调函数)

    int     cbClsExtra; //窗口类附加字节,为该类窗口所共享。通常0

    int     cbWndExtra; //窗口附加字节。通常设为0

    HANDLE  hInstance;  //当前应用程序事例句柄。

    HICON   hIcon;      //图标句柄 LoadIcon();

    HCURSOR hCursor;    //光标句柄 LoadCursor();

    HBRUSH  hbrBackground; //画刷句柄 (HBRUSH)GetStockObject();

    LPCTSTR lpszMenuName;  //菜单名字

    LPCTSTR lpszClassName; //类的名字

} WNDCLASS;

 

 

7.      源码(在VC中建立Win32 Application):

#include<windows.h>

#include<stdio.h>

 

//回调函数声明

LRESULT CALLBACK WindowProc(

   HWND hwnd,      // handle to window

   UINT uMsg,      // message identifier

   WPARAM wParam,  // first message parameter

   LPARAM lParam   // second message parameter

);

 

int WINAPI WinMain(

   HINSTANCE hInstance,  // handle to current instance

   HINSTANCE hPrevInstance,  // handle to previous instance

   LPSTR lpCmdLine,      // pointer to command line

   int nCmdShow          // show state of window

)

{

   //第一步:设计窗口类

   WNDCLASS wndcls;

   wndcls.cbClsExtra=0;

   wndcls.cbWndExtra=0;

 

   //The GetStockObject function retrieves a handle to one of the predefined stock pens, brushes, fonts, or palettes.

   wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //得到预定义的画刷,画笔等

   wndcls.hCursor=LoadCursor(NULL,IDC_CROSS); //如果采用预定义的光标,则第一参数为NULL

   wndcls.hIcon=LoadIcon(NULL,IDI_WARNING);//同上

   wndcls.hInstance=hInstance;

   wndcls.lpfnWndProc=WindowProc; //回调函数

   wndcls.lpszClassName="winmain"; //给本窗口类取个名字

   wndcls.lpszMenuName=NULL;

   wndcls.style=CS_HREDRAW | CS_VREDRAW; //水平和垂直重画,这在窗口水平和垂直调整大小的时候告知窗口是否需要重画,如果填写上述两个参数,则表示重画,窗口上的内容将清除重画

 

   //第二步:注册窗口类

   RegisterClass(&wndcls);

  

   //第三步:创建窗口

   HWND hwnd;

   hwnd=CreateWindow("winmain","this is first lesson",WS_OVERLAPPEDWINDOW,                CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,                 NULL,hInstance,NULL);

 

   //第四步:显示窗口

   ShowWindow(hwnd,SW_SHOWNORMAL);

 

   //第五步:重刷一下窗口,该语句可有可无

   UpdateWindow(hwnd);

 

   MSG msg;

 

   //每次循环从消息队列中取出一条消息进行处理If the GetMessage retrieves a message other than WM_QUIT, the return value is nonzero.If the function retrieves the WM_QUIT message, the return value is zero.

   while(GetMessage(&msg,NULL,0,0))

   {

        //该语句将类似于WM_KeyDownWM_KeyUp转换生成新WM_CHAR投递给系统处理

        //The WM_CHAR message is posted to the window with the keyboard focus

        //when a WM_KEYDOWN message is translated by the TranslateMessage function.

        //WM_CHAR contains the character code of the key that was pressed.

        TranslateMessage(&msg);

 

        //将消息投递出去给操作系统,操作系统会自动调用回调函数处理

        DispatchMessage(&msg);

   }

   return 0;

}

 

LRESULT CALLBACK WindowProc(

   HWND hwnd,      // handle to window

   UINT uMsg,      // message identifier

   WPARAM wParam,  // first message parameter

   LPARAM lParam   // second message parameter

                                    )

{

   HDC hdc;

   switch(uMsg) {

   case WM_PAINT:

        PAINTSTRUCT ps;

        hdc=BeginPaint(hwnd,&ps);

        TextOut(hdc,0,10,"hello world!",strlen("hello world!"));

        EndPaint(hwnd,&ps);

        break;

   case WM_CHAR:

        char szChar[20];

        sprintf(szChar,"char is %d",wParam);

        MessageBox(hwnd,szChar,"消息",MB_OK);

   case WM_LBUTTONDOWN:

        hdc=GetDC(hwnd); //得到当前窗口的上下文句柄

        TextOut(hdc,0,50,"beijing2008!",strlen("beijing2008!"));

        ReleaseDC(hwnd,hdc);

        break;

   case WM_CLOSE:

        if(IDOK==MessageBox(hwnd,"确认要退出嘛?","消息",MB_OK))

        {

              //销毁窗口,但进程中还是保留的,该函数直接抛出WM_DESTROY消息

              DestroyWindow(hwnd);

        }

        break;

   case WM_DESTROY:

        PostQuitMessage(0); //终止消息循环,并抛出WM_QUIT消息,从而导致上面的消息循环退出

   default:

        //对于代码中没有涉及到的消息,由提交给系统处理,此句一定要加,否则窗口不会出现

        return DefWindowProc(hwnd,uMsg,wParam,lParam);

   }

   return 0;

}