c++memoryclipboarddata

C++ Clipboard entries keep overwriting instead of having separate entries


I am writing a program that takes all objects from a JSON array and copies them into the clipboard. However, when I open the Clipboard history only the last object from the file is shown, therefore they keep overwriting each other.

This is my Code:

void loadOldClipboard() {
    // Load the JSON data from our File
    std::ifstream file("pastEntries.json");
    Json::Value root;
    file >> root;
    file.close();
    OpenClipboard(0);
    EmptyClipboard();
    for (const auto& obj : root) {
        std::string entry = obj["clipboardEntry"].asString();
        std::cout << "clipboardEntry: " << entry << std::endl;

        // Allocate global memory for the clipboard data
        HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, entry.size() + 1);
        if (hMem == NULL) {
            // Handle memory allocation error
            CloseClipboard();
            return;
        }

        // Copy the entry to the global memory
        char* pMem = static_cast<char*>(GlobalLock(hMem));
        if (pMem == NULL) {
            // Handle memory locking error
            GlobalFree(hMem);
            CloseClipboard();
            return;
        }
        strcpy_s(pMem, entry.size() + 1, entry.c_str());
        GlobalUnlock(hMem);

        // Set the clipboard data for the current entry
        SetClipboardData(CF_TEXT, hMem);
    }
    CloseClipboard();
}

just in case I also added my current JSON File:

[
    {
        "clipboardEntry": "Entry 1"
    },
    {
        "clipboardEntry": "Entry 2"
    },
    {
        "clipboardEntry": "Entry 3"
    }
]

UPDATE:

I tried opening and closing the clipboard on each loop iteration, but it still doesn't work.

void loadOldClipboard() {
    // Load the JSON data from our File
    std::ifstream file("pastEntries.json");
    Json::Value root;
    file >> root;
    file.close();

    // Allocate global memory for each string and copy it to the clipboard
    for (const auto& text : root) {
        if (!OpenClipboard(0)) {
            std::cerr << "Failed to open clipboard\n";
            return;
        }

        // Empty the clipboard
        EmptyClipboard();

        std::string entry = text["clipboardEntry"].asString();
        std::cout << "clipboardEntry: " << entry << std::endl;
        // Allocate global memory for the clipboard data
        HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, entry.size() + 1);
        if (hMem == NULL) {
            // Handle memory allocation error
            CloseClipboard();
            return;
        }

        // Copy the text to the global memory
        char* pMem = static_cast<char*>(GlobalLock(hMem));
        if (pMem == NULL) {
            // Handle memory locking error
            GlobalFree(hMem);
            CloseClipboard();
            return;
        }
        strcpy_s(pMem, entry.size() + 1, entry.c_str());
        GlobalUnlock(hMem);

        // Set the clipboard data
        SetClipboardData(CF_TEXT, hMem);

        // Close the clipboard
        CloseClipboard();
    }
}

UPDATE:

I got it to work, it turns out that similar to what @Halfix mentioned, I needed to put in a Sleep() delay of around 1/2 - 1 second. Otherwise, the program couldn't process it properly.


Solution

  • Since @MarioRütsche didn't show the final code himself, I took it upon myself. I quickly recreated it and ended up with this new function. It looks like the problem was indeed with the built-in Clipboard Viewer from Windows not properly receiving the Data, so I added a Sleep() of 1 second.

    void loadOldClipboard() {
        // Load the JSON data from our File
        std::ifstream file("pastEntries.json");
        Json::Value root;
        file >> root;
        file.close();
    
    
        // Allocate global memory for each string and copy it to the clipboard
        for (const auto& text : root) {
            if (!OpenClipboard(0)) {
                std::cerr << "Failed to open clipboard\n";
                return;
            }
    
            // Empty the clipboard
            EmptyClipboard();
    
            std::string entry = text["clipboardEntry"].asString();
            std::cout << "clipboardEntry: " << entry << std::endl;
            // Allocate global memory for the clipboard data
            HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, entry.size() + 1);
            if (hMem == NULL) {
                // Handle memory allocation error
                CloseClipboard();
                return;
            }
    
            // Copy the text to the global memory
            char* pMem = static_cast<char*>(GlobalLock(hMem));
            if (pMem == NULL) {
                // Handle memory locking error
                GlobalFree(hMem);
                CloseClipboard();
                return;
            }
            strcpy_s(pMem, entry.size() + 1, entry.c_str());
            GlobalUnlock(hMem);
    
            // Set the clipboard data
            SetClipboardData(CF_TEXT, hMem);
    
            HANDLE hData = GetClipboardData(CF_TEXT);
            char* pszData = static_cast<char*>(GlobalLock(hData));
            std::string clipboardContent = pszData;
    
            // Close the clipboard
            CloseClipboard();
            Sleep(1000); // Wait for 1000ms before checking again
        }
     }