第十二章 Winform 框架

目录1 Win32 应用程序结构1.1 Windows 消息循环1.2 窗口过程1.3 创建基于 Win32 的单窗体应用程序1.4 创建基于 Win32 的多窗体应用程序2 .NET Winform 程序与传统 Win32 程序的关联3 Windows Forms 框架4 Winform 程序结构4.1 UI线程4.2 消息循环4.3 窗口过程5 ...
摘要由CSDN通过智能技术生成

目录

1 Win32 应用程序结构

1.1 Windows 消息循环

1.2 窗口过程

1.3 创建基于 Win32 的单窗体应用程序

1.4 创建基于 Win32 的多窗体应用程序

2 .NET Winform 程序与传统 Win32 程序的关联

3 Windows Forms 框架

4 Winform 程序结构

4.1 UI线程

4.2 消息循环

4.3 窗口过程

5 模式窗体与非模式窗体


1 Win32 应用程序结构

1.1 Windows 消息循环

Windows 消息循环结构类似下图:

C++ 中 Windows 消息循环代码类似如下:

MSG msg; // 代表一条消息
BOOL bRet;

// 从UI线程消息队列中取出一条消息
while ((bRet = GetMessage(&msg,NULL,0,0)) != 0)
{
    if (bRet == -1)
    {
        // 错误处理代码,通常是直接退出程序
    }
    else
    {
        TranslateMessage(&msg);   // 转换消息格式
        DispatchMessage(&msg);    // 分发消息给相应的窗体
    }
}

上图显示了 Windows 消息循环的结构,GetMessage 从操作系统中的消息队列(一种数据结构)获取 Windows 消息,(这些消息包括操作系统将用户输入转换而成的、操作系统本身发送给程序的以及其它程序发送给本程序的)。如果获取到的消息不为 WM_QUIT(表示退出含义),那么经过 TranslateMessage 方法进行预处理后,再由 DispatchMessage 将消息投递到指定的窗口过程(WndProc),窗口过程则负责处理消息。

注:GetMessage 方法有三种返回值,当取得 WM_QUIT 消息时,返回 0 值,While 循环退出;当有异常发生时,返回 -1 值;当获取非 WM_QUIT 的其它消息时,返回非 0 非 -1 的值。如果一个程序需要退出,那么 Windows 消息循环所在的线程必须结束,也就是说,While 循环中的 GetMessage 方法必须返回 0 值,由于 WM_QUIT 时 While 循环退出的条件,因此,消息队列中包含有一个 WM_QUIT 消息是程序退出的前提。

C++中 Windows 消息结构体的定义如下:

typedef struct tagMSG {
   HWND        hwnd;
   UINT        message;
   WPARAM      wParam;
   LPARAM      lParam;
   DWORD       time;
   POINT       pt;
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

如上代码所示,消息中包含有消息接收者的窗口句柄 hwnd,消息类型 message(一个数值,代码中常用 WM_PAINT、WM_QUIT 等代表),以及两个消息参数 wParam 和 IParam,还有发送消息时间 time 以及当前光标在屏幕中的坐标位置。消息投递方法 DispatchMessage 就是根据 hwnd 字段,将消息投递给指定窗口的窗口过程,最终由窗口过程处理这一消息。

1.2 窗口过程

消息处理的关键是 DispatchMessage 函数。这个函数根据取出的消息中所包含的窗体句柄,将这一消息转发给此句柄所对应的窗体对象。
而窗体负责响应消息的函数称为 “窗体过程(Window Procedure)”。

窗口过程用 C++ 代码声明类似如下:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   int wmId, wmEvent;
   switch (message)
   {
      case WM_COMMAND:
         wmId = LOWORD(wParam); // 发送消息的控件或菜单的ID
         wmEvent = HIWORD(wParam); // 通知消息
         // 分析菜单选择
         switch (wmId)
         {
            case IDM_ABOUT:
               DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
               break;
            case IDM_EXIT:
               DestroyWindow(hWnd);
               break;
            default:
               return DefWindowProc(hWnd, message, wParam, lParam);
         }
         break;
      case WM_PAINT:
         // draw something here with gdi win32 api
         break;
      case WM_DESTROY:
         PostQuitMessage(0);   // 给消息队列发送一个 WM_QUIT 消息,下一次消息循环时,GetMessage 从操作系统中的消息队列中取出 WM_QUIT 后,While 消息循环就会结束。
         break;
      default:
         return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

注:如果窗口为一个程序的主窗体,那么当这个窗口关闭后,程序应该退出(While 循环结束),又因为当关闭窗体后,系统会有一个 WM_DESTROY 消息发送给窗口过程(注意是直接发送给窗口过程),那我们完全可以在 switch/case 中拦截 WM_DESTROY 消息,然后调用 PostQuitMessage 这个 Win32 API 处理。

在 Windows 中,消息分成了两类:

1、队列消息:需要存入消息队列,然后由消息循环取出来之后才能被窗口过程处理。例如:WM_PAINT、WM_QUIT

2、非队列消息:不需要存入消息队列,也不经过消息循环,它们直接传递给窗口过程,由窗口过程直接处理。例如:WM_DESTROY

注:可以用 PostMessage() 或 SendMessage() 发送消息。PostMessage() 把一个消息放入消息队列后立即返回,也就是当调用 PostMessage(),函数执行完成返回时,很可能消息尚未处理。SendMessage() 直接将消息发送到窗口,直到这个消息处理完成才返回。如果要关闭一个窗口,可以给它发送一个 WM_CLOSE 消息,像PostMessage(hwnd,WM_CLOSE,0,0); 效果跟点击窗口右上角的关闭按钮是一样的。注意这里的 wParam 和 IParam 的值都是0,因为 WM_CLOSE 消息会忽略上述两个参数。

1.3 创建基于 Win32 的单窗体应用程序

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)    //NO.1 程序入口方法
{
   WNDCLASSEX wcex;
   wcex.
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值