win32程序值窗口程序,以及消息机制

一丶简介

  通过上一讲.我们了解了窗口其实是绘制出来的.而且是不断绘制的过程. 所以窗口的本质是绘制. 但是我们现在看到的窗口程序.都可以点击关闭按钮. 使用鼠标点击会有反应.

而我们要怎么实现那.

  其实鼠标点击是产生了一个消息.  window把这个消息封装成了消息结构体. 发送给了我们的窗口程序.  那么windows怎么知道你点击的那个窗口那?

是这样的. 当我们点击的时候. 会记录点击坐标.消息.等等. windows系统会接受到. 然后遍历内核中的WINOBJ结构. 而这个结构中存储着窗口对象. 窗口对象对应着消息线程.

所以windows一层一层的遍历.则找到了对应的窗口以及窗口对应的线程.然后发送给我们的应用程序.

上面说的我们需要了解. 要知道消息怎么产生的. 怎么传递的.那么下面编程就明白了.

例如下图:

每个应用程序都有一个线程对象. 而这个线程对象如果创建窗口.那么内核中就有这个窗口对象.

如果我们有鼠标点击的消息.键盘消息等等.操作系统都会遍历窗口对象. 而窗口对象也会保存着创建这个窗口对象对应的线程对象. 而这个线程对象中则有消息队列.

这样的话操作系统则会封装消息发送给我们窗口对象.

二丶Wind窗口类结构.创建窗口程序.

1.进行窗口编程需要注意的问题

  在Windows中进行窗口编程.入口点已经改成WinMain了. 有四个参数.

如以下代码所示

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,               //窗口的实例句柄 hinstance代表模块意思 HWND代表窗口意思. HANDLE代表内核对象. HDC 设备上下文.
_In_opt_ HINSTANCE hPrevInstance, //父窗口句柄.不需要.
_In_ LPWSTR lpCmdLine, //命令行参数
_In_ int nCmdShow) //命令. 最大化命令.还是最小化命令.
{ return ;
}
wWinMain  因为有UNICODE跟ASCII区别. 所以我是UNICODE使用wWinMain. A版本就是用WinMain

2.进行Windows编程的调试手法

  在Windows中我们调试程序不能简单的使用printf进行调试.或者打印输出了. 我们可以使用两个API进行操作.

1.Sprintf() 格式化字符串.

2.OutPutDebugString() 输出调试字符串.

具体两个API. 不再累赘.百度搜索即可.

因为OutPutDebugString() 只能打印固定字符串.所以使用sprintf进行格式化字符串.如下面代码.

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{ TCHAR str[] = { NULL };
wsprintf(str,TEXT( "%s"),TEXT("HelloWin32")); //因为是Unicode所以使用W版本.
OutputDebugStringW(str);
return ;
}

我们编译出程序之后.可以使用DebugView这款工具查看.

3.窗口编程的步骤

1.创建窗口类. windows提供的窗口样式.我们需要给定.

2.注册窗口类.创建了窗口我们需要注册到windows系统中.

3.创建窗口.如果注册窗口成功.那么我们需要创建出来这个窗口.并且显示跟更新.

4.消息处理

4.窗口编程需要的主要结构

  窗口的创建Windows已经为我们提供了. 这个结构就是WNDCLASSEXW 结构

看下这个结构中的内容吧

typedef struct _WNDCLASSEX {
UINT cbSize; 扩展的大小. 自己WndClass本身大小.
UINT style; 风格
WNDPROC lpfnWndProc; 窗口回调.消息都要进入这个回调
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance; 实例句柄
HICON hIcon; 图标
HCURSOR hCursor; 光标
HBRUSH hbrBackground; 背景
LPCTSTR lpszMenuName; 菜单名称
LPCTSTR lpszClassName; 类名称
HICON hIconSm; 最小化图标
} WNDCLASSEX, *PWNDCLASSEX;

这个结构就是说.你的窗口是什么样式. 大小.是否有图标. 消息处理函数在哪里等等.需要我们给指定.

5.完整代码.

// WindoS.cpp : 定义应用程序的入口点。
// #include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include "WindoS.h" #define MAX_LOADSTRING 100 // 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING] = TEXT("第一个我的窗口"); // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING] = TEXT("MyWindow"); // 主窗口类名 // 此代码模块中包含的函数的前向声明: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//1.自定义窗口样式
WNDCLASS wcex; wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; //设置回调
wcex.cbClsExtra = ;
wcex.cbWndExtra = ;
wcex.hInstance = hInstance; //设置模块实例句柄
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOS));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + ); //设置背景颜色
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOS);
wcex.lpszClassName = szWindowClass; //设置类名

  //上面主要就是4个参数有用. 回调函数 背景颜色 模块句柄. 类名
//2.注册窗口类
BOOL bRet = RegisterClass(&wcex); //A RegisterClass U RegisterClassW 扩展 RegisterClassExA /ExW
if (bRet == FALSE)
{
return ;
}
//3.创建窗口 并且显示跟更新窗口
HWND hWnd = CreateWindowW(
szWindowClass, //我们的类名
szTitle, //我们自定义的窗口名称
WS_OVERLAPPEDWINDOW, //窗口的创建样式
CW_USEDEFAULT,
,
CW_USEDEFAULT,
,
nullptr,
nullptr,
hInstance, //实例句柄
nullptr);
//上面重要的也就是4个参数.其余参数查询下MSDN.
if (!hWnd)
{
return FALSE;
} ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd); //4.消息循环.
MSG msg;
/* 1参数是消息结构体.操作系统会往里面填写消息.
2 参数窗口句柄 因为每个线程可以有多个窗口.表示我要取那个窗口的消息
3.4 参数表示我要取这个窗口的那个消息. 后面三个参数属于过滤条件 */
while ((bRet = GetMessage(&msg, NULL, , )) != )
{
if (bRet == -)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg); //键盘消息转换为小写.
DispatchMessage(&msg); //分发消息.将我们的消息传递给我们的回调函数处理. 重要函数.此消息会将Windows的消息.发送给我们 定义窗口类的时候给的回调函数.这样我们就可以根据消息执行我们代码了.
}
} return ;
} //
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
// 我们的窗口回调.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND: //菜单消息类型
{
int wmId = LOWORD(wParam); //取低两位为菜单ID.根据菜单ID可以进行操作我们的窗口
// 分析菜单选择:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam); //如果不处理.则必须调用这个函数教给默认的窗口回调处理
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
LineTo(hdc, , );
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return ;
}

创建完毕的结果

三丶消息类型

我们回调中有我们的消息类型.我们可以判断消息类型进行我们不同的操作.

比如菜单消息.

WM_COMMAND.  如果是这个消息.那么回调函数的 wparam等附加信息就是WM_COMMAND的附加消息了. 我们可以取低位得出操作的菜单ID.进而进行消息处理.

WM_PAINT  这个消息是绘制的消息.我们知道.窗口是不断绘制的.所以绘制消息会一直来.

WM_DESTROY  窗口关闭消息. 如果接受到这个消息.则调用API往消息队列中(MSG)中传递退出消息. 此时外层主线程就会结束.

具体API:

  postQuitMessage(0);

当前具体的消息还要查询MSDN. 因为消息种类很多.

windows消息都是WM开头的.

比如查询WM_COMMAND消息

可以清楚的看到.她会告诉你如果是WM_COMMAND消息来了.那么回调函数的参数.分别代表的是什么意思.

win32程序之窗口程序,以及消息机制的更多相关文章

  1. WPF的消息机制(一)- 让应用程序动起来

    原文:WPF的消息机制(一)- 让应用程序动起来 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/powertoolsteam/article/det ...

  2. WPF的消息机制(二)- WPF内部的5个窗口之隐藏消息窗口

    目录 WPF的消息机制(一)-让应用程序动起来 WPF的消息机制(二)-WPF内部的5个窗口 (1)隐藏消息窗口 (2)处理激活和关闭的消息的窗口和系统资源通知窗口 (3)用于用户交互的可见窗口 (4 ...

  3. WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口

    原文:WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/p ...

  4. WPF的消息机制

    前言 谈起“消息机制”这个词,我们都会想到Windows的消息机制,系统将键盘鼠标的行为包装成一个Windows Message,然后系统主动将这些Windows Message派发给特定的窗口,实际 ...

  5. 深入Delphi -- Windows 消息机制

    http://www.txsz.net/xs/delphi/3/Windows%20%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6.htm Windows 消息机制 by m ...

  6. Win32窗口消息机制 x Android消息机制 x 异步执行

    如果你开发过Win32窗口程序,那么当你看到android代码到处都有的mHandler.sendEmptyMessage和 private final Handler mHandler = new ...

  7. windows程序消息机制(Winform界面更新有关)

    windows程序消息机制(Winform界面更新有关) 转自:http://www.cnblogs.com/blosaa/archive/2013/05/31/3109586.html 1. Win ...

  8. Windows程序消息机制浅析

    1.消息  消息是由MSG结构体来表示的.如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lPar ...

  9. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

随机推荐

  1. vue中 关于$emit的用法

    1.父组件可以使用 props 把数据传给子组件.2.子组件可以使用 $emit 触发父组件的自定义事件. vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( ev ...

  2. mqtt mosquitto 源码安装

    下载地址 ububtu  : wget https://codeload.github.com/eclipse/mosquitto/zip/master 安装依赖 sudo apt-get insta ...

  3. java开发师笔试面试每日12题(3)

    1.JDK和JRE的区别是什么? Java运行时环境(JRE)是将要执行Java程序的Java虚拟机.它同时也包含了执行applet需要的浏览器插件.Java开发工具包(JDK)是完整的Java软件开 ...

  4. 我们的爬虫从pyspider开始说起(一)

    看各种爬虫文献也有好几天了,总是感觉下不了手,总结一句“提笔忘字,总是因为看的太多而写的太少”.所以从现在开始,把看到的想到的,需要总结的东西慢慢的都沉淀下来,扎扎实实的走好每一步. 先来说这几天遇到 ...

  5. Windows与系统信息相关的DOS命令

    首先,以管理员身份打开CMD命令框, 输入 start msinfo32:回车之后,出现一个弹窗,上面有大部分的系统信息:系统版本,电脑名称,BIOS,CPU,内存等: wmic bios:显示BIO ...

  6. Windows平台最方便最易用的法语输入法

    原文:http://wenwen.sogou.com/z/q1700007921.htm 对于XP,在“控制面板”中选择“输入法区域设置”,单击“更改”,出现一个“设置”框:选择“添加”,然后选择“法 ...

  7. 1.Spring AOP应用

    首先咱们来了解一下具体的业务场景(这是个真实的项目的业务场景):具体的业务是这样的,现在系统中有六十多个主档(功能模块),每个主档都有新增.修改.删除功能,当我们在对每个主档做这些操作时需要对其记录日 ...

  8. day_12函数默认值,数据类型的补充,函数对象名称空间与作用域,函数的嵌套定义

    复习, 昨天讲了字符串的比较,按照从左往右比较每一个字符,通过字符对应的ASCII码进行比较 函数的参数,‘ 实参与形参 形参:在函数定义时()中出现的参数 实参,在函数调用时()中出现的参数 实参的 ...

  9. weblogic.xml 精妙设置

    1.一:weblogic 页面访问速度比tomcat慢的原因和解决办法 一:weblogic 页面访问速度比tomcat慢的原因和解决办法 公司有个项目,部署在weblogic8.1上之后,发现比在t ...

  10. Tmux会话的使用

    不想看废话的直接拖到下面看干货部分! 我们管理Linux服务器通常是通过ssh远程连接过去,如果在服务器上执行比较耗时的操作,比如下载安装软件.编译等等,如果需要数个小时来完成这些工作,但是又不得不关 ...