Windows程序内部运行机制实例详解

本文以孙鑫老师VC++教程中的程序为基础,详细讲解了Windows程序内部运行机制,相信可以帮助大家更好的理解Windows程序运行原理及相应的VC++程序设计。具体内容如下:

创建一个Win32应用程序步骤:

1、编写WinMain函数;

2、创建窗口(步骤如下):

a、设计(一个)窗口类(WNDCLASS)

b、注册(该)窗口类。

c、创建窗口。

d、显示并更新窗口。

3、编写消息循环。

4、编写窗口过程函数。

//WinMain.cpp
#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WinAzeProc(
   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,     // command line
          int nCmdShow       // show state
          )
{
  //设计一个窗口类
  WNDCLASS wndcls;
  wndcls.cbClsExtra = 0;
  wndcls.cbWndExtra = 0;
  wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);
  wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);
  wndcls.hInstance = hInstance;  //应用程序实例句柄由WinMain函数传进来
  wndcls.lpfnWndProc = WinAzeProc;
  wndcls.lpszClassName = "aze_003";
  wndcls.lpszMenuName = NULL;
  wndcls.style = CS_HREDRAW | CS_VREDRAW;

  RegisterClass(&wndcls);  //注册窗口类

  //创建窗口,定义一个变量用来保存成功创建后返回的句柄
  HWND hwnd;
  hwnd = CreateWindow("aze_003", "first Application", WS_OVERLAPPEDWINDOW, 0, 0, 600, 500, NULL, NULL,hInstance, NULL);

  ShowWindow(hwnd, SW_SHOWNORMAL);  //显示窗口
  UpdateWindow(hwnd);    //刷新窗口

  //定义消息结构体,开始消息循环
  MSG msg;
  while( GetMessage(&msg, NULL, 0, 0) )
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

//编写窗口过程函数
LRESULT CALLBACK WinAzeProc(
   HWND hwnd,   // handle to window
   UINT uMsg,   // message identifier
   WPARAM wParam, // first message parameter
   LPARAM lParam  // second message parameter
   )
{
  switch(uMsg)
  {
  case WM_CHAR:
    char szChar[20];
    sprintf(szChar, "char code is %d", wParam);
    MessageBox(hwnd, szChar, "char", 0);
    break;
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, "mouse clicked", "message", 0);
    HDC hdc;
    hdc = GetDC(hwnd);    //不能在响应WM_PAINT消息时调用
    TextOut( hdc, 0, 50, "程序员之家!",strlen("程序员之家!") );
    ReleaseDC(hwnd, hdc);
    break;
  case WM_PAINT:
    HDC hDC;
    PAINTSTRUCT ps;
    hDC = BeginPaint(hwnd, &ps);  //BeginPaint只能在响应WM_PAINT消息是调用
    TextOut(hDC, 0, 0, "http://www.sunxin.org", strlen("http://www.sunxin.org"));
    EndPaint(hwnd, &ps);
    break;
  case WM_CLOSE:
    if( IDYES == MessageBox(hwnd, "是否真的退出?", "message", MB_YESNO) )
    {
      DestroyWindow(hwnd);
    }
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
  }
  return 0;
}

程序运行后显示界面如下:

窗口分为客户区(是窗口的一部分)与非客户区。

标题栏、菜单栏、系统菜单、最小(大)化框、可调边框统称为窗口的非客户区,由Windows系统管理;应用程序主要管理客户区的外观及操作(显示文字、绘制图形)。

对话框、消息框也是一种窗口;对话框上还包括许多子窗口:按钮、单选按钮、复选框、组狂、文本编辑框等。

2、窗口与句柄:

在Windows应用程序中,窗口是通过窗口句柄(HWND)来标识的;要对某个窗口进行操作,就必须要得到这个窗口的句柄。

句柄是Windows程序中一个重要的概念(图标句柄(HICON)、光标句柄(HCURSOR)、画刷句柄(HBRUSH))。

3、消息与消息队列:

Windows程序设计模式是一种事件驱动方式的程序设计模式,主要是基于消息的。(当系统感知到一事件时(如点击鼠标),系统会将这个事件包装成一个消息,投递到应用程序的消息队列中,然后应用程序从消息队列中取出消息并进行响应。在这个处理过程中,操作系统也会给应用程序“发送消息”。“发送消息”:实际指:操作系统调用程序中一个负责处理消息的窗口过程函数)

(1)消息:Windows中,消息由MSG结构体表示,如下: 

//The MSG structure contains message information from a thread's message queue. 

typedef struct tagMSG {
 HWND  hwnd;     //消息所属的窗口,消息都是与窗口相关联的
 UINT  message;   //the message identifier
 WPARAM wParam;    //指定消息的附加消息
 LPARAM lParam;    //指定消息的附加消息
 DWORD time;     //消息投递到队列中的时间
 POINT pt;      //鼠标的当前位置
} MSG, *PMSG;

Windows中,消息是由一个个数值表示的;Windows将消息对应的数值定义为WM_XXX宏(WM:Window Message)的形式,XXX对应某种消息的英文拼写的大写形式。如:WM_LBUTTONDOWN:鼠标左键按下消息、WM_KEYDOWN:键盘按下消息、WM_CHAR:字符消息···

(2)消息队列:每一个Windows应用程序开始执行后,系统都会为改程序创建一个消息队列,这个消息队列用来存放改程序创建的窗口的消息。

(3)进队消息 与 不进队消息:

      进队的消息将由系统放入到应用程序的消息队列中,然后由应用程序取出并发送;

      不进队消息在系统调用窗口过程时,直接发送给窗口;

      两者最终都是有系统调用窗口过程函数对消息进行处理。

4、WinMain函数

(一)MSDN上的WinMain函数定义如下(备有详尽的注释):

//The WinMain function is called by the system as the initial entry point for a Windows-based application. 

int WINAPI WinMain(
 HINSTANCE hInstance,   // handle to current instance当前窗口句柄
 HINSTANCE hPrevInstance, // handle to previous instance前一个打开的窗口句柄
 LPSTR lpCmdLine,     // command line 指定传递给应用程序的*命令行*参数
 int nCmdShow       // show state 指定窗口应该如何显示,如:最大(小)化、隐藏等
);

(二)窗口类的结构体的定义:

(1)本文程序中对应代码如下:

typedef struct _WNDCLASS {
  UINT    style;    //指定*这一类型*窗口的样式,如:CS_HREDRAW、CS_VREDRAW、CS_NOCLOSE、CS_DBLCLKS
  WNDPROC  lpfnWndProc;   //函数指针,指向窗口过程函数(窗口过程函数是一回调函数)
  int    cbClsExtra;   //一般为0
  int    cbWndExtra;   //同上
  HINSTANCE hInstance;   //指定包含窗口过程的程序的实例句柄
  HICON   hIcon;     //指定窗口类的图标句柄
  HCURSOR  hCursor;   //指定窗口类的光标句柄
  HBRUSH   hbrBackground;   //指定窗口类的背景画刷句柄;当窗口发生重绘值,系统使用这里指定的画刷来查处窗口的背景
  LPCTSTR  lpszMenuName;   //指定菜单资源的名字 **菜单并不是一个窗口**
  LPCTSTR  lpszClassName;   //指定窗口类的名字
} WNDCLASS, *PWNDCLASS;

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时有另一方调用的,用于该事件或条件进行响应。

回调函数的实现机制是:

    ①定义一个回调函数。

    ②提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者。

    ③当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。

针对Windows的消息处理机制,窗口过程函数被调用的过程如下:

    ①在设计窗口类的时候,将窗口过程函数的地址赋值给lpfnWndProc成员变量;

    ②调用RegisterClass(&wndclass)注册窗口类,那么系统就有了我们所编写的窗口过程函数的地址。

    ③当应用程序接收到某一窗口的消息时,调用DispatchMessage(&msg)将对消息回传给系统。系统则利用先前注册窗口类时得到的函数指针,调用窗口过程函数对消息进行处理。

提示:一个Windows程序可以包含多个窗口过程函数,一个窗口过程总是与某一个特定的窗口类相关联(通过WNDCLASS结构体中的lpfnWndProc成员变量指定),基于该窗口类创建的窗口使用同一个窗口过程。

lpfnWndProc成员变量的类型是WNDPROC,定义如下:

typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM); //LRESULT=long, CALLBACK=_stdcall WNDPROC是函数指针类型。

注意:WNDPROC被定义为指向窗口过程函数的指针类型,窗口过程函数的格式必须与WNDPROC相同。

在VC++中,资源是通过标识符(ID)来标识的,同一个ID可以标识多个不同的资源(资源的ID本质上是一个整数)。如:菜单资源:IDM_XXX(M表示Menu)、图标资源:IDI_XXX(I表示图标)、按钮资源:IDB_XXX(B表示Button)

可以调用GetStockObject(int fnObject) 来得到系统的标准画刷。声明如下:

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

HGDIOBJ GetStockObject(
 int fnObject  // stock object type
);

GetStockObject函数:返回多种资源对象的句柄,如:画刷、画笔、字体、调色板等;

函数返回时,需进行类型转换。如:

wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

(2)注册窗口类:设计窗口类(WNDCLASS)后,需要调用RegisterClass函数对其进行注册,注册成功后,才可以创建该类型的窗口。声明如下:

ATOM RegisterClass(
 CONST WNDCLASS *lpWndClass // class data, 窗口类对象的指针
               // Pointer to a WNDCLASS structure. You must fill the structure with the appropriate class attributes before passing it to the function.
);

(3)创建窗口:CreateWindow函数声明如下:

HWND CreateWindow(
 LPCTSTR lpClassName, // registered class name 即:窗口类WNDCLASS的lpszClassName成员指定的名称(必须先注册)
 LPCTSTR lpWindowName, // window name  指定窗口的名字
 DWORD dwStyle,    // window style 指定创建窗口的样式 如:WS_OVERLAPPEDWINDOW
 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 作为WM_CREATE消息的附加参数lParam传入的数据指针(一般为:NULL)
);

如果窗口创建成功,CreateWindow函数将返回系统为该窗口分配的句柄;否则,返回NULL。

·注意:在创建窗口之前应先定义一个窗口句柄变量来接收创建窗口之后的句柄值。

显示及更新窗口:

(4)显示窗口:ShowWindow声明如下:

BOOL ShowWindow(
 HWND hWnd,   // handle to window 该参数为成功创建窗口后返回的那个窗口句柄
 int nCmdShow  // show state 如:SW_HIDE、SW_SHOW、SW_SHOWNORMAL、SW_SHOWMINIMIZED、SW_SHOWMAXIMIZED··
);

(5)更新(刷新)窗口:UpdateWindow函数声明原型如下:

BOOL UpdateWindow(
 HWND hWnd  // handle to window 创建成功后的窗口句柄
);

UpdateWindow函数通过发送一个WM_PAINT消息来刷新窗口,UpdateWindow将WM_PAINT消息直接发送给了窗口过程函数进行处理,而没有放到消息队列里面。

(三)、消息循环

窗口 创建、显示、更新后;需要编写一个消息循环,不断的从消息队列中取出消息,并进行响应。

GetMessage()函数:从消息队列中取出消息

BOOL GetMessage(
 LPMSG lpMsg,     // message information 指向一个消息(MSG)结构体,GetMessage从线程的消息队列中取出的消息信息将保存在该结构体对象中
 HWND hWnd,      // handle to window 指定接收属于哪一个窗口的消息;NULL:用于接收属于调用线程的所有窗口的窗口消息
 UINT wMsgFilterMin, // first message 指定获取打的消息的最小值
 UINT wMsgFilterMax  // last message 如果wMsgFilterMin=0和wMsgFilterMax=0,则接收所有消息
);

GetMessage函数接收到除WM_QUIT外的消息均返回非零值。

//消息循环代码,一般形式
  MSG msg;
  while( GetMessage(&msg, NULL, 0, 0) )
  {
    TranslateMessage(&msg); //TranslateMessage函数将虚拟键消息*转换*为字符消息,被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出
    DispatchMessage(&msg);  //DispatchMessage函数分派一个消息到窗口过程,有窗口过程函数对消息进行处理
//DispatchMessage实际上是将消息会传给操作系统,有操作系统调用窗口过程函数对消息进行处理(响应)
  }

Windows应用程序的消息处理机制如下图所示:

Windows应用程序的消息处理过程:

    (1)操作系统就收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。

    (2)应用程序在消息循环汇总调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,如:放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。

    (3)应用程序调用DisPatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。故:DisPatchMessage函数总能进行正确的传递。

    (4)操作利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。

补充:

  (1)从消息队列中获取消息还可以调用PeekMessage函数,函数原型如下:

BOOL PeekMessage(
 LPMSG lpMsg,     // message information
 HWND hWnd,      // handle to window
 UINT wMsgFilterMin, // first message
 UINT wMsgFilterMax, // last message
 UINT wRemoveMsg   // removal options
);

前四个参数与GetMessage函数的参数作用相同;

最后一个参数指定消息获取的方式;如果设为PM_NOREMOVE, 那么消息将不会从消息队列中被移除;如果设为PM_REMOVE, 那么消息将从消息队列中被移除(与GetMessage函数的行为一致)

  (2)发送消息可以使用SendMessage和PostMessage函数。

      SendMessage将消息直接发送给窗口,并调用该窗口的窗口过程进行处理;在窗口过程对消息处理完毕后,该函数才返回(SendMessage发送的消息为不进队消息)。

      PostMessage函数将消息放入与创建窗口的线程相关联的消息队列后立即返回。

      PostThreadMessage函数,用于向线程发送消息。

      对于线程消息,MSG结构体中的hwnd成员为NULL。

(四)、编写窗口过程函数:用于处理发送给窗口的消息

LRESULT CALLBACK WindowProc(  //窗口过程函数的名字可以随便取,如:WinAzeProc,但函数声明与定义要一致;
 HWND hwnd,   // handle to window
 UINT uMsg,   // message identifier 消息代码
 WPARAM wParam, // first message parameter 消息代码的两个附加值
 LPARAM lParam  // second message parameter
);

提示:系统通过窗口过程函数的地址(指针)来调用窗口过程函数,而不是名字。

//编写窗口过程函数
LRESULT CALLBACK WinAzeProc(
              HWND hwnd,   // handle to window
              UINT uMsg,   // message identifier
              WPARAM wParam, // first message parameter
              LPARAM lParam  // second message parameter
              )
{
  switch(uMsg)
  {
  case WM_CHAR:  //通过调用TranslateMessage函数转换得到
    char szChar[20];
    sprintf(szChar, "char code is %d", wParam);
    MessageBox(hwnd, szChar, "char", 0);
    break;
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, "mouse clicked!", "message", 0);
    HDC hdc;
    hdc = GetDC(hwnd);    //用hdc保存GetDC函数返回的与特定窗口相关联的DC的句柄。
                //GetDC()不能在响应WM_PAINT消息时调用
    TextOut( hdc, 0, 50, "程序员之家!",strlen("程序员之家!") );  //TextOut利用得到的DC句柄在指定的位置(0,50)出输出一行文字
    ReleaseDC(hwnd, hdc);  //释放hdc
    break;
  case WM_PAINT:  //当窗口客服区的一部分或者全部变为“无效”时,系统会发送WM_PAINT消息,通知应用程序重新绘制窗口
          //窗口刚创建时,客户区是无效状态,当调用UpdateWindow函数时,会发送WM_PAINT消息给窗口过程,对窗口进行刷新
          //当窗口从无到有、改变尺寸、最小化在恢复、被其他窗口遮盖后在显示时,窗口的客户区都将变为无效,此时系统会给应用程序发送WM_PAINT消息,通知应用程序重新绘制
          //提示:窗口大小发生变化时,是否发生重绘,取决于WNDCLASS结构体中style成员是否设置了CS_HREDRAW和CS_VREDRAW标志
    HDC hDC;
    PAINTSTRUCT ps;    //ps用于接收绘制的信息
    hDC = BeginPaint(hwnd, &ps);  //BeginPaint只能在响应WM_PAINT消息是调用
    TextOut(hDC, 0, 0, "http://www.sunxin.org", strlen("http://www.sunxin.org"));
    EndPaint(hwnd, &ps);
    break;
  case WM_CLOSE:
    if( IDYES == MessageBox(hwnd, "是否真的退出?", "message", MB_YESNO) )
    {
      DestroyWindow(hwnd);
    }
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam); //DefWindowProc调用默认的窗口过程,对应用程序没有处理的其他消息提供默认处理。
//对于大多数的消息,应用程序可以直接调用DefWindowProc函数进行处理。
//在编写窗口过程时,应将DefWindowProc函数的调用放到default语句中,并将该函数的返回值作为窗口过程函数的返回值。
  }
  return 0;
}

提示:要在窗口中输出文字或者显示图形,需要用到设备描述表(Device ConText)。

设备描述表(简称DC):

DC是一个包含设备(物理输出设备,如显示器、设备驱动器)信息的结构体,在Windows平台下,所有的图形操作都是利用DC来完成的。

第30、31行代码:在调用BeginPaint时,如果客户区的背景还没有被擦除,那么BeginPaint会发送WM_ERASEBKGND消息给窗口,系统就会使用WNDCLASS结构体的hbrBackGround成员指定的画刷来擦除背景。如果我们想要让某个图形时钟在窗口中显示,就应该将图形的绘制操作放到响应WM_PAINT消息的代码中,如TextOut()的位置。

第34-48行代码:DestroyWindow函数在销毁窗口后会向窗口过程发送WM_DESTROY消息。注意:此时窗口虽然销毁了,但应用程序并没有退出。故:如果自己要控制程序是否退出,应该在WM_CLOSE消息的响应代码中完成。

   对WM_CLOSE消息的响应并不是必须的,如果应用程序没有对该消息进行响应,系统将把这条消息传给DefWindowProc函数,而DefWindowProc函数则条用DestroyWindow函数来响应 这条WM_CLOSE消息。

第40-42行代码:DestroyWindow函数在销毁窗口后,会给窗口过程发送WM_DESTROY消息, 然后在该消息的响应代码中调用PostQuitMessage函数。PostQuitMessage函数项应用程序的消息队列中投递一条WM_QUIT消息并返回。GetMessage函数只有在收到WM_QUIT消息时才返回0,此时消息循环才结束,程序退成。

  想让程序正常退出,我们必须响应WM_DESTROY消息,并在消息响应代码中调用PostQuitMessage,向应用程序的消息队列中投递WM_QUIT消息。传递给PostQuitMessage函数的参数值将作为WM_QUIT消息的wParam参数,这个值通常用做WinMain函数的返回值。

(0)

相关推荐

  • Windows的钩子机制详解

    一.概述: 了解windows程序设计的人都知道,Windows系统程序的运行是建立在消息传递机制的基础之上的,几乎所有的程序活动都由消息来驱动.钩子机制可以看作是一个消息的中转站,控制系统发出消息的处理和传递.利用钩子,我们可以截获系统发给应用程序的消息,并且在经过处理后决定是否将消息再发给下一个应用程序.利用钩子的这一特性,我们可以创建一个监控程序,收集和控制系统发出的消息. 二.Windows钩子程序的编制 编制Windows的钩子程序,需要用到几个SDK中的API函数.下面列出这几个函数

  • Windows消息传递机制详解

    对于windows程序设计,这里有几个关键词需要注意:消息,消息循环,窗口过程.   所谓的Windows消息传递机制就类似于生活中的物流公司.当寄件人(例如鼠标.键盘)将包裹(消息)交给物流公司(Windows系统)时,物流公司(Windows系统)会进行整理并且派发(整理及派发主要由消息循环完成),交给相应的快递员(窗口过程)来处理.快递员(窗口过程)拿到包裹(消息)后则有多种方式来处理,如立马交给收件人,等一天交给收件人,或转交给其他快递派发,这就需要在窗口过程中用swich/case来区

  • Windows网络命令行程序参数说明

    Windows网络命令行程序  C:\>nslookup www.jb51.net Server:  www Address:  192.168.5.8 Non-authoritative answer: Name:    www.jb51.net Address:  202.103.69.64 这部分包括:  shi 使用 ipconfig /all 查看配置  使用 ipconfig /renew 刷新配置  对于启用 DHCP 的 Windows 95 和 Windows 98 客户,请使

  • C++ 学习之旅 Windows程序内部运行原理

    学习C++与.net不同的是,一定要搞清楚Windows程序内部运行原理,因为他所涉及大多数是操作系统的调用,而.net毕竟是在.netFrameWork上唱戏. 那Windows应用程序,操作系统,计算机硬件之间的相互关系究竟什么了,下面的图就给予很好的解释. 向下箭头①是 应用程序运行判断处理的结果,输出到输出的设备. 向上箭头②是输入设备,输入到操作系统中. 向下箭头③代表API,我们要解释以下API是什么.API是应用程序接口, 表示应用程序可以通知操作系统执行某个具体的动作,如操作系统

  • Windows 服务控制管理器通信的命令行程序

    SC 是用于与服务控制管理器通信的命令行程序. 用法: sc <server> [command] [service name] <option1> <option2>... 选项 <server> 的格式为 "\\ServerName" 可以键入 "sc [command]"以获得命令的进一步帮助 命令: query-----------查询服务的状态, 或枚举服务类型的状态. queryex---------查询服

  • windows的文件系统机制引发的PHP路径爆破问题分析

    1.开场白 此次所披露的是以下网页中提出的问题所取得的测试结果: http://code.google.com/p/pasc2at/wiki/SimplifiedChinese <?php for ($i=0; $i<255; $i++) { $url = '1.ph' . chr($i); $tmp = @file_get_contents($url); if (!empty($tmp)) echo chr($i) . "\r\n"; } ?> 已知1.php存在,

  • windows消息和消息队列实例详解

    本文详细讲述了windows消息和消息队列的原理与应用方法.分享给大家供大家参考.具体分析如下: 与基于MS - DOS的应用程序不同,Windows的应用程序是事件(消息)驱动的.它们不会显式地调用函数(如C运行时库调用)来获取输入,而是等待windows向它们传递输入. windows系统把应用程序的输入事件传递给各个窗口,每个窗口有一个函数,称为窗口消息处理函数.窗口消息处理函数处理各种用户输入,处理完成后再将控制权交还给系统.窗口消息处理函数一般是在注册一个窗口的时候指定的.你可以从典型

  • Windows程序内部运行机制实例详解

    本文以孙鑫老师VC++教程中的程序为基础,详细讲解了Windows程序内部运行机制,相信可以帮助大家更好的理解Windows程序运行原理及相应的VC++程序设计.具体内容如下: 创建一个Win32应用程序步骤: 1.编写WinMain函数; 2.创建窗口(步骤如下): a.设计(一个)窗口类(WNDCLASS) b.注册(该)窗口类. c.创建窗口. d.显示并更新窗口. 3.编写消息循环. 4.编写窗口过程函数. //WinMain.cpp #include <windows.h> #inc

  • Java 反射机制实例详解

    Java 反射机制实例详解 一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,Java和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反射.通过反射,Java可以于运行时加载.探知和使用编译期间完全求和的类.生成其对象实体,调用其方法或者对属性设值.所以Java算是一个半动态的语言吧. 反射的概念: 在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对

  • Java编程Retry重试机制实例详解

    本文研究的主要是Java编程Retry重试机制实例详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下 1.业务场景 应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作.这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务逻辑包装给处理方法返回处理结果:第二步拿到第一步结果或者捕捉异常,如果出现错误或异常实现重试上传逻辑,否则继续逻辑操作. 2.常规解决方案演化 1)try-catch-redo简单重试模式: 包装正

  • java中构造器内部调用构造器实例详解

    可能为一个类写了多个构造器,有时可能想在一个构造器里面调用另外一个构造器,为了减少代码的重复,可用this关键字做到这一点. public class Flower { private String string; private int age; public Flower() { // 先调用public Flower(String string, int age) this("leon", 120); // 先调用public Flower(String string, int

  • 微信小程序 本地数据存储实例详解

    微信小程序 本地数据存储实例详解 前言 如果您在看此文章之前有过其他程序的开发经验,那一定会知道一般例如安卓或者苹果的原生APP都提供了本地的存储功能,甚至可以使用sqlite数据库来做存储.可是微信的小程序框架基于微信本身,其实际运行环境只是在浏览器里面,所以不会提供那么丰富的数据存储实力.但html5开始已经可以在浏览器里面存储数据,好在微信的小程序给这个功能封装好了,这样我们可以使用数据存储. 每个微信小程序都可以有自己的本地缓存,可以通过 wx.setStorage(wx.setStor

  • 微信小程序-getUserInfo回调的实例详解

    微信小程序-getUserInfo回调的实例详解 前言: 这里就不吹嘘微信小程序有多厉害了,毕竟也不是我写的,直接谈谈我在做小程序开发时遇到的奇异Bug. getUserInfo多次调用: 对于wx.getUserInfo应该很多开发者都用过,用于获取用户基本信息,前提是需要用户授权,如果用户先前没有授权,则弹出一个提示框如下: 点击允许后,我们就能拿到用户信息,再进行后面的一系列操作.这一切看起来都是那么美好,可是在某次运行中,点允许授权后,程序并没有按照我们的预期往下执行.最后发现在其他的地

  • Java的SPI机制实例详解

    Java的SPI机制实例详解 SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoader的文档里有比较详细的介绍.究其思想,其实是和"Callback"差不多."Callback"的思想是在我们调用API的时候,我们可以自己写一段逻辑代码,传入到API里面,API内部在合适的时候会调用它,从而实现某种程度的"定制". 典型的是Colle

  • php实现自运行的实例详解

    说明 1.创建一个PHP示例文件:然后输入"ignore_user_abort();". 2.通过"do{$fp = fopen('test.php','a')...}while(true)..."方法实现任务自动执行即可. 关于PHP代码如何自动执行,我们通常做定时任务需要做到代码自动执行,往往会借助系统来实现,例如linux的crontab或者windows的定时计划等等,现在分享一个纯代码实现的自动执行. 下面是用到的一窜PHP的执行代码,效率不是很好,但是能

  • java回调机制实例详解

    java回调机制实例详解 以前不理解什么叫回调,天天听人家说加一个回调方法啥的,心里想我草,什么叫回调方法啊?然后自己就在网上找啊找啊找,找了很多也不是很明白,现在知道了,所谓回调:就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,D这个方法就叫回调方法,这样子说你是不是有点晕晕的,其实我刚开始也是这样不理解,看了人家说比较经典的回调方式: Class A实现接口CallBack callback--背景1 class A中包含一个class B的引用b --背景2 clas

随机推荐