001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Dmitry A. Durnev
019: * @version $Revision$
020: */package org.apache.harmony.awt.wtk.windows;
021:
022: import java.awt.Color;
023: import java.awt.Dimension;
024: import java.awt.Rectangle;
025: import java.awt.event.InputEvent;
026: import java.awt.event.KeyEvent;
027: import java.awt.image.BufferedImage;
028:
029: import org.apache.harmony.awt.internal.nls.Messages;
030: import org.apache.harmony.awt.nativebridge.Int32Pointer;
031: import org.apache.harmony.awt.nativebridge.NativeBridge;
032: import org.apache.harmony.awt.nativebridge.windows.Win32;
033: import org.apache.harmony.awt.nativebridge.windows.WindowsDefs;
034: import org.apache.harmony.awt.wtk.NativeRobot;
035:
036: /**
037: * WinRobot
038: */
039: public class WinRobot implements NativeRobot {
040: private static final int[] upFlags = {
041: WindowsDefs.MOUSEEVENTF_LEFTUP,
042: WindowsDefs.MOUSEEVENTF_MIDDLEUP,
043: WindowsDefs.MOUSEEVENTF_RIGHTUP };
044: private static final int[] dnFlags = {
045: WindowsDefs.MOUSEEVENTF_LEFTDOWN,
046: WindowsDefs.MOUSEEVENTF_MIDDLEDOWN,
047: WindowsDefs.MOUSEEVENTF_RIGHTDOWN };
048:
049: private final NativeBridge nb = NativeBridge.getInstance();
050: private final Win32 win32 = Win32.getInstance();
051:
052: /**
053: * @see org.apache.harmony.awt.wtk.NativeRobot#createScreenCapture(java.awt.Rectangle)
054: */
055: public BufferedImage createScreenCapture(Rectangle screenRect) {
056:
057: int w = screenRect.width;
058: int h = screenRect.height;
059: int size = w * h;
060: long compBMP = createScreenBMP(screenRect);
061: if (compBMP == 0l) {
062: return null;
063: }
064:
065: Win32.BITMAPINFO bmi = createAndFillBMI(w, h);
066:
067: // now get device independent bitmap bits from
068: // compBMP and use them to create BufferedImage
069: Int32Pointer pData = nb.createInt32Pointer(size, false);
070: win32.DeleteObject(compBMP);
071: long screenDC = win32.GetDC(0l);
072: int nLines = win32.GetDIBits(screenDC, compBMP, 0, h, pData,
073: bmi, WindowsDefs.DIB_RGB_COLORS);
074: win32.ReleaseDC(0, screenDC);
075:
076: if (nLines != h) {
077: return null;
078: }
079: BufferedImage bufImg = new BufferedImage(w, h,
080: BufferedImage.TYPE_INT_RGB);
081: int[] data = new int[size];
082: pData.get(data, 0, data.length);
083: bufImg.setRGB(0, 0, w, h, data, 0, w);
084: return bufImg;
085: }
086:
087: /**
088: * @see org.apache.harmony.awt.wtk.NativeRobot#getPixel(int, int)
089: */
090: public Color getPixel(int x, int y) {
091: long screenDC = win32.GetDC(0l);
092: long bgr = win32.GetPixel(screenDC, x, y);
093: win32.ReleaseDC(0, screenDC);
094: return fromBGR(bgr);
095: }
096:
097: private Color fromBGR(long bgr) {
098: return new Color((int) bgr & 0xFF, (int) (bgr >> 8 & 0xFF),
099: (int) (bgr >> 16 & 0xFF));
100: }
101:
102: /**
103: * @see org.apache.harmony.awt.wtk.NativeRobot#keyEvent(int, boolean)
104: */
105: public void keyEvent(int keycode, boolean press) {
106: win32.keybd_event(translateKeyCode(keycode), (byte) 0,
107: (press ? 0 : WindowsDefs.KEYEVENTF_KEYUP), 0l);
108: }
109:
110: /**
111: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseButton(int, boolean)
112: */
113: public void mouseButton(int buttons, boolean press) {
114: int flags = 0;
115: int[] allFlags = (press ? dnFlags : upFlags);
116:
117: if ((buttons & InputEvent.BUTTON1_MASK) != 0) {
118: flags |= allFlags[0];
119: }
120: if ((buttons & InputEvent.BUTTON2_MASK) != 0) {
121: flags |= allFlags[1];
122: }
123: if ((buttons & InputEvent.BUTTON3_MASK) != 0) {
124: flags |= allFlags[2];
125: }
126: win32.mouse_event(flags, 0, 0, 0, 0l);
127:
128: }
129:
130: /**
131: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseMove(int, int)
132: */
133: public void mouseMove(int x, int y) {
134: Dimension screenSize = getScreenSize();
135: double k = 65535.;
136: double kx = k / (screenSize.width - 1);
137: double ky = k / (screenSize.height - 1);
138: win32.mouse_event(WindowsDefs.MOUSEEVENTF_ABSOLUTE
139: | WindowsDefs.MOUSEEVENTF_MOVE, (int) (kx * x),
140: (int) (ky * y), 0, 0l);
141:
142: }
143:
144: /**
145: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseWheel(int)
146: */
147: public void mouseWheel(int wheelAmt) {
148: // windows wheel amount is opposite to Java wheel amount
149: win32.mouse_event(WindowsDefs.MOUSEEVENTF_WHEEL, 0, 0,
150: -wheelAmt * WindowsDefs.WHEEL_DELTA, 0l);
151:
152: }
153:
154: private byte translateKeyCode(int keyCode) {
155: int vKey = keyCode;
156: switch (keyCode) {
157: case KeyEvent.VK_ENTER:
158: vKey = WindowsDefs.VK_RETURN;
159: break;
160:
161: case KeyEvent.VK_INSERT:
162: vKey = WindowsDefs.VK_INSERT;
163: break;
164: case KeyEvent.VK_DELETE:
165: vKey = WindowsDefs.VK_DELETE;
166: break;
167: case KeyEvent.VK_SEMICOLON:
168: vKey = WindowsDefs.VK_OEM_1;
169: break;
170: case KeyEvent.VK_SLASH:
171: vKey = WindowsDefs.VK_OEM_2;
172: break;
173: case KeyEvent.VK_OPEN_BRACKET:
174: vKey = WindowsDefs.VK_OEM_4;
175: break;
176: case KeyEvent.VK_BACK_SLASH:
177: vKey = WindowsDefs.VK_OEM_5;
178: break;
179: case KeyEvent.VK_CLOSE_BRACKET:
180: vKey = WindowsDefs.VK_OEM_6;
181: break;
182: case KeyEvent.VK_COMMA:
183: vKey = WindowsDefs.VK_OEM_COMMA;
184: break;
185: case KeyEvent.VK_PERIOD:
186: vKey = WindowsDefs.VK_OEM_PERIOD;
187: break;
188: case KeyEvent.VK_MINUS:
189: vKey = WindowsDefs.VK_OEM_MINUS;
190: break;
191: case KeyEvent.VK_EQUALS:
192: vKey = WindowsDefs.VK_OEM_PLUS;
193: break;
194: }
195: if ((keyCode >= KeyEvent.VK_F13)
196: && (keyCode <= KeyEvent.VK_F24)) {
197: vKey = WindowsDefs.VK_F13 + keyCode - KeyEvent.VK_F13;
198: }
199: if ((vKey < 3) || (vKey > 254) || (vKey >= 4) && (vKey <= 7)
200: || (vKey >= 0xA) && (vKey <= 0xB) || (vKey >= 0xE)
201: && (vKey <= 0xF) || (vKey == 0x16) || (vKey == 0x1A)
202: || (vKey >= 0x3A) && (vKey <= 0x40) || (vKey >= 0x5B)
203: && (vKey <= 0x5F) || (vKey >= 0x88) && (vKey <= 0x8F)
204: || (vKey >= 0x92) && (vKey <= 0x9F) || (vKey >= 0xB8)
205: && (vKey <= 0xB9) || (vKey >= 0xC1) && (vKey <= 0xDA)
206: || (vKey >= 0xE0) && (vKey <= 0xE1) || (vKey >= 0xE3)
207: && (vKey <= 0xE4) || (vKey == 0xE6) || (vKey >= 0xE8)
208: && (vKey <= 0xF5)) {
209: // awt.1B=Invalid key code
210: throw new IllegalArgumentException(Messages
211: .getString("awt.1B")); //$NON-NLS-1$
212: }
213: return (byte) vKey;
214: }
215:
216: private long createScreenBMP(Rectangle screenRect) {
217: int w = screenRect.width;
218: int h = screenRect.height;
219: long screenDC = win32.GetDC(0l);
220: long compBMP = win32.CreateCompatibleBitmap(screenDC, w, h);
221: long compDC = win32.CreateCompatibleDC(screenDC);
222: // create a compatible bitmap to copy screen to
223:
224: if (compBMP == 0) {
225: return 0l; //error
226: }
227: long hObj = win32.SelectObject(compDC, compBMP);
228: if (hObj == 0) {
229: return 0l; //error
230: }
231:
232: // copy color data from the part of the screen into
233: // a compatible bitmap
234: final int SRCCOPY = 0x00CC0020;
235: hObj = win32.BitBlt(compDC, 0, 0, w, h, screenDC, screenRect.x,
236: screenRect.y, SRCCOPY);
237: win32.ReleaseDC(0, screenDC);
238: win32.ReleaseDC(0, compDC);
239: return compBMP;
240: }
241:
242: private Win32.BITMAPINFO createAndFillBMI(int w, int h) {
243: Win32.BITMAPINFO bmi = win32.createBITMAPINFO(false);
244: Win32.BITMAPINFOHEADER bmih = bmi.get_bmiHeader();
245: bmih.set_biSize(bmih.size());
246: bmih.set_biWidth(w);
247: bmih.set_biHeight(-h);
248: bmih.set_biPlanes((short) 1);
249: bmih.set_biBitCount((short) 32);
250: bmih.set_biCompression(WindowsDefs.BI_RGB);
251: return bmi;
252: }
253:
254: @Override
255: protected void finalize() throws Throwable {
256: super .finalize();
257: }
258:
259: private Dimension getScreenSize() {
260: int w = win32.GetSystemMetrics(WindowsDefs.SM_CXSCREEN);
261: int h = win32.GetSystemMetrics(WindowsDefs.SM_CYSCREEN);
262: return new Dimension(w, h);
263: }
264: }
|