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. UVA 11374 Airport Express(最短路)

    最短路. 把题目抽象一下:已知一张图,边上的权值表示长度.现在又有一些边,只能从其中选一条加入原图,使起点->终点的距离最小. 当加上一条边a->b,如果这条边更新了最短路,那么起点st- ...

  2. Android Studio进行NDK编程

  3. POJ 3067 Japan

    Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25489   Accepted: 6907 Descriptio ...

  4. 程序破解之 API HOOK技术 z

    API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socke ...

  5. DzzOffice添加动态壁纸例子-Bing每日壁纸

    Bing每日壁纸介绍:bing网站每天会更新一张不同的精选图片. 此压缩包内的程序,可以自动同步更新cn.bing.com网站每天更新的图片,作为dzzoffice的壁纸使用.实现自动每天更换不同的云 ...

  6. STM32 TIM重映射

    复用功能 没有重映射 部分重映射 完全重映射 TIM3_CH1 PA6 PB4 PC6 CH2 PA7 PB5 PC7 CH3 PB0 PB0 PC8 CH4 PB1 PB1 PC9 /**重映射 t ...

  7. g++安装 Gnome/Gtk+开发库 的 环境安装(安装widgets的必要条件)

    sudo yum install gcc-c++ 我在更新软件源后,看了看最新版的GTK开发版是3.0的. 所以,基本可以照搬. sudo yum -t install gtk3 sudo yum - ...

  8. Google Maps API显示地图的小示例

    来源:http://www.ido321.com/1089.html 效果(新版Firefox中测试): 代码: <!DOCTYPE> <html> <head> ...

  9. [学习笔记] Web设计过程中该做和不该做的

    原文网址: http://www.javascriptstyle.com/the-dos-and-donts-of-web-design -该做的: QR代码QR代码即快速响应代码,这是矩阵条形码的一 ...

  10. ACM1995

    /* 汉诺塔V Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...