IPC through windows clipboard using c++ - c++

This is how you can get last text item from clipboard:
OpenClipboard(nullptr);
HANDLE hData = GetClipboardData(CF_TEXT);
char* pszText = static_cast<char*>(GlobalLock(hData));
std::string text;
if (pszText != nullptr)
{
text.assign(pszText);
}
GlobalUnlock(hData);
CloseClipboard();
std::cout << text;
This is how you can set an text item from clipboard:
std::string source("text");
if (OpenClipboard(nullptr))
{
HGLOBAL clipbuffer;
char* buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.length() + 1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, source.c_str());
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT, clipbuffer);
CloseClipboard();
}
But I don't know how to delete last text item from clipboard, I would like to be able to not let the user see that I am using the clipboard or change his clipboard so he cant paste last thing he copied...
How can I do this, delete an text item from windows clipboard using c++ ?

This is the strangest way to pass text from one app to another! Sending e-mail also comes to mind.
There is a Windows-native way to do that: send a WM_COPYDATA message.
See https://learn.microsoft.com/en-us/windows/win32/dataxchg/wm-copydata for details.

Related

Cpp copy to clipboard event

As the topic, i know that is a way to get clipboard text but i wanna get the data from clipboard only when user click copy or trigger CTRL+C.
I found this X11 Wait for and Get Clipboard Text
but isn't for windows.
I tried also that but the result doesn't satisfy me.
std::string GetClipboardText() {
// Try opening the clipboard
if (! OpenClipboard(nullptr))
... // error
// Get handle of clipboard object for ANSI text
HANDLE hData = GetClipboardData(CF_TEXT);
if (hData == nullptr)
... // error
// Lock the handle to get the actual text pointer
char * pszText = static_cast<char*>( GlobalLock(hData) );
if (pszText == nullptr)
... // error
// Save text in a string class instance
std::string text( pszText );
// Release the lock
GlobalUnlock( hData );
// Release the clipboard
CloseClipboard();
return text;
}

Can't append to a string in a COM Dll Strange behaviour

I am creating a Windows Shell Extension to add some options in the explorer context menu by making a COM dll but I get a strange problems with a vector.
I'm trying to append contents of a std::vector (member of the class) which contains paths into a std::wstring but at the end, only one path is added to the string. I know this is a problem with the vector itself because if I replace the vector by a local one instead of m_selectedFiles, it works.
Here is the code :
HRESULT FilesEncryptContextMenuHandler::InvokeCommand(CMINVOKECOMMANDINFO *pici) {
wchar_t filename[MAX_PATH] = {0};
GetModuleFileName((HMODULE)g_hInstance, filename, MAX_PATH);
std::wstring str = filename;
std::wstring exe = str.substr(0, str.find_last_of('\\')) + L"\\FilesEncrypt.exe";
std::basic_stringstream<wchar_t> ss;
for (std::vector<std::wstring>::iterator it = m_selectedFiles.begin(); it != m_selectedFiles.end(); ++it) {
MessageBox(NULL, it->c_str(), L"Test", MB_OK);
ss << *it << L" ";
}
std::wstring args = ss.str();
MessageBox(NULL, args.c_str(), L"Test", MB_OK);
args = args.substr(0, args.size() - 1);
ShellExecute(NULL, L"open", exe.c_str(), args.c_str(), NULL, SW_SHOWNA);
return S_OK;
}
Here, The MessageBox in the for loop is called multiple times with the paths but the second MessageBox only shows PATH1. For a reason I really don't know, the other elements in the vector are not appended.
It's because the line:
ss << *it << L" ";
places a NUL in the stream, the message box stops there. You will need to copy it->begin() to it->end()-1 to the stream.

SDL draw PNG image from raw image data string

I've setup a PNG resource file in my SDL2 project for Windows 32bit in C++.
HRSRC hRes = FindResource(0, MAKEINTRESOURCE(IMGID), "PNG");
if (!hRes) {
Log::Error("Find resource IMGID");
return;
}
HGLOBAL hData = LoadResource(0, hRes);
if (!hData) {
Log::Error("Load resource IMGID");
return;
}
DWORD dataSize = SizeofResource(0, hRes);
char* data = (char*)LockResource(hData);
std::string result;
result.assign(data, dataSize);
The result variable contains all the characters of the PNG image (if it was converted to a string).
How can I use this image string with SDL Image and display it on the window?
Use SDL_RWFromConstMem(data, dataSize) to create a read-only memory-targeted SDL_RWops and pass that in to IMG_Load_RW().

How to change clipboard data in Windows

I have the following clipboard data:
Can I somehow change indexes of these records?
Also can I remove / make zero-length some of them?
Is it possible via WinAPI?
As for the first question, I don't see any function for this purpose.
As for the second question, I wrote the following code:
#include <Windows.h>
int main()
{
OpenClipboard(NULL);
HGLOBAL hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(int));
int* dst = (int*)GlobalLock(hdst);
dst[0] = 0;
GlobalUnlock(hdst);
SetClipboardData(49166, hdst);
CloseClipboard();
}
but it didn't zeroed the record of the 49166 format.
How can I do it?
This is a method to do that. First, obtain the clipboard data string by use GetClipboardData api, and then modify the data string by your way. Second, rewrite string to cliboard by use SetClipboardData api.
You don't call GetClipboardData first from you code, you can do that like this:
char *buffer = NULL;
CString fromClipboard;
//open the cliboard
if (OpenClipboard())
{
HANDLE hData = GetClipboardData(CF_TEXT);
char* buffer = (char *)GlobalLock(hData);
fromClipboard = buffer;
//modify fromClipboard string by your method and rewrite to clipboard
//maybe like this
fromCliboard.Replace("hello", "world");
HGLOBAL clipbuffer;
char* buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(source));
GlobalUnlock(hData);
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}

Am I Incorrectly using the Windows Clipboard?

I have some code to copy and paste:
void WinClipboard::copy( const std::string& input )
{
LPWSTR lptstrCopy;
HGLOBAL hglbCopy;
std::wstring text;
text = _winUTF8ToUTF16(input);
// Open the clipboard, and empty it.
if (!OpenClipboard(NULL))
return;
EmptyClipboard();
// Allocate a global memory object for the text.
hglbCopy = GlobalAlloc(GMEM_MOVEABLE,
((text.length() + 1) * sizeof(WCHAR)));
if (hglbCopy == NULL)
{
CloseClipboard();
return;
}
// Lock the handle and copy the text to the buffer.
lptstrCopy = (LPWSTR)GlobalLock(hglbCopy);
memcpy(lptstrCopy, text.c_str(),
(text.length() + 1) * sizeof(WCHAR) );
lptstrCopy[(text.length() + 1) * sizeof(WCHAR)] = (WCHAR) 0; // null character
GlobalUnlock(hglbCopy);
// Place the handle on the clipboard.
SetClipboardData(CF_UNICODETEXT, hglbCopy);
// Close the clipboard.
CloseClipboard();
}
std::string WinClipboard::paste()
{
HGLOBAL hglb;
LPWSTR lptstr;
std::string result;
std::wstring input;
// get the clipboard text.
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
return result;
if (!OpenClipboard(NULL))
return result;
hglb = GetClipboardData(CF_UNICODETEXT);
if (hglb != NULL)
{
lptstr = (LPWSTR)GlobalLock(hglb);
if (lptstr != NULL)
{
GlobalUnlock(hglb);
input = lptstr;
result = _winUTF16ToUTF8(input);
}
CloseClipboard();
}
return result;
}
It works great except, when I quickly do CTRL C then CTRL-V (essentially calling the above copy and paste functions) the entire application freezes.
Am I forgetting to check for something or forgetting to release a resource?
I see two problems in your paste() function:
1) it is calling GlobalUnlock() before assigning the clipboard data to your std::wstring variable. You need to reverse those operations - call GlobalUnlock() after copying the data, not before.
2) it is not calling CloseClipboard() if GetClipboardData() fails.
Another "problem".
In the copy function:
The line
lptstrCopy[(text.length() + 1) * sizeof(WCHAR)] = (WCHAR) 0;
should be
lptstrCopy[text.length() + 1] = (WCHAR) 0;
to avoid the overflow/heap corruption.