PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/reactos/base/applications/clipbrd/clipbrd.c

https://gitlab.com/dj-tech/reactos
C | 597 lines | 489 code | 100 blank | 8 comment | 58 complexity | 8e25f227ac56b0a0bdc731459cf5daad MD5 | raw file
  1. /*
  2. * COPYRIGHT: See COPYING in the top level directory
  3. * PROJECT: ReactOS Clipboard Viewer
  4. * FILE: base/applications/clipbrd/clipbrd.c
  5. * PURPOSE: Provides a view of the contents of the ReactOS clipboard.
  6. * PROGRAMMERS: Ricardo Hanke
  7. */
  8. #include "precomp.h"
  9. static const WCHAR szClassName[] = L"ClipBookWClass";
  10. CLIPBOARD_GLOBALS Globals;
  11. SCROLLSTATE Scrollstate;
  12. static void UpdateLinesToScroll(void)
  13. {
  14. UINT uLinesToScroll;
  15. if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uLinesToScroll, 0))
  16. {
  17. Globals.uLinesToScroll = 3;
  18. }
  19. else
  20. {
  21. Globals.uLinesToScroll = uLinesToScroll;
  22. }
  23. }
  24. static void SaveClipboardToFile(void)
  25. {
  26. OPENFILENAMEW sfn;
  27. WCHAR szFileName[MAX_PATH];
  28. WCHAR szFilterMask[MAX_STRING_LEN + 10];
  29. LPWSTR c;
  30. ZeroMemory(&szFilterMask, sizeof(szFilterMask));
  31. c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_NT, szFilterMask, MAX_STRING_LEN) + 1;
  32. wcscpy(c, L"*.clp");
  33. ZeroMemory(&szFileName, sizeof(szFileName));
  34. ZeroMemory(&sfn, sizeof(sfn));
  35. sfn.lStructSize = sizeof(sfn);
  36. sfn.hwndOwner = Globals.hMainWnd;
  37. sfn.hInstance = Globals.hInstance;
  38. sfn.lpstrFilter = szFilterMask;
  39. sfn.lpstrFile = szFileName;
  40. sfn.nMaxFile = ARRAYSIZE(szFileName);
  41. sfn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
  42. sfn.lpstrDefExt = L"clp";
  43. if (!GetSaveFileNameW(&sfn))
  44. return;
  45. if (!OpenClipboard(Globals.hMainWnd))
  46. {
  47. ShowLastWin32Error(Globals.hMainWnd);
  48. return;
  49. }
  50. WriteClipboardFile(szFileName, CLIP_FMT_NT /* CLIP_FMT_31 */);
  51. CloseClipboard();
  52. }
  53. static void LoadClipboardDataFromFile(LPWSTR lpszFileName)
  54. {
  55. if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance,
  56. STRING_DELETE_MSG, STRING_DELETE_TITLE,
  57. MB_ICONWARNING | MB_YESNO) != IDYES)
  58. {
  59. return;
  60. }
  61. if (!OpenClipboard(Globals.hMainWnd))
  62. {
  63. ShowLastWin32Error(Globals.hMainWnd);
  64. return;
  65. }
  66. EmptyClipboard();
  67. ReadClipboardFile(lpszFileName);
  68. CloseClipboard();
  69. }
  70. static void LoadClipboardFromFile(void)
  71. {
  72. OPENFILENAMEW ofn;
  73. WCHAR szFileName[MAX_PATH];
  74. WCHAR szFilterMask[MAX_STRING_LEN + 10];
  75. LPWSTR c;
  76. ZeroMemory(&szFilterMask, sizeof(szFilterMask));
  77. c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_GEN, szFilterMask, MAX_STRING_LEN) + 1;
  78. wcscpy(c, L"*.clp");
  79. ZeroMemory(&szFileName, sizeof(szFileName));
  80. ZeroMemory(&ofn, sizeof(ofn));
  81. ofn.lStructSize = sizeof(ofn);
  82. ofn.hwndOwner = Globals.hMainWnd;
  83. ofn.hInstance = Globals.hInstance;
  84. ofn.lpstrFilter = szFilterMask;
  85. ofn.lpstrFile = szFileName;
  86. ofn.nMaxFile = ARRAYSIZE(szFileName);
  87. ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  88. if (!GetOpenFileNameW(&ofn))
  89. return;
  90. LoadClipboardDataFromFile(szFileName);
  91. }
  92. static void LoadClipboardFromDrop(HDROP hDrop)
  93. {
  94. WCHAR szFileName[MAX_PATH];
  95. DragQueryFileW(hDrop, 0, szFileName, ARRAYSIZE(szFileName));
  96. DragFinish(hDrop);
  97. LoadClipboardDataFromFile(szFileName);
  98. }
  99. static void SetDisplayFormat(UINT uFormat)
  100. {
  101. CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_UNCHECKED);
  102. Globals.uCheckedItem = uFormat + CMD_AUTOMATIC;
  103. CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_CHECKED);
  104. if (uFormat == 0)
  105. {
  106. Globals.uDisplayFormat = GetAutomaticClipboardFormat();
  107. }
  108. else
  109. {
  110. Globals.uDisplayFormat = uFormat;
  111. }
  112. if (Globals.hDspBmp)
  113. {
  114. DeleteObject(Globals.hDspBmp);
  115. }
  116. ZeroMemory(&Scrollstate, sizeof(Scrollstate));
  117. UpdateWindowScrollState(Globals.hMainWnd, Globals.hDspBmp, &Scrollstate);
  118. InvalidateRect(Globals.hMainWnd, NULL, TRUE);
  119. }
  120. static void InitMenuPopup(HMENU hMenu, LPARAM index)
  121. {
  122. if ((GetMenuItemID(hMenu, 0) == CMD_DELETE) || (GetMenuItemID(hMenu, 1) == CMD_SAVE_AS))
  123. {
  124. if (CountClipboardFormats() == 0)
  125. {
  126. EnableMenuItem(hMenu, CMD_DELETE, MF_GRAYED);
  127. EnableMenuItem(hMenu, CMD_SAVE_AS, MF_GRAYED);
  128. }
  129. else
  130. {
  131. EnableMenuItem(hMenu, CMD_DELETE, MF_ENABLED);
  132. EnableMenuItem(hMenu, CMD_SAVE_AS, MF_ENABLED);
  133. }
  134. }
  135. DrawMenuBar(Globals.hMainWnd);
  136. }
  137. static void UpdateDisplayMenu(void)
  138. {
  139. UINT uFormat;
  140. WCHAR szFormatName[MAX_FMT_NAME_LEN + 1];
  141. HMENU hMenu;
  142. hMenu = GetSubMenu(Globals.hMenu, DISPLAY_MENU_POS);
  143. while (GetMenuItemCount(hMenu) > 1)
  144. {
  145. DeleteMenu(hMenu, 1, MF_BYPOSITION);
  146. }
  147. if (CountClipboardFormats() == 0)
  148. return;
  149. if (!OpenClipboard(Globals.hMainWnd))
  150. return;
  151. AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
  152. uFormat = EnumClipboardFormats(0);
  153. while (uFormat)
  154. {
  155. RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE, szFormatName, ARRAYSIZE(szFormatName));
  156. if (!IsClipboardFormatSupported(uFormat))
  157. {
  158. AppendMenuW(hMenu, MF_STRING | MF_GRAYED, 0, szFormatName);
  159. }
  160. else
  161. {
  162. AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName);
  163. }
  164. uFormat = EnumClipboardFormats(uFormat);
  165. }
  166. CloseClipboard();
  167. }
  168. static int ClipboardCommandHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  169. {
  170. switch (LOWORD(wParam))
  171. {
  172. case CMD_OPEN:
  173. {
  174. LoadClipboardFromFile();
  175. break;
  176. }
  177. case CMD_SAVE_AS:
  178. {
  179. SaveClipboardToFile();
  180. break;
  181. }
  182. case CMD_EXIT:
  183. {
  184. PostMessageW(Globals.hMainWnd, WM_CLOSE, 0, 0);
  185. break;
  186. }
  187. case CMD_DELETE:
  188. {
  189. if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance,
  190. STRING_DELETE_MSG, STRING_DELETE_TITLE,
  191. MB_ICONWARNING | MB_YESNO) != IDYES)
  192. {
  193. break;
  194. }
  195. DeleteClipboardContent();
  196. break;
  197. }
  198. case CMD_AUTOMATIC:
  199. {
  200. SetDisplayFormat(0);
  201. break;
  202. }
  203. case CMD_HELP:
  204. {
  205. HtmlHelpW(Globals.hMainWnd, L"clipbrd.chm", 0, 0);
  206. break;
  207. }
  208. case CMD_ABOUT:
  209. {
  210. HICON hIcon;
  211. WCHAR szTitle[MAX_STRING_LEN];
  212. hIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCE(CLIPBRD_ICON));
  213. LoadStringW(Globals.hInstance, STRING_CLIPBOARD, szTitle, ARRAYSIZE(szTitle));
  214. ShellAboutW(Globals.hMainWnd, szTitle, NULL, hIcon);
  215. DeleteObject(hIcon);
  216. break;
  217. }
  218. default:
  219. {
  220. break;
  221. }
  222. }
  223. return 0;
  224. }
  225. static void ClipboardPaintHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  226. {
  227. HDC hdc;
  228. PAINTSTRUCT ps;
  229. RECT rc;
  230. if (!OpenClipboard(Globals.hMainWnd))
  231. return;
  232. hdc = BeginPaint(hWnd, &ps);
  233. GetClientRect(hWnd, &rc);
  234. switch (Globals.uDisplayFormat)
  235. {
  236. case CF_NONE:
  237. {
  238. break;
  239. }
  240. case CF_UNICODETEXT:
  241. {
  242. DrawTextFromClipboard(hdc, &rc, DT_LEFT | DT_NOPREFIX);
  243. break;
  244. }
  245. case CF_BITMAP:
  246. {
  247. BitBltFromClipboard(hdc, rc.left, rc.top, rc.right, rc.bottom, 0, 0, SRCCOPY);
  248. break;
  249. }
  250. case CF_DIB:
  251. {
  252. SetDIBitsToDeviceFromClipboard(CF_DIB, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
  253. break;
  254. }
  255. case CF_DIBV5:
  256. {
  257. SetDIBitsToDeviceFromClipboard(CF_DIBV5, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
  258. break;
  259. }
  260. case CF_METAFILEPICT:
  261. {
  262. PlayMetaFileFromClipboard(hdc, &rc);
  263. break;
  264. }
  265. case CF_ENHMETAFILE:
  266. {
  267. PlayEnhMetaFileFromClipboard(hdc, &rc);
  268. break;
  269. }
  270. default:
  271. {
  272. DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
  273. break;
  274. }
  275. }
  276. EndPaint(hWnd, &ps);
  277. CloseClipboard();
  278. }
  279. static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  280. {
  281. switch(uMsg)
  282. {
  283. case WM_CREATE:
  284. {
  285. Globals.hMenu = GetMenu(hWnd);
  286. Globals.hWndNext = SetClipboardViewer(hWnd);
  287. UpdateDisplayMenu();
  288. SetDisplayFormat(0);
  289. break;
  290. }
  291. case WM_CLOSE:
  292. {
  293. DestroyWindow(hWnd);
  294. break;
  295. }
  296. case WM_DESTROY:
  297. {
  298. ChangeClipboardChain(hWnd, Globals.hWndNext);
  299. PostQuitMessage(0);
  300. break;
  301. }
  302. case WM_PAINT:
  303. {
  304. ClipboardPaintHandler(hWnd, uMsg, wParam, lParam);
  305. break;
  306. }
  307. case WM_KEYDOWN:
  308. {
  309. HandleKeyboardScrollEvents(hWnd, uMsg, wParam, lParam);
  310. break;
  311. }
  312. case WM_MOUSEWHEEL:
  313. {
  314. HandleMouseScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
  315. break;
  316. }
  317. case WM_HSCROLL:
  318. {
  319. HandleHorizontalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
  320. break;
  321. }
  322. case WM_VSCROLL:
  323. {
  324. HandleVerticalScrollEvents(hWnd, uMsg, wParam, lParam, &Scrollstate);
  325. break;
  326. }
  327. case WM_SIZE:
  328. {
  329. UpdateWindowScrollState(hWnd, Globals.hDspBmp, &Scrollstate);
  330. if ((Globals.uDisplayFormat == CF_METAFILEPICT) ||
  331. (Globals.uDisplayFormat == CF_ENHMETAFILE) ||
  332. (Globals.uDisplayFormat == CF_DSPENHMETAFILE) ||
  333. (Globals.uDisplayFormat == CF_DSPMETAFILEPICT))
  334. {
  335. InvalidateRect(Globals.hMainWnd, NULL, FALSE);
  336. }
  337. else if (!IsClipboardFormatSupported(Globals.uDisplayFormat))
  338. {
  339. InvalidateRect(Globals.hMainWnd, NULL, TRUE);
  340. }
  341. break;
  342. }
  343. case WM_CHANGECBCHAIN:
  344. {
  345. if ((HWND)wParam == Globals.hWndNext)
  346. {
  347. Globals.hWndNext = (HWND)lParam;
  348. }
  349. else if (Globals.hWndNext != NULL)
  350. {
  351. SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
  352. }
  353. break;
  354. }
  355. case WM_DRAWCLIPBOARD:
  356. {
  357. UpdateDisplayMenu();
  358. SetDisplayFormat(0);
  359. SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
  360. break;
  361. }
  362. case WM_COMMAND:
  363. {
  364. if ((LOWORD(wParam) > CMD_AUTOMATIC))
  365. {
  366. SetDisplayFormat(LOWORD(wParam) - CMD_AUTOMATIC);
  367. }
  368. else
  369. {
  370. ClipboardCommandHandler(hWnd, uMsg, wParam, lParam);
  371. }
  372. break;
  373. }
  374. case WM_INITMENUPOPUP:
  375. {
  376. InitMenuPopup((HMENU)wParam, lParam);
  377. break;
  378. }
  379. case WM_DROPFILES:
  380. {
  381. LoadClipboardFromDrop((HDROP)wParam);
  382. break;
  383. }
  384. case WM_QUERYNEWPALETTE:
  385. {
  386. if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
  387. {
  388. InvalidateRect(hWnd, NULL, TRUE);
  389. UpdateWindow(hWnd);
  390. return TRUE;
  391. }
  392. return FALSE;
  393. }
  394. case WM_PALETTECHANGED:
  395. {
  396. if ((HWND)wParam != hWnd)
  397. {
  398. if (RealizeClipboardPalette(hWnd) != GDI_ERROR)
  399. {
  400. InvalidateRect(hWnd, NULL, TRUE);
  401. UpdateWindow(hWnd);
  402. }
  403. }
  404. break;
  405. }
  406. case WM_SYSCOLORCHANGE:
  407. {
  408. SetDisplayFormat(Globals.uDisplayFormat);
  409. break;
  410. }
  411. case WM_SETTINGCHANGE:
  412. {
  413. if (wParam == SPI_SETWHEELSCROLLLINES)
  414. {
  415. UpdateLinesToScroll();
  416. }
  417. break;
  418. }
  419. default:
  420. {
  421. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  422. }
  423. }
  424. return 0;
  425. }
  426. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
  427. {
  428. MSG msg;
  429. HACCEL hAccel;
  430. HWND hPrevWindow;
  431. WNDCLASSEXW wndclass;
  432. WCHAR szBuffer[MAX_STRING_LEN];
  433. hPrevWindow = FindWindowW(szClassName, NULL);
  434. if (hPrevWindow)
  435. {
  436. BringWindowToFront(hPrevWindow);
  437. return 0;
  438. }
  439. ZeroMemory(&Globals, sizeof(Globals));
  440. Globals.hInstance = hInstance;
  441. ZeroMemory(&wndclass, sizeof(wndclass));
  442. wndclass.cbSize = sizeof(wndclass);
  443. wndclass.lpfnWndProc = MainWndProc;
  444. wndclass.hInstance = hInstance;
  445. wndclass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(CLIPBRD_ICON));
  446. wndclass.hCursor = LoadCursorW(0, IDC_ARROW);
  447. wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  448. wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU);
  449. wndclass.lpszClassName = szClassName;
  450. if (!RegisterClassExW(&wndclass))
  451. {
  452. ShowLastWin32Error(NULL);
  453. return 0;
  454. }
  455. LoadStringW(hInstance, STRING_CLIPBOARD, szBuffer, ARRAYSIZE(szBuffer));
  456. Globals.hMainWnd = CreateWindowExW(WS_EX_CLIENTEDGE | WS_EX_ACCEPTFILES,
  457. szClassName,
  458. szBuffer,
  459. WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
  460. CW_USEDEFAULT,
  461. CW_USEDEFAULT,
  462. CW_USEDEFAULT,
  463. CW_USEDEFAULT,
  464. NULL,
  465. NULL,
  466. Globals.hInstance,
  467. NULL);
  468. if (!Globals.hMainWnd)
  469. {
  470. ShowLastWin32Error(NULL);
  471. return 0;
  472. }
  473. ShowWindow(Globals.hMainWnd, nCmdShow);
  474. UpdateWindow(Globals.hMainWnd);
  475. hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(ID_ACCEL));
  476. if (!hAccel)
  477. {
  478. ShowLastWin32Error(Globals.hMainWnd);
  479. }
  480. /* If the user provided a path to a clipboard data file, try to open it */
  481. if (lpCmdLine != NULL && *lpCmdLine)
  482. LoadClipboardDataFromFile(lpCmdLine);
  483. UpdateLinesToScroll();
  484. while (GetMessageW(&msg, 0, 0, 0))
  485. {
  486. if (!TranslateAcceleratorW(Globals.hMainWnd, hAccel, &msg))
  487. {
  488. TranslateMessage(&msg);
  489. DispatchMessageW(&msg);
  490. }
  491. }
  492. if (Globals.hDspBmp)
  493. {
  494. DeleteObject(Globals.hDspBmp);
  495. }
  496. return (int)msg.wParam;
  497. }