编程笔记一:Windows程序内部运行原理

本文详细介绍了一个简单的Windows程序设计过程,包括窗口类的设计、注册、创建和显示,以及如何通过消息循环响应用户操作。

《疯狂的程序员》里面boss绝的数据库老师说,“‘数据库原理与应用’,实际上就是数据库应用,像原理这种高深的东西,不能说,说了你们也无法理解。”想来教训得是,什么windows程序内部运行原理,其实就是教我们怎样编写一个窗口程序,一个简单的窗口程序。好,开始吧。

 

一、 程序编写

函数预处理就不用说了:

#include <windows.h>/*头文件,不解释*/

#include <stdio.h>

 

Windows程序的入口函数,是WinMain,让我们查询MSDN。得到如下:

int WINAPI WinMain(

             HINSTANCE hInstance,

             HINSTANCE hPrevInstance,

             LPWSTR lpCmdLine,

             int nShowCmd

);

说到MSDN,我忍不住要说两句。我在网上找了半天(头回编程,没有这个装备呀),好容易找了个,下了半天,居然是刻录文件。无语,后来才发现微软官网上原来是可以在线查的。http://msdn.microsoft.com/en-us/library/aa139781.aspx

 

     接下来就是正事,创建一个完整的窗口有四个步骤:

1、  设计一个窗口类;

2、  注册窗口类;

3、  创建窗口;

4、  显示及更新窗口。

一、以下则是建立一个窗口类,参照MSDN给各个成员变量赋值

 

       WNDCLASS wndcls;/*定义wndcls结构体,然后参照MSDN给每个成员变量进行赋值*/

wndcls.cbClsExtra=0;/*cbClsExtracbWndExtra两成员变量,一开始不小心把两个都写成了cbClsExtra,结果是编译通过,就是不运行,link出错,而且更诡异的是,改正也一样,必须是退出重新打开,才能正确运行。MSDN上的定义是“指定额外的字节数分配后的窗口类结构。该系统初始化为零字节。”好吧,我承认,看不懂*/

wndcls.cbWndExtra=0;/*MSDN上的定义是指定额外的字节数分配如下窗口实例。该系统初始化为零字节。如果应用程序使用WNDCLASS注册一个对话框,通过使用资源文件的CLASS指令创建,应用程序必须设置cbWndExtra等于获得了价值为cbWndExtra当应用程序调用GetClassInfo功能在系统对话框类*/

wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_PEN);/*hbrBackgrund变量,如其英文意思,就是背景。HBRUSH是用来强制类型转换的。至于GetStockObject(WHITE_PEN),是因为它本身也是一个函数,必须给它的成员变量赋值。参照MSDN,上面有很多标准*/

wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);/*同样的,hCursor即是光标(h是句柄的符号,具体再讨论),它有两个变量,第一个是hInstance,即实例。也就是说到底是属于哪个窗口,第二个是光标类型,同样,MSDN给我们提供了很多种*/

wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);/*Icon是图标,即窗口最左上角的那个小图标(最小化时在桌面下面栏上的那个),也是两个变量,第一个是也是hInstance,第二个是图标类型*/

wndcls.hInstance=hInstance;/*告诉我们,当前我们创建的窗口的实例号,就是hInstance*/

wndcls.lpfnWndProc=WinWinProc;/*指定一个过程函数,也就是说我们建好的这个窗口要是对它进行操作的话,用哪个函数进行响应,系统会自动调用,但是函数具体是什么,要我们自己写*/

wndcls.lpszClassName="winldra";/*类的名字,我们创建的窗口类的名字*/

wndcls.lpszMenuName=NULL;/*窗口菜单的名字*/

以上三个变量都是lp开头,即是长指针

wndcls.style=CS_HREDRAW | CS_VREDRAW;/*类的类型,这里面有个概念需要理解——宏,*/

   

二、窗口类设计完成,接下来是注册窗口类

 

       RegisterClass(&wndcls);/*注册窗口类,(&wndcls取地址符)*/

       

三、利用CreateWindow函数创建窗口

HWND hwnd;/*创建句柄*/

      hwnd=CreateWindow("Windlra","疯狂的程序员",WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL);/*使用CreateWindow函数创建窗口,查询MSDN,依次给变量赋值*/

 

四、显示及更新窗口

       ShowWindow(hwnd,SW_SHOWNORMAL);/*显示窗口,两个变量,第一个是到底显示哪一个窗口,第二个是显示的状态*/

       UpdateWindow(hwnd);/*刷新窗口*/

 

 

 

窗口创建完成后,需要设置消息循环

 

 

MSG msg;//系统自动会生成一个消息队列

       while (GetMessage(&msg,NULL,0,0))//利用GetMessage函数来从消息队列中提取消息

       {

             TranslateMessage(&msg);//转换消息,把按键等消息转换为char消息

             DispatchMessage(&msg);//传递消息,把char消息传递给过程函数

       }/*消息循环,*/

       return 0;

}

 

让我们通俗一点来理解,应用程序是不能直接控制电脑的,它们只能接受消息,处理消息,发出消息。它们的消息会被系统自动生成一个消息队列。我们按鼠标或者键盘,由TranslateMessage函数转换成char消息,再由DispatchMessage函数传递给过程函数。好比应用程序就是人的大脑,它只能接受生物电流,处理生物电流,发出生物电流。它是不和具体的肌肉(好比输入输出设备)打交道的。而我们的神经系统好比操作系统。

 

到现在,我们的程序已经基本构建好了,只有一个问题,我们的构成函数还没有写,好比我们创建一个窗口,但是我们让它实现功能,而这个具体的功能需要我们自己写。这个函数,就叫做过程函数。

 

同样的,过程函数到底怎么写呢?我们同样查询MSDN。得到如下:

 

LRESULT CALLBACK WinWinProc(

    HWND hwnd,

    UINT uMsg,

    WPARAM wParam,

    LPARAM lParam

)

 

现在我们来完成过程函数的具体内容,现在让我们想想我们需要什么样的功能。首先,我们要用我们按下键盘的某个按钮,窗口就会弹一个小窗口出来,还有就是点击鼠标左键,然后是我们调整窗口大小,最后还有关闭窗口啦。重要的是,我们只对这些消息感兴趣,所以我们又要用到消息缺省。

Switch case 语句来实现,(额,那个,我承认,我不懂。C语言没过关呀)

 

{

       switch (uMsg)

       {

       case WM_CHAR://char消息

               char szChar[20];

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

        MessageBox(hwnd,szChar,"Windlra",0);

break;

       case WM_LBUTTONDOWN://鼠标左键消息

         MessageBox(hwnd,"mouse clicked","Windlra",0);

         HDC hdc;//DCDevice Context)设备描述表

                hdc=GetDC(hwnd);//获取dc句柄

                TextOut(hdc,0,50,"疯狂的程序员",strlen("疯狂的程序员"));//文本输出函数

                ReleaseDC(hwnd,hdc);//释放dc

               break;

       case WM_PAINT://窗口放大缩小消息

               HDC hDc;

               PAINTSTRUCT ps;

               hDc=BeginPaint(hwnd,&ps);

               TextOut(hDc,0,0,"圣哥制作",strlen("圣哥制作"));

               EndPaint(hwnd,&ps);//窗口重绘,也就是刷新。

 

 

               break;

       case WM_CLOSE://关闭窗口消息

               if (IDYES==MessageBox(hwnd,"是否真的结束程序?","Windlra",MB_YESNO))

               {

          DestroyWindow(hwnd);//销毁窗口

               }

               break;//关闭窗口

       case WM_DESTROY://销毁窗口消息

               PostQuitMessage(0);//退出程序

               break;

       default://缺省,即忽略无关消息

               return DefWindowProc(hwnd,uMsg,wParam,lParam);//缺省处理,实际上就是忽略其他无关的消息

       }

       return 0;

}

 

到现在为止,程序就算编写完了,需要注意的是应该在Win32 Application工程下创建,而不能在Win32Console Application工程下创建。(坦白说,工程栏下面那么多东西,什么是什么根本不知道。)

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值