第一个windows程序(windows程序设计笔记)

以下内容大多由《Windows程序设计》,《VC++深入详解》等书籍以及MSDN,网上一些资料和本人的理解整合而来,以作笔记之用。

---------------------------------------------------------------------------------------------

1.几个常用的术语:

API(Application Programming Interface)应用程序编程接口

SDK(Software Development Kit)软件开发包

2.匈牙利符号表示法(节选)

 

 

 理牙利符号表示法对windows程序设计有不小的好处,但是个人认为不必强记。

3.MessageBox(消息框)

 

#include<windows.h>

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)

{

         MessageBox(NULL,TEXT("xfatenet"),TEXT("HelloMsg"),0);

 

         return 0;

}

 

3.1逐个分析所有windows程序入口函数WinMain()的参数:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int nCmdShow)

WINAPI CALLBACK也是如此):

#define   WINAPI   _stdcall

_stdcall   区别于   _cdecl

前者(_stdcall)一般用于调用win32   api函数;函数的参数自右向左通过栈传递。在主调用函数中负责压栈,被调用函数在返回前清理传送参数的内存栈。

后者是c/c++函数的默认调用方式。函数的参数自右向左通过栈传递。由主调用函数进行参数压栈,主调用函数把参数弹出栈。对于传送参数的内存栈是由主调用函数来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。

HINSTANCE hinstance

该参数是一个windows为你的应用程序生成的实例句柄。实例是一个用来跟踪资源的指针或数。句柄是实例指针的索引. 通过句柄能找到实例的地址.

hprevinstance

由名字可以知道是指产生当前实例的应用程序实例,跟踪应用程序以前(prev-)的实例(instance)。

szCmdLine:和int main(int argc,char **argv)函数中的命令行参数相似。

nCmdShow :在启动过程中被传递给应用程序,带有如何打开主应用程序窗口的信息。控制应用程序如何启动。常用的参数值:

 

SW_HIDE

Hides the window and activates another window.(隐藏一个窗口,激活另一个窗口)

SW_SHOW

Activates a window and displays it in its current size and position.(激活窗口按照当前尺寸和位置显示它。)

SW_SHOWNA

Displays a window in its current state. The active window remains active.(以当前状态显示一个窗口,激活的窗口保持激活状态)

SW_SHOWNOACTIVATE

Displays a window in its most recent size and position. The active window remains active.(以上次的尺寸和位置显示窗口,激活窗口保持激活状态)

SW_SHOWNORMAL

Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position (same as SW_RESTORE).(激活和显示窗口,如果窗口最小化或最大化,则恢复到原始尺寸和位置,应用程序将指定该状态)

MessageBox的第一参数通常是窗口句柄,第二参数是显示的内容,第三参数是消息框的标题栏的字符串。第四参数是常数组合用于显示消息框的按钮样式。

#define MB_OK—— 0

#define MB_OKCANCEL—— 1

#define MB_ABORTRETRYIGNORE——2

#define MB_YESNOCANCEL——3

#define MB_YESNO——4

#define MB_RETRYCANCEL——5

可以用或运算符比如MB_OK|MB_ICONEXCLAMATION

如果想有声音的话,最简单的方法调用

BOOL WINAPI MessageBeep(

  __in          UINT uType

);

比如MessageBeep(MB_OK);

 

4. 创建windows应用程序

 

创建一个完整的windows应用程序需要:

1. 创建一个windows

2. 创建一个winProc

3. windows注册windows

4. 用前面创建的windows类创建一个窗口

5. 创建一个能够从事件句柄获得是或向事件句柄传递windows信息的主事件循环。

4.1消息队列和窗口

Windows程序设计是OOP(面向对象),每一个小的可视对象都是一窗口(子窗口或是控件窗口),窗口以消息的形式接受窗口的输入,窗口以消息与其他窗口通讯。Windows给程序发送消息是指windows调用程序中的一个函数,位于windows程序中的函数被称为窗口过程Windows通过窗口过程来给窗口发送消息。窗口过程根据此消息进行处理,然后将控制返回给windows

         Windows程序开始执行后,windows为该程序创建一个消息队列,这个消息队列用来存放该程序可能创建的各个不同窗口的消息。程序中有一段代码,叫做消息循环。用来从队列中取出消息。并且将他们发送到相应的窗口过程。有些消息直接发送给窗口过程,不用放进消息队列中。

4.2 创建一个windows

控制windows类信息的数据结构有两个:WNDCLASSWNDCLASSX

看下WNDCLASSX的结构:

 

  

 

 

 

4.2.1.注册windows

 

windows类已经定义并且存放在winclass中,必须将新的类注册,可以使用RegisterClassEx()RegisterClass()这两个函数实现,前者对应WNDCLASSX,后者对应WNDCLASS

函数原型:

ATOM RegisterClassEx(         

CONST WNDCLASSEX *lpwcx

);

参数是一个指向新类定义的指针。

4.3 创建窗口

创建一个窗口使用CreateWIndowEx()或是CreateWindow()函数,下面来看下CreateWindowEx()的函数原型

 

4.3.1.显示和更新窗口

创建完窗口后,窗口却不一定可见,如果dwStyle没有设为为WS_VISIBLE,那就要手工显示窗口:

 

ShowWindow(hwnd,nCmdShow)

然后让windows更新窗口的内容

UpdateWindow();

 

4.4.事件句柄(event handle)| WinProc(窗口过程)

就是当事情发生时windows从主事件循环调用的回调函数。

每一个windows类都有一个独立的事件句柄,称为windows procedure 简称winproc(窗口过程)。

当运行任务时,窗口和其他应用程序窗口就会产生事件和消息,所有的消息进入一个队列,而该窗口消息发送到该窗口的专用队列中,然后主事件循环检索这些消息,并且将他们发送到该窗口的winproc(窗口过程)中来处理。

窗口过程函数原型:

LRESULT CALLBACK WindowProc(

  HWND hwnd, //窗口句柄

  UINT uMsg, //消息标识符

 //进一步匹配或分类发送到msg参数中的信息

  WPARAM wParam,

  LPARAM lParam

);

例子:

 

4.5 主事件循环

主事件循环函数

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

{

         //虚拟加速键翻译器,把虚拟键消息转为字符消息

         TranslateMessage(&msg);

         //分派消息到窗口过程,由窗口过程来处理消息

         DispatchMessage(&msg);

}

MSG结构:

typedef struct tagMSG {

  HWND hwnd; //产生消息的窗口

  UINT message; //消息标识符

  //进一步匹配或分类发送到msg参数中的信息

  WPARAM wParam;

  LPARAM lParam;

  DWORD time; //消息事件发生的时间

  POINT pt; //鼠标位置

} MSG;

GetMessage()函数原型

//GetMessage()除了WM_QUIT返回值,其他都返回非零值。

BOOL GetMessage(

  LPMSG lpMsg, //GetMessage()从消息队列中取出的消息

  HWND hWnd, //窗口句柄,通常设为NULL,接受调用线程的所有窗口的窗口消息

  UINT wMsgFilterMin, //要获取的窗口消息的最小值

  UINT wMsgFilterMax //要获取的窗口消息的最大值,最小值和最大值设为,则为接受所有消息

);

可以看出,当程序在等待通过GetMessage()传递的消息的同时,主事件循环基本上是锁定的。如果要实现实时的无等候的事件循环,可以用PeekMessage()函数

BOOL PeekMessage(        

         LPMSG lpMsg,

    HWND hWnd,

    UINT wMsgFilterMin,

    UINT wMsgFilterMax,

         //控制如何从消息序列中检索消息

    //PM_NOREMOVE:PeekMessage()处理后,消息没有从序列中取出

    //PM_REMOVE:PeekMessage()处理后,消息已经从序列中去除

    UINT wRemoveMsg

);

例子:

while(true)

{

         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))

         {

                   if(msg.message == WM_QUIT)

                   {

                            break;

                   }

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

         }

}

假设GetMessage(&msg,NULL,0,0)写成GetMessage(&msg,hwnd,0,0)会出现什么情况?

当点击关闭时,窗口句柄会被销毁,此时GetMessage(&msg,hwnd,0,0)将会返回-1值,由于在C++中,0是假其他都是真,所以条件为真,循环会继续下去,因此会陷入死循环中。打开任务管理器会看到cpu占用率到了100%(双核的应该是50%

 

整个windows应用程序的创建 过程:

 

一个完整的windows应用程序如下:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值