通用的 、面向过程式的 高级 计算机程序设计语言
1972 年,为了 移植与开发 UNIX 操作系统 丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言
C 语言最开始是于 1972 年在 美商迪吉多电脑 DEC PDP-11 计算机上被首次实现
在 1978 年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)制作了 C 的第一个公开可用的描述,现在被称为 K&R 标准
截至 1973 年 UNIX 操作系统,C编译器,和几乎所有的 UNIX 应用程序都是用 C 语言编写的。
计算机编程术语 C 语言编程概念
C 语言是以 B 语言为基础的,B 语言大概是在 1970 年被引进的。
C 语言标准是于 1988 年由美国国家标准协会(ANSI,全称 American National Standard Institute)制定的。
最新的 C 语言标准为 C18 ,在它之前的 C 语言标准有 C17、C11…C99 等
目前,C 语言是最广泛使用的系统程序设计语言。
大多数先进的软件都是使用 C 语言实现的。
当今最流行的 Linux 操作系统和 RDBMS(Relational Database Management System:关系数据库管理系统) MySQL 都是使用 C 语言编写的。
最初是用于系统开发工作,特别是组成操作系统的程序
由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。
一个 C 语言程序,可以是 3 行,也可以是数百万行,
它可以写在一个或多个扩展名为 “.c” 的文本文件中,
例如,hello.c。您可以使用 “vi”、“vim” 或任何其他文本编辑器来编写您的 C 语言程序。
C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011,是当前最新的C语言标准。在它之前的C语言标准为C99。
对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符,aligned_alloc函数以及头文件)。
_Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。
_Generic 关键字。
多线程(Multithreading)支持,包括:
_Thread_local存储类型标识符,头文件,里面包含了线程的创建和管理函数。
_Atomic类型修饰符和头文件。
增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件。
删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。
增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。
增加了更多浮点处理宏(宏)。
匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。
静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
新的 fopen() 模式,("…x")。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。
设置 C 语言环境, 确保电脑上有以下两款可用的软件,文本编辑器和 C 编译器。
这将用于输入您的程序。
文本编辑器的名称和版本在不同的操作系统上可能会有所不同。
Notepad 通常用于 Windows 操作系统上,vim/vi 可用于 Linux/UNIX 操作系统上。
通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。
C 程序的源文件通常使用扩展名 .c。
在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。
写在源文件中的源代码是人类可读的源。
它需要"编译",转为机器语言,这样 CPU 可以按给定指令执行程序。
C 语言编译器用于把源代码编译成最终的可执行程序。
如果 HP 或 Solaris,则可以使用各自操作系统上的编译器。
不同的操作系统上安装 GNU 的 C/C++ 编译器。
这里同时提到 C/C++,主要是因为 GNU 的 gcc 编译器适合于 C 和 C++ 编程语言。
使用的是 Linux 或 UNIX,请在命令行使用下面的命令来检查您的系统上是否安装了 GCC:
gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr .......
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
Cent OS Linux
Mac OS X Xcode 开发环境
Windows 上安装 GCC 安装 MinGW
http://mingw-w64.org/doku.php
当安装 MinGW 时,您至少要安装 gcc-core、gcc-g++、binutils 和 MinGW runtime,但是一般情况下都会安装更多其他的项。
添加您安装的 MinGW 的 bin 子目录到您的 PATH 环境变量中,这样您就可以在命令行中通过简单的名称来指定这些工具。
当完成安装时,您可以从 Windows 命令行上运行 gcc、g++、ar、ranlib、dlltool 和其他一些 GNU 工具。
基本构建块之前
最小的 C 程序结构 Hello World 实例
C 程序主要包括以下部分:
#include // stdio.h 是一个头文件 (标准输入输出头文件) ,
// #include 是一个预处理命令,用来引入头文件。告诉 C 编译器在实际编译之前要包含 stdio.h 文件
int main() //所有的 C 语言程序都需要包含 main()主函数。 代码从 main() 函数开始执行。
{
/* 我的第一个 C 程序 */
// /* ... */ 用于注释说明 会被编译器忽略。
printf("Hello, World! \n"); // printf() 用于格式化输出到屏幕。 在 "stdio.h" 头文件中声明。
// 当编译器遇到 printf() 函数时,如果没有找到 stdio.h 头文件,会发生编译错误。
return 0; // 语句用于表示退出程序 终止 main() 函数,并返回值 0。
}
接下来让我们看看如何把源代码保存在一个文件中,以及如何编译并运行它。
$ gcc hello.c
$ ./a.out
Hello, World!
请确保您的路径中已包含 gcc 编译器,并确保在包含源文件 hello.c 的目录中运行它。
如果是多个 c 代码的源码文件,编译方法如下:
$ gcc test1.c test2.c -o main.out
$ ./main.out
test1.c 与 test2.c 是两个源代码文件。
理解 C 语言的其他基本的构建块
C 程序由各种令牌组成
令牌可以是关键字、标识符、常量、字符串值,或者是一个符号。
五个令牌分别是:
printf
(
"Hello, World! \n"
)
;
在 C 程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。 eg:
return 0;
C 语言有两种注释方式:
您不能在注释内嵌套注释,注释也不能出现在字符串或字符值中。
// 单行注释 以 // 开始的单行注释,这种注释可以单独占一行。
/* 单行注释 */ /* */ 这种格式的注释可以单行或多行。
/*
多行注释
多行注释
多行注释
*/
C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。
一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。
C 标识符内不允许出现标点字符,比如 @、$ 和 %。
C 是区分大小写的编程语言。
因此,在 C 中,Manpower 和 manpower 是两个不同的标识符。下面列出几个有效的标识符:
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
下表列出了 C 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。
关键字 | 说明 |
---|---|
auto | 声明自动变量 |
break | 跳出当前循环 |
case | 开关语句分支 |
char | 声明字符型变量或函数返回值类型 |
const | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 |
continue | 结束当前循环,开始下一轮循环 |
default | 开关语句中的"其它"分支 |
do | 循环语句的循环体 |
double | 声明双精度浮点型变量或函数返回值类型 |
else | 条件语句否定分支(与 if 连用) |
enum | 声明枚举类型 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 |
float | 声明浮点型变量或函数返回值类型 |
for | 一种循环语句 |
goto | 无条件跳转语句 |
if | 条件语句 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数返回值类型 |
register | 声明寄存器变量 |
return | 子程序返回语句(可以带参数,也可不带参数) |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
sizeof | 计算数据类型或变量长度(即所占字节数) |
static | 声明静态变量 |
struct | 声明结构体类型 |
switch | 用于开关语句 |
typedef | 用以给数据类型取别名 |
unsigned | 声明无符号类型变量或函数 |
union | 声明共用体类型 |
void | 声明函数无返回值或无参数,声明无类型指针 |
volatile | 说明变量在程序执行中可被隐含地改变 |
while | 循环语句的循环条件 |
C99 新增关键字
_Bool |
_Complex |
_Imaginary |
inline |
restrict |
---|---|---|---|---|
C11 新增关键字
_Alignas |
_Alignof |
_Atomic |
_Generic |
_Noreturn |
---|---|---|---|---|
_Static_assert |
_Thread_local |
只包含空格的行,被称为空白行,可能带有注释,C 编译器会完全忽略它。
在 C 中,空格用于描述空白符、制表符、换行符和注释。
空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,下一个元素在哪里开始。
因此,在下面的语句中:
int age;
在这里,int 和 age 之间必须至少有一个空格字符(通常是一个空白符),这样编译器才能够区分它们。
fruit = apples + oranges; // 获取水果的总数
fruit 和 =,或者 = 和 apples 之间的空格字符不是必需的,
但是为了增强可读性,您可以根据需要适当增加一些空格。
用于声明不同类型的变量或函数的一个广泛的系统
变量的类型决定了变量存储占用的空间
以及如何解释存储的位模式
C 中的类型可分为以下几种:
序号 | 类型与描述 |
---|---|
1 | 基本类型: 算术类型,包括两种类型:整数类型 和 浮点类型。 |
2 | 枚举类型: 算术类型,被用来定义 在程序中 只能赋予其一定的 离散 整数值 的变量。 |
3 | void 类型: 类型说明符 void 表明没有可用的值。 |
4 | 派生类型: 它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。 |
数组类型和结构类型统称为聚合类型。
函数的类型指的是函数返回值的类型
下表列出了关于 标准整数类型 的存储大小和 值范围的细节:
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1 字节 | -128 到 127 或 0 到 255 |
unsigned char | 1 字节 | 0 到 255 |
signed char | 1 字节 | -128 到 127 |
int | 2 或 4 字节 | -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647 |
unsigned int | 2 或 4 字节 | 0 到 65,535 或 0 到 4,294,967,295 |
short | 2 字节 | -32,768 到 32,767 |
unsigned short | 2 字节 | 0 到 65,535 |
long | 4 字节 | -2,147,483,648 到 2,147,483,647 |
unsigned long | 4 字节 | 0 到 4,294,967,295 |
各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主
32位系统与64位系统的存储大小的差别(windows 相同)
为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。
表达式 sizeof(type) 得到 对象或类型的 存储字节大小。
#include
#include
int main()
{
printf("int 存储大小 : %lu \n", sizeof(int));
// %lu 为 32 位无符号整数
return 0;
}
Linux 上编译并执行上面的程序时,它会产生下列结果
int 存储大小 : 4
标准浮点类型 的占用的存储空间大小、值范围和精度的细节:
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4 字节 | 1.2E-38 到 3.4E+38 | 6 位小数 |
double | 8 字节 | 2.3E-308 到 1.7E+308 | 15 位小数 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 | 19 位小数 |
头文件 float.h 定义了宏,在程序中可以使用这些值和其他有关实数二进制表示的细节。
#include
#include
int main()
{
printf("float 存储最大字节数 : %lu \n", sizeof(float));
printf("float 最小值: %E\n", FLT_MIN );
//%E 为以指数形式输出单、双精度实数
printf("float 最大值: %E\n", FLT_MAX );
printf("精度值: %d\n", FLT_DIG );
return 0;
}
float 存储最大字节数 : 4
float 最小值: 1.175494E-38
float 最大值: 3.402823E+38
精度值: 6
void 类型指定没有可用的值。它通常用于以下三种情况下:
序号 | 类型与描述 |
---|---|
1 | 函数返回为空 各种函数 不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status); |
2 | 函数参数为空 函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void); |
3 | 指针指向 void 类型为 void * 的指针代表对象的地址,而不是类型。例如,内存分配函数 void *malloc( size_t size ); 返回指向 void 的指针,可以转换为任何数据类型。 |
一、 C++ primer Plus
在 继承C语言 高效简洁 快速 可移植性 基础上 添加 面向对象 编程 和 泛型编程 支持
模板特性——泛型编程
写一个类的时候表明这个initialize函数是这个类的构造函数
array.join(分隔符separator) 用于把数组中所有元素 放入一个字符串
parseInt() 函数可解析一个字符串 ,并返回一个整数。
parseInt(string, radix)
要解析的数字的基数
array_unshift() 函数在数组开头插入一个或多个元素
被加上的元素作为一个整体添加,这些元素在数组中的顺序和在参数中的顺序一样
https://www.bilibili.com/video/BV1et411b73Z?from=search&seid=3666679728868779694
PB
system 注意 两点
转义字符 空格
在qq 退出之前 没法 执行下一步
可以用 异步 注意参数
打开 notepad 但是 隐藏 窗口
可以悄无声息 卡死
图形界面 没有 但是 进程 列表 有
第四个 第五个 为了拓展
3 最大化 (很烦人 全屏弹出 )
打开qq 并且 移动窗口
for while
do while goto 递归
写一个 move
可以 利用 窗口 终止进程 exe
获取 窗口的 位置 用到 OD 的 工具 (调试 )
指向 结构体的 指针
找到窗口 需要 这样一个 指针 存储 窗口 地址
然后 利用这个 指针 去 操作
窗口 class 名 和 标题
任何 一个 窗口 都有一个 标题 和 class 名
NULL 空指针 意味着 内存数据 没有初始化 操作系统 不允许 随便访问内存
原理是遍历文件,
如果相邻的两个元素大小不符合预期,则进行交换,重复直到有序为止。
第一遍时,从左到右比较相邻两个元素,当两个元素中右边的元素较小时,将其与左边的元素进行交换。
直到最终将最大的元素移到队列的最右边。
第二遍时,将次大的元素放到队列右边的第二位中…
void bubb(int a[],int n)
{
int i,j=0;
for(i=0;i<n-1;i++)//n个元素,只需要n-1趟冒泡
{
for(j=1;j<n-i;j++)//j=1,为了和前一个a[j-1]进行比较。n-i表示每趟排序都有一个元素被放置到后面正确的位置,之后不需移动。
{
if(a[j-1] > a[j])
swap(&a[j-1],&a[j]); //swap函数用于交换
swap 包含在命名空间std 里面
}
}
return;
}
思路是从第一个元素开始,将第一个元素依次与剩余的元素比较,记录更大(小)的元素,将整个数组的元素比较完毕,记录下来最大(小)的元素并排列在数组首位。
然后将剩下的元素进行相同的循环操作,依次放在的前面元素的末尾,直到全部排列结束。
#include<stdio.h>
int main()
{void sort(int x[],int n);
return 0;
}
void sort(int x[],int n){
int i,j,max,temp;
for(i=0;i<n-1;i++){
k=i; //记录位置
for(j=i+1;j<n;j++)
if(x[max]<x[j])max=j; //如果找到更大的元素,则将max记录更大元素的位置
if(max!=i)
{temp=x[i];x[i]=x[max];x[max]=temp;} //交换
}
}
(1)什么是递归函数?
我们都知道,一个函数可以调用其他函数。
如果这个函数在内部调用它自己,那么这个函数就叫递归函数。
(2)递归函数的作用
举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * … * n
#不使用递归的方法:
n=4 #求4的阶乘
result=1
i=1
while i<=4:
result=result*i
i+=1
print(result)
#使用递归的方法:
def test1(n):#定义函数来计算数字n的阶乘
if n==1:
return 1
return n * test1(n-1)
print(test1(5))
#1在函数的内部调用自己本身
#2递归函数本质是一个方法的循环调用,注意:有可能出现死循环
#3一定要定义递归的边界(什么时候退出循环)
从上面两中方法的对比可以看出,递归函数的作用和循环的方法效果一样,即递归函数本质上是一个方法的循环调用,
注意:有可能会出现死循环。
因此,使用递归函数时,一定要定义递归的边界
(即什么时候退出循环)。
递归函数的另一个案例是斐波纳契数列。
斐波纳契数列:1,1,2,3,5,8,13。。。
(该数列中,有n个数字,从第三个数字开始:数值 =前一个数字 + 前面一个数字)
即,n=(n-2)+(n-1)
def get_num(n):#获取斐波拉契数列中第n个数字的值
if n==1 or n==2:
return 1
return get_num(n-1) + get_num(n-2)
#把获取的斐波拉契数字存放到列表中
nums=[]
for i in range(1,21):
nums.append(get_num(i))#get_num获得一个斐波拉契数字
print(nums)
以上两个案例是递归函数的经典案例,需要记住其使用方法。
注意:在实际使用中,递归函数由于消耗时间比较长
(相比for循环和while循环),所以很少使用。
// 比较常用的C/C++预处理指令
// 只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次
//指C/C++中包含头文件命令 用于将指定头文件嵌入源文件中
//数据收集类模板(MFC template-based Collection Classes)的头文件
//用到了lists,maps或者arrays等数据结构 基于模板的(template-based)数据收集类
//声明了MFC常用的一些控件类(CListCtrl、CProgressCtrl、CToolTipCtrl等)
//自动升级服务源
// “if not defined” 的简写 宏定义 的一种
// 可以根据是否已经定义了一个变量来进行分支选择,一般用于调试
//预处理功能中三种( 宏定义 ,文件包含和 条件编译 )中的第三种—— 条件编译
//预处理指令,其中的“#”表示这是一条预处理命令·。
//凡是以“#”开头的均为预处理命令,“define”为宏定义命令,“标识符”为所定义的宏名
// 预编译处理 指令中的 条件编译
// 用于结束 条件编译
//编译时与前面最近的#if、 #ifdef 或 #ifndef 作为一对
//常一起使用,编译两者之间的部分 程序段
// 为复杂的声明定义简单的别名,它与宏定义有些差异。
//本身是一种存储类的关键字
// 一种数据类型定义一个新名字 包括内部数据类型(int,char等)
和自定义的数据类型(struct等)
//auto、extern、mutable、static、register等关键字不能出现在同一个表达式中
//在C中定义一个结构体类型要用typedef:
C++中起到的作用是头文件 预编译 ,
把C++工程中使用的MFC头文件预先编译,以后该工程编译时,直接使用预编译的结果,以加快编译速度。
C++编译器通过一个头文件 stdafx.h 来使用预编译头文件。
str – 要被分解成一组小字符串的字符串。
delim – 包含分隔符的 C 字符串。
//分解字符串 str 为一组字符串,delim 为分隔符
输出缓冲区里的的值取决于格式说明符(即"%")。
如果写入的是文字,此函数给写入的文字的末尾追加一个’\0’。
函数的返回值是写入的长度,但不包括最后的’\0’。
P:比例
I:积分
D:微分
MultiWii.cpp
// 输出流,直接点说就是in(输入) out(输出) stream(流),取in、out的首字母与stream合成
//将一个数值限制到某一区间
x: 被限制到某一区间的数值(可以是任何数据类型)
a: 限制区间下限(可以是任何数据类型)
b: 限制区间上限(可以是任何数据类型)
x: 如果x介于a与b之间,则返回x
a: 如果x小于限制区间下限a,则返回a
b: 如果x大于限制区间上限b,则返回b
#pragma once
//class实现 qq发射类
class QQmsg
{
public:
QQmsg();
~QQmsg();
// static 创建class 入口
//面向对象最重要的概念就是类(Class)和实例(Instance)
static QQmsg *Instance() {
static QQmsg object;
return &object;
}
//入口函数 开始 发射函数实现
void Start(const wchar_t *msg); //const 发射信息
private:
//线程函数
static unsigned int WINAPI RunThreadProc(void *param);
//发射函数
void SendMain();
//模拟键盘函数
void PressKey(BYTE vkey);
//发送消息
void SendMsg();
//把文字拷贝到剪切板
void CopyTextToClipborad();
private:
CString sent_msg;
};
#include "stdafx.h"
#include "QQmsg.h"
QQmsg::QQmsg()
{
}
QQmsg::~QQmsg()
{
}
//入口函数 (开启 发射 的函数实现)
void QQmsg::Start(const wchar_t *msg)
{
sent_msg = CString(msg);
//开始线程
_beginthreadex(NULL, 0, QQmsg::RunThreadProc, NULL, 0, NULL);
}
//线程函数
unsigned int QQmsg::RunThreadProc(void *param)
{
QQmsg::Instance()->SendMain();
return 0;
}
//发送主函数
void QQmsg::SendMain()
{
int errtimes = 0;
//实现整个发送消息的流程
//复制文字到剪切板
CopyTextToClipborad();
int i;
while (errtimes <= 4)
{
//2.找到QQ窗口
HWND hQQWnd = FindWindow(L"TXGuiFoundation", L"QQ");
//windows系统中窗口的查找.1.窗口类名称.2.标题
//工具 --> spy++
//找到一个最前的窗口
HWND hfront = GetForegroundWindow();
if (hQQWnd != hfront)
{
if (!SetForegroundWindow(hQQWnd))//强制把QQ窗口置顶
{
MessageBox(NULL, L"找不到QQ窗口", L"警告", MB_OK);
break;
}
}
模拟按键 keybd_event函数
if (errtimes == 0)
{//使用循环这里会出问题
// i = 6;
// while (i--)
// {
// PressKey(VK_TAB);
// }
//按下6次TAB键
PressKey(VK_TAB);
PressKey(VK_TAB);
PressKey(VK_TAB);
PressKey(VK_TAB);
PressKey(VK_TAB);
PressKey(VK_TAB);
}
PressKey(VK_DOWN);
PressKey(VK_RETURN);
HWND hcurfrontWnd = GetForegroundWindow();
if (hcurfrontWnd == hQQWnd)
{
errtimes++;
continue;
}
errtimes = 0;
SendMsg();
}
}
//模拟键盘函数
void QQmsg::PressKey(BYTE vkey)
{
//模拟按键 keybd_event函数
keybd_event(vkey, 0, 0, 0);
Sleep(100);//时间间隔100ms
keybd_event(vkey, 0, KEYEVENTF_KEYUP, 0);
Sleep(100);
}
//发送消息
void QQmsg::SendMsg()
{
//ctrl+v
keybd_event(VK_CONTROL, 0, 0, 0);
Sleep(100);
keybd_event(0x56, 0, 0, 0);
Sleep(100);
keybd_event(0x56, 0, KEYEVENTF_KEYUP, 0);
Sleep(100);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
Sleep(100);
PressKey(VK_RETURN);//enter
PressKey(VK_ESCAPE);//Esc 关闭
}
//把文字拷贝到剪切板
void QQmsg::CopyTextToClipborad()
{
//全局内存中找一内存来存放字符串
int memLen = sent_msg.GetLength() * sizeof(wchar_t) + 2;
HANDLE hHandle = GlobalAlloc(GHND, memLen);
void *addr = GlobalLock(hHandle);
ZeroMemory(addr, memLen);
memcpy(addr, (const wchar_t*)sent_msg.GetBuffer(), memLen);
GlobalUnlock(hHandle);
//
OpenClipboard(NULL);//打开剪切板
EmptyClipboard();//清空
SetClipboardData(CF_UNICODETEXT, hHandle);//设置剪切板内容
CloseClipboard();//
}
void CqqsentDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(true);
QQmsg::Instance()->Start(sent_msg.GetBuffer());//m_msg.GetBuffer() 获取指针
//指针操作符
}