说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Android开发中实现跨进程通讯的AIDL接口

HTML文档下载 WORD文档下载 PDF文档下载
在Android开发中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享. 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可

 

在Android开发中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢?  显然, Java中不允许跨进程内存共享. 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦.
AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.
AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.
Android开发中实现跨进程通讯的具体步骤如下:
1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。 如: ITaskBinder.adil
package com.cmcc.demo;
import com.cmcc.demo.ITaskCallback;
interface ITaskBinder {
    boolean isTaskRunning();
    void stopRunningTask();
    void registerCallback(ITaskCallback cb);
    void unregisterCallback(ITaskCallback cb);
}
其中: ITaskCallback在文件ITaskCallback.aidl中定义:
package com.cmcc.demo;
interface ITaskCallback {
    void actionPerformed(int actionId);
}
注意: 理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数, 据说用Ant编译可以, 我没做尝试.
2、Android开发中编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.
3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
ITaskBinder.aidl中接口的实现, 在MyService.java中接口以内嵌类的方式实现:
private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {
        public void stopRunningTask() {
            //@TODO
        }
        public boolean isTaskRunning() {
            //@TODO
            return false;
        }
        public void registerCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.register(cb);
        }
        public void unregisterCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.unregister(cb);
        }
};
在MyActivity.java中ITaskCallback.aidl接口实现:
private ITaskCallback mCallback = new ITaskCallback.Stub() {
        public void actionPerformed(int id) {
           //TODO
            printf("callback id=" + id);
        }
};
4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。这个地方返回的mBinder,就是上面通过内嵌了定义的那个. (MyService.java)
    public IBinder onBind(Intent t) {
        printf("service on bind");
        return mBinder;
}
在Activity中, 可以通过Binder定义的接口, 来进行远程调用.
5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数在:MyService.java中:
    void callback(int val) {
        final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).actionPerformed(val);
            } catch (RemoteException e) {
                // The RemoteCallbackList will take care of removing
                // the dead object for us.
            }
        }
        mCallbacks.finishBroadcast();
}
AIDL的创建方法:
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:
1. 不需要import声明的简单Java编程语言类型(int,boolean等)
2. String, CharSequence不需要特殊声明 
3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型. 
((另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).
下面是AIDL语法: 
// 文件名: SomeClass.aidl 
// 文件可以有注释, 跟java的一样 
// 在package以前的注释, 将会被忽略. 
// 函数和变量以前的注释, 都会被加入到生产java代码中.package com.cmcc.demo; 
// import 引入语句import com.cmcc.demo.ITaskCallback;
interface ITaskBinder {
    //函数跟java一样, 可以有0到多个参数 ,可以有一个返回值
    boolean isTaskRunning();
    void stopRunningTask();   
    //参数可以是另外的一个aidl定义的接口
    void registerCallback(ITaskCallback cb);  
    void unregisterCallback(ITaskCallback cb);
    //参数可以是String, 可以用in表入输入类型, out表示输出类型.
    int getCustomerList(in String branch, out String[] customerList);
}
实现接口时有几个原则:
.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的..IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。 也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理..不能在AIDL接口中声明静态属性。IPC的调用步骤:
1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。 
2. 实现ServiceConnection。 
3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.  
4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用    YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。 
5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。 
6. 断开连接,调用接口实例中的ApplicationContext.unbindService()
下面是Android开发中实现AIDL接口的整个程序:
1. ITaskCallback.aidl
package com.cmcc.demo;
interface ITaskCallback {
    void actionPerformed(int actionId);
}
2. ITaskBinder.aidl
package com.cmcc.demo;
import com.cmcc.demo.ITaskCallback;
interface ITaskBinder {
    boolean isTaskRunning();
    void stopRunningTask();   
    void registerCallback(ITaskCallback cb);   
    void unregisterCallback(ITaskCallback cb);
}
3.  MyService.java
package com.cmcc.demo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
    @Override
    public void onCreate() {
        printf("service create");
    }
    @Override
    public void onStart(Intent intent, int startId) {
        printf("service start id=" + startId);
        callback(startId);
    }
    @Override
    public IBinder onBind(Intent t) {
        printf("service on bind");
        return mBinder;
    }
    @Override
    public void onDestroy() {
        printf("service on destroy");
        super.onDestroy();
    }
    @Override
    public boolean onUnbind(Intent intent) {
        printf("service on unbind");
        return super.onUnbind(intent);
    }
    public void onRebind(Intent intent) {
        printf("service on rebind");
        super.onRebind(intent);
    }
    private void printf(String str) {
        Log.e("TAG", "###################------ " + str + "------");
    }
    void callback(int val) {
        final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).actionPerformed(val);
            } catch (RemoteException e) {
                // The RemoteCallbackList will take care of removing
                // the dead object for us.
            }
        }
        mCallbacks.finishBroadcast();
    }
    private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {
        public void stopRunningTask() {
        }
        public boolean isTaskRunning() {
            return false;
        }
        public void registerCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.register(cb);
        }
        public void unregisterCallback(ITaskCallback cb) {
            if (cb != null) mCallbacks.unregister(cb);
        }
    };
   
    final RemoteCallbackList<ITaskCallback> mCallbacks
        = new RemoteCallbackList<ITaskCallback>();
}
4. MyActivity.java
package com.cmcc.demo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintWriter;
public class MyActivity extends Activity {
   
    private Button btnOk;
    private Button btnCancel;
   
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.test_service);
        btnOk = (Button)findViewById(R.id.btn_ok);
        btnCancel = (Button)findViewById(R.id.btn_cancel);
        btnOk.setText("Start Service");
        btnCancel.setTag("Stop Service");
        btnOk.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
                onOkClick();
            }
        });
        btnCancel.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                onCancelClick();
            }
        });
    }
    void onOkClick() {
        Bundle args = new Bundle();       
        Intent intent = new Intent(this, MyService.class);
        intent.putExtras(args);  
        //printf("send intent to start");
        //startService(intent);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        startService(intent);
    }
    void onCancelClick() {
        Intent intent = new Intent(this, MyService.class);
        //printf("send intent to stop");
        unbindService(mConnection);
        //stopService(intent);
    }
    private void printf(String str) {
        Log.e("TAG", "###################------ " + str + "------");
    }
    ITaskBinder mService;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            mService = ITaskBinder.Stub.asInterface(service);
            try {
                mService.registerCallback(mCallback);
            } catch (RemoteException e) {
            }
        }
        public void onServiceDisconnected(ComponentName className) {
            mService = null;
        }
    };
    private ITaskCallback mCallback = new ITaskCallback.Stub() {
        public void actionPerformed(int id) {
            printf("callback id=" + id);
        }
    };
}

作者:sdhjob

 

在Android开发中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢?  显然, Java中不允许跨进程内存共享. 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦.

AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.

AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.

Android开发中实现跨进程通讯的具体步骤如下:

 

1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。 如: ITaskBinder.adil

 

package com.cmcc.demo;

 

import com.cmcc.demo.ITaskCallback;

 

interface ITaskBinder {

    boolean isTaskRunning();

    void stopRunningTask();

    void registerCallback(ITaskCallback cb);

    void unregisterCallback(ITaskCallback cb);

}

 

其中: ITaskCallback在文件ITaskCallback.aidl中定义:

 

package com.cmcc.demo;

interface ITaskCallback {

    void actionPerformed(int actionId);

}

 

注意: 理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数, 据说用Ant编译可以, 我没做尝试.

 

2、Android开发中编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.

 

3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.

 

ITaskBinder.aidl中接口的实现, 在MyService.java中接口以内嵌类的方式实现:

 

private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {

        public void stopRunningTask() {

            //@TODO

        }

 

        public boolean isTaskRunning() {

            //@TODO

            return false;

        }

 

        public void registerCallback(ITaskCallback cb) {

            if (cb != null) mCallbacks.register(cb);

        }

 

        public void unregisterCallback(ITaskCallback cb) {

            if (cb != null) mCallbacks.unregister(cb);

        }

};

 

在MyActivity.java中ITaskCallback.aidl接口实现:

 

private ITaskCallback mCallback = new ITaskCallback.Stub() {

        public void actionPerformed(int id) {

           //TODO

            printf("callback id=" + id);

        }

};

 

4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。这个地方返回的mBinder,就是上面通过内嵌了定义的那个. (MyService.java)

 

    public IBinder onBind(Intent t) {

        printf("service on bind");

        return mBinder;

}

 

在Activity中, 可以通过Binder定义的接口, 来进行远程调用.

 

5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数在:MyService.java中:

 

    void callback(int val) {

        final int N = mCallbacks.beginBroadcast();

        for (int i=0; i<N; i++) {

            try {

                mCallbacks.getBroadcastItem(i).actionPerformed(val);

            } catch (RemoteException e) {

                // The RemoteCallbackList will take care of removing

                // the dead object for us.

            }

        }

        mCallbacks.finishBroadcast();

}

 

AIDL的创建方法:

 

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

 

1. 不需要import声明的简单Java编程语言类型(int,boolean等)

 

2. String, CharSequence不需要特殊声明 

3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型. 

((另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).

下面是AIDL语法: 

// 文件名: SomeClass.aidl 

// 文件可以有注释, 跟java的一样 

// 在package以前的注释, 将会被忽略. 

// 函数和变量以前的注释, 都会被加入到生产java代码中.package com.cmcc.demo; 

// import 引入语句import com.cmcc.demo.ITaskCallback;

 

interface ITaskBinder {

    //函数跟java一样, 可以有0到多个参数 ,可以有一个返回值

 

    boolean isTaskRunning();

    void stopRunningTask();   

 

    //参数可以是另外的一个aidl定义的接口

    void registerCallback(ITaskCallback cb);  

 

    void unregisterCallback(ITaskCallback cb);

 

    //参数可以是String, 可以用in表入输入类型, out表示输出类型.

 

    int getCustomerList(in String branch, out String[] customerList);

 

}

实现接口时有几个原则:

 

.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的..IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。 也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理..不能在AIDL接口中声明静态属性。IPC的调用步骤:

 

1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。 

2. 实现ServiceConnection。 

3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.  

4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用    YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。 

5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。 

6. 断开连接,调用接口实例中的ApplicationContext.unbindService()

 

下面是Android开发中实现AIDL接口的整个程序:

 

1. ITaskCallback.aidl

 

package com.cmcc.demo;

interface ITaskCallback {

    void actionPerformed(int actionId);

}

 

2. ITaskBinder.aidl

package com.cmcc.demo;

import com.cmcc.demo.ITaskCallback;

interface ITaskBinder {

    boolean isTaskRunning();

    void stopRunningTask();   

    void registerCallback(ITaskCallback cb);   

    void unregisterCallback(ITaskCallback cb);

}

 

3.  MyService.java

 

package com.cmcc.demo;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteCallbackList;

import android.os.RemoteException;

import android.util.Log;

public class MyService extends Service {

    @Override

    public void onCreate() {

        printf("service create");

    }

    @Override

    public void onStart(Intent intent, int startId) {

        printf("service start id=" + startId);

        callback(startId);

    }

 

    @Override

    public IBinder onBind(Intent t) {

        printf("service on bind");

        return mBinder;

    }

 

    @Override

    public void onDestroy() {

        printf("service on destroy");

        super.onDestroy();

    }

 

    @Override

 

    public boolean onUnbind(Intent intent) {

        printf("service on unbind");

        return super.onUnbind(intent);

    }

 

    public void onRebind(Intent intent) {

        printf("service on rebind");

        super.onRebind(intent);

    }

 

    private void printf(String str) {

        Log.e("TAG", "###################------ " + str + "------");

    }

 

    void callback(int val) {

        final int N = mCallbacks.beginBroadcast();

        for (int i=0; i<N; i++) {

            try {

                mCallbacks.getBroadcastItem(i).actionPerformed(val);

            } catch (RemoteException e) {

                // The RemoteCallbackList will take care of removing

                // the dead object for us.

            }

        }

        mCallbacks.finishBroadcast();

    }

 

    private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {

        public void stopRunningTask() {

        }

 

        public boolean isTaskRunning() {

            return false;

        }

 

        public void registerCallback(ITaskCallback cb) {

            if (cb != null) mCallbacks.register(cb);

        }

 

        public void unregisterCallback(ITaskCallback cb) {

            if (cb != null) mCallbacks.unregister(cb);

        }

    };

 

 

 

    final RemoteCallbackList<ITaskCallback> mCallbacks

        = new RemoteCallbackList<ITaskCallback>();

 

}

 

4. MyActivity.java

 

package com.cmcc.demo;

import android.app.Activity;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.ServiceConnection;

import android.graphics.Color;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.view.ViewGroup;

import android.view.View.OnClickListener;

import android.widget.AbsoluteLayout;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.RelativeLayout;

import android.widget.TextView;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.PrintWriter;

 

public class MyActivity extends Activity {

 

 

    private Button btnOk;

    private Button btnCancel;

 

    @Override

 

    public void onCreate(Bundle icicle) {

        super.onCreate(icicle);

        setContentView(R.layout.test_service);

        btnOk = (Button)findViewById(R.id.btn_ok);

        btnCancel = (Button)findViewById(R.id.btn_cancel);

        btnOk.setText("Start Service");

        btnCancel.setTag("Stop Service");

        btnOk.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

                onOkClick();

            }

        });

 

        btnCancel.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                onCancelClick();

            }

        });

    }

 

    void onOkClick() {

        Bundle args = new Bundle();       

        Intent intent = new Intent(this, MyService.class);

        intent.putExtras(args);  

        //printf("send intent to start");

        //startService(intent);

        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        startService(intent);

    }

 

    void onCancelClick() {

        Intent intent = new Intent(this, MyService.class);

        //printf("send intent to stop");

 

        unbindService(mConnection);

        //stopService(intent);

    }

 

    private void printf(String str) {

        Log.e("TAG", "###################------ " + str + "------");

    }

 

    ITaskBinder mService;

 

    private ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className,

                IBinder service) {

            mService = ITaskBinder.Stub.asInterface(service);

            try {

                mService.registerCallback(mCallback);

            } catch (RemoteException e) {

            }

        }

 

        public void onServiceDisconnected(ComponentName className) {

            mService = null;

        }

    };

 

    private ITaskCallback mCallback = new ITaskCallback.Stub() {

        public void actionPerformed(int id) {

            printf("callback id=" + id);

        }

    };

}

 

来源:http://blog.csdn.net/sdhjob

 

在 ListBox 之中, 如何检测鼠标所在位置的选项? -VB资料 在 Textbox 中,录入 N 个字符后移到下栏-VB资料 在 VB 中控制 Word 在GotFocus时快速选择文本 -VB资料 在VB中使用文件对象 在VB中使用艺术字 在VB中引用.dbf及索引文件 在Windows操作系统中改变文件打开方式-VB资料 在程序运行时,怎样把多个文本框的内容保存起来-VB资料 在打印字符串时自动换行 -VB资料 在文本框中快速增加一串字符-VB资料 在文本框中实现由加减号输入数据-VB资料 在引用项目找不到Excel、Word等Office软体Lib的解决法-VB资料 VB怎样从文件列表框中取得文件的完整路径和名称 VB制作一个有参数的执行文件(方法之简单难以想像) 资源档(.RES)的应用-VB资料 自定义Text的pop-up菜单-VB资料 自动出现动画、进度和确认的文件操作 -VB资料 自动选择 Text 的内容-VB资料 VB 调用 IMAGE 控件实现图像缩放的一种方法 VB5 实 现 窗 口 图 像 缩 放、 滚 动 技 巧 VB编程之提速攻略(一) VB开发通讯软件 VB实现图形动画的三种方法 VB随机图像的魅力 VB中不规则图形热点的实现 VB中任意旋转位图的实现 VB中实现图像特技 VB中随机图像的魅力 VB中位图旋转的实现 Visual Basic设计图形浏览器示例 我写的一个粒子系统屏保,大家看看不?其中有些技术问题,希望和大家讨论讨论。 菜鸟初学问题,别人给我的SQL Scripts File如何执行 菜鸟提问:如何进入xp的安全模式????? 我们企业要上ERP,交通施工行业,请推荐一些企业上ERP方面好一点的文章,不同行业也行,一篇给50分,在线等,多多益善! 初级问题:使用CDO时的cdoSendUserReplyEmailAddress,cdoSendEmailAddress这两项怎么设置? 请教菜鸟问题,在线等待 高分:"MyGina.dll"哪位高手有这个文件,用于屏蔽CTRL+ALT+DELETE?? 急!用odbc操作access时,可以添加,但不可以删除.(表的列比较多140个) 推荐几本比较好的适合初学的汇编教材 寻找对手,乒乓球,围棋,台球,本人在深圳大冲 初学类,不太明白其中关于const的使用。 请教:如何看/etc/wtmp的內容,打开都是乱码 一个字符串数组的问题??? 请问要怎样才能跟踪一个不出现窗口的系统进程直到结束? 急,如果一个CWnd类不作派生,怎么在它的包容wnd中,截获其Windows消息??? 偶尔找不到硬盘 寻求对,围棋,乒乓球,台球,本人在深圳大冲 请教` 请问我要在邮局汇款单上打印.... 怎么样用语句把ACCESS数据库里的数据导入DATAGIRD 红色!!!!!你过来!我要和你打架!我是淡蓝色!~!!!! 有需要函数库的!superruntimerlibary包含258个函数。图标菜单。。。。。 WindowsMediaPlayer怎么用? 请问我下载的fastreport v2.5中的fr_class.pas怎么用,在哪里可找到fr v2.5的注册版? 初学者又问 dxImageEdit的问题(DevExpress) 问一个关于richtext控件的简单问题,有分 在线求:光纤网络方案,最好有价格! 大家快帮帮忙,急!!分不够可以再加 当选中datagrid的某行时,怎样让这一行获得焦点(改变颜色)? 多少钱可以把我们给买了! “WGE”团队诚邀英才 怎样将IPAddress类型转换成Int64整型? 只放frreport1到form上運行都會出現問題。 统计项目咨询? 能否在ASP中做个导出到EXCEL的 请问高手:document.all.item起什么作用啊??? 如何调试J2ME程序哟 ????????高分问题??????????? 请问在对话框的edit框输入完成后,输入回车键如何把回车处理成对应的按牛单击? 客户机程序怎么读取服务器上的SQL数据库呢? 求下拉列表联动的jsp源码 前辈请推荐几本关于Delphi数据库开发的好书 我要在wsda5.0下使用jdk1.4,怎么办? aspx页面滚动如何实现 第二届深圳Delphi爱好者聚会通知 我的InterBase7为何登录不了? 两个窗体问题,希望今晚能结贴。谢谢了!!! Microsoft.Web.UI.WebControls --- Treeview的应用(请大家帮帮忙) 请为一个界面问题 在9i中为什么提示这个表或视图不存在? 用贪婪.堕落.多愁善感.描写某个人物性格的语言,有一种以上的修辞手法,80字左右. 自己种的牧草,能不能给自己的动物吃,如果能,怎么办 猪吃得牧草有哪几种? 农场种植的牧草,怎样才能让自己的动物吃啊 我想在家乡种牧草养羊,听人说,羊吃过草,草就不长了,是不是真的?本人想在家乡种牧草养羊,但是听别人说,羊吃过的草,草就不会在长,或者长的很慢.请问大家这是不是真的,如果真的是这样,请 锦马超的称号是怎么来的? 做衣柜用生态板好吗?做衣柜用生态板划算吗? 用生态板打衣柜好吗? 马超为什么叫马正义 用纯巧克力可以做什么简单的甜品?不要用到焗炉.材料不要太多、太复杂. 微积分 学前应该知道点什么?具体点学了对初三有用么? 东道主哈萨克斯坦成世界拳击锦标赛最大谁拥有小布什政府最终决定权?———新外媒:中国经略周边消除“中国威胁论”美媒:安倍讲话相当于给中国人“当面一韩向美要求:日本行使集体自卫权时需先阿根廷举行中期议会选举 女总统执政联马达加斯加大选结束 各方观察团认为投新闻集团窃听丑闻将开审 或付出16亿纽约华裔家庭五人被杀案疑犯被捕 为被薛理泰:中国远海军演检验新海军战略奥巴马医保网站问题频出 美卫生部长被居住5年后,按房价140%回购等了三天的快递粽子,到手全馊了引发国内首个朋友圈维权事件股指果然上扬,金股大面积走好之江:打造两个换乘中心北仑新增环线公交728路省人民医院成立健康学院颜色特别青的“返青粽叶”要小心氨氮超标,杭州还须加油看了两个月的购房者,果断下单看好创业板反弹韩娱之不灭的爱超级拟物王古神继承人雷霆之君砍遍诸天洪荒李源星神的暗黑战锤狂想曲异界仙侠志地狱式卧底重生之我为饕餮驱魔之邪佛爷洞旅游泽雅旅游滨海公园旅游上海浦东展览馆旅游魅力凤凰篝火晚会旅游万龙八易滑雪场旅游渔阳滑雪场旅游南山滑雪场旅游扶风旅游甘珠尔庙旅游虎英旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘