Android屏幕校准

  • Post author:
  • Post category:其他


android原始版本里是没有屏幕校准功能的,tp坐标到lcd坐标是完全按照线性关系来转换的。例如,tp坐标是(X

t

,Y

t

)分辨率是(W

t

x H

t

),lcd坐标是(X,Y),分辨率是(W x H),则 X=(X

t

*W)/W

t,

Y=(Y

t

*H)/H

t

。但是一般触摸屏不是完全线性的,自然转换关系也就不一样了,好在有tslib,能帮我们解决这个问题。但是android里没有tslib,我们也不需 要完全将tslib移植过来,只需要其中根据采样点生成转换矩阵的部分,这部分是由ts_calibrate.c文件中的 perform_calibration()函数来实现的。所以只需要将该函数移植过来就可以。这里将该函数及用到的数据结构代码贴出来如下:

typedef struct{

int x[5], xfb[5];      //x[5],y[5]是分别是tp五个点的x,y坐标,xfb[5],yfb[5]是lcd五个点的x,y坐标。

int y[5], yfb[5];

int a[7];                //a[7]是生成的7个转换参数,tp到lcd坐标转换方程是: X

lcd

= (X

tp

*a[1] + Y

tp

*a[2] + a[0])/a[6]

}calibration;               //  Y

lcd

= (X

tp

*a[4] + Y

tp

*a[5] + a[3])/a[6]

int perform_calibration(calibration *cal) {


int j;

float n, x, y, x2, y2, xy, z, zx, zy;

float det, a, b, c, e, f, i;

float scaling = 65536.0;

// Get sums for matrix

n = x = y = x2 = y2 = xy = 0;

for(j=0;j<5;j++) {


n += 1.0;

x += (float)cal->x[j];

y += (float)cal->y[j];

x2 += (float)(cal->x[j]*cal->x[j]);

y2 += (float)(cal->y[j]*cal->y[j]);

xy += (float)(cal->x[j]*cal->y[j]);

}

// Get determinant of matrix — check if determinant is too small

det = n*(x2*y2 – xy*xy) + x*(xy*y – x*y2) + y*(x*xy – y*x2);

if(det < 0.1 && det > -0.1) {


printf(“ts_calibrate: determinant is too small — %f/n”,det);

return 0;

}

// Get elements of inverse matrix

a = (x2*y2 – xy*xy)/det;

b = (xy*y – x*y2)/det;

c = (x*xy – y*x2)/det;

e = (n*y2 – y*y)/det;

f = (x*y – n*xy)/det;

i = (n*x2 – x*x)/det;

// Get sums for x calibration

z = zx = zy = 0;

for(j=0;j<5;j++) {


z += (float)cal->xfb[j];

zx += (float)(cal->xfb[j]*cal->x[j]);

zy += (float)(cal->xfb[j]*cal->y[j]);

}

// Now multiply out to get the calibration for framebuffer x coord

cal->a[0] = (int)((a*z + b*zx + c*zy)*(scaling));

cal->a[1] = (int)((b*z + e*zx + f*zy)*(scaling));

cal->a[2] = (int)((c*z + f*zx + i*zy)*(scaling));

printf(“%f %f %f/n”,(a*z + b*zx + c*zy),

(b*z + e*zx + f*zy),

(c*z + f*zx + i*zy));

// Get sums for y calibration

z = zx = zy = 0;

for(j=0;j<5;j++) {


z += (float)cal->yfb[j];

zx += (float)(cal->yfb[j]*cal->x[j]);

zy += (float)(cal->yfb[j]*cal->y[j]);

}

// Now multiply out to get the calibration for framebuffer y coord

cal->a[3] = (int)((a*z + b*zx + c*zy)*(scaling));

cal->a[4] = (int)((b*z + e*zx + f*zy)*(scaling));

cal->a[5] = (int)((c*z + f*zx + i*zy)*(scaling));

printf(“%f %f %f/n”,(a*z + b*zx + c*zy),

(b*z + e*zx + f*zy),

(c*z + f*zx + i*zy));

// If we got here, we’re OK, so assign scaling to a[6] and return

cal->a[6] = (int)scaling;

return 1;

有了上面的基础,接下来就是将上面的代码移植到android中并在setting里面添加屏幕校准入口,要完成这些,需要修改的文件有:

1. frameworks/base/services/java/com/android/server/InputDevice.java

2. packages/apps/Settings/AndroidManifest.xml

3. packages/apps/Settings/res/xml/settings.xml

另外在Setting源码目录里再添加一个Calibration.java文件。

frameworks/base/services/java/com/android/server/InputDevice.java修改的地方如下(

红色

表示添加,蓝色 表示删除):

public class InputDevice {


static final boolean DEBUG_POINTERS = false;

static final boolean DEBUG_HACKS = false;

/** Amount that trackball needs to move in order to generate a key event. */

static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;

/** Maximum number of pointers we will track and report. */

static final int MAX_POINTERS = 10;

static final String CALIBRATION_FILE=”/data/pointercal”;

final int id;

final int classes;

final String name;

final AbsoluteInfo absX;

final AbsoluteInfo absY;

final AbsoluteInfo absPressure;

final AbsoluteInfo absSize;

………………..

final AbsoluteInfo absX = device.absX;

final AbsoluteInfo absY = device.absY;

final AbsoluteInfo absPressure = device.absPressure;

final AbsoluteInfo absSize = device.absSize;

float tmpX = 0;

float tmpY = 0;

String prop = SystemProperties.get(“sys.config.calibrate”, “noset”);

if ( !prop.equalsIgnoreCase(“loaded”) )

{


if ( prop.equalsIgnoreCase(“start”) )

{


TransformInfo.xs =  0;

TransformInfo.ys =  0;

}

else if ( prop.equalsIgnoreCase(“done”) )

{


readCalibrate();

}

if ( TransformInfo.xs == 0 && absX != null )

{


TransformInfo.x1 = w;

TransformInfo.y1 = 0;

TransformInfo.z1 = 0-absX.minValue*w;

TransformInfo.xs =  absX.range;

}

if ( TransformInfo.ys == 0 && absY != null )

{


TransformInfo.x2 = 0;

TransformInfo.y2 = h;

TransformInfo.z2 = 0-absY.minValue*h;

TransformInfo.ys =  absY.range;

}

SystemProperties.set(“sys.config.calibrate”, “loaded”);

}

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


final int j = i * MotionEvent.NUM_SAMPLE_DATA;

tmpX = reportData[j + MotionEvent.SAMPLE_X];

tmpY = reportData[j + MotionEvent.SAMPLE_Y];

if (absX != null ) {


reportData[j + MotionEvent.SAMPLE_X] =

((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)

/ absX.range) * w;

reportData[j + MotionEvent.SAMPLE_X] = (TransformInfo.x1 * tmpX + TransformInfo.y1 * tmpY + TransformInfo.z1) / TransformInfo.xs;

}

if (absY != null ) {


reportData[j + MotionEvent.SAMPLE_Y] =

((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)

/ absY.range) * h;

reportData[j + MotionEvent.SAMPLE_Y] = (TransformInfo.x2 * tmpX + TransformInfo.y2 * tmpY + TransformInfo.z2) / TransformInfo.ys;

}

if (absPressure != null) {


reportData[j + MotionEvent.SAMPLE_PRESSURE] =

((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)

/ (float)absPressure.range);

}

if (absSize != null) {


reportData[j + MotionEvent.SAMPLE_SIZE] =

((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)

/ (float)absSize.range);

}

…………………………….

static class AbsoluteInfo {


int minValue;

int maxValue;

int range;

int flat;

int fuzz;

};

static class TransformInfo {


static int x1;

static int y1;

static int z1;

static int x2;

static int y2;

static int z2;

static int xs;

static int ys;

};

InputDevice(int _id, int _classes, String _name,

AbsoluteInfo _absX, AbsoluteInfo _absY,

AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {


id = _id;

classes = _classes;

name = _name;

absX = _absX;

absY = _absY;

absPressure = _absPressure;

absSize = _absSize;

TransformInfo.xs =  0;

TransformInfo.ys =  0;

readCalibrate();

}

static void readCalibrate(){


try {


FileInputStream is = new FileInputStream(CALIBRATION_FILE);

byte[] mBuffer = new byte[64];

int len = is.read(mBuffer);

is.close();

if (len > 0) {


int i;

for (i = 0; i < len; i++) {


if (mBuffer[i] == ‘/n’ || mBuffer[i] == 0) {


break;

}

}

len = i;

}

StringTokenizer st = new StringTokenizer(new String(mBuffer, 0, len));

TransformInfo.x1 = Integer.parseInt(st.nextToken());

TransformInfo.y1 = Integer.parseInt(st.nextToken());

TransformInfo.z1 = Integer.parseInt(st.nextToken());

TransformInfo.x2 = Integer.parseInt(st.nextToken());

TransformInfo.y2 = Integer.parseInt(st.nextToken());

TransformInfo.z2 = Integer.parseInt(st.nextToken());

TransformInfo.xs = Integer.parseInt(st.nextToken());

TransformInfo.ys = TransformInfo.xs;

SystemProperties.set(“sys.config.calibrate”, “loaded”);

} catch (java.io.FileNotFoundException e) {


Log.i(“InputDevice”, “calibration file not found exception”);

} catch (java.io.IOException e) {


Log.i(“InputDevice”, “io exception”);

} catch (java.lang.NumberFormatException e) {


Log.i(“InputDevice”, “number format exception”);

}

}

};

packages/apps/Settings/AndroidManifest.xml文件修改地方如下:

<activity android:name=”.fuelgauge.PowerUsageDetail”

android:label=”@string/details_title”>

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.DEFAULT” />

</intent-filter>

</activity>

<activity android:name=”Calibration”

android:label=”@string/screen_calibration_settings”>

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.DEFAULT” />

</intent-filter>

</activity>

<receiver android:name=”.widget.SettingsAppWidgetProvider” android:label=”@string/gadget_title”>

<intent-filter>

<action android:name=”android.appwidget.action.APPWIDGET_UPDATE” />

packages/apps/Settings/res/xml/settings.xml文件修改地方如下:

<com.android.settings.IconPreferenceScreen

settings:icon=”@drawable/ic_settings_date_time”

android:title=”@string/date_and_time_settings_title”>

<intent

android:action=”android.intent.action.MAIN”

android:targetPackage=”com.android.settings”

android:targetClass=”com.android.settings.DateTimeSettings” />

</com.android.settings.IconPreferenceScreen>

<!– touchscreen Calibration –>

<com.android.settings.IconPreferenceScreen

settings:icon=”@drawable/ic_settings_privacy”

android:title=”@string/screen_calibration_settings”>

<intent

android:action=”android.intent.action.MAIN”

android:targetPackage=”com.android.settings”

android:targetClass=”com.android.settings.Calibration”/>

</com.android.settings.IconPreferenceScreen>

<!– About Device –>

<com.android.settings.IconPreferenceScreen

settings:icon=”@drawable/ic_settings_about”

android:title=”@string/about_settings”>

<intent

android:action=”android.intent.action.MAIN”

android:targetPackage=”com.android.settings”

android:targetClass=”com.android.settings.DeviceInfoSettings” />

</com.android.settings.IconPreferenceScreen>

Calibration.java文件代码如下


  1. package

    com.android.settings;

  2. import

    java.io.FileNotFoundException;

  3. import

    java.io.FileOutputStream;

  4. import

    java.io.IOException;

  5. import

    android.app.Activity;

  6. import

    android.content.Context;

  7. import

    android.graphics.Bitmap;

  8. import

    android.graphics.Canvas;

  9. import

    android.graphics.Color;

  10. import

    android.graphics.Paint;

  11. import

    android.os.Bundle;

  12. import

    android.os.RemoteException;

  13. import

    android.os.ServiceManager;

  14. import

    android.util.Log;

  15. import

    android.view.Display;

  16. import

    android.view.IWindowManager;

  17. import

    android.view.MotionEvent;

  18. import

    android.view.View;

  19. import

    android.view.Window;

  20. import

    android.view.WindowManager;

  21. import

    android.widget.Toast;

  22. import

    android.os.SystemProperties;

  23. public


    class

    Calibration

    extends

    Activity {

  24. static


    final


    int

    SAMPLE_COUNTS =

    5

    ;

  25. static


    final


    int

    POINT_DEGREE =

    2

    ;

  26. static


    final


    int

    FACTOR_COUNTS =

    7

    ;

  27. static


    final


    int

    TOP_LEFT =

    0

    ;

  28. static


    final


    int

    TOP_RIGHT =

    1

    ;

  29. static


    final


    int

    BOTTOM_RIGHT =

    2

    ;

  30. static


    final


    int

    BOTTOM_LEFT =

    3

    ;

  31. static


    final


    int

    CENTER =

    4

    ;

  32. static


    final


    int

    X_AXIS =

    0

    ;

  33. static


    final


    int

    Y_AXIS =

    1

    ;

  34. static


    final


    int

    EDGE_GAP =

    50

    ;

  35. static


    final

    String CALIBRATION_FILE =

    “/data/pointercal”

    ;

  36. static


    final

    String TAG =

    “Calibration”

    ;

  37. static


    final


    boolean

    DEBUG =

    true

    ;

  38. private


    int

    X_RES;

  39. private


    int

    Y_RES;

  40. private

    Display dpy;

  41. class

    calibration {

  42. int

    x[] =

    new


    int

    [

    5

    ];

  43. int

    y[] =

    new


    int

    [

    5

    ];

  44. int

    xfb[] =

    new


    int

    [

    5

    ];

  45. int

    yfb[] =

    new


    int

    [

    5

    ];

  46. int

    a[] =

    new


    int

    [

    7

    ];
  47. };

  48. private

    calibration cal;

  49. @Override

  50. protected


    void

    onCreate(Bundle savedInstanceState) {

  51. super

    .onCreate(savedInstanceState);
  52. SystemProperties.set(

    “sys.config.calibrate”

    ,

    “start”

    );
  53. cal =

    new

    calibration();
  54. dpy = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
  55. X_RES = dpy.getWidth();
  56. Y_RES = dpy.getHeight();

  57. this

    .initScreenPoints();
  58. setContentView(

    new

    MyView(

    this

    ));
  59. }

  60. // TopLeft–>TopRight–>BottomRight–>BottomLeft–>Center

  61. // For 240 * 320 resolution, we use 50 pixel as edge gap

  62. private


    boolean

    initScreenPoints() {
  63. cal.xfb[TOP_LEFT] = EDGE_GAP;

    // TopLeft
  64. cal.yfb[TOP_LEFT] = EDGE_GAP;
  65. cal.xfb[TOP_RIGHT] = X_RES – EDGE_GAP;

    // TopRight
  66. cal.yfb[TOP_RIGHT] = EDGE_GAP;
  67. cal.xfb[BOTTOM_RIGHT] = X_RES – EDGE_GAP;

    // BottomRight
  68. cal.yfb[BOTTOM_RIGHT] = Y_RES – EDGE_GAP;
  69. cal.xfb[BOTTOM_LEFT] = EDGE_GAP;

    // BottomLeft
  70. cal.yfb[BOTTOM_LEFT] = Y_RES – EDGE_GAP;
  71. cal.xfb[CENTER] = X_RES /

    2

    ;

    // Center
  72. cal.yfb[CENTER] = Y_RES /

    2

    ;

  73. return


    true

    ;
  74. }

  75. private


    boolean

    perform_calibration() {

  76. float

    n, x, y, x2, y2, xy, z, zx, zy;

  77. float

    det, a, b, c, e, f, g;

  78. float

    scaling = (

    float

    )

    65536.0

    ;
  79. n = x = y = x2 = y2 = xy =

    0

    ;

  80. for

    (

    int

    i =

    0

    ; i < SAMPLE_COUNTS; i++) {
  81. n +=

    1.0

    ;
  82. x += (

    float

    )cal.x[i];
  83. y += (

    float

    )cal.y[i];
  84. x2 += (

    float

    )(cal.x[i] * cal.x[i]);
  85. y2 += (

    float

    )(cal.y[i] * cal.y[i]);
  86. xy += (

    float

    )(cal.x[i] * cal.y[i]);
  87. }
  88. det = n * (x2 * y2 – xy * xy) + x * (xy * y – x * y2) + y * (x * xy – y * x2);

  89. if

    (det <

    0.1

    && det > –

    0.1

    ) {
  90. Log.w(

    “bigcren”

    ,

    “determinant is too small, det =”

    + det);

  91. return


    false

    ;
  92. }

  93. if

    (DEBUG) {
  94. Log.i(

    “bigcren”

    ,

    “(n,x,y,x2,y2,xy,det)=(”
  95. + n +

    “,”
  96. + x +

    “,”
  97. + y +

    “,”
  98. + x2 +

    “,”
  99. + y2 +

    “,”
  100. + xy +

    “,”
  101. + det +

    “)”

    );
  102. }
  103. a = (x2 * y2 – xy * xy) / det;
  104. b = (xy * y – x * y2) / det;
  105. c = (x * xy – y * x2) / det;
  106. e = (n * y2 – y * y) / det;
  107. f = (x * y – n * xy) / det;
  108. g = (n * x2 – x * x) / det;
  109. Log.i(

    “bigcren”

    ,

    “(a,b,c,e,f,g)=(”
  110. + a +

    “,”
  111. + b +

    “,”
  112. + c +

    “,”
  113. + e +

    “,”
  114. + f +

    “,”
  115. + g +

    “)”

    );

  116. // Get sums for x calibration
  117. z = zx = zy =

    0

    ;

  118. for

    (

    int

    i =

    0

    ; i < SAMPLE_COUNTS; i++) {
  119. z += (

    float

    )cal.xfb[i];
  120. zx += (

    float

    )(cal.xfb[i] * cal.x[i]);
  121. zy += (

    float

    )(cal.xfb[i] * cal.y[i]);
  122. }

  123. // Now multiply out to get the calibration for X coordination
  124. cal.a[

    0

    ] = (

    int

    )((a * z + b * zx + c * zy) * (scaling));
  125. cal.a[

    1

    ] = (

    int

    )((b * z + e * zx + f * zy) * (scaling));
  126. cal.a[

    2

    ] = (

    int

    )((c * z + f * zx + g * zy) * (scaling));

  127. // Get sums for y calibration
  128. z = zx = zy =

    0

    ;

  129. for

    (

    int

    i =

    0

    ;i < SAMPLE_COUNTS; i++) {
  130. z += (

    float

    )cal.yfb[i];
  131. zx += (

    float

    )(cal.yfb[i] * cal.x[i]);
  132. zy += (

    float

    )(cal.yfb[i] * cal.y[i]);
  133. }

  134. // Now multiply out to get the calibration for Y coordination
  135. cal.a[

    3

    ] = (

    int

    )((a * z + b * zx + c * zy) * (scaling));
  136. cal.a[

    4

    ] = (

    int

    )((b * z + e * zx + f * zy) * (scaling));
  137. cal.a[

    5

    ] = (

    int

    )((c * z + f * zx + g * zy) * (scaling));
  138. cal.a[

    6

    ] = (

    int

    )scaling;

  139. return


    true

    ;
  140. }

  141. private


    boolean

    saveCalibrationResult() {
  142. FileOutputStream os;
  143. String res =

    “”

    ;

  144. // save the calibration factor in file system for InputDevice

  145. try

    {
  146. os =

    new

    FileOutputStream(CALIBRATION_FILE);
  147. res = String.format(

    “%d %d %d %d %d %d %d”

    , cal.a[

    1

    ], cal.a[

    2

    ], cal.a[

    0

    ], cal.a[

    4

    ], cal.a[

    5

    ], cal.a[

    3

    ], cal.a[

    6

    ]);

  148. if

    (DEBUG) {
  149. Log.i(

    “bigcren”

    ,

    “calibration result=”

    + res);
  150. }
  151. os.write(res.getBytes());
  152. os.close();
  153. }

    catch

    (FileNotFoundException e1) {

  154. // TODO Auto-generated catch block
  155. e1.printStackTrace();
  156. Log.w(TAG,

    “open calibration file write error: ”

    + CALIBRATION_FILE );
  157. }

    catch

    (IOException e) {

  158. // TODO Auto-generated catch block
  159. e.printStackTrace();
  160. }

  161. return


    true

    ;
  162. }

  163. public


    class

    MyView

    extends

    View {

  164. private

    Canvas cv;

  165. private

    Paint paint;

  166. private

    Bitmap bmp;

  167. private


    int

    screen_pos;

  168. private

    Context mContext;

  169. public

    MyView(Context c) {

  170. super

    (c);

  171. // set full screen and no title
  172. requestWindowFeature(Window.FEATURE_NO_TITLE);
  173. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  174. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  175. mContext=c;
  176. paint =

    new

    Paint();
  177. paint.setDither(

    true

    );
  178. paint.setAntiAlias(

    true

    );
  179. paint.setStrokeWidth(

    2

    );
  180. paint.setColor(Color.WHITE);
  181. paint.setStyle(Paint.Style.STROKE);
  182. bmp = Bitmap.createBitmap(X_RES, Y_RES, Bitmap.Config.ARGB_8888);
  183. cv =

    new

    Canvas(bmp);
  184. screen_pos =

    0

    ;
  185. drawCalibrationCross(screen_pos);
  186. }

  187. protected


    void

    onDraw(Canvas canvas) {
  188. canvas.drawColor(Color.BLACK);
  189. canvas.drawBitmap(bmp,

    0

    ,

    0

    ,

    null

    );
  190. }

  191. private


    boolean

    drawCalibrationCross(

    int

    pos) {

  192. if

    (DEBUG) {
  193. Log.i(

    “bigcren”

    ,

    “draw cross at pos ”

    + pos);
  194. }
  195. cv.drawColor(Color.BLACK);

  196. // draw X line
  197. cv.drawLine(cal.xfb[pos] –

    10

    , cal.yfb[pos],
  198. cal.xfb[pos] –

    2

    , cal.yfb[pos], paint);
  199. cv.drawLine(cal.xfb[pos] +

    2

    , cal.yfb[pos],
  200. cal.xfb[pos] +

    10

    , cal.yfb[pos], paint);

  201. // draw Y line
  202. cv.drawLine(cal.xfb[pos], cal.yfb[pos] –

    10

    ,
  203. cal.xfb[pos], cal.yfb[pos] –

    2

    , paint);
  204. cv.drawLine(cal.xfb[pos], cal.yfb[pos] +

    2

    ,
  205. cal.xfb[pos], cal.yfb[pos] +

    10

    , paint);
  206. invalidate();

  207. return


    true

    ;
  208. }

  209. public


    boolean

    onTouchEvent(MotionEvent event) {

  210. float

    tmpx, tmpy;

  211. boolean

    ret;

  212. if

    (screen_pos > SAMPLE_COUNTS –

    1

    ) {
  213. Log.i(

    “bigcren”

    ,

    “get sample ok”

    );

  214. return


    true

    ;
  215. }

  216. if

    (event.getAction() == MotionEvent.ACTION_UP) {
  217. tmpx = event.getX();
  218. tmpy = event.getY();

  219. if

    (Math.abs(cal.xfb[screen_pos]-tmpx)>

    15

    &&
  220. Math.abs(cal.yfb[screen_pos]-tmpy)>

    15

    ){
  221. Toast.makeText(mContext, R.string.calibration_error,Toast.LENGTH_SHORT).show();

  222. return


    false

    ;
  223. }
  224. cal.x[screen_pos] = (

    int

    )(event.getX()*

    4096.0

    /(

    float

    )X_RES +

    0.5

    );
  225. cal.y[screen_pos] = (

    int

    )(event.getY()*

    4096.0

    /(

    float

    )Y_RES +

    0.5

    );

  226. if

    (screen_pos ==

    4

    ) {
  227. ret = perform_calibration();

  228. if

    (ret) {
  229. saveCalibrationResult();
  230. SystemProperties.set(

    “sys.config.calibrate”

    ,

    “done”

    );
  231. finish();

  232. return


    true

    ;
  233. }

    else

    {
  234. screen_pos =

    0

    ;
  235. Log.w(TAG,

    “Calibration failed”

    );
  236. }
  237. }

    else

    {
  238. screen_pos++;
  239. drawCalibrationCross(screen_pos);
  240. }
  241. }

  242. return


    true

    ;
  243. }
  244. }
  245. }

转自:


http://blog.csdn.net/king_sundi/archive/2011/01/19/6152865.aspx


http://blogold.chinaunix.net/u3/90973/showart_2162315.html


http://blog.csdn.net/cpuwolf/archive/2011/01/11/6130010.aspx


http://blog.csdn.net/dafeifly/archive/2009/10/13/4662498.aspx