C++ Clipboard

Olá! Pessoal eu preciso de um help, estou precisando fazer 2 métodos em C++, um que saiba o conteúdo que o usuário seleciona e copia, e o outro método que ative o evento de colar. Bem já dei uma pesquisada e achei um programa que faz +/- isso, mas eu não estou conseguindo entender o maldito código… sou leigo em C++.
Será que alguém pode me ajudar me dando algumas dicas, links ou projetos? Eu vou até criar um link para vcs baixarem o programa que eu achei, deixa eu chegar em casa…

Desde já agradeço!

Supondo que você está programando em C++ para Windows:
Abaixo o código do jeito que uso e que não tive problemas de memory leaks (esse negócio de usar memória global pra que fique disponível a outras aplicações tem umas pegadinhas).

Não sei se se encaixa no jeito que você precisa. Uso c++ e chamadas diretas a API WIN32 (sou meio velhinho, rsrs)


// Trecho de código do COPIAR - TEXTO
// hWnd é uma HWND , se for 0 é o Desktop
if(OpenClipboard(hWnd)) {

    HGLOBAL clipbuffer = NULL;
    LPTSTR  lptstrCopy = NULL;

    EmptyClipboard();

    // Aloca memória global para o objeto

    clipbuffer = GlobalAlloc(GMEM_MOVEABLE, 16384 * sizeof(TCHAR));
    if (clipbuffer == NULL) {
        CloseClipboard();
        return FALSE;
    }

    // szGlobal_EditTxt contém o texto a ser copiado, no caso limitado a 16383 chars

    // Bloqueia o ponteiro e copia o texto para buffer
    lptstrCopy = (LPTSTR) GlobalLock(clipbuffer);
    memcpy(lptstrCopy, szGlobal_EditTxt, 16384 * sizeof(TCHAR));
    lptstrCopy[16383] = (TCHAR) 0;
    GlobalUnlock(clipbuffer);

    SetClipboardData(CF_TEXT, clipbuffer);
    CloseClipboard();
}


// Trecho de código do COLAR - TEXTO

HGLOBAL clipbuffer;
LPTSTR  lptstrCopy;

// Se não for texto, sai
if (!IsClipboardFormatAvailable(CF_TEXT))
    return 0;
if (!OpenClipboard(hwnd))
    return 0;

clipbuffer = GetClipboardData(CF_TEXT);

if (clipbuffer != NULL) {
    lptstrCopy = (LPTSTR) GlobalLock(clipbuffer);
    if (lptstrCopy != NULL) {

        // Aqui você usa o conteúdo de lptsrtCopy do jeito que achar melhor...
    }
    GlobalUnlock(clipbuffer);
}
CloseClipboard();

Poxa velhão vlw, vou testar esse código!!

Bem estou dando o upload do código que eu mencionei no meu primeiro post.

jamirdeajr ô meu rei, tentei usar o seu código, mas eu não sei como testa-lo, não sei nada de C++, tem como me dar um código junto para testar? De preferência com o projeto de console.
Infelizmente estou pedindo tudo mastigado, é pq eu não tenho tempo de aprender C++ no momento, então eu peço um pouco de compreensão :?

jp.fernandz , só vi hoje seu retorno,
então, preciso saber qual versão do compilador C++ você está usando.

Para funcionar é necessário criar um projeto WINDOWS mesmo, não pode ser console ‘caracter’. Ou seja, um jeito muito simples, com poucas linhas de código creio que não seja possível.

O exemplo que você passou funciona, a diferença é que ele utiliza MFC (Microsoft Foundation Classes) e suporta também outros modos além de texto (imagens etc).
Se não me engano o suporte ao MFC não tem mais nas versões ‘Express’ do Microsoft C++.

Bom, seguem alguns passos para criar um projeto mínimo do Visual C++ 2003 ou 2005 (a versão que utilizo):

  • File - New - Project . Selecione o tipo ‘Win 32 Project’
  • dê um nome , exemplo: Clipboard, confirme

Ele irá criar um projeto básico com uma janela principal e um menu com opções ‘Exit’ e ‘About’

  • Vá no ‘Resource Files’, edite o Clipboard.rc - Menu - e inclua as opções ‘Copiar’ e ‘Colar’ , defina o ID deles como IDM_COPIAR e IDM_COLAR , confirme.

  • Agora edite o Clipboard.cpp pra ficar como esse, note que somente a parte IDM_COPIAR e IDM_COLAR foram inseridas, o resto foi gerado automático no projeto:

// Clipboard.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Clipboard.h"
#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name

// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_CLIPBOARD, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CLIPBOARD);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_CLIPBOARD);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCTSTR)IDC_CLIPBOARD;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;

	hInst = hInstance; // Store instance handle in our global variable

	hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message) 
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam); 
		wmEvent = HIWORD(wParam); 
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;

			// Aqui o código que foi incluído, o resto foi gerado pelo 'New Project' 'Win 32 Project'
		case IDM_COPIAR:
			{

				// Trecho de código do COPIAR - TEXTO
				// hWnd é uma HWND , se for 0 é o Desktop
				if(OpenClipboard(hWnd)) {

					HGLOBAL clipbuffer = NULL;
					LPTSTR  lptstrCopy = NULL;

					EmptyClipboard();

					// Aloca memória global para o objeto

					clipbuffer = GlobalAlloc(GMEM_MOVEABLE, 16384 * sizeof(TCHAR));
					if (clipbuffer == NULL) {
						CloseClipboard();
						return FALSE;
					}

					// szGlobal_EditTxt contém o texto a ser copiado, no caso limitado a 16383 chars

					char szGlobal_EditTxt[16384] = {0};

					strcpy(szGlobal_EditTxt,"Texto que eu quero que vá para o clipboard");

					// Bloqueia o ponteiro e copia o texto para buffer
					lptstrCopy = (LPTSTR) GlobalLock(clipbuffer);
					memcpy(lptstrCopy, szGlobal_EditTxt, 16384 * sizeof(TCHAR));
					lptstrCopy[16383] = (TCHAR) 0;
					GlobalUnlock(clipbuffer);

					SetClipboardData(CF_TEXT, clipbuffer);
					CloseClipboard();
				}
			}
			break;

		case IDM_COLAR:

			// Trecho de código do COLAR - TEXTO

			HGLOBAL clipbuffer;
			LPTSTR  lptstrCopy;

			// Se não for texto, sai
			if (!IsClipboardFormatAvailable(CF_TEXT))
				return 0;
			if (!OpenClipboard(hWnd))
				return 0;

			clipbuffer = GetClipboardData(CF_TEXT);

			if (clipbuffer != NULL) {
				lptstrCopy = (LPTSTR) GlobalLock(clipbuffer);
				if (lptstrCopy != NULL) {

					// Aqui você usa o conteúdo de lptsrtCopy do jeito que achar melhor...
				}
				GlobalUnlock(clipbuffer);
			}
			CloseClipboard();

			break;
			// Fim

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		return TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
		{
			EndDialog(hDlg, LOWORD(wParam));
			return TRUE;
		}
		break;
	}
	return FALSE;
}

Espero ter ajudado, boa sorte!

Segue o projeto que criei.

Complementando, é um exemplo bem básico mesmo. Você precisa ainda incluir um campo de edição na tela e capturar o conteúdo para jogar no clipboard.

Mas acho que já é um começo.

Muito obrigado jamirdeajr, consegui já fazer oq eu pretendia, cara sua ajuda foi d+, obrigado!