/src/backend/win32/ftk_display_win32.cpp

http://ftk.googlecode.com/ · C++ · 522 lines · 423 code · 63 blank · 36 comment · 40 complexity · e3b5cc65bb023b01c863fd4da27c0b80 MD5 · raw file

  1. /*
  2. * File: ftk_display_win32_win32.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: win32 display
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-11-17 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include <windows.h>
  31. #include "ftk.h"
  32. #include "ftk_typedef.h"
  33. #include "ftk_log.h"
  34. #include "ftk_bitmap.h"
  35. #include "ftk_event.h"
  36. #include "ftk_globals.h"
  37. #include "ftk_wnd_manager.h"
  38. #include "ftk_display_win32.h"
  39. #include "ftk_input_method_manager.h"
  40. #include "ftk_input_method_win32.h"
  41. #define DISPLAY_WIDTH 640
  42. #define DISPLAY_HEIGHT 480
  43. static char szClassName[ ] = "FtkEmulator";
  44. static LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
  45. static HWND ftk_create_display_window(void)
  46. {
  47. HWND hwnd; /* This is the handle for our window */
  48. WNDCLASSEX wincl; /* Data structure for the windowclass */
  49. int width = DISPLAY_WIDTH + GetSystemMetrics(SM_CXFRAME) * 2;
  50. int height = DISPLAY_HEIGHT + GetSystemMetrics(SM_CYFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
  51. /* The Window structure */
  52. wincl.hInstance = NULL;
  53. wincl.lpszClassName = szClassName;
  54. wincl.lpfnWndProc = WinProc; /* This function is called by windows */
  55. wincl.style = CS_DBLCLKS; /* Catch double-clicks */
  56. wincl.cbSize = sizeof (WNDCLASSEX);
  57. /* Use default icon and mouse-pointer */
  58. wincl.hIcon = NULL;
  59. wincl.hIconSm = NULL;
  60. wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  61. wincl.lpszMenuName = NULL; /* No menu */
  62. wincl.cbClsExtra = 0; /* No extra bytes after the window class */
  63. wincl.cbWndExtra = 64; /* structure or the window instance */
  64. /* Use Windows's default color as the background of the window */
  65. wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
  66. /* Register the window class, and if it fails quit the program */
  67. if (!RegisterClassEx (&wincl))
  68. return 0;
  69. /* The class is registered, let's create the program*/
  70. hwnd = CreateWindowEx (
  71. 0, /* Extended possibilites for variation */
  72. szClassName, /* Classname */
  73. "FtkEmulator", /* Title Text */
  74. WS_OVERLAPPEDWINDOW, /* default window */
  75. CW_USEDEFAULT, /* Windows decides the position */
  76. CW_USEDEFAULT, /* where the window ends up on the screen */
  77. width, /* The programs width */
  78. height, /* and height in pixels */
  79. HWND_DESKTOP, /* The window is a child-window to desktop */
  80. NULL, /* No menu */
  81. NULL, /* Program Instance handler */
  82. NULL /* No Window Creation data */
  83. );
  84. return hwnd;
  85. }
  86. typedef struct _PrivInfo
  87. {
  88. HWND wnd;
  89. void* bits;
  90. void* revert_bits;
  91. HBITMAP hBitmap;
  92. FtkEvent event;
  93. }PrivInfo;
  94. static LRESULT WinOnPaint(HWND hwnd)
  95. {
  96. HDC dc = NULL;
  97. PAINTSTRUCT ps;
  98. HBITMAP hBitmap;
  99. PrivInfo* priv = NULL;
  100. HBITMAP hDisplay = NULL;
  101. BeginPaint(hwnd, &ps);
  102. priv = (PrivInfo*)GetWindowLong(hwnd, GWL_USERDATA);
  103. hDisplay = priv->hBitmap;
  104. dc = CreateCompatibleDC(ps.hdc);
  105. hBitmap = (HBITMAP)SelectObject(dc, hDisplay);
  106. BitBlt(ps.hdc, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, dc, 0, 0, SRCCOPY);
  107. SelectObject(dc, hBitmap);
  108. DeleteObject(dc);
  109. EndPaint(hwnd, &ps);
  110. return 0;
  111. }
  112. static int s_key_map[0xff] = {0};
  113. static Ret ftk_on_key_event(PrivInfo* priv, int down, unsigned char vkey)
  114. {
  115. priv->event.type = down ? FTK_EVT_KEY_DOWN : FTK_EVT_KEY_UP;
  116. priv->event.u.key.code = s_key_map[vkey];
  117. return RET_OK;
  118. }
  119. static char* ftk_on_ime_event(HWND hwnd, LPARAM lParam)
  120. {
  121. LONG n;
  122. char* gb2312;
  123. wchar_t* unicode;
  124. char* utf8;
  125. HIMC himc;
  126. himc = ImmGetContext(hwnd);
  127. if(himc == NULL)
  128. {
  129. return NULL;
  130. }
  131. n = ImmGetCompositionString(himc, GCS_RESULTSTR, NULL, 0);
  132. if(n <= 0)
  133. {
  134. ImmReleaseContext(hwnd, himc);
  135. return NULL;
  136. }
  137. gb2312 = (char*) FTK_ALLOC(n + 1);
  138. if(gb2312 == NULL)
  139. {
  140. ImmReleaseContext(hwnd, himc);
  141. return NULL;
  142. }
  143. if(ImmGetCompositionString(himc, GCS_RESULTSTR, gb2312, n) != n)
  144. {
  145. FTK_FREE(gb2312);
  146. ImmReleaseContext(hwnd, himc);
  147. return NULL;
  148. }
  149. ImmReleaseContext(hwnd, himc);
  150. gb2312[n] = '\0';
  151. ftk_logd("%s:%d WM_IME_COMPOSITION:%s\n", __FILE__, __LINE__, gb2312);
  152. n = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
  153. if(n < 1)
  154. {
  155. FTK_FREE(gb2312);
  156. return NULL;
  157. }
  158. unicode = (wchar_t*) FTK_ALLOC(n * 2);
  159. if(unicode == NULL)
  160. {
  161. FTK_FREE(gb2312);
  162. return NULL;
  163. }
  164. n = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, unicode, n);
  165. if(n < 1)
  166. {
  167. FTK_FREE(gb2312);
  168. FTK_FREE(unicode);
  169. return NULL;
  170. }
  171. FTK_FREE(gb2312);
  172. n = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
  173. if(n < 1)
  174. {
  175. FTK_FREE(unicode);
  176. return NULL;
  177. }
  178. utf8 = (char*) FTK_ALLOC(n);
  179. if(utf8 == NULL)
  180. {
  181. FTK_FREE(unicode);
  182. return NULL;
  183. }
  184. n = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, n, NULL, NULL);
  185. if(n < 1)
  186. {
  187. FTK_FREE(unicode);
  188. FTK_FREE(utf8);
  189. return NULL;
  190. }
  191. FTK_FREE(unicode);
  192. return utf8;
  193. }
  194. static LRESULT CALLBACK WinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  195. {
  196. PrivInfo* priv = (PrivInfo*)GetWindowLong(hwnd, GWL_USERDATA);
  197. if(priv != NULL)
  198. {
  199. memset(&priv->event, 0, sizeof(FtkEvent));
  200. }
  201. switch (message) /* handle the messages */
  202. {
  203. case WM_DESTROY:
  204. FTK_QUIT();
  205. PostQuitMessage (0); /* send a WM_QUIT to the message queue */
  206. break;
  207. case WM_PAINT:
  208. {
  209. WinOnPaint(hwnd);
  210. break;
  211. }
  212. case WM_KEYDOWN:
  213. case WM_KEYUP:
  214. {
  215. ftk_on_key_event(priv, message==WM_KEYDOWN, 0xFF & wParam);
  216. break;
  217. }
  218. case WM_LBUTTONUP:
  219. case WM_LBUTTONDOWN:
  220. {
  221. int xPos = LOWORD(lParam);
  222. int yPos = HIWORD(lParam);
  223. priv->event.u.mouse.x = xPos;
  224. priv->event.u.mouse.y = yPos;
  225. priv->event.type = message == WM_LBUTTONUP? FTK_EVT_MOUSE_UP : FTK_EVT_MOUSE_DOWN;
  226. break;
  227. }
  228. case WM_MOUSEMOVE:
  229. {
  230. int xPos = LOWORD(lParam);
  231. int yPos = HIWORD(lParam);
  232. priv->event.u.mouse.x = xPos;
  233. priv->event.u.mouse.y = yPos;
  234. priv->event.type = FTK_EVT_MOUSE_MOVE;
  235. break;
  236. }
  237. case WM_IME_COMPOSITION:
  238. {
  239. char* buf;
  240. FtkInputMethod* im = NULL;
  241. if(!(lParam & GCS_RESULTSTR))
  242. {
  243. return DefWindowProc(hwnd, message, wParam, lParam);
  244. }
  245. if(ftk_input_method_manager_get(ftk_default_input_method_manager(), 2, &im) == RET_FAIL || im == NULL)
  246. {
  247. return DefWindowProc(hwnd, message, wParam, lParam);
  248. }
  249. if(ftk_input_method_win32_get_editor(im) == NULL)
  250. {
  251. return DefWindowProc(hwnd, message, wParam, lParam);
  252. }
  253. buf = ftk_on_ime_event(hwnd, lParam);
  254. if(buf == NULL)
  255. {
  256. return DefWindowProc(hwnd, message, wParam, lParam);
  257. }
  258. priv->event.u.extra = buf;
  259. priv->event.type = FTK_EVT_OS_IM_COMMIT;
  260. break;
  261. }
  262. default: /* for messages that we don't deal with */
  263. return DefWindowProc (hwnd, message, wParam, lParam);
  264. }
  265. if(priv->event.type != FTK_EVT_NOP)
  266. {
  267. ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &priv->event);
  268. priv->event.type = FTK_EVT_NOP;
  269. }
  270. return 0;
  271. }
  272. static Ret ftk_display_win32_update(FtkDisplay* thiz, FtkBitmap* bitmap, FtkRect* rect, int xoffset, int yoffset)
  273. {
  274. int i = 0;
  275. int j = 0;
  276. MSG msg;
  277. DECL_PRIV(thiz, priv);
  278. BITMAPINFO bmi;
  279. int display_width = DISPLAY_WIDTH;
  280. int display_height = DISPLAY_HEIGHT;
  281. FtkColor* bits = (FtkColor*)priv->bits;
  282. memset(&bmi, 0x00, sizeof(bmi));
  283. bmi.bmiHeader.biBitCount = 32;
  284. bmi.bmiHeader.biCompression = BI_RGB;
  285. bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  286. bmi.bmiHeader.biWidth = DISPLAY_WIDTH;
  287. bmi.bmiHeader.biHeight = DISPLAY_HEIGHT;
  288. bmi.bmiHeader.biPlanes = 1;
  289. ftk_bitmap_copy_to_data_bgra32(bitmap, rect,
  290. priv->bits, xoffset, yoffset, display_width, display_height);
  291. /* top-down bitmap */
  292. FtkColor* src = (FtkColor*)priv->bits;
  293. FtkColor* dst = (FtkColor*)priv->revert_bits + ((DISPLAY_HEIGHT - 1) * DISPLAY_WIDTH);
  294. for(j = 0; j < DISPLAY_HEIGHT; j++)
  295. {
  296. for(i = 0; i < DISPLAY_WIDTH; i++)
  297. {
  298. dst[i] = src[i];
  299. }
  300. src += DISPLAY_WIDTH;
  301. dst -= DISPLAY_WIDTH;
  302. }
  303. /* The origin for DIBs is the lower-left corner of the bitmap */
  304. ::SetDIBits(GetDC(priv->wnd), priv->hBitmap, 0, DISPLAY_HEIGHT, priv->revert_bits, &bmi, DIB_RGB_COLORS);
  305. InvalidateRect(priv->wnd, NULL, FALSE);
  306. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  307. {
  308. TranslateMessage(&msg);
  309. DispatchMessage(&msg);
  310. if(msg.message == WM_PAINT) break;
  311. }
  312. return RET_OK;
  313. }
  314. static int ftk_display_win32_width(FtkDisplay* thiz)
  315. {
  316. return DISPLAY_WIDTH;
  317. }
  318. static int ftk_display_win32_height(FtkDisplay* thiz)
  319. {
  320. return DISPLAY_HEIGHT;
  321. }
  322. static Ret ftk_display_win32_snap(FtkDisplay* thiz, FtkRect* r, FtkBitmap* bitmap)
  323. {
  324. FtkRect rect = {0};
  325. DECL_PRIV(thiz, priv);
  326. int w = ftk_display_width(thiz);
  327. int h = ftk_display_height(thiz);
  328. int bw = ftk_bitmap_width(bitmap);
  329. int bh = ftk_bitmap_height(bitmap);
  330. rect.x = r->x;
  331. rect.y = r->y;
  332. rect.width = FTK_MIN(bw, r->width);
  333. rect.height = FTK_MIN(bh, r->height);
  334. return ftk_bitmap_copy_from_data_bgra32(bitmap, priv->bits, w, h, &rect);
  335. }
  336. static void ftk_display_win32_destroy(FtkDisplay* thiz)
  337. {
  338. DECL_PRIV(thiz, priv);
  339. if(priv != NULL)
  340. {
  341. CloseWindow(priv->wnd);
  342. FTK_FREE(priv->bits);
  343. FTK_FREE(priv->revert_bits);
  344. DeleteObject(priv->hBitmap);
  345. FTK_FREE(thiz);
  346. }
  347. return;
  348. }
  349. static void ftk_keymap_init(void)
  350. {
  351. s_key_map[0xBD] = FTK_KEY_MINUS;
  352. s_key_map[0x20] = FTK_KEY_SPACE;
  353. s_key_map[0xBB] = FTK_KEY_EQUAL;
  354. s_key_map[0x08] = FTK_KEY_BACKSPACE;
  355. s_key_map[0x09] = FTK_KEY_TAB;
  356. s_key_map[0xC0] = FTK_KEY_QUOTELEFT;
  357. s_key_map[0xDE] = FTK_KEY_QUOTERIGHT;
  358. s_key_map[0xDB] = FTK_KEY_BRACKETLEFT;
  359. s_key_map[0xDD] = FTK_KEY_BRACKETRIGHT;
  360. s_key_map[0x0d] = FTK_KEY_ENTER;
  361. s_key_map[0xBA] = FTK_KEY_SEMICOLON;
  362. s_key_map[0x30] = FTK_KEY_0;
  363. s_key_map[0x31] = FTK_KEY_1;
  364. s_key_map[0x32] = FTK_KEY_2;
  365. s_key_map[0x33] = FTK_KEY_3;
  366. s_key_map[0x34] = FTK_KEY_4;
  367. s_key_map[0x35] = FTK_KEY_5;
  368. s_key_map[0x36] = FTK_KEY_6;
  369. s_key_map[0x37] = FTK_KEY_7;
  370. s_key_map[0x38] = FTK_KEY_8;
  371. s_key_map[0x39] = FTK_KEY_9;
  372. s_key_map[0x70] = FTK_KEY_F1;
  373. s_key_map[0x71] = FTK_KEY_F2;
  374. s_key_map[0x72] = FTK_KEY_F3;
  375. s_key_map[0x73] = FTK_KEY_F4;
  376. s_key_map[0x74] = FTK_KEY_F5;
  377. s_key_map[0x75] = FTK_KEY_F6;
  378. s_key_map[0x76] = FTK_KEY_F7;
  379. s_key_map[0x77] = FTK_KEY_F8;
  380. s_key_map[0x78] = FTK_KEY_F9;
  381. s_key_map[0xBC] = FTK_KEY_COMMA;
  382. s_key_map[0xBE] = FTK_KEY_DOT;
  383. s_key_map[0xBF] = FTK_KEY_SLASH;
  384. s_key_map[0x10] = FTK_KEY_RIGHTSHIFT;
  385. s_key_map[0x11] = FTK_KEY_LEFTCTRL;
  386. s_key_map[0x14] = FTK_KEY_CAPSLOCK;
  387. s_key_map[0x40] = FTK_KEY_LEFTALT;
  388. s_key_map[0x41] = FTK_KEY_a;
  389. s_key_map[0x42] = FTK_KEY_b;
  390. s_key_map[0x43] = FTK_KEY_c;
  391. s_key_map[0x44] = FTK_KEY_d;
  392. s_key_map[0x45] = FTK_KEY_e;
  393. s_key_map[0x46] = FTK_KEY_f;
  394. s_key_map[0x47] = FTK_KEY_g;
  395. s_key_map[0x48] = FTK_KEY_h;
  396. s_key_map[0x49] = FTK_KEY_i;
  397. s_key_map[0x4a] = FTK_KEY_j;
  398. s_key_map[0x4b] = FTK_KEY_k;
  399. s_key_map[0x4c] = FTK_KEY_l;
  400. s_key_map[0x4d] = FTK_KEY_m;
  401. s_key_map[0x4e] = FTK_KEY_n;
  402. s_key_map[0x4f] = FTK_KEY_o;
  403. s_key_map[0x50] = FTK_KEY_p;
  404. s_key_map[0x51] = FTK_KEY_q;
  405. s_key_map[0x52] = FTK_KEY_r;
  406. s_key_map[0x53] = FTK_KEY_s;
  407. s_key_map[0x54] = FTK_KEY_t;
  408. s_key_map[0x55] = FTK_KEY_u;
  409. s_key_map[0x56] = FTK_KEY_v;
  410. s_key_map[0x57] = FTK_KEY_w;
  411. s_key_map[0x58] = FTK_KEY_x;
  412. s_key_map[0x59] = FTK_KEY_y;
  413. s_key_map[0x5a] = FTK_KEY_z;
  414. s_key_map[0x21] = FTK_KEY_PAGEUP;
  415. s_key_map[0x25] = FTK_KEY_LEFT;
  416. s_key_map[0x27] = FTK_KEY_RIGHT;
  417. s_key_map[0x24] = FTK_KEY_HOME;
  418. s_key_map[0x23] = FTK_KEY_END;
  419. s_key_map[0x28] = FTK_KEY_DOWN;
  420. s_key_map[0x22] = FTK_KEY_PAGEDOWN;
  421. s_key_map[0x2d] = FTK_KEY_INSERT;
  422. s_key_map[0x2e] = FTK_KEY_DELETE;
  423. s_key_map[0x26] = FTK_KEY_UP;
  424. return;
  425. }
  426. FtkDisplay* ftk_display_win32_create(void)
  427. {
  428. FtkDisplay* thiz = (FtkDisplay*)FTK_ZALLOC(sizeof(FtkDisplay) + sizeof(PrivInfo));
  429. if(thiz != NULL)
  430. {
  431. PrivInfo* p = NULL;
  432. BITMAPINFO bmi = {0};
  433. HBITMAP hBitmap = NULL;
  434. DECL_PRIV(thiz, priv);
  435. thiz->update = ftk_display_win32_update;
  436. thiz->width = ftk_display_win32_width;
  437. thiz->height = ftk_display_win32_height;
  438. thiz->snap = ftk_display_win32_snap;
  439. thiz->destroy = ftk_display_win32_destroy;
  440. priv->wnd = ftk_create_display_window();
  441. memset(&bmi, 0x00, sizeof(bmi));
  442. bmi.bmiHeader.biBitCount = 32;
  443. bmi.bmiHeader.biHeight = DISPLAY_HEIGHT;
  444. bmi.bmiHeader.biWidth = DISPLAY_HEIGHT;
  445. bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  446. bmi.bmiHeader.biPlanes = 1;
  447. bmi.bmiHeader.biCompression = BI_RGB;
  448. bmi.bmiHeader.biSizeImage = 0;
  449. hBitmap = CreateBitmap(DISPLAY_WIDTH, DISPLAY_HEIGHT, 1, 32, NULL);
  450. priv->hBitmap = hBitmap;
  451. priv->bits = FTK_ZALLOC(DISPLAY_WIDTH * DISPLAY_HEIGHT * 4);
  452. priv->revert_bits = FTK_ZALLOC(DISPLAY_WIDTH * DISPLAY_HEIGHT * 4);
  453. SetWindowLong(priv->wnd, GWL_USERDATA, (LONG)priv);
  454. ShowWindow (priv->wnd, SW_SHOW);
  455. UpdateWindow(priv->wnd);
  456. ftk_keymap_init();
  457. }
  458. return thiz;
  459. }