windows编程基础

 

说明:只供学习交流,转载请注明出处

 

windows编程基础

1):APISDK

我们在编写标准C程序的时候,经常会调用各种库函数来辅助完成某些功能:初学者使用得最多的库函数就是printf了,这些库函数是由你所使用的编译器厂商所提供的。在Windows平台下,也有类似的函数可供调用。不同的是,这些函数是由Windows操作系统本身提供的。Windows操作系统提供了各种各样的函数,以方便我们开发Windows应用程序。这些函数是Windows操作系统提供给应用程序编程的接口(ApplicationProgrammingInterface),简称为API函数。我们在编写Windows程序时所说的API函数,就是指系统提供的函数,所有主要的Windows函数都在Windows.h头文件中进行了说明。

我们经常听到Win32SDK开发、QtSDK开发等等说法。那么什么是SDK呢?SDK的全称是Software Development Kit,中文译为软件开发包。比如我们现在要开发与短信猫相关的通信程序,在购买短信猫的同时,厂商会提供短信猫的SDK开发包,以方便我们对短信猫的编程操作。这个开发包通常都会包括短信猫的API函数库、帮助文档、使用手册、辅助工具等资源。也就是说,SDK实际上就是开发所需资源的一个集合。

需要明确的是,APISDK是一种广泛使用的专业术语,并没有专指某一种特定的APISDKWindows操作系统提供了1000多种API函数,作为开发人员,要全部记住这些函数调用的语法几乎是不可能的。那么我们如何才能更好的去使用和掌握这些函数呢?答案是熟练使用MSDN

 

2):窗口

窗口是Windows应用程序中一个非常重要的元素,一个Windows应用程序至少要有一个窗口,称为主窗口。窗口是指屏幕上的一块矩形区域,是Windows应用程序与用户进行

交互的接口。利用窗口,可以接收用户的输入以及显示输出。

一个应用程序窗口通常都包含标题栏、菜单栏、系统菜单、最小化框、最大化框、可调边框,有的还有滚动条。

窗口可以分为客户区和非客户区,客户区是窗口的一部分,应用程序通常在客户区中显示文字或者绘制图形。标题栏、菜单栏、系统菜单、最小化框和最大化框、可调边框统称

为窗口的非客户区,它们由Windows系统来管理,而应用程序则主要管理客户区的外观及操作。

窗口可以有一个父窗口,有父窗口的窗口称为子窗口。

对话框和消息框也是一种窗口。在对话框上通常还包含许多子窗口,这些子窗口的形式有按钮、单选按钮、复选框、组框、文本编辑框等。此外,我们在启动Windows系统后,看到的桌面也是一个窗口,称为桌面窗口,是位于最上层的窗口,由Windows系统创建和管理。

 

3):句柄

Windows具有很强的面向对象特性。Windows对象有很多,譬如桌面、读取所使用的程序等等。那么,如何区分这些东西呢?答案是使用句柄。句柄是引用不同Windows对象的方式。可以使用Windows的句柄、文件的句柄、分配内存的

句柄、图像的句柄等等。系统在创建这些资源时会为它们分配内存,并返回标识这些资源的标识号,这就是句柄。实际上我们也可以将这些句柄看作指针。在使用句柄之前,必须先创建它们,当不再使用时,应当及时销毁它们。如果不销毁它们,最终将导致资源泄露(resourceleak),资源泄露有可能导致系统崩溃,所以,务必确保在适当的时候销毁不再使用的句柄。在windows应用程序中,窗口是通过窗口句柄(HWND)来标识的。我们要对某个窗口进行操作,首先就要得到这个窗口的句柄,这就是窗口和句柄的联系。

 

4):消息与消息队列

Windows程序设计是一种基于消息的事件驱动方式的设计模式,完全不同于传统的DOS方式的程序设计方法。在Windows中,编程的骨架都是响应和发送消息。例如,当用户在窗口中画图的时候,按下鼠标左键,此时操作系统会感知这一事件,于是将这个事件包装成一个消息,投递到应用程序的消息队列中,然后应用程序从消息队列中取出消息并响应。在这个处理过程中,操作系统也会给应用程序“发送消息”。所谓“发送消息”,实际上是操作系统调用程序中一个专门处理消息的函数,称为“窗口过程”。

 

windows程序中,消息是由MSG结构体来表示的。MSG结构体的定义如下:

typedef struct tagMSG

{

HWND  hwnd;

UINT   message;

WPARAM  wParam;

LPARAM   lParam;

DWORD   time;

POINT   pt;

}MSG;

该结构体中各成员变量的含义如下:

hwnd表示消息所属的窗口。我们开发的程序都是窗口应用程序,消息一般都是与某个窗口相关联的。在Windows程序中,用HWND类型的变量来标识窗口。

message变量指定了消息的标识符。在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。但是由于数值不便于记忆,所以Windows将消息对应的数值定义

WM_XXX宏(WMWindow Message的缩写)的形式,XXX对应某种消息的英文拼写的大写形式。例如,鼠标左键按下的消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN,字符消息是WM_CHAR等等。在程序中,我们通常都是用WM_XXX宏的形式来使用消息的。此外,我们可以定义自己的消息,并给窗口发送这些消息,您完全不用担心如何使这些消息与代码联系起来,因为这是应用程序框架的事情。但是另一方面,这也在一定程度上固定了程序设计上的一些结构。

 

wParamlParam用于指定消息的其他附加信息。比如,当我们收到一个字符消息的时候,message成员变量的值就是WM_CHAR,但用户输入的是那些字符,就由wParam

lParam来说明。wParamlParam表示的信息随消息的不同而有变化。

 

timept分别表示消息投递到消息队列的时间和鼠标的当前位置。

 

消息队列:

每一个Windows应用程序开始执行后,系统都会为该程序创建一个消息队列,这个消息队列用来存放该程序创建的窗口的消息。Windows将产生的消息依次放入消息队列中,而

应用程序则通过消息循环不断从队列中取出消息,进行响应。这种消息机制,就是Windows程序运行的基本机制。

 

5):窗口句柄和消息

现在我们将消息与句柄联系起来。假如有一个窗口,且拥有该窗口的一个句柄(称作一个HWND),我们命名该句柄为your_HWND。假设因为其他的窗口刚刚从该窗口上移走,那

么操作系统希望重绘这个窗口。Windows将传递如下所示消息:

PostMessage(your_HWND,WM_PAINT,0,0);

这个函数通过句柄your_HWND给窗口发送了一条绘制消息。最后两个参数用作消息的额外信息,暂时可以不必深究它们的具体细节。

 

现在,应用程序中有一个函数用一个庞大的case语句来处理所有信息。例如:

Void HandleTheMessage()

{

switch(Message)

{

Case WM_PAINT:

DrawWindow();

break;

case WM_KEYDOWN:

break;

......

}

}

以上就是Windows中的消息和句柄的大致工作过程。了解这些后原理后,下面就可以学习一下有关主程序以及窗口创建的知识。

 

6):主程序-WinMain函数

windows操作系统下,用C或者C++来编写MS-DOS应用程序时,最起码要有一个main函数。当用户运行该应用程序时,操作系统会自动调用main。但当编写Windows应用程序时,就一定要有WinMain函数,因为当用户运行该程序时,操作系统首先调用程序中的WinMain函数。该函数一般用来完成某些特殊的任务,其中最重要的任务就是要创建该应用程序的“主窗口”。许多Windows集成开发环境,包括使用Microsoft MFC类库的VisualC++,都通过隐藏WinMain函数及构造消息-控制机制来简化编程。虽然使用MFC编程不再需要过多关注WinMain函数,但是弄清楚操作系统与程序之间的这种关系是最基本的要求。

 

7):创建窗口

Windows窗口在创建之前,其属性必须设定好,所谓属性包括类的名字、图标、光标及窗口过程处理函数等属性。为了设定这些属性,Windows要求注册窗口类,一经注册,就可

以创建更多的同类窗口,无需再次注册。窗口类仅仅定义了窗口的特征,所有创建窗口的对象都用窗口类来创建窗口。程序必须在产生窗口前先利用API函数RegisterClass设定属

性,这一个过程就是注册窗口类。

窗口注册完之后,就可以创建相应的窗口。注册窗口时,必须给函数传递一个指针,这个指针指向一个包含窗口属性的结构。该结构有2个版本,WNDCLASSWNDCLASSEX,前者本来用于Windows早期版本,但现在仍可沿用;后者用于32Windows,该结构包含1cbSize成员和1个指向小图标的句柄,其它两者相同。

WNDCLASSEX定义如下:

typedef struct_WNDCLASSEX

{

UINT cbSize;

UINT style;

WNDPROC lpfnWndProc;

int  cbClsExtra;

int  cbWndExtra;

HANDLE  hInstance;

HICON  hIcon;

HCURSOR  hCursor;

HBRUSH  hbrBackground;

LPCTSTR  lpszMenuName;

LPCTSTR  lpszClassName;

HICON hIconSm;

}WNDCLASSEX;

 

ATOM RegisterClassEx

(

CONST WNDCLASSEX  *lpwcx

);

 

调用过程如下:

WNDCLASSEX wcex;

wcex.cbSize =  sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW| CS_VREDRAW; //窗口风格

wcex.lpfnWndproc = (WNDPROC)WndProc; //窗口过程,处理消息响应

wcex.cbClsExtra = 0;

wcex.cbWndExtra = 0;

wcex.hInstance = hInstance; //程序实例

wcex.hIcon = 0; //图标

wcex.hCursor = LoadCursor(NULL,IDC_ARROW);//光标

wcex.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); //背景色

wcex.lpszMenuName = NULL; //菜单资源

wcex.lpszClassName =YourClassName; //窗口类名

wcex.hIconSm = NULL; //小图标

RegisterClassEx(&wcex); //注册窗口类

 

在此之后,就可以使用函数CreateWindow创建窗口了。不过,这个函数还有11个参数,第1个参数就是:

wcex.lpszClassName = “YourClassName”;

只有用注册过的窗口类名才可以创建窗体。不过,用户一般情况下不用担心这些事情,因为,MFC已经做了其中的大部分事情。如:

⑴在3个应用程序框架里,主要的窗口都已经被创建了,可以直接使用C++对象;

⑵在资源编辑器里,控件窗口也被设计好了,您可以用ClassWizard为控件窗口连接C++对象。

⑶如果是动态创建控件,您只需要用Create等函数来创建窗口,这一过程中,MFC提供了方法来判断窗口类是否注册。若未注册,则先注册,再创建窗口(您完全可以不了解这

些内容)。

 

8):环境变量

和类Unix系统一样,Windows系统也有环境变量,分为系统环境变量和用户环境变量两种。

一般来说,系统环境变量影响所有的用户和程序,但更改系统环境变量后,对已经启动的服务程序并不起作用,因为此服务程序并不知道环境变量已发生改变,需要重新启动操

作系统。

在命令提示符下,运行set可以看到当前所有的环境变量。同时,set也可以更改环境变量的值,但仅对当前的命令提示符下启动的程序起作用。

Windows也提供GUI工具来修改环境变量,做法是单击【开始】菜单,或者在【我的电脑】图标上单击鼠标右键,在弹出的菜单中选择【属性】命令,弹出【系统属性】对话框。

切换到【高级】选项页,单击下方的【环境变量】按钮,弹出【环境变量】对话框,可以查看或修改增加环境变量。

 

环境变量PATH的功能和Unix下的PATH加上LD_LIBRARY_PATH是一样的,同时影响可执行文件和动态链接库。执行命令时,Windows会根据是否含路径,是否是cmd内部命令,当前路径下是否有可执行扩展名的文件,然后再在PATH环境变量(先系统的再到用户的)路径里查找有无可执行扩展名的文件。如果匹配,则执行。对于动态链接库,则是查找是否包含路径,系统的system3232OS情况下)路径,然后是PATH环境变量(先系统的再到用户的)路径里查找动态链接库的文件。

其他需要传递的信息对C/C++程序员影响比较小,因为传递信息的方式已经被存取注册表这种方式取代。

 

9):注册表

注册表可以看作是一个系统的数据库,大量系统及用户的数据在此存放,尤其是配置数据及运行状态数据。这些数据有字符、数字及二进制数组等类型。通过以Reg开头的一系列函数,可以存取注册表数据。

需要注意的是,注册表中的数据是透明的,其他程序及regeditregedt32等系统工具,也可以存取这些数据,这些数据并不是被某个用户所独占的。

 

10)使用MSDN

SDNMicrosoftSoftwareDeveloperNetwork的简称,是微软针对开发者的帮助网络,可以在http://msdn.microsoft.com看到有关的详细介绍。MSDN可以单独购买订阅,也可以在购买VisualStudio套件时得到。

MSDN的安装比较简单,只需要按照向导提示安装即可完成。安装完毕后,可以在Windows的开始菜单里找到【MicrosoftDeveloperNetwork】→【MSDN

LibraryforVisualStudio2005】这一项(因为笔者安装的是这个版本,你的可能会有所不同),通过这个菜单就可以打开MSDN了,也可以在VisualStudio中按下F1键打开MSDN

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端安全配置之Content-Security-Policy(csp)

From: https://www.cnblogs.com/heyuqing/p/6215761.html 什么是CSP CSP全称Content Security Policy ,可以直接翻译为内容安全策略,说白了,就是为了页面内容安全而制定的一系列防护策略. 通过CSP所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、i…

springboot跨域配置

From: https://www.cnblogs.com/nananana/p/8492185.html 前言: 当它请求的一个资源是从一个与它本身提供的第一个资源的不同的域名时,一个资源会发起一个跨域HTTP请求(Cross-site HTTP request)。 比如说,域名A ( http://domaina.example …

字符函数

getchar: 从stdio流中读字符 a getchar(); fputs:指定的文件写入一个字符串(不自动写入字符串结束标记符\0) fgets:从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取 bufsize-1个字符…

SpringBoot配置Cors解决跨域请求问题

From: https://www.cnblogs.com/yuansc/p/9076604.html 一、同源策略简介 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。 同源策略是浏览器安全的基石。 什么是源 源[origin]就…

Server Develop (三) 多进程实现C/S

多进程实现C/S 把上次的多进程简单的添加一个fork就可以实现一个简单的多进程服务器。具体进程创建和使用的函数,有时间得总结一下了~~~~ if(fork()0){char buffer[1024];strcpy(buffer, "this is server! welcom…

l2正则化

在机器学习中,无论是分类还是回归,都可能存在由于特征过多而导致的过拟合问题。当然解决的办法有 (1)减少特征,留取最重要的特征。 (2)惩罚不重要的特征的权重。 但是通常情况下,我们…

机房收费系统的合作版

概述 机房收费系统的合作版自己负责的是B层和Facade层,在做这块的时候有很多的感触:动态SQL语句;设计模式;合作开发应该注意的点。其中动态SQL语句的理解已经在上一篇博客中写了,如果你有意向的话,可以看一…

ajax跨域,这应该是最全的解决方案了

From: https://segmentfault.com/a/1190000012469713 前言 从刚接触前端开发起,跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了,16年时也整理过一篇相关文章,但是感觉还是差…

centos 7.0防火墙导致vagrant端口映射失败

在vagrant上部署了centos7.0后,Vagrantfile端口转发设置后,宿主机访问客户机站点还是无法访问,问题出在:centos7.0以上版本默认会安装firewalld防火墙, firewalld有区(zone)概念,默认在public区,public:指定外部链接可以进入 先查看下当前端口…

如何导入ShareSDK的sample

由于项目需要,最近需要做10几个平台的分享,如果自己去集成,浪费很多时间,而且还很难成功。最后发现Sharesdk,可以满足项目需求。 首先,需要到他们的官网http://sharesdk.cn/下载android版本的SDK。 然后玩了一下他们的…

Spring Boot配置跨域访问策略

From: https://blog.csdn.net/garyond/article/details/80192760 1. 引言 我们在开发过程中通常因为不同应用之间的接口调用或者应用之间接口集成时经常会遇到跨域问题, 导致无法正常获取接口数据,那么什么是跨域? 跨域的解决办法是什么&am…

SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)

【题目链接】 http://www.spoj.pl/problems/PHRASES/ 【题目大意】 求在每个字符串中出现至少两次的最长的子串 【题解】 注意到这么几个关键点:最长,至少两次,每个字符串。   首先对于最长这个条件,我们可以想到二分答案&…

EF5.x Code First 一对多关联条件查询,Contains,Any,All

背景 通过多个部门id获取所有用户,部门和用户是多对多。 已知部门id,获取该部门包括该部门下的所有子部门的所有用户。 关系如下: public class Entity:IEntity{public Guid Id { get; set; }public string CreateUser { get; set; }public D…

Spring5:@Autowired注解、@Resource注解和@Service注解

From: https://www.cnblogs.com/szlbm/p/5512931.html 什么是注解 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如…

C#通过SSH连接MySql

出于安全考虑,有的时候数据库服务器只能通过SSH访问,比如MySql服务装在了服务器A上,并且A机器只允许B机器才能访问,而部署环境可能在C机器上,这时候就要C服务器通过B服务器连接A服务器,这时候就需要用到SSH…

CCNA实验(8) -- PPP HDLC

HDLC帧格式与以太帧格式有很大差别,HDLC帧没有源MAC和目的MAC地址。HDLC不能提供验证,缺少对链路保护。Cisco设备与Cisco设备连接,可用HDLC封装。Cisco设备与非Cisco设备连接,应使用PPP协议。PPP经过4个过程在点到点链路上建立连接…

Spring Boot实战:数据库操作

From: https://www.cnblogs.com/paddix/p/8178943.html 上篇文章中已经通过一个简单的HelloWorld程序讲解了Spring boot的基本原理和使用。本文主要讲解如何通过spring boot来访问数据库,本文会演示三种方式来访问数据库,第一种是JdbcTemplate&#xff0…

PDB调试Python程序

pdb是python内置的调试工具, 它可以在终端中调试Python程序, 这允许pdb在很多无法安装IDE的服务器上使用. 虽然远程调试使用广泛, 但在必要的时候(比如难以在本地搭建运行环境)pdb仍然是一个便利的选择. 我们可以在python源代码中设置断点: i…

不使用中间变量交换2个数据

2019独角兽企业重金招聘Python工程师标准>>> 第一种方法&#xff1a; <!-- lang: cpp -->aab;ba-b;aa-b;可能产生越界和溢出。 第二种方法&#xff1a; <!-- lang: cpp -->aa^b;ba^b;aa^b;这种方法只适用整形数。 写成宏的形式 <!-- lang: cpp -->…

slf4j的简单用法以及与log4j的区别

From: https://www.cnblogs.com/qlqwjy/p/9275415.html 之前在项目中用的日志记录器都是log4j的日志记录器&#xff0c;可是到了新公司发现都是slf4j&#xff0c;于是想着研究一下slf4j的用法。 注意:每次引入Logger的时候注意引入的jar包&#xff0c;因为有Logger的包太多了。…