3.17.5 - Пример листинга Окна Просмотра буфера обмена

Следующий пример показывает простую прикладную программу окна просмотра буфера обмена.

HINSTANCE hinst;
UINT uFormat = (UINT)(-1);
BOOL fAuto = TRUE;

LRESULT APIENTRY MainWndProc(hwnd, uMsg, wParam, lParam)
HWND hwnd;
UINT uMsg;
WPARAM wParam;
LPARAM lParam;
{
	static HWND hwndNextViewer;

	HDC hdc;
	HDC hdcMem;
	PAINTSTRUCT ps;
	LPPAINTSTRUCT lpps;
	RECT rc;
	LPRECT lprc;
	HGLOBAL hglb;
	LPSTR lpstr;
	HBITMAP hbm;
	HENHMETAFILE hemf;
	HWND hwndOwner;

	switch (uMsg)
	{
		case WM_PAINT:
			hdc = BeginPaint(hwnd, &ps);

			// Переход в зависимости от формата буфера обмена
			switch (uFormat)
			{
				case CF_OWNERDISPLAY:
					hwndOwner = GetClipboardOwner();
					hglb = GlobalAlloc(GMEM_DDESHARE,
						sizeof(PAINTSTRUCT));
					lpps = GlobalLock(hglb);
					memcpy(lpps, &ps, sizeof(PAINTSTRUCT));

					GlobalUnlock(hglb);

					SendMessage(hwndOwner, WM_PAINTCLIPBOARD,
						(WPARAM) hwnd, (LPARAM) hglb);

					GlobalFree(hglb);
					break;

				case CF_BITMAP:
					hdcMem = CreateCompatibleDC(hdc);
					if (hdcMem != NULL)
					{
						if (OpenClipboard(hwnd))
						{
							hbm = (HBITMAP)GetClipboardData(uFormat);
							SelectObject(hdcMem, hbm);
							GetClientRect(hwnd, &rc);

							BitBlt(hdc, 0, 0, rc.right, rc.bottom,
								hdcMem, 0, 0, SRCCOPY);
							CloseClipboard();
						}
						DeleteDC(hdcMem);
					}
					break;

				case CF_TEXT:
					if (OpenClipboard(hwnd))
					{
						hglb = GetClipboardData(uFormat);
						lpstr = GlobalLock(hglb);

						GetClientRect(hwnd, &rc);
						DrawText(hdc, lpstr, -1, &rc, DT_LEFT);

						GlobalUnlock(hglb);
						CloseClipboard();
					}
					break;


				case CF_ENHMETAFILE:
					if (OpenClipboard(hwnd))
					{
						hemf = GetClipboardData(uFormat);
						GetClientRect(hwnd, &rc);
						PlayEnhMetaFile(hdc, hemf, &rc);
						CloseCowner-displaylipboard();
					}
					break;

				case 0:
					GetClientRect(hwnd, &rc);
					DrawText(hdc, "The clipboard is empty.", -1,
						&rc, DT_CENTER | DT_SINGLELINE |
						DT_VCENTER);
					break;

				default:
					GetClientRect(hwnd, &rc);
					DrawText(hdc, "Unable to display format.", -1,
						&rc, DT_CENTER | DT_SINGLELINE |
						DT_VCENTER);
			}
			EndPaint(hwnd, &ps);
			break;

		case WM_SIZE:
			if (uFormat == CF_OWNERDISPLAY)

			{
				hwndOwner = GetClipboardOwner();
				hglb = GlobalAlloc(GMEM_DDESHARE, sizeof(RECT));
				lprc = GlobalLock(hglb);
				GetClientRect(hwnd, lprc);
				GlobalUnlock(hglb);

				SendMessage(hwndOwner, WM_SIZECLIPBOARD,
					(WPARAM) hwnd, (LPARAM) hglb);

				GlobalFree(hglb);
			}
			break;

		case WM_CREATE:


			// Добавим окно к цепочке окон просмотра буфера обмена.

			hwndNextViewer = SetClipboardViewer(hwnd);
			break;

		case WM_CHANGECBCHAIN:

			// Если следующее окно закрывается, восстанавливаем цепочку.

			if ((HWND) wParam == hwndNextViewer)
				hwndNextViewer = (HWND) lParam;

			// Иначе, передаем сообщение в следующее звено.

			else if (hwndNextViewer != NULL)
				SendMessage(hwndNextViewer, uMsg, wParam, lParam);
			break;

		case WM_DESTROY:
			ChangeClipboardChain(hwnd, hwndNextViewer);
			PostQuitMessage(0);
			break;

		case WM_DRAWCLIPBOARD:  // буфер обмена изменил содержание.

			// Модифицируем окно, используя Автоформат буфера обмена


			SetAutoView(hwnd);

			// Передаем сообщение следующему окну в цепочке окон просмотра буфера обмена

			SendMessage(hwndNextViewer, uMsg, wParam, lParam);
			break;

		case WM_INITMENUPOPUP:
			if (!HIWORD(lParam))
				InitMenu(hwnd, (HMENU) wParam);
			break;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case IDM_EXIT:
					DestroyWindow(hwnd);
					break;

				case IDM_AUTO:
					SetAutoView(hwnd);
					break;

				default:
					fAuto = FALSE;
					uFormat = LOWORD(wParam);
					InvalidateRect(hwnd, NULL, TRUE);
			}
			break;

		default:
			return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
	return (LRESULT) NULL;
}

void WINAPI SetAutoView(HWND hwnd)
{
	static UINT auPriorityList[] = {
		CF_OWNERDISPLAY,
		CF_TEXT,
		CF_ENHMETAFILE,
		CF_BITMAP

	};

	uFormat = GetPriorityClipboardFormat(auPriorityList, 4);
	fAuto = TRUE;

	InvalidateRect(hwnd, NULL, TRUE);
	UpdateWindow(hwnd);
}
void WINAPI InitMenu(HWND hwnd, HMENU hmenu)
{
	UINT uFormat;
	char szFormatName[80];
	LPCSTR lpFormatName;
	UINT fuFlags;
	UINT idMenuItem;

	// Если меню - не отображаемое меню, никакой инициализации не надо.

	if (GetMenuItemID(hmenu, 0) != IDM_AUTO)
		return;

	// Удаляем все пункты меню за исключением первого.

	while (GetMenuItemCount(hmenu) > 1)
		DeleteMenu(hmenu, 1, MF_BYPOSITION);

	// Проверьте или не проверяйте пункт Автоменю.

	fuFlags = fAuto ? MF_BYCOMMAND | MF_CHECKED :
		MF_BYCOMMAND | MF_UNCHECKED;
	CheckMenuItem(hmenu, IDM_AUTO, fuFlags);

	// Если не имеется никаких форматов буфера обмена, возврат из функции

	if (CountClipboardFormats() == 0)
		return;

	// Откроем буфер обмена.

	if (!OpenClipboard(hwnd))
		return;

	// Добавим разделитель, а затем пункт меню для каждого формата.
	AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
	uFormat = EnumClipboardFormats(0);

	while (uFormat)
	{
	 	// Вызовем определяемую программой функцию, чтобы получить имя формата буфера обмена.
		lpFormatName = GetPredefinedClipboardFormatName(uFormat);
		// Для зарегистрированных форматов, получим зарегистрированное имя.

		if (lpFormatName == NULL)
		{
			if (GetClipboardFormatName(uFormat, szFormatName,sizeof(szFormatName)))
				lpFormatName = szFormatName;
			else
				lpFormatName = "(unknown)";
		}

		// Добавим пункт меню для формата.
		// Для воспроизводимых форматов, используем ID формата для ID меню.

		if (IsDisplayableFormat(uFormat))
		{
			fuFlags = MF_STRING;
			idMenuItem = uFormat;
		}
		else
		{
			fuFlags = MF_STRING | MF_GRAYED;
			idMenuItem = 0;
		}
		AppendMenu(hmenu, fuFlags, idMenuItem, lpFormatName);

		uFormat = EnumClipboardFormats(uFormat);
	}
	CloseClipboard();

}

BOOL WINAPI IsDisplayableFormat(UINT uFormat)
{
	switch (uFormat)
	{
		case CF_OWNERDISPLAY:
		case CF_TEXT:
		case CF_ENHMETAFILE:
		case CF_BITMAP:
			return TRUE;
	}
	return FALSE;
}

Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Владимир Соковиков - 15.02.2002