初识API函数
我之前是一个只会编写数值计算的程序的OIer,但我并不甘于这种现状,于是我编写了我的第一个使用API函数的C++程序,开发平台是VS2012:
// ConsoleApplication.cpp : 定义控制台应用程序的入口点。 // #include<stdio.h> #include"stdafx.h" #include<Windows.h> int _tmain(int argc, _TCHAR* argv[]) { HWND wnd; wnd=FindWindowA(NULL,"无标题 - 记事本"); SendMessage(wnd,WM_CLOSE,,); system("pause"); return ; }
之前有在看谷夕写的HACK编程实例精讲,第一节有介绍API函数,他的书上用的是hDesk=OpenDesktop(lpszDesktop,0,FALSE,DESKTOP_ENUMERATE);在这之前我连如何调用API函数都不知道,尝试过#include<stdafx.h>等等乱七八糟的东西,结果都不行.后来百度了一下,才发现原来是要加#include<windows.h>
明白如何才能可以调用API函数之后,尝试使用书上介绍的OpenDesktop函数,因为我什么都不知道,于是程序我就这么写了:
// ConsoleApplication.cpp : 定义控制台应用程序的入口点。 // #include<stdio.h> #include"stdafx.h" #include<Windows.h> int _tmain(int argc, _TCHAR* argv[]) { int hDesk=OpenDesktop(lpszDesktop,,FALSE,DESKTOP_ENUMERATE); system("pause"); return ; }
结果是关于lpszDesktop发生了某种我理解不了的错误.于是再次百度API函数应用实例,就找到了第一个程序.
一开始仍然编译不过,编译器提示错误.
我也不知道LPCWSTR是什么,不过看网上关于FindWindow函数的介绍是这么说的:函数的定义:HWND WINAPI FindWindow(LPCSTR lpClassName ,LPCSTR lpWindowName);这上边居然是LPCSTR,于是我试了试类似的函数,发现FindWindowA函数上是LPCWSTR,于是改成FindWindowA终于编译过了,实现的功能就是把名为无标题 - 记事本的窗口关闭.
我学习这类东西一向喜欢先弄出来一个能正确运行的样例,然后再弄明白有问题的地方,这次也不例外.关于这个程序我主要有这几个方面不太明白:1.句柄是个啥玩意;2.LPCSTR和LPCWSTR又是什么东西;3.FindWindow函数还有啥其他调用方式.
先搞明白句柄是什么东西,当然还要靠百度.
句柄,是整个windows编程的基础.一个句柄是指使用的一个唯一的整数值,即一个四字节长的数值,来标志应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等.应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针,程序不能利用句柄来直接阅读文件中的信息.如果句柄不用在I/O文件中,它是毫无用处的.句柄是windows用来标志应用程序中建立的或是使用的唯一整数,windows使用了大量的句柄来标志很多对象.
关于句柄我是这样理解的:它有点类似于算法中的哈希值,对于一个对象系统分配给它一个唯一的值来标记存储该对象变动情况的位置.
LPCWSTR是一个指向unicode编码字符串的32位指针,所指向字符串是wchar型,而不是char型.
原来LPCWSTR是unicode字符串指针,那unicode又是什么东西呢(请原谅我的无知,我真的连unicode是啥都不知道)?看过这篇文章之后才大概有了个了解.比较特别之处在于定义unicode字符串时要在左边加一个L,就像这样:
wchar_t wStr[] = L"中文";
除此之外,我又了解到在VS2005以后,编码方式默认为unicode,部分函数在使用时默认调用unicode方式(函数名加W),而非ansi方式(函数名加A).之前那个程序由于"无标题 - 记事本"是编码为ansi的字符串,所以调用默认的unicode方式时出现错误,而使用FindWindowA之后采用ansi方式才编译通过.然后我又把刚才的调用方式改为wnd=FindWindow(NULL,L"无标题 - 记事本");终于编译通过.wchar_t的输出:一般说来有两种方式,一个是wcout,还有是wprintf()之类的函数,悲剧的是无论哪种方法都没编译过.后来看一个博客里说要在main函数里加上_tsetlocale(LC_ALL, L"CHS");于是wcout能用了,wprintf仍然不行.先不管它,继续往后看.
第二个API函数:SendMessage函数.SendMessage函数能向指定句柄所对应的对象发送信息,示例程序:
POINT curpos; while () { GetCursorPos(&curpos); HWND hWnd=WindowFromPoint(curpos); SendMessage(hWnd,WM_CHAR,WPARAM('g'),); Sleep(); }
该程序实现的功能是向鼠标所指向的编辑窗口输入g.
POINT就是表示坐标的数据类型.GetCursorPos(&curpos)表示取当前鼠标的坐标.WindowFromPoint(curpos)表示获得curpos处的对象的句柄.
WM_CHAR表示输出字符.
接着,我想写一个程序给自己发送标准输入数据:
while () { GetCursorPos(&curpos); HWND hWnd=WindowFromPoint(curpos); SendMessage(hWnd,WM_CHAR,WPARAM('g'),); SendMessage(hWnd,WM_CHAR,WPARAM('\r'),); Sleep(); char ch; cerr<<"waiting for reading"<<endl; cin>>ch; if (ch=='g') break; }
意思就是当通过SendMessage函数向程序窗口发送一个g,如果被成功读入就跳出循环,一开始我第2个SendMessage里发送的是’\n’,结果没法触发读入,接着改成’\0’,还是不行,又改成’\r’,这次终于成功了,原来回车键输入的是一个’\r’啊,之前一直以为是’\n’呢...
再往下又看到一个更有趣的:模拟鼠标动作
void RightClick(HWND wnd) { SendMessage(wnd,WM_RBUTTONDOWN,,); Sleep(); SendMessage(wnd,WM_RBUTTONUP,,); }
其中,WM_RBUTTONDOWN表示鼠标右键按下,WM_RBUTTONUP表示鼠标右键抬起.测试了一下运行没什么大问题,不过看起开必须等我再单击一下鼠标左键才能让程序继续执行.这样感觉用起来很不舒服,而且也没有什么应用价值.后来有看到专门有一个函数mouse_event能模拟鼠标的点击.关于这个函数的详细信息我看不太懂,就只用了一个最简单的应用:鼠标左击.再结合刚才的SendMessage函数,做了一个刷屏软件,虽然功能很弱,但做完的时候还是感觉很激动.弱弱地贴一下我的代码:
// 刷屏软件.cpp : 定义控制台应用程序的入口点。
//
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"stdafx.h"
#include<Windows.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<locale>
#include<cstring>
using namespace std; void Home_Page()
{
printf("1.使用说明.\n");
printf("2.开始运行.\n");
printf("3.退出程序.\n");
} void Left_Click()
{
mouse_event(MOUSEEVENTF_LEFTDOWN,,,,);
mouse_event(MOUSEEVENTF_LEFTUP,,,,);
} void Software_Description()
{
printf("本软件使用很简单,只要按提示一步一步操作即可.\n");
printf("也许有些使用者觉得软件写的太脑残,请原谅,我刚接触这方面,这个程序纯属练手.\n");
printf("特别提示:由于作者水平问题,请您在所有信息发送完成之前不要移动您的鼠标,否则可能会产生难以预料的结果.\n");
printf("同样由于作者的水平问题,目前只支持英文文本(Ansi字符集)的发送.\n");
printf("如果发送内容中包含多个单词,建议用下划线\'_\'连接\n");
printf("联系作者:winifred.oier@gmail.com\n");
system("pause");
} void Main_Program()
{
printf("请输入您希望发送的内容(一行):\n");
string TexttobeSend;
cin>>TexttobeSend;
printf("请输入您希望每隔多长时间发送一次(单位:毫秒):\n");
int DelayTime;
cin>>DelayTime;
printf("您希望将该信息发送多少遍:\n");
int SendTime;
cin>>SendTime;
printf("请在5秒内将鼠标放在发送信息的编辑框里\n");
HWND InputBox;
POINT curpos;
Sleep();
GetCursorPos(&curpos);
InputBox=WindowFromPoint(curpos);
cerr<<"The Input Box has been engaged"<<endl;
printf("请在5秒内将鼠标放在发送按钮上.再次提示:由于作者水平太烂,执行完之前千万别乱动鼠标.\n");
Sleep();
for (int i=;i<=SendTime;i++)
{
for (int j=;j<TexttobeSend.length();j++)
SendMessage(InputBox,WM_CHAR,WPARAM(TexttobeSend[j]),);
Left_Click();
Sleep(DelayTime);
}
} int _tmain(int argc, _TCHAR* argv[])
{
int Command_Code;
while (true)
{
Home_Page();
cin>>Command_Code;
switch(Command_Code)
{
case :
Software_Description();
break;
case :
Main_Program();
break;
case :
return ;
}
system("cls");
}
return ;
}
不过在写代码的时候发现一个问题,不同的头文件包含顺序可能会影响能否编译,还有就是编译出来的可执行文件只能在我的电脑上执行,我用同学的电脑测试发现缺少一个MS...的动态链接库,不明白为什么.
初识API函数的更多相关文章
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- C#中可直接调用WIN32的API函数--USER32.DLL
Win32的API函数可以直接在C#中直接调用,在做WinForm时还是很有帮助的.有时候直接调用Win32的API,可以很高效的实现想要的效果. using System; using System ...
- Appium常用的API函数
在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...
- mfc 调用Windows的API函数实现同步异步串口通信(源码)
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
- C#调用Windows API函数截图
界面如下: 下面放了一个PictureBox 首先是声明函数: //这里是调用 Windows API函数来进行截图 //首先导入库文件 [System.Runtime.InteropServices ...
- C#中导入Win32 API函数
C#中导入Win32 API的方法: 1.引用命名空间 using System.Net.Security; using System.Runtime.InteropServices; 2. [Dll ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- [转]SQLITE3 C语言接口 API 函数简介
SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...
- 替换应用程序exe图标,主要使用BeginUpdateResource,UpdateResource API函数
替换应用程序exe图标,主要使用的API函数是BeginUpdateResource(),UpdateResource(),EndUpdateResource()来使用自定义的ico文件类替换exe程 ...
随机推荐
- vimcommandfilepatchcmdfold VIM技巧之分隔窗口 一级精华
VIM技巧之分隔窗口 分类: 技术2010-07-08 09:57 754人阅读 评论(1) 收藏 举报 同时显示两个不同的文件, 或者同时查看同一个文件的两个不同位置, 或者是同步显示两个文件的 ...
- C#开发实例 鼠标篇
鼠标的操作控制: 鼠标是计算机的一个重要组成部分,有很多默认的设置,如双击时间间隔,闪烁频率,移动速度等,本篇使用C#获取这些基本的信息. 1.1获取鼠标信息 ①实例001 获取鼠标双击时间间隔 主要 ...
- win7+ubuntu双系统中卸载ubuntu方法
双系统中,如果要卸载ubuntu是不能够直接卸载的,需要使用一些特殊的方法.下面就为大家详细的介绍介绍. Step1 MBR引导区修复: 进入win7,下载个软件MbrFix,放在C:\windows ...
- selenium启动Chrome时,加载用户配置文件
selenium启动Chrome时,加载用户配置文件 Selenium操作浏览器是不加载任何配置的,网上找了半天,关于Firefox加载配置的多点,Chrome资料很少,下面是关于加载Chrome ...
- spring mvc 406 (Not Acceptable) json转换错误
spring mvc通过@RequestMapping("/register")和@ResponseBody返回json格式的字符串时出现如下异常: The resource id ...
- [转]C程序内存区域分配(5个段作用)
[转]C程序内存区域分配(5个段作用) 2012-08-10 14:45:32| 分类: C++基础|字号 订阅 参考:http://www.360doc.com/content/11/03 ...
- Java for LeetCode 160 Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- codeforces 489C.Given Length and Sum of Digits... 解题报告
题目链接:http://codeforces.com/problemset/problem/489/C 题目意思:给出 m 和 s,需要构造最大和最小的数.满足长度都为 m,每一位的数字之和等于 s. ...
- Mac 安装Java JDK
(一)Java JDK 首先到该网址,下载JavaSE http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads- ...
- HTML5学习记录1-新特性
新特性 HTML5 中的一些有趣的新特性: 1. 用于绘画的 canvas 元素 2. 用于媒介回放的 video 和 audio 元素 3. 对本地离线存储的更好的支持 4. 新的特殊内容元素,比如 ...