Windows开发的常识

1)窗口

Windows中最基本的概念也许就是窗口了,每一个前台程序都至少有一个窗口,一个窗口也是你可以看到的部分,比如,QQ有如下的登录窗口
基本上你在Windows中可见的都是一个窗口,窗口也是Windows中用于用户直接交互的基本元素(GUI程序)。

2)句柄

窗口、文件、socket、信号量、管道、邮槽(mailslot)……都是Windows平台中的基本对象,为了操作这些对象,我们需要一个能够引用这些对象的东西,这个引用这些对象的东西就是句柄(Handle)。句柄对于资源就像遥控器对于电视机,用遥控器能更好地操作电视机而不用关心内部实现的细节,句柄也是这样的,用句柄你能更好地操作Windows对象,而不需要关系其内部的实现细节。事实上,你想操作Windows对象也只能通过句柄操作。比如,你想操作一个线程,你看看SuspendThread的原型如下所示:(第一个参数就是一个线程句柄)
Syntax
DWORD WINAPI SuspendThread(
__in HANDLE hThread
);

又比如,你想读一个文件,其函数ReadFile的原型如下:( 第一个参数就是一个文件的句柄。)

BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);

…………类似的例子还有很多,基本上想操作Windows对象都需要指向它们的句柄,句柄在语义上与C中的 指针一样,但是,语法上是完全不一样的。

3)进程

一些操作系统教材上对进程的定义为:进程是一个程序的一次运行过程。这个定义其实是对的,但是,也是错的,为什么呢?在Windows之前还有许多其它的操作系统,比如OS 360、UNIX……进程的概念提出来的时候Windows 还根本没出生呢。不过,在Windows中,进程的概念完全不是这样的,在Windows里面,进程是程序隔离的基本单元,每一个32位应用程序在自己的进程空间里面运行,进程只为这个程序提供4G的虚拟地址空间,并且,不同的进程之间互相不干扰(当然,后面会讲到,进程之间会通信)。

4)线程

在Windows里面,真正运行程序的其实是线程,线程在进程提供的4G虚拟地址空间里面运行,它执行PE文件的.text段。也就是说,线程才是真正的执行体。

基本的正常的Windows程序

代码

创建一个工程,还是按照上次的方法,在上一节里面有,然后输入以下代码:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("BossJue");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {0};
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = hInstance;
wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = szAppName;
wndclassex.hIconSm = wndclassex.hIcon; if (!RegisterClassEx (&wndclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
szAppName,
TEXT ("WindowTitle"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL); ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd); while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static const LPTSTR text = TEXT("Hello,World");
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
return (0); case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
TextOut (hdc, 0, 0, text, lstrlen(text));
EndPaint (hwnd, &ps);
return (0); case WM_DESTROY:
PostQuitMessage (0);
return (0);
}
return DefWindowProc (hwnd, message, wParam, lParam);
}

运行

按下Ctrl + F5,你可能会碰到如下的链接错误:


不要急,这个错误的设置是因为Windows把这个程序当作console程序,而console程序默认入口函数是main,而我们在这里面并没有定义main,而是定义了一个叫WinMain的入口函数,所以链接器不认,而我们希望的却是编译器认为我们这个程序是一个GUI程序,GUI程序的入口函数是WinMain(如果你用#pragma comment(linker…………)修改的话当然也是可以的,这种方法我在第一章里面就写到了。当然,我们还可以直接在Visual Studio IDE里面直接设置,方法是打开项目属性,然后如下设置:
这样设置之后,再按Ctrl + F5,有没有看到如下的一个窗口呢?
对,就是这样,你看到的就是一个正常的Windows程序的编写。

代码解释

编写Windows程序的过程

编写一个Windows程序,你需要做的是三步,第一步是注册一个窗口类,第二步是创建窗口,第三步是编写消息响应函数。其中第一步和第二步是基本固定的,除了个别的参数需要自己调整之外,最重要的是第三步,
一个Windows程序中,代码量最大的基本都在第三步。在Windows应用程序里面,如果我们想要接收用户的输入、在窗口上面显示一些信息……我们都需要处理相关的消息,Windows把与这个程序相关的事件都以消息告诉程序,至于怎么处理这些消息,则是我们自己的事情。上面的RegisterClassEx (&wndclassex)其实就是注册窗口类CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, 
                 szAppName, 
                 TEXT ("WindowTitle"),
                 WS_OVERLAPPEDWINDOW,
                 CW_USEDEFAULT, 
                 CW_USEDEFAULT, 
                 CW_USEDEFAULT, 
                 CW_USEDEFAULT, 
                 NULL, 
                 NULL, 
                 hInstance,
                 NULL); 其实就是创建窗口,LRESULT CALLBACK WndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam)其实就是那个消息处理函数,只不过,这个消息处理函数不需要我们自己调用,当有消息的时候,Windows会自己调用这个函数来处理,我们只需要编写处理代码,但是,编写的代码不需要我们自己手动调用(这也许就是Callback函数的原因)。

剩下的

剩下的如果还有不懂的自己可以读msdn,比如,对CreateWindow不熟悉,可以直接在MSDN里面搜索CreateWindow,MSDN不仅会告诉你这个函数怎么用,还会告诉你消息循环是什么之类的,在此我就不仔细展开说明了。

[置顶] 《Windows编程零基础》__2 一个完整的程序的更多相关文章

  1. 《Windows编程零基础学》第零节

    首先很开心申请到了这一个专栏<Windows编程零基础学> 这是第一篇文章,在这里,我将讲述一些基础的知识. 什么是Windows编程 所谓Windows编程就是在Windows平台上开发 ...

  2. 编程零基础应当如何开始学习 Python?

    提前说一下,这篇福利多多,别的不说,直接让你玩回最有手感的怀旧游戏,参数贴图很方便自己可以根据喜好修改哦. 本篇通过以下四块展开,提供大量资源对应. 选一个好版本 有没有看过<在下坂本,有何贵干 ...

  3. Java 零基础跑起第一个程序

    Java 零基础跑起第一个程序 一 概述 1  java代码编译 编译后才干在计算机中执行.编译就是把人能看懂的代码转换成机器能看懂的形式 2 java的长处 一次编译.到处执行.由于java代码是在 ...

  4. 学习ASP.NET Core Blazor编程系列二——第一个Blazor应用程序(中)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 四.创建一个Blazor应用程序 1. 第一种创 ...

  5. 学习ASP.NET Core Blazor编程系列二——第一个Blazor应用程序(下)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  6. 学习ASP.NET Core Blazor编程系列二——第一个Blazor应用程序(完)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  7. Siki_Unity_1-4_C#编程(零基础)

    1-4 C#编程(零基础) 任务1:第一章课程资料 任务2:简介 任务3:安装设置IDE工具 Unity内置IDE:MonoDevelop 推荐Visual Studio 下载/安装 VS Commu ...

  8. [置顶] JDK工具(零)--简要介绍JDK1.6自带的42个工具

    Java的开发人员肯定都知道JDK的bin目录中有“java.exe”和“javac.exe”这两个命令行工具, 但并非所有的Java程序员都了解过JDK的bin目录之中其它命令行程序的作用. JDK ...

  9. [置顶] Windows显示驱动(WDDM)编程初步(2)

    欢迎转载[作者:张佩][原文:http://www.yiiyee.cn/Blog/wddm2/] 第二部分专门只讲VIDPN.这是后面内容的基础.WDDM框架用VIDPN这个概念,来描述它所要处理的显 ...

随机推荐

  1. AI 行为树

    by AKara 2010-12-09 @ http://blog.csdn.net/akara @ akarachen(at)gmail.com @weibo.com/akaras 谈到游戏AI,很 ...

  2. Hide Xcode8 strange log.

    Product > Scheme > Edit Scheme Environment Variables set OS_ACTIVITY_MODE = disable

  3. VS2010开发2dx无法解析的外部符号解决记录

    首先新建HelloWorld项目... 想使用Cocos2d扩展包需要引入相关头文件,如:#include “cocos-ext.h”...接下来我们右键工程属性->配置属性->c/c++ ...

  4. 【MySQL for Mac】终极解决——MySQL在Mac的字符集设置

    这个问题烦恼一天了,现在终于得以解决.分享给大家 首先贴出来,亲测不可行的博客连接: http://www.2cto.com/database/201305/215563.html http://bl ...

  5. JavaScript 现状:方言篇

    导读 JavaScript 和其他编程语言有一个很大的不同,它不像单纯的一个语言,而像一个由众多方言组成大家族.从 2009 年 CoffeeScript 出现开始,近几年出现了大量基于 JavaSc ...

  6. C++ primer里的template用法

    来源:http://c.chinaitlab.com/cc/ccjq/200806/752604_2.html --  template 的用法    在程序设计当中经常会出现使用同种数据结构的不同实 ...

  7. codeforces 675E Trains and Statistic 线段树+贪心统计

    分析:这个题刚看起来无从下手 但是我们可以先简化问题,首先可以固定起点i,求出i+1到n的最小距离 它可以到达的范围是[i+1,a[i]],贪心的想,我们希望换一次车可以到达的距离尽量远 即:找一个k ...

  8. C++继承与派生的概念、什么是继承和派生

    在C++中可重用性是通过继承(inheritance)这一机制来实现的.因此,继承是C++的一个重要组成部分. 前面介绍了类,一个类中包含了若干数据成员和成员函数.在不同的类中,数据成员和成员函数是不 ...

  9. WeChat Official Account Admin Platform Message API Guide

    Keyword: WeChat Message API Text Image Location Link Event Music RichMedia Author: PondBay Studio[We ...

  10. Android应用性能优化笔记(java代码优化)

    Java代码优化  缓存结果:  如果计算代价过高,最好把过去的结果缓存起来. 伪代码如下: result=cache.get(n);        //输入参数n作为键 if(result==nul ...