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
11 static const WCHAR szClassName
[] = L
"ClipBookWClass";
13 CLIPBOARD_GLOBALS Globals
;
14 SCROLLSTATE Scrollstate
;
16 static void UpdateLinesToScroll(void)
20 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &uLinesToScroll
, 0))
22 Globals
.uLinesToScroll
= 3;
26 Globals
.uLinesToScroll
= uLinesToScroll
;
30 static void SaveClipboardToFile(void)
33 WCHAR szFileName
[MAX_PATH
];
34 WCHAR szFilterMask
[MAX_STRING_LEN
+ 10];
37 ZeroMemory(&szFilterMask
, sizeof(szFilterMask
));
38 c
= szFilterMask
+ LoadStringW(Globals
.hInstance
, STRING_FORMAT_NT
, szFilterMask
, MAX_STRING_LEN
) + 1;
41 ZeroMemory(&szFileName
, sizeof(szFileName
));
42 ZeroMemory(&sfn
, sizeof(sfn
));
43 sfn
.lStructSize
= sizeof(sfn
);
44 sfn
.hwndOwner
= Globals
.hMainWnd
;
45 sfn
.hInstance
= Globals
.hInstance
;
46 sfn
.lpstrFilter
= szFilterMask
;
47 sfn
.lpstrFile
= szFileName
;
48 sfn
.nMaxFile
= ARRAYSIZE(szFileName
);
49 sfn
.Flags
= OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT
;
50 sfn
.lpstrDefExt
= L
"clp";
52 if (!GetSaveFileNameW(&sfn
))
55 if (!OpenClipboard(Globals
.hMainWnd
))
57 ShowLastWin32Error(Globals
.hMainWnd
);
61 WriteClipboardFile(szFileName
, CLIP_FMT_NT
/* CLIP_FMT_31 */);
66 static void LoadClipboardDataFromFile(LPWSTR lpszFileName
)
68 if (MessageBoxRes(Globals
.hMainWnd
, Globals
.hInstance
,
69 STRING_DELETE_MSG
, STRING_DELETE_TITLE
,
70 MB_ICONWARNING
| MB_YESNO
) != IDYES
)
75 if (!OpenClipboard(Globals
.hMainWnd
))
77 ShowLastWin32Error(Globals
.hMainWnd
);
82 ReadClipboardFile(lpszFileName
);
87 static void LoadClipboardFromFile(void)
90 WCHAR szFileName
[MAX_PATH
];
91 WCHAR szFilterMask
[MAX_STRING_LEN
+ 10];
94 ZeroMemory(&szFilterMask
, sizeof(szFilterMask
));
95 c
= szFilterMask
+ LoadStringW(Globals
.hInstance
, STRING_FORMAT_GEN
, szFilterMask
, MAX_STRING_LEN
) + 1;
98 ZeroMemory(&szFileName
, sizeof(szFileName
));
99 ZeroMemory(&ofn
, sizeof(ofn
));
100 ofn
.lStructSize
= sizeof(ofn
);
101 ofn
.hwndOwner
= Globals
.hMainWnd
;
102 ofn
.hInstance
= Globals
.hInstance
;
103 ofn
.lpstrFilter
= szFilterMask
;
104 ofn
.lpstrFile
= szFileName
;
105 ofn
.nMaxFile
= ARRAYSIZE(szFileName
);
106 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
;
108 if (!GetOpenFileNameW(&ofn
))
111 LoadClipboardDataFromFile(szFileName
);
114 static void LoadClipboardFromDrop(HDROP hDrop
)
116 WCHAR szFileName
[MAX_PATH
];
118 DragQueryFileW(hDrop
, 0, szFileName
, ARRAYSIZE(szFileName
));
121 LoadClipboardDataFromFile(szFileName
);
124 static void SetDisplayFormat(UINT uFormat
)
126 CheckMenuItem(Globals
.hMenu
, Globals
.uCheckedItem
, MF_BYCOMMAND
| MF_UNCHECKED
);
127 Globals
.uCheckedItem
= uFormat
+ CMD_AUTOMATIC
;
128 CheckMenuItem(Globals
.hMenu
, Globals
.uCheckedItem
, MF_BYCOMMAND
| MF_CHECKED
);
132 Globals
.uDisplayFormat
= GetAutomaticClipboardFormat();
136 Globals
.uDisplayFormat
= uFormat
;
141 DeleteObject(Globals
.hDspBmp
);
144 ZeroMemory(&Scrollstate
, sizeof(Scrollstate
));
145 UpdateWindowScrollState(Globals
.hMainWnd
, Globals
.hDspBmp
, &Scrollstate
);
147 InvalidateRect(Globals
.hMainWnd
, NULL
, TRUE
);
150 static void InitMenuPopup(HMENU hMenu
, LPARAM index
)
152 if ((GetMenuItemID(hMenu
, 0) == CMD_DELETE
) || (GetMenuItemID(hMenu
, 1) == CMD_SAVE_AS
))
154 if (CountClipboardFormats() == 0)
156 EnableMenuItem(hMenu
, CMD_DELETE
, MF_GRAYED
);
157 EnableMenuItem(hMenu
, CMD_SAVE_AS
, MF_GRAYED
);
161 EnableMenuItem(hMenu
, CMD_DELETE
, MF_ENABLED
);
162 EnableMenuItem(hMenu
, CMD_SAVE_AS
, MF_ENABLED
);
166 DrawMenuBar(Globals
.hMainWnd
);
169 static void UpdateDisplayMenu(void)
172 WCHAR szFormatName
[MAX_FMT_NAME_LEN
+ 1];
175 hMenu
= GetSubMenu(Globals
.hMenu
, DISPLAY_MENU_POS
);
177 while (GetMenuItemCount(hMenu
) > 1)
179 DeleteMenu(hMenu
, 1, MF_BYPOSITION
);
182 if (CountClipboardFormats() == 0)
185 if (!OpenClipboard(Globals
.hMainWnd
))
188 AppendMenuW(hMenu
, MF_SEPARATOR
, 0, NULL
);
190 uFormat
= EnumClipboardFormats(0);
193 RetrieveClipboardFormatName(Globals
.hInstance
, uFormat
, TRUE
, szFormatName
, ARRAYSIZE(szFormatName
));
195 if (!IsClipboardFormatSupported(uFormat
))
197 AppendMenuW(hMenu
, MF_STRING
| MF_GRAYED
, 0, szFormatName
);
201 AppendMenuW(hMenu
, MF_STRING
, CMD_AUTOMATIC
+ uFormat
, szFormatName
);
204 uFormat
= EnumClipboardFormats(uFormat
);
210 static int ClipboardCommandHandler(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
212 switch (LOWORD(wParam
))
216 LoadClipboardFromFile();
222 SaveClipboardToFile();
228 PostMessageW(Globals
.hMainWnd
, WM_CLOSE
, 0, 0);
234 if (MessageBoxRes(Globals
.hMainWnd
, Globals
.hInstance
,
235 STRING_DELETE_MSG
, STRING_DELETE_TITLE
,
236 MB_ICONWARNING
| MB_YESNO
) != IDYES
)
241 DeleteClipboardContent();
253 HtmlHelpW(Globals
.hMainWnd
, L
"clipbrd.chm", 0, 0);
259 WCHAR szTitle
[MAX_STRING_LEN
];
262 hIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCE(CLIPBRD_ICON
));
263 LoadStringW(Globals
.hInstance
, STRING_CLIPBOARD
, szTitle
, ARRAYSIZE(szTitle
));
264 ShellAboutW(Globals
.hMainWnd
, szTitle
, 0, hIcon
);
277 static void ClipboardPaintHandler(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
283 if (!OpenClipboard(Globals
.hMainWnd
))
286 hdc
= BeginPaint(hWnd
, &ps
);
287 GetClientRect(hWnd
, &rc
);
289 switch (Globals
.uDisplayFormat
)
298 DrawTextFromClipboard(hdc
, &rc
, DT_LEFT
| DT_NOPREFIX
);
304 BitBltFromClipboard(hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
, 0, 0, SRCCOPY
);
310 SetDIBitsToDeviceFromClipboard(CF_DIB
, hdc
, rc
.left
, rc
.top
, 0, 0, 0, DIB_RGB_COLORS
);
316 SetDIBitsToDeviceFromClipboard(CF_DIBV5
, hdc
, rc
.left
, rc
.top
, 0, 0, 0, DIB_RGB_COLORS
);
320 case CF_METAFILEPICT
:
322 PlayMetaFileFromClipboard(hdc
, &rc
);
328 PlayEnhMetaFileFromClipboard(hdc
, &rc
);
334 DrawTextFromResource(Globals
.hInstance
, ERROR_UNSUPPORTED_FORMAT
, hdc
, &rc
, DT_CENTER
| DT_WORDBREAK
| DT_NOPREFIX
);
344 static LRESULT WINAPI
MainWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
350 Globals
.hMenu
= GetMenu(hWnd
);
351 Globals
.hWndNext
= SetClipboardViewer(hWnd
);
365 ChangeClipboardChain(hWnd
, Globals
.hWndNext
);
372 ClipboardPaintHandler(hWnd
, uMsg
, wParam
, lParam
);
378 HandleKeyboardScrollEvents(hWnd
, uMsg
, wParam
, lParam
);
384 HandleMouseScrollEvents(hWnd
, uMsg
, wParam
, lParam
, &Scrollstate
);
390 HandleHorizontalScrollEvents(hWnd
, uMsg
, wParam
, lParam
, &Scrollstate
);
396 HandleVerticalScrollEvents(hWnd
, uMsg
, wParam
, lParam
, &Scrollstate
);
402 UpdateWindowScrollState(hWnd
, Globals
.hDspBmp
, &Scrollstate
);
404 if ((Globals
.uDisplayFormat
== CF_METAFILEPICT
) ||
405 (Globals
.uDisplayFormat
== CF_ENHMETAFILE
) ||
406 (Globals
.uDisplayFormat
== CF_DSPENHMETAFILE
) ||
407 (Globals
.uDisplayFormat
== CF_DSPMETAFILEPICT
))
409 InvalidateRect(Globals
.hMainWnd
, NULL
, FALSE
);
411 else if (!IsClipboardFormatSupported(Globals
.uDisplayFormat
))
413 InvalidateRect(Globals
.hMainWnd
, NULL
, TRUE
);
419 case WM_CHANGECBCHAIN
:
421 if ((HWND
)wParam
== Globals
.hWndNext
)
423 Globals
.hWndNext
= (HWND
)lParam
;
425 else if (Globals
.hWndNext
!= NULL
)
427 SendMessageW(Globals
.hWndNext
, uMsg
, wParam
, lParam
);
433 case WM_DRAWCLIPBOARD
:
438 SendMessageW(Globals
.hWndNext
, uMsg
, wParam
, lParam
);
444 if ((LOWORD(wParam
) > CMD_AUTOMATIC
))
446 SetDisplayFormat(LOWORD(wParam
) - CMD_AUTOMATIC
);
450 ClipboardCommandHandler(hWnd
, uMsg
, wParam
, lParam
);
455 case WM_INITMENUPOPUP
:
457 InitMenuPopup((HMENU
)wParam
, lParam
);
463 LoadClipboardFromDrop((HDROP
)wParam
);
467 case WM_QUERYNEWPALETTE
:
469 if (RealizeClipboardPalette(hWnd
) != GDI_ERROR
)
471 InvalidateRect(hWnd
, NULL
, TRUE
);
478 case WM_PALETTECHANGED
:
480 if ((HWND
)wParam
!= hWnd
)
482 if (RealizeClipboardPalette(hWnd
) != GDI_ERROR
)
484 InvalidateRect(hWnd
, NULL
, TRUE
);
491 case WM_SYSCOLORCHANGE
:
493 SetDisplayFormat(Globals
.uDisplayFormat
);
497 case WM_SETTINGCHANGE
:
499 if (wParam
== SPI_SETWHEELSCROLLLINES
)
501 UpdateLinesToScroll();
508 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
514 int WINAPI
wWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPWSTR lpCmdLine
, int nCmdShow
)
519 WNDCLASSEXW wndclass
;
520 WCHAR szBuffer
[MAX_STRING_LEN
];
522 hPrevWindow
= FindWindowW(szClassName
, NULL
);
525 BringWindowToFront(hPrevWindow
);
529 ZeroMemory(&Globals
, sizeof(Globals
));
530 Globals
.hInstance
= hInstance
;
532 ZeroMemory(&wndclass
, sizeof(wndclass
));
533 wndclass
.cbSize
= sizeof(wndclass
);
534 wndclass
.lpfnWndProc
= MainWndProc
;
535 wndclass
.hInstance
= hInstance
;
536 wndclass
.hIcon
= LoadIconW(hInstance
, MAKEINTRESOURCEW(CLIPBRD_ICON
));
537 wndclass
.hCursor
= LoadCursorW(0, IDC_ARROW
);
538 wndclass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
539 wndclass
.lpszMenuName
= MAKEINTRESOURCEW(MAIN_MENU
);
540 wndclass
.lpszClassName
= szClassName
;
542 if (!RegisterClassExW(&wndclass
))
544 ShowLastWin32Error(NULL
);
548 LoadStringW(hInstance
, STRING_CLIPBOARD
, szBuffer
, ARRAYSIZE(szBuffer
));
549 Globals
.hMainWnd
= CreateWindowExW(WS_EX_CLIENTEDGE
| WS_EX_ACCEPTFILES
,
552 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
561 if (!Globals
.hMainWnd
)
563 ShowLastWin32Error(NULL
);
567 ShowWindow(Globals
.hMainWnd
, nCmdShow
);
568 UpdateWindow(Globals
.hMainWnd
);
570 hAccel
= LoadAcceleratorsW(Globals
.hInstance
, MAKEINTRESOURCEW(ID_ACCEL
));
573 ShowLastWin32Error(Globals
.hMainWnd
);
576 /* If the user provided a path to a clipboard data file, try to open it */
577 if (lpCmdLine
!= NULL
&& *lpCmdLine
)
578 LoadClipboardDataFromFile(lpCmdLine
);
580 UpdateLinesToScroll();
582 while (GetMessageW(&msg
, 0, 0, 0))
584 if (!TranslateAcceleratorW(Globals
.hMainWnd
, hAccel
, &msg
))
586 TranslateMessage(&msg
);
587 DispatchMessageW(&msg
);
593 DeleteObject(Globals
.hDspBmp
);
596 return (int)msg
.wParam
;