633cb87c93a15240aafdb99f65492c03b0309ee5
[reactos.git] / reactos / base / applications / clipbrd / clipbrd.c
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
9 #include "precomp.h"
10
11 static const WCHAR szClassName[] = L"ClipBookWClass";
12
13 CLIPBOARD_GLOBALS Globals;
14
15 static void SetDisplayFormat(UINT uFormat)
16 {
17 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_UNCHECKED);
18 Globals.uCheckedItem = uFormat + CMD_AUTOMATIC;
19 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_CHECKED);
20
21 if (uFormat == 0)
22 {
23 Globals.uDisplayFormat = GetAutomaticClipboardFormat();
24 }
25 else
26 {
27 Globals.uDisplayFormat = uFormat;
28 }
29
30 InvalidateRect(Globals.hMainWnd, NULL, TRUE);
31 UpdateWindow(Globals.hMainWnd);
32 }
33
34 static void InitMenuPopup(HMENU hMenu, LPARAM index)
35 {
36 if (GetMenuItemID(hMenu, 0) == CMD_DELETE)
37 {
38 if (CountClipboardFormats() == 0)
39 {
40 EnableMenuItem(hMenu, CMD_DELETE, MF_GRAYED);
41 }
42 else
43 {
44 EnableMenuItem(hMenu, CMD_DELETE, MF_ENABLED);
45 }
46 }
47
48 DrawMenuBar(Globals.hMainWnd);
49 }
50
51 void UpdateDisplayMenu(void)
52 {
53 UINT uFormat;
54 WCHAR szFormatName[MAX_STRING_LEN];
55 HMENU hMenu;
56
57 hMenu = GetSubMenu(Globals.hMenu, DISPLAY_MENU_POS);
58
59 while (GetMenuItemCount(hMenu) > 1)
60 {
61 DeleteMenu(hMenu, 1, MF_BYPOSITION);
62 }
63
64 if (CountClipboardFormats() == 0)
65 return;
66
67 if (!OpenClipboard(NULL))
68 return;
69
70 AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
71
72 uFormat = EnumClipboardFormats(0);
73 while (uFormat)
74 {
75 RetrieveClipboardFormatName(Globals.hInstance, uFormat, szFormatName, ARRAYSIZE(szFormatName));
76
77 if (!IsClipboardFormatSupported(uFormat))
78 {
79 AppendMenuW(hMenu, MF_STRING | MF_GRAYED, 0, szFormatName);
80 }
81 else
82 {
83 AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName);
84 }
85
86 uFormat = EnumClipboardFormats(uFormat);
87 }
88
89 CloseClipboard();
90 }
91
92 static int ClipboardCommandHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
93 {
94 switch (LOWORD(wParam))
95 {
96 case CMD_EXIT:
97 {
98 PostMessageW(Globals.hMainWnd, WM_CLOSE, 0, 0);
99 break;
100 }
101
102 case CMD_DELETE:
103 {
104 if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance, STRING_DELETE_MSG, STRING_DELETE_TITLE, MB_ICONWARNING | MB_YESNO) == IDYES)
105 {
106 DeleteClipboardContent();
107 }
108 break;
109 }
110
111 case CMD_AUTOMATIC:
112 {
113 SetDisplayFormat(0);
114 break;
115 }
116
117 case CMD_HELP:
118 {
119 HtmlHelpW(Globals.hMainWnd, L"clipbrd.chm", 0, 0);
120 break;
121 }
122
123 case CMD_ABOUT:
124 {
125 WCHAR szTitle[MAX_STRING_LEN];
126 LoadStringW(Globals.hInstance, STRING_CLIPBOARD, szTitle, ARRAYSIZE(szTitle));
127 ShellAboutW(Globals.hMainWnd, szTitle, 0, NULL);
128 break;
129 }
130
131 default:
132 {
133 break;
134 }
135 }
136 return 0;
137 }
138
139 static void ClipboardPaintHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
140 {
141 HDC hdc;
142 PAINTSTRUCT ps;
143 RECT rc;
144
145 hdc = BeginPaint(hWnd, &ps);
146 GetClientRect(hWnd, &rc);
147
148 switch (Globals.uDisplayFormat)
149 {
150 case CF_NONE:
151 {
152 break;
153 }
154
155 case CF_UNICODETEXT:
156 {
157 DrawTextFromClipboard(hdc, &rc, DT_LEFT);
158 break;
159 }
160
161 case CF_BITMAP:
162 {
163 BitBltFromClipboard(hdc, rc.left, rc.top, rc.right, rc.bottom, 0, 0, SRCCOPY);
164 break;
165 }
166
167 case CF_DIB:
168 {
169 SetDIBitsToDeviceFromClipboard(CF_DIB, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
170 break;
171 }
172
173 case CF_DIBV5:
174 {
175 SetDIBitsToDeviceFromClipboard(CF_DIBV5, hdc, rc.left, rc.top, 0, 0, 0, DIB_RGB_COLORS);
176 break;
177 }
178
179 case CF_ENHMETAFILE:
180 {
181 PlayEnhMetaFileFromClipboard(hdc, &rc);
182 break;
183 }
184
185 case CF_METAFILEPICT:
186 {
187 PlayMetaFileFromClipboard(hdc, &rc);
188 break;
189 }
190
191 default:
192 {
193
194 DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc, &rc, DT_CENTER | DT_WORDBREAK);
195 break;
196 }
197 }
198
199 EndPaint(hWnd, &ps);
200 }
201
202 static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
203 {
204 switch(uMsg)
205 {
206 case WM_PAINT:
207 {
208 ClipboardPaintHandler(hWnd, uMsg, wParam, lParam);
209 break;
210 }
211
212 case WM_SIZE:
213 {
214 InvalidateRect(hWnd, NULL, TRUE);
215 UpdateWindow(hWnd);
216 break;
217 }
218
219 case WM_CREATE:
220 {
221 Globals.hMenu = GetMenu(hWnd);
222 Globals.hWndNext = SetClipboardViewer(hWnd);
223 UpdateDisplayMenu();
224 SetDisplayFormat(0);
225 break;
226 }
227
228 case WM_CLOSE:
229 {
230 DestroyWindow(hWnd);
231 break;
232 }
233
234 case WM_DESTROY:
235 {
236 ChangeClipboardChain(hWnd, Globals.hWndNext);
237 PostQuitMessage(0);
238 break;
239 }
240
241 case WM_CHANGECBCHAIN:
242 {
243 if ((HWND)wParam == Globals.hWndNext)
244 {
245 Globals.hWndNext = (HWND)lParam;
246 }
247 else if (Globals.hWndNext != NULL)
248 {
249 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
250 }
251
252 break;
253 }
254
255 case WM_DRAWCLIPBOARD:
256 {
257 UpdateDisplayMenu();
258 SetDisplayFormat(0);
259
260 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam);
261 break;
262 }
263
264 case WM_COMMAND:
265 {
266 if ((LOWORD(wParam) > CMD_AUTOMATIC))
267 {
268 SetDisplayFormat(LOWORD(wParam) - CMD_AUTOMATIC);
269 }
270 else
271 {
272 ClipboardCommandHandler(hWnd, uMsg, wParam, lParam);
273 }
274 break;
275 }
276
277 case WM_INITMENUPOPUP:
278 {
279 InitMenuPopup((HMENU)wParam, lParam);
280 break;
281 }
282
283 default:
284 {
285 return DefWindowProc(hWnd, uMsg, wParam, lParam);
286 }
287 }
288 return 0;
289 }
290
291 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
292 {
293 MSG msg;
294 HACCEL hAccel;
295 HWND hPrevWindow;
296 WNDCLASSEXW wndclass;
297 WCHAR szBuffer[MAX_STRING_LEN];
298
299 hPrevWindow = FindWindowW(szClassName, NULL);
300 if (hPrevWindow)
301 {
302 BringWindowToFront(hPrevWindow);
303 return 0;
304 }
305
306 ZeroMemory(&Globals, sizeof(Globals));
307 Globals.hInstance = hInstance;
308
309 ZeroMemory(&wndclass, sizeof(wndclass));
310 wndclass.cbSize = sizeof(wndclass);
311 wndclass.lpfnWndProc = MainWndProc;
312 wndclass.hInstance = hInstance;
313 wndclass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(CLIP_ICON));
314 wndclass.hCursor = LoadCursorW(0, IDC_ARROW);
315 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
316 wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU);
317 wndclass.lpszClassName = szClassName;
318
319 if (!RegisterClassExW(&wndclass))
320 {
321 ShowLastWin32Error(NULL);
322 return 0;
323 }
324
325 LoadStringW(hInstance, STRING_CLIPBOARD, szBuffer, ARRAYSIZE(szBuffer));
326 Globals.hMainWnd = CreateWindowExW(WS_EX_CLIENTEDGE,
327 szClassName,
328 szBuffer,
329 WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
330 CW_USEDEFAULT,
331 CW_USEDEFAULT,
332 CW_USEDEFAULT,
333 CW_USEDEFAULT,
334 NULL,
335 NULL,
336 Globals.hInstance,
337 NULL);
338 if (!Globals.hMainWnd)
339 {
340 ShowLastWin32Error(NULL);
341 return 0;
342 }
343
344 ShowWindow(Globals.hMainWnd, nCmdShow);
345 UpdateWindow(Globals.hMainWnd);
346
347 hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(ID_ACCEL));
348 if (!hAccel)
349 {
350 ShowLastWin32Error(Globals.hMainWnd);
351 }
352
353 while (GetMessageW(&msg, 0, 0, 0))
354 {
355 if (!TranslateAcceleratorW(Globals.hMainWnd, hAccel, &msg))
356 {
357 TranslateMessage(&msg);
358 DispatchMessageW(&msg);
359 }
360 }
361
362 return (int)msg.wParam;
363 }