欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

初步认识win32基础框架1

程序员文章站 2022-04-02 22:57:16
...

      这是我第一次写博客,目的也很简单,就是希望自己能对学习的知识有个整理,以后能方便查阅,同时也希望这些内容能帮助到一些人。

今天主要介绍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;
}

 

运行的大致效果如下图所示

初步认识win32基础框架1

 

下面来主要介绍.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的环境修改

初步认识win32基础框架1

 

 

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);//显示类型

初步认识win32基础框架1

初步认识win32基础框架1

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 接口实现播放任意格式声音

  1. #include <mmsystem.h> //导入声音头文件库   
  2. #pragma comment(lib,"winmm.lib")//导入声音的链接库  

然后直接用mciSendString函数即可 

  1. mciSendString("open C:/123.mp3" , NULL, 0, 0);  
  2. mciSendString("play C:/123.mp3 ", NULL, 0, 0); 
  3. mciSendString("close movie",buf,sizeof(buf),NULL);
  4.   
  5. LPCTSTR lpszCommand, // 指向以null结尾的命令字符串:”命令 设备[ 参数]”
  6. LPTSTR lpszReturnString,// 指向接收返回信息的缓冲区,为NULL时不返回信息
  7. UINT cchReturn, // 上述缓冲区的大小
  8. HANDLE hwndCallback // 在命令串中含notify时,它指定一个回调窗口的句柄
  9. // 一般为NULL
  10. );
  11. 如:mciSendString(L"open sample.wav type waveaudio alias wave", NULL, 0, NULL);
  12. 更多详细的mciSendString函数介绍参见 https://blog.csdn.net/daiyutage/article/details/8267463

 

相关标签: win32