初步认识win32基础框架1
这是我第一次写博客,目的也很简单,就是希望自己能对学习的知识有个整理,以后能方便查阅,同时也希望这些内容能帮助到一些人。
今天主要介绍win32的基础框架, 我使用的开发环境是VS2013.使用的语言是C/C++
windows四大程序模块:
1.1控制台程序
没有自己的窗口,dos-显示或者运行程序,入口mian()
1.2窗口程序
有自己的窗口,win32,mfc,qt,入口WinMain
1.3动态库
后缀dll,不可以单独运行,直接注入到可执行程序中
入口函数DllMain,不是必须.
1.4静态库
以lib为后缀的程序,只用来存储代码和数据.
执行程序直接赋值代码,没有入口函数
win32 概述:
Win32 API作为 Microsoft 32位平台(包括:Windows 9x,Windows NT3.1/4.0/5.0,WindowsCE)的应用程序编程接口,它是构筑所有32位Windows平台的基石,所有在Windows平台上运行的应用程序都可以调用这些函数。
win32基础框架 :
(使用vs2013自动生成的win32项目,不会的,可以参考https://jingyan.baidu.com/article/ea24bc398573b3da62b33104.html)如下:(只展示.cpp部分)
// test.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "test.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
运行的大致效果如下图所示
下面来主要介绍.cpp部分的代码的大致功能
1.头文件
#include "stdafx.h"
#include "test.h"stdafx.h 是 Standard Application Framework Extensions(标准应用程序框架的扩展)的缩写,
它里面包含的内容如下
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//#pragma once //避免一个文件被多次包含,只是从物理上减少重复包含。
#include "targetver.h" //这个里面包含的是目标版本的环境,也就是开发平台的环境,即能够运行在Windows什么系统上。
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h> //从事windows开发的,必须要的头文件// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// TODO: 在此处引用程序需要的其他头文件
也就是说,包含stdafx.h的目的就是把公共的常用的头文件包含进去,减少工程中每个.cpp 文件的包含次数,也就提高了编译的效率
2.介绍字符集概念和编码方式
字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。
编码方式
1从windowsNT开始,windows完全使用unicode来构建,所以核心函数(创建窗口,显示文本,字符串处理)都提供了unicode版本.
2在window中,函数通常有两个版本,一个带w(wide)结尾和带A(ASNI)结尾的;例如CreateWindowExA(….)和CreateWindowExW(…),通常情况,我们只接使用CreateWindowEx就可以,如果是unicode编码方式会有一个UNICODE的宏,会直接根据条件编译调用后缀是W版本的
3.windows API函数(openFile ,winExec等)只兼容于ANSI,不兼容unicode编码,所以需要转换成unicode效率低下并且转换是有可能有bug,所以用Createprocess和createfile替换,
4.ANSI中字符串处理 Strlen(…)
Unicode中字符串处理 Wcslen(…)
兼容版本字符串处理函数 _tcslen();
5unicode编码方式是两个字节代表一个字符,需要在字符串前加L,或者加_T(字符串)----兼容版本, sizeof(L“TANZHOU”) = 16,
6.运行安全检查:添加头文件StrSafe.h
Scanf 警告不安全,可能会操作一块布可以操作的内存.导致内存错误,所以微软重新提供_s的安全版本.
7.修改unicode编码方式截图如下vs的环境修改
3介绍入口函数_tWinMain() 相对于c/c++语言的改变,以及Windows函数的特点和窗口创建的流程
以前刚学c/c++编程的时候,经常使用的入口函数 是main()函数, 但是微软为Windows开发者封装了一套函数,包括入口函数也进行了封装,所以入口函数变成了WinMain。使用_tWinMain() 是利用了vs编译器自已定义的宏,如果是unicode编码方式会有一个UNICODE的宏 这样的话,如果你的编译环境是Unicode编码,会自动将_tWinMain()装换成宽字节对应的函数。(需要包含头文件 <tchar.h>, 才能做到这样的效果。)
//多字节,宽字节,以及tchar的使用:
//需要从外部加载或输入字符串用多字节
//tchar很方便,但是在项目中应该有选择性的直接使用char或wchar_t
//只要和字符串相关的函数都会有2套//Windows函数的相对于c/c++的一些改变:
//WinMain win32项目的入口函数
//win32里面会接触win32的数据类型
//数据类型都是基于C语言的,在C语言的类型上面重命名,1、已区别C语言;2、能够做到见名知义
//1、H开头,在win32里面叫句柄(无类型指针)
//2、P LP开头,在win32里面代表指针
//3、win32数据类型全大写//Windows窗口创建的流程
1.入口函数
2.注册窗口
3.创建窗口
4.显示窗口
5.更新窗口
6.消息循环
4.介绍入口函数_tWinMain() (说明部分直接写在注释里)
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, //实例句柄(什么是实例, 就好比一个文本文件相对于记事本 //软件而言)
//APIENTRY 只是一个宏, 为了说明函数的特点,可以不需要
_In_opt_ HINSTANCE hPrevInstance, //父实例句柄
_In_ LPTSTR lpCmdLine, //命令行
_In_ int nCmdShow) //窗口显示方式
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); //这两个宏是为了解除vs的安全等级检查,可以不需要// TODO: 在此放置代码。
MSG msg; //消息结构体变量,用于存放这个软件的消息
HACCEL hAccelTable; //快捷键句柄// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING); //程序需要用到的字符串资源,也就 // 是窗口标题和窗口类名
MyRegisterClass(hInstance); //用户自定义的窗口注册函数// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow)) //实例化窗口
{
return FALSE;
}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST)); //加载快捷键资源
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0)) //主消息循环
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}return (int) msg.wParam; //入口函数结束
}
5.介绍一些刚开始接触win32常用的函数
1 messagebox详解 //消息盒子 ,在win32里面经常用于一些测试和用于用户简单交互
Int MessageBox(HWND hWnd,//窗口句柄
LPCSTR lpTt,//中间显示字符串
LPCSTR lpCap,//标题字符串
UINT uType);//显示类型
2 .音乐媒体处理函数
mmsystem.h—多媒体处理头文件,winmm.lib相关
PlaySound(
第一个: 播放音乐字符串,该参数可以是WAVE文件的名字,或是WAV资源的名字,或是内存中声音数据的指针,或是在系统注册表WIN.INI中定义的系统事件声音。如果该参数为NULL则停止正在播放的声音
第二个:参数hmod是应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL。
第三个:参数fdwSound是标志的组合
SND_SYNC ---同步播放声音,在播放完后PlaySound函数才返回。
SND_ASYNC---用异步方式播放声音,PlaySound函数在开始播放后立即返回。
SND_FILENAME---pszSound参数指定了WAVE文件名。
SND_RESOURCE --pszSound参数是WAVE资源的标识符,这时要用到hmod参数。
SND_PURGE---停止声音。若参数pszSound为NULL,就停止所有的声音,否则,停止pszSound指定的声音。
SND_NOSTOP ----PlaySound不打断原来的声音播出并立即返回FALSE。
SND_LOOP---重复播放声音,必须与SND_ASYNC标志一块使用。
利用MCI 接口实现播放任意格式声音
- #include <mmsystem.h> //导入声音头文件库
- #pragma comment(lib,"winmm.lib")//导入声音的链接库
然后直接用mciSendString函数即可
- mciSendString("open C:/123.mp3" , NULL, 0, 0);
- mciSendString("play C:/123.mp3 ", NULL, 0, 0);
- mciSendString("close movie",buf,sizeof(buf),NULL);
- LPCTSTR lpszCommand, // 指向以null结尾的命令字符串:”命令 设备[ 参数]”
- LPTSTR lpszReturnString,// 指向接收返回信息的缓冲区,为NULL时不返回信息
- UINT cchReturn, // 上述缓冲区的大小
- HANDLE hwndCallback // 在命令串中含notify时,它指定一个回调窗口的句柄
- // 一般为NULL
- );
- 如:mciSendString(L"open sample.wav type waveaudio alias wave", NULL, 0, NULL);
- 更多详细的mciSendString函数介绍参见 https://blog.csdn.net/daiyutage/article/details/8267463