现在我用我所知道的为楼主介绍VB.NET的API调用,请楼主浏览一下,看看行不行。
成都创新互联长期为上千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为尼玛企业提供专业的网站设计制作、网站制作,尼玛网站改版等技术服务。拥有10余年丰富建站经验和众多成功案例,为您定制开发。
Windows API就是Windows系统的API函数简称(Application Program Interface,即:应用程序接口函数),它是Windows操作系统提供给各种开发基于Windows平台应用软件的开发语言的一些公用的函数,这些函数一般都比较底层,所以当各种开发语言使用自带的函数或类库已无法解决问题时,调用Windows API函数往往是一种非常直接、有效的解决方法。但由于在程序中调用Windows API函数一般都很复杂,所以对于程序员来说,是否能够灵活的使用Windows API函数,往往也是其水平高低的一个重要标志。但自从微软推出.Net框架以后,各种开发基于.Net平台下的程序语言,如Visual Basic .Net、Visual C#等却很少使用Windows API函数,并且微软公司也不像以前那样,提倡在这些.Net开发语言中使用Windows API函数,其主要的原因如下:
1. .Net框架所附带的类库.Net FrameWork SDK是一个内容丰富、功能强大的软件开发包,各种Windows API函数所实现的各种功能几乎都可以在这个软件开发包中找到与之对应的部分。
2. 微软Visual Basic .Net、Visual C#等目的是编写跨平台的应用程序,如果在Visual Basic .Net、Visual C#等中使用Windows API函数,这也就注定了编写出的程序只能运行于Windows平台之下,而弱化了.NET的跨平台能力。这也就是为什么微软不提倡在.Net平台调用Windows API函数的原因。
虽然微软并不提倡在Visual Basic .Net、Visual C#中调用Windows API函数,但由于目前.Net 框架推出时间较短,.Net FrameWork SDK中提供的类库还并不足以完全替换Windows API函数的所有功能,所以在某些时候,.Net开发语言还是必须要调用Windows API函数。
一.平台调用、托管DLL、非托管DLL简介:
托管DLL就是能够在公共语言运行库(Common Language Runtime,简称CLR)中能够直接引用的,并且扩展名为“DLL”的文件。具体所指就是封装各种命名空间所在的DLL文件,如System.dll等。非托管DLL就是平常所的动态链接库等,其中就包括了封装所有Windows API函数的DLL文件。各种非托管DLL中的函数在公共语言运行库中不能直接被调用,而需要经过.Net框架提供的“平台调用”服务后才可以。
“平台调用”是.Net框架为Visual Basic .Net、Visual C#等.Net开发语言提供的一种服务,用以在托管代码中引入各种非托管DLL中封装的函数(其中包括Windows API函数)。“平台调用”依赖于元数据在运行时查找导出函数并封装其参数。图01公共语言运行库利用“平台服务”调用非托管DLL中的函数的流程图:
图01:“平台服务”的调用非托管函数的流程图
在托管代码中使用“平台调用”服务调用非托管DLL中封装的函数时,“平台服务”将依次执行以下操作:
1. 查找包含该函数所在的DLL文件。
2. 如果找到,则将该DLL文件 加载到内存中。
3. 查找函数在内存中的地址并将其参数推到堆栈上,并封送所需的数据。
4. 将控制权转移给非托管函数。 这样整个函数调用完成。
在Visual Basic .Net中使用“平台调用”服务,申明Windows API函数主要有二种具体的实现方法:
1. 使用DllImport特征类来申明Windows API函数。
2. 使用“Declare”语句来申明Windows API函数。
这二种方法虽有异曲同工之效,但在繁简上却有很大差异,第一种方法申明过程比较复杂,很容易在申明Windows API函数时出错,所以并不提倡。而第二种方法相对简单,并且又保存了以前Visual Basic中的很多语法,所以在平常时大都使用这种方法来申明Windows API函数。
二.VB.Net查看文件中图标的函数及申明Windows API的方法:
Visual Basic .Net要实现查看文件中的图标,目前只使用.Net FrameWork SDK是无法实现这种功能的,正如前面所说,主要是由于.Net FrameWork SDK推出的时间较短,其功能还不可能面面俱到。解决问题的关键是正确使用Windows API函数,其中所涉及到的Windows API函数主要有二个:其一是获得指定文件中的图标数目;其二是从指定文件的指定位置导出图标的Windows句柄。这二个函数都位于“Shell32.dll”文件中,并且函数的入口点都为“ExtractIcon”。下面是在Visual Basic .Net中分别使用DllImport特征类和“Declare”语句申明这二个Windows API函数的具体方法。
(1).使用DllImport特征类来申明Windows API函数:
下面是在Visual Basic .Net中使用DllImport特征类申明二个Windows API函数的具体示例:
'函数ExtractIcon,其功能是是从指定文件的指定位置导出图标的Windows句柄。
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'函数Icon_Num,其功能是获得指定文件中的图标数目
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
Icon_Num ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
End Function
在使用DllImport特征类申明Windows API函数时,如果申明的函数名称和函数的入口点相同,则可以在申明Windows API函数时,省略定义函数入口点对应的代码,即EntryPoint对象字段对应的代码,这样声明ExtractIcon函数的代码也可以简化为如下所示:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
(2).使用“Declare”语句来申明Windows API函数:
使用“Declare”语句的确比使用DllImport特征类要简单了许多,下面是在Visual Basic .Net中使用“Declare”语句来声明上述二个Windows API函数的具体方法:
Declare Auto Function ExtractIcon Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
'声明ExtractIcon函数
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
'声明Icon_Num函数
在Visual Basic .Net中声明Windows API函数时,“Declare”语句中Alias关键字的作用相当于使用DllImport特征类中的EntryPoint对象字段。同样在使用“Declare”语句声明Windows API函数时,如果声明的函数和函数的入口点相同,也可以省略Alias关键字对应的代码,所以ExtractIcon函数也可以简化为如下:
Declare Auto Function ExtractIcon Lib "Shell32.dll" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
下面就结合一个示例的编写过程来掌握的这二个Windows API函数的具体使用方法,这个示例的作用就是读取指定文件中的图标数目,并显示文件中的图标。
三.本文中程序的编写、调试和运行环境:
(1).视窗2000高级服务器版。
(2).Visual Studio .Net 2003企业结构设计版,.Net FrameWork SDK版本号4322。
四.Visual Basic .Net读取文件中的图标的实现步骤:
下面介绍的示例,其功能读取指定文件中包含的图标数目,并把这些图标全部显示出来。下面是这个示例的实现步骤:
1. 启动Visual Studio .Net。
2. 选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框。
3. 将【项目类型】设置为【Visual Basic项目】。
4. 将【模板】设置为【Windows应用程序】。
5. 在【名称】文本框中输入【Visual Basic .Net查看文件中的图标】。
6. 在【位置】的文本框中输入【E:\VS.NET项目】,然后单击【确定】按钮,这样在【E:\VS.NET项目】目录中就产生了名称为【Visual Basic .Net查看文件中的图标】文件夹,里面存放着【Visual Basic .Net查看文件中的图标】项目的所有文件。具体如图02所示:
图02:【Visual Basic .Net查看文件中的图标】项目的【新建项目】对话框
7. 选择菜单【项目】|【添加新项】,在弹出的对话框中的【模板】设置为【模块】,【名称】文本框设置为【Module1.vb】后。单击【打开】按钮,则在项目中增加了一个模板文件,名称为【Module1.vb】。
8. 把Visual Stuido .Net的当前窗口切换到Module1.vb的代码编辑窗口,并在其Module1的代码区中添加下列代码,下列代码是用二种方式声明二个Windows API函数:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'声明ExtractIcon函数
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As Integer ) As Integer
9. 把Visual Studio .Net的当前窗口切换到Form1窗体的设计查看,并从【工具箱】中的【Windows窗体】选项卡中拖入下列组件到Form1窗体:
四个Label组件,其中二个用以显示提示信息,另外二个分别用以显示选择的文件名称和这个文件中包含的图标数目。
一个ListView组件,利用其显示大图标的属性用以显示选定文件中的图标。
一个OpenFileDialog组件,用以选择要查看图标的文件名称。
一个ImageList组件,它起的是桥梁的作用,首先把从文件中导出的图标存放到这里,然后再提供ListView组件显示出来。
一个Button组件。
10. 按照表01中数值来设定设定组件的主要属性:
组件类型 组件名称 属性 设置结果
Form Form1 Text VB.NET查看文件中的图标
Form1 MaximizeBox False
Form1 MinimizeBox False
Form1 FormBorderStyle FixedSingle
ListView ListView1 ImageList1 LargeImageList
ListView1 MultiSelect False
ListView1 Size Size ( 380 , 208 )
Button Button1 Text 选择文件
Button1 FlatStyle Flat
ImageList ImageList1 Size Size ( 32 , 32 )
ImageList1 TransparentColor Color.Transparent
Label Label1 Text 文件名称:
Label2 Text 图标数目:
Label3 Text ""
Label4 Text "0"
表01:【Visual Basic .Net查看文件中的图标】项目窗体中各组件的主要属性设定数值表
并按照图02中各组件的位置、大小和排列方式来调整窗体中各个组件:
图02:【Visual Basic .Net查看文件中的图标】项目的设计界面
11. 把Visual Studio .Net当前窗口切换到Form.vb的代码编辑窗口,并用下列代码替换Form1.vb中的Button1组件的Click事件的处理代码,下列代码是在Button1组件的Click事件中处理查看文件中图标的功能,具体如下:
Private Sub Button1_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button1.Click
If OpenFileDialog1.ShowDialog ( ) = DialogResult.OK Then
'清除组件中的所有项目
ListView1.Items.Clear ( )
ImageList1.Images.Clear ( )
Dim sfName As String = OpenFileDialog1.FileName
Label3.Text = sfName
Dim iIcon_Num As Integer = Icon_Num ( IntPtr.Zero , sfName , -1 )
'显示文件中的图标数目
Label4.Text = iIcon_Num.ToString ( )
Dim i As Integer
For i = 0 To iIcon_Num - 1 Step 1
'强制实现int到uint类型转换
Dim j As UInt32
j = System.Convert.ToUInt32 ( i )
Dim hIcon As System.IntPtr = ExtractIcon ( IntPtr.Zero , sfName , j )
'在imageList1组件中加入当然提取的图标
ImageList1.Images.Add ( Icon.FromHandle ( hIcon ).ToBitmap ( ) )
'在ListView组件中加入一个项目
ListView1.Items.Add ( "第" + ( i + 1 ).ToString ( ) + "个图标" )
'把加入项目的图象索引指向刚才加入图标在imagList1组件中的索引,从而显示图标
ListView1.Items ( i ).ImageIndex = i
Next i
End If
End Sub
12. 至此,在上述步骤都正确执行后,【Visual Basic .Net查看文件中的图标】项目的全部工作就完成了。单击快捷键F5就可以运行程序,此时单击【选择文件】按钮选择文件后,程序就能够读取这个文件中的图标及其数目,并显示出来了。具体如图03所示:
图03:【Visual Basic .Net查看文件中的图标】项目的运行界面
五.总结:
解决Visual Basic .Net查看文件中的图标的关键并非是使用.Net框架中提供的类库,而是使用Windows的API函数。虽然这与利用Visual Basic .Net开发跨平台程序的初衷相违背,但的确不失为一种解决问题的方法。有些时候通过Windows API函数能够快捷、方便的解决实际问题,而这往往是只使用.Net FrameWork SDK所望尘莫及的,但随着.Net FrameWork SDK内容的不断丰富,各种新的组成部分和新的功能不断加入,可以预见的是,在未来的.Net FrameWork SDK中必将拥有可以替换本文中介绍的二个Windows API函数的组成部分。
网络问题。vb淘宝买东西用支付宝付20元,但信息现示22元多数是网络连接异常导致。
1、首先打开电脑检查网络。
2、其次打支付宝进行测试网络连接是否异常。
3、最后点击重新进入即可。
基本思路:
1,设置绘图区域的坐标。
2,将每个站点的坐标(x,y)保存到数组。
3,通过鼠标单击点的坐标(x,y)与数组比较,然后确定显示相应信息。
Case 4 '支付宝支付
Dim cmd, subject, body, order_no, prices, rurl, types, number, transport, ordinary_fee, express_fee, readonlytrue, buyer_msg, buyer, buyer_name, buyer_address, buyer_zipcode, buyer_tel, buyer_mobile, partner As String
Dim t1, t2, t3, t4, t5 As String
Dim AlipayObj, itemUrl As String
t1 = ":" '支付接口
t2 = ConfigurationSettings.AppSettings("adminaliPay") '商户支付宝账户(改成你自己的)
t3 = "m7yeav29bcdz14szvi2rbfcixywob59y" '安全校验码
cmd = "0001" '命令码
subject = "订单号:" NoID '商品名称
body = Convert.ToString(ViewState("CourseName")) '商品描述
order_no = NoID '商户订单号
prices = Convert.ToString(ViewState("NowPrice")) '商品单价
rurl = Request.Url.ToString() '商品展示网址
types = "1" '支付类型 1:商品购买,2:服务购买,3:网络拍卖,4:捐赠
number = "1" '购买数量
transport = "3" '发货方式 1:平邮,2:快递,3:虚拟物品
ordinary_fee = "0" '平邮运费
express_fee = "0" '快递运费
readonlytrue = "true" '交易信息是否只读,true或false,默认值为false
buyer_msg = "" '买家给卖家的留言:string(200)
'buyer = Convert.ToString(ViewState("txtIDEmail")) '买家Email
buyer_name = Convert.ToString(ViewState("txtIDName")) ",Email:" Convert.ToString(ViewState("txtIDEmail")) '买家姓名,买家Email
buyer_address = Convert.ToString(ViewState("txtIDaddress")) '买家地址
buyer_zipcode = Convert.ToString(ViewState("txtIDPost")) '买家邮编
buyer_tel = Convert.ToString(ViewState("txtIDtelephone")) '买家电话号码
buyer_mobile = Convert.ToString(ViewState("txtIDTel")) '买家手机号码
partner = "" '合作伙伴ID(保留字段)
itemUrl = creatAlipayItemURL(t1, t2, t3, t4, t5, cmd, subject, body, order_no, prices, rurl, types, number, transport, ordinary_fee, express_fee, readonlytrue, buyer_msg, buyer, buyer_name, buyer_address, buyer_zipcode, buyer_tel, buyer_mobile, partner)
itemUrl = "script language=javascript" vbCrLf "!--" vbCrLf "document.forms[0].submit();" vbCrLf "//--" vbCrLf "/script"
Response.Write(itemUrl)
End Select
接入支付宝支付SDK
可以说支付宝支付接入是所有SDK最好接入的,没有之一。
客户端不用签名,也不用管包名,也不用管签名文件,就接口返回订单,把订单交给支付宝SDK调用就行,成功或者失败都在当前界面返回给你。你再去通知接口。
支付流程图
官方文档地址
!支付宝支付官方文档地址
按照文档说明接入SDK和相关配置,在这就不重复了
客户端支付关键代码===》支付接口的调用(调起支付弹框)
记住支付接口的调用必须在独立的非ui线程中执行,即需新开线程里面调用。可以想官方demo一样用new Thread方式。
下面我给出用Observable方式示例代码
在PayUtils中
/**
* desc:支付宝支付
* Created by congge on 2018/8/27 17:20
* @param orderInfo 接口返回的订单
**/
public static void aliPay(final Activity activity, final String orderInfo, final OrderListener orderListener) {
Observable.just(orderInfo)
.map(new Function () {
@Override
public String apply(String orderInfo) throws Exception {
//用户在商户app内部点击付款,是否需要一个loading做为在钱包唤起之前的过渡,这个值设置为true
return new PayTask(activity).pay(orderInfo, true);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer () {
@Override
public void accept(String payResult) throws Exception {
orderListener.onPayResult(payResult);
}
});
}
支付结果返回处理
返回例子:
resultStatus={9000};memo={};result={{"alipay_trade_app_pay_response":{"code":"10000","msg":"Success","app_id":"2016091300503896","auth_app_id":"2016091300503896","charset":"utf-8","timestamp":"2018-08-28 17:51:11","out_trade_no":"nVElbd74TW6WnEyxQwvX8A","total_amount":"0.01","trade_no":"2018082821001004680500208879","seller_id":"2088102175487650"},"sign":"W0Hg9k4GxL8Oaxymvqk2i65WNDQxYp6HGve32ek6VjSRnymmI3GQTjpQVbZuDzvjcwQ/HIkM97PoBGAVlTmi/wiJcqDgSSDzDY7AFnNN0OcK0ehWGwKQINA4IDGh51A7yY/vYKmR0VW+2OwGhlRPPMMZtQOEqh8a9/aIijzT6ZLwy9Hl4ayG/fVKhdC1VdckF6+C25BFNp3fIxarg5tfEunm7N9iWngKCUsnP+IZz05OHdvynimgYPcBnbBERHG97GVqRT/EdBWTQyIDMc0LemScAYxJixTVgXDkRddQjzWZ7HgLdBfjs0nXY24puHudT76ERxVY+8NkoKle/QI+FA==","sign_type":"RSA2"}}
也可以自己打log看看
处理示例代码:
//支付宝支付
PayUtils.aliPay(this, result.getSignDataStr(), new PayUtils.OrderListener() {
@Override
public void onPayResult(String payResult) {
PayResult pr = new PayResult(payResult);
String rs = pr.getResultStatus();
String r = pr.getResult();
switch (rs) {
case AliPayResultStatus.PAY_SUCCESS:
ToastUtils.show(R.string.pay_success);
//通知接口支付成功
break;
case AliPayResultStatus.PAY_PROCESSING:
case AliPayResultStatus.PAY_UNKNOWN:
ToastUtils.show(R.string.pay_fail);
//支付可能成功,要接口去查询
break;
default:
ToastUtils.show(R.string.pay_fail);
//通知接口支付失败,取消订单
}
}
});
上面方法中:
//通知接口支付成功 //支付可能成功,要接口去查询 //通知接口支付失败,取消订单。根据你产品需求要不要通知你服务器做的操作。正常是要的,用来改变订单状态
PayResult.class
public class PayResult {
private String resultStatus;
private String result;
private String memo;
public PayResult(String rawResult) {
if (TextUtils.isEmpty(rawResult))
return;
String[] resultParams = rawResult.split(";");
for (String resultParam : resultParams) {
if (resultParam.startsWith("resultStatus")) {
resultStatus = gatValue(resultParam, "resultStatus");
}
if (resultParam.startsWith("result")) {
result = gatValue(resultParam, "result");
}
if (resultParam.startsWith("memo")) {
memo = gatValue(resultParam, "memo");
}
}
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}
private String gatValue(String content, String key) {
String prefix = key + "={";
return content.substring(content.indexOf(prefix) + prefix.length(),
content.lastIndexOf("}"));
}
public String outOrder() {
String order = ""out_trade_no"";
if (result.contains(order)) {
String begin = result.substring(result.indexOf(order));
String ss = begin.split(",")[0];
String newS = ss.replace(""", "")
.replace("}", "")
.replace(":", "")
.replace("out_trade_no", "");
try {
return newS;
} catch (Exception e) {
e.printStackTrace();
}
}
return "";
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}}
最后给下支付返回码表
AliPayResultStatus.class
public class AliPayResultStatus {
/**
* 订单支付成功,唯一肯定是支付成功的
*/
public static final String PAY_SUCCESS = "9000";
/**
* 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
*/
public static final String PAY_PROCESSING = "8000";
/**
* 订单支付失败
*/
public static final String PAY_FAIL = "4000";
/**
* 重复请求
*/
public static final String PAY_REPEAT = "5000";
/**
* 用户中途取消
*/
public static final String PAY_PROCESS_CANCEL = "6001";
/**
* 网络连接出错
*/
public static final String PAY_NET_ERROR = "6002";
/**
* 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
*/
public static final String PAY_UNKNOWN = "6004";}
还有一个直接弃用沙箱调试模式,否则提示支付失败也有可能不知道错在那,怕金额大,和接口商量,测试服务器就用0.01测试。