第一个手写Win32窗口程序

摘要:
第一个手写Win32窗口程序-Windows编程基础1.Win32应用程序的基本类型1.1.控制台程序不需要完美的Windows窗口,但可以在DOS窗口模式下显示。Win32窗口程序:它将生成自己的窗口,并可以输出结果或接受来自窗口的输入。

第一个手写Win32窗口程序

一 Windows编程基础

1 Win32应用程序的基本类型

1.1 控制台程序
不需要完善的Windows窗口,可以使用DOS窗口
的方式显示。
1.2 Win32窗口程序
包含窗口的程序。可以通过窗口与程序进行交互。
1.3 Win32库程序
提供已有的代码,供其他程序使用。
动态库:DLL 是在执行的时候可以加载的程序。
静态库:LIB 是在编译链接是使用的程序。
1.4 对比
1.4.1 程序的入口函数不同
控制台:main
Win32窗口程序:WinMain
动态库DLL:DllMain
静态库LIB:无

1.4.2 编译链接后存在的形式不同
控制台和Win32窗口程序:EXE文件,可以执行
动态库DLL:DLL文件,无法执行
静态库LIB:LIB文件,无法执行

1.4.3 执行结果不同
控制台:使用DOS窗口,自己没有窗口。
Win32窗口程序:会产生自己的窗口,
可以将结果输出或者从窗口接受输入。
动态库DLL:自己无法执行,提供可以执行
的代码,当EXE等程序执行时,可以使用
这些代码.执行时,该库必须在指定的路径.
静态库LIB: 自己无法执行,提供给程序在
编译链接时使用,将库中的代码嵌入到
程序当中.执行时,不需要该库存在.

二 Win32窗口程序和编译环境

2.1 开发和编译环境
VC1.5 - VC6.0(2008) - VC10.0(2010)

2.1.1 编译器 CL.EXE(在VC安装目录的VC98/Bin目录下)
将原代码编译目标代码. OBJ文件.
2.1.2 链接器 Link.EXE(在VC安装目录的VC98/Bin目录下)
将OBJ文件和库函数链接.生成EXE.
2.1.3 资源编译器 rc.exe(在VC安装目录的MSDev98Bin目录下)
将资源脚本编译成可以链接的文件(RES).

2.2 头文件和库
2.2.1 头文件 windows.h包含了windows
常用的定义等.其他,还包含了一些其他的
头文件:
windef.h - 定义了各种的数据类型
winbase.h- 定义了kernel的相关函数
wingdi.h - 定义了绘图和文字
winuser.h- 窗口 控件等函数
winnt.h - 提供Unicode支持

2.2.2 库
kernel32.lib - 提供进程/线程/内存等等
API函数支持
user32.lib - 包括窗户/界面等等.
gdi32.lib - 提供绘图/文字等。

2.3 Hello World程序

2.3.1 入口函数
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pszCmdLine,
int nShowCmd )
hInstance - 应用程序的实例句柄
hPrevInstance - 该应用程序的前一个实例句柄
pszCmdLine - 命令行参数
nShowCmd - 窗口的显示方式

2.3.2 MessageBox

2.4 编译环境的准备

在VC98的BIN目录下VCVARS32.BAT

2.5 编译CL.EXE
CL的常用选项
/c 只编译不链接
/TC 编译C文件
/TP 编译C++文件
如果不指定,CL会根据文件类型自动区分
/I 头文件所在路径
字符大小写敏感
2.6 链接LINK.EXE
LINK常用选项:
/out:文件名,链接成指定文件名的程序
/LIBPATH:LIB文件存放的路径, /LIBPATH:"E:XXX"
/SUBSYSTEM: CONSOLE/WINDOW
字符大小写不敏感

2.7 执行
正常执行或带参数执行

三 第一个窗口程序

3.1 入口函数WinMain
3.2 窗口处理函数
当窗口处理消息事件时,系统调用该函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // 窗口的句柄
UINT uMsg, // 消息的ID号
WPARAM wParam, // 消息所对应的参数
LPARAM lParam // 消息所对应的参数
);
3.3 注册窗口类型
typedef struct _WNDCLASS {
UINT style; //窗口类的风格
WNDPROC lpfnWndProc; //窗口处理函数
int cbClsExtra; //窗口类附加数据大小
int cbWndExtra; //窗口附加数据大小
HANDLE hInstance; //当前应用程序的实例句柄
HICON hIcon; //窗口图标
HCURSOR hCursor; //窗口的鼠标
HBRUSH hbrBackground; //窗口的背景画刷
LPCTSTR lpszMenuName; //菜单
LPCTSTR lpszClassName; //类型名称
} WNDCLASS;

注册函数 RegisterClass
3.4 创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类型名称
LPCTSTR lpWindowName, //窗口名称
DWORD dwStyle, //窗口类型
int x, //窗口的左上角X坐边
int y, //窗口的左上角X坐边
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //窗口菜单句柄
HANDLE hInstance, //应用程序的实例句柄
LPVOID lpParam //创建的参数,一般为NULL
);

3.5 显示窗口
ShowWindow 显示窗口
BOOL ShowWindow(
HWND hWnd, //显示的窗口句柄
int nCmdShow //显示的方式
);
UpdateWindow 刷新窗口
3.6 消息处理
GetMessage 获取消息
DispatchMessage 派发消息

3.7 程序退出
窗口销毁时,退出程序。在WndProc中实现。
WM_DESTROY: 当窗口销毁时,会调用WndProc
传递给使用者。
PostQuitMessage:发送一个退出消息。

四 资源的处理

4.1 资源和资源脚本
资源:ICON/CUSRUR/BITMAP/MENU......
资源脚本: 扩展名为rc文件。
4.2 编译资源
使用rc.exe编译资源,生成RES文件
4.3 链接资源
使用link.exe将RES文件链接到程序当中
4.4 ICON的使用
LoadIcon从指定程序中加载ICON资源。

HelloWorld.c代码如下:

  1 #include <windows.h>
  2 
  3 
  4 // 2、窗口过程函数
  5 LRESULT CALLBACK WindowProc(  HWND hwnd,
  6                               UINT uMsg,
  7                               WPARAM wParam,
  8                               LPARAM lParam )
  9 {
 10     //判断消息ID
 11     switch (uMsg)
 12     {
 13         case WM_DESTROY:    // 窗口销毁消息
 14             PostQuitMessage( 0 );   //  发送退出消息
 15             return 0;
 16     }
 17     // 其他的消息调用缺省的消息处理程序
 18     return DefWindowProc( hwnd, uMsg, wParam, lParam );
 19 }
 20 
 21 // 3、注册窗口类型
 22 BOOL RegisterWindow( LPCSTR lpcWndName, HINSTANCE hInstance )
 23 {
 24     ATOM nAtom = 0;
 25 
 26     // 构造创建窗口参数
 27     WNDCLASS wndClass = { 0 };
 28     
 29     wndClass.style = CS_HREDRAW | CS_VREDRAW;
 30     wndClass.lpfnWndProc = WindowProc;      // 指向窗口过程函数
 31     wndClass.cbClsExtra = 0;
 32     wndClass.cbWndExtra = 0;
 33     wndClass.hInstance = hInstance;
 34     wndClass.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( 100 ) );// 100为在HelloWorld.rc文件中定义的ID号
 35     wndClass.hCursor = NULL;
 36     wndClass.hbrBackground = (HBRUSH)COLOR_GRAYTEXT;
 37     wndClass.lpszMenuName = NULL;
 38     wndClass.lpszClassName = lpcWndName;    // 注册的窗口名称,并非标题,以后创建窗口根据此注册的名称创建
 39     
 40     nAtom = RegisterClass( &wndClass );
 41     if( 0 == nAtom)
 42     {
 43         MessageBox( NULL, "Register Failed",
 44                     "Error", MB_OK|MB_ICONERROR );
 45         return FALSE;
 46     }
 47     else
 48     {
 49         MessageBox( NULL, "Register Successed",
 50                     "Sucessed", MB_OK );
 51     }
 52     return TRUE;
 53 }
 54 
 55 // 4、创建窗口(lpClassName 一定是已经注册过的窗口类型)
 56 HWND CreateMyWindow( LPCTSTR lpClassName, HINSTANCE hInstance )
 57 {
 58     HWND hWnd = NULL;
 59     // 创建窗口
 60     hWnd = CreateWindow( lpClassName, "Hello World",
 61                   WS_OVERLAPPEDWINDOW,
 62                   0, 0, 500, 300,
 63                   NULL, NULL, hInstance, NULL );
 64     if( NULL == hWnd )
 65     {
 66         MessageBox( NULL, "Create Window Failed",
 67                     "Error", MB_OK|MB_ICONERROR );
 68         return NULL;
 69     }
 70     else
 71     {
 72         MessageBox( NULL, "Create Window Successed",
 73                     "Sucessed", MB_OK );
 74     }
 75     return hWnd;
 76 }
 77 
 78 // 5、 显示窗口
 79 void DisplayMyWnd( HWND hWnd )
 80 {
 81     ShowWindow( hWnd, SW_SHOW );
 82     UpdateWindow( hWnd );
 83 }
 84 
 85 void doMessage()        // 消息循环处理函数
 86 {
 87     MSG msg = { 0 };
 88     // 获取消息
 89     while( GetMessage( &msg, NULL, 0, 0 ) ) // 当接收到WM_QIUT消息时,GetMessage函数返回0,结束循环
 90     {
 91         DispatchMessage( &msg ); // 派发消息,到WindowPro函数处理
 92     }
 93 }
 94 
 95 
 96 // 1、 入口函数
 97 int WINAPI WinMain( HINSTANCE hInstance,
 98                     HINSTANCE hPrevInstance,
 99                     LPWSTR lpCmdLine,
100                     int nShowCmd )
101 {
102     HWND hWnd = NULL;
103     LPCTSTR lpClassName = "MyWnd";  // 注册窗口的名称
104     RegisterWindow( lpClassName, hInstance );
105     hWnd = CreateMyWindow( lpClassName, hInstance );
106 
107     DisplayMyWnd( hWnd );
108     doMessage();
109     
110     return 0;
111 }

HelloWorld.rc资源脚本如下:

其中 100:表示资源的ID号

       ICON:表示资源的类型

     ”resources/ICO.ico“ 表示资源Ico图标的路径

1 100 ICON "resources/ICO.ico"

运行方法:(首先运行VC98/bin/VCVARS32.bat配置好运行环境)

1、在Cmd控制台中找到代码当前路径,使用CL HelloWorld.c /c  命令只编译不链接文件,会生成一个HelloWorld.obj的目标文件

2、使用 rc HelloWorld.rc 命令编译HelloWorld.rc 资源脚本文件,会生成一个HelloWorld.RES的编译过的资源脚本文件

3、使用 link HelloWorld.obj user32.lib HelloWorld.res 链接这几个文件,会生成一个带图标的HelloWorld.exe文件

4、可以在 cmd 窗口中继续使用 HelloWorld 命令运行该程序,也可以点击生成的HelloWorld.exe运行改程序

运行结果如下:

(1)                                                  (2)    

第一个手写Win32窗口程序第1张                                第一个手写Win32窗口程序第2张

(3)可以看到左上角的图标也改变了

第一个手写Win32窗口程序第3张

免责声明:文章转载自《第一个手写Win32窗口程序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇2362: 愚公的遗愿postman--常用授权下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

occamy恶意软件c2分析

删除Trojan:Win32/Occamy.CA4的正确指南 Trojan:Win32/Occamy.CA4被大多数反病毒套件识别为危险的计算机威胁。顾名思义,这是一种有害的特洛伊木马病毒,旨在对它进行远程控制,以在受感染的设备内执行恶意操作。由于Windows Task Manager中列出了该恶意软件的进程,因此可以很容易地检测到该恶意软件的感染。一旦...

delphi 各新版本特性收集

增强的数据库浏览器 BDP 数据提供者相应的数据库浏览器已经在几个地方作了增强。 现在可以简单的将数据从一个BDP数据提供者迁移到另外一个,这个功能能够允许你将一个数据表从一个BDP数据提供者复制另外一个上面. 这样会复制和重新建立复制目标数据表的元数据, 即使这个数据根本就是来之不同的数据源, 如将Oracle的数据迁移到MSSQL上.这和BdpCopy...

zlib的应用

主要分析应用的demo,有空再分析底层实现 官方demo位于zlib-1.2.11contribminizip 对官方代码的分析 /*miniunz.c Version 1.1, February 14h, 2010 sample part of the MiniZip project - ( http://www.winimage.com/...

eclipse官网下载

Provided byIBM Cloud Eclipse IDE for Java Developers http://eclipse.bluemix.net/packages/photon/data/eclipse-java-photon-R-win32-x86_64.zip http://eclipse.bluemix.net/packages/p...

RF环境搭建

前言:自动化运用 数据驱动开发:用户,上下文,场景,数据,验证 自动化用例组织:领域,史诗故事,拓扑和测试用例 用例规划: 三个步骤:确定业务领域,规划用例环境拓扑,规划测试套和测试用例 Robot提供了一个图形化,可编辑的环境。其基础还是python的SSH等库,robot起到一个综合处理的过程。 如果没有robot,那么python写测试用例也可以这样...

转-VS2010常用功能使用介绍

原文链接:http://www.jizhuomi.com/software/27.html 1.几个基础概念 在讲VS2010之前先讲下程序开发过程中的几个基本概念:源程序、目标程序和翻译程序。 源程序就是我们用各种语言写的程序,我们常说写代码其实就是在写源程序。源程序可以是汇编语言或者高级语言等其他语言所写。 目标程序是经过翻译之后生成的程序,可以是机器...