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

  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

猜你喜欢

转载自blog.csdn.net/ASZSYJ/article/details/82077545