So I was writing a program that would take a string from clipboard, do some stuff and put the new string back to clipboard. My code so far is posted below. The problem is I want my program to wait for me until I 'ctrl+C' something. I know that GetClipboardData() returns NULL if something goes wrong. Is it true that it also returns NULL if clipboard is empty ?

Code :

# include <stdio.h>
# include <math.h>
# include <windows.h>

int prime_check ( int i )
{
    int j = 0;

    for(j=2; j <= sqrt(i); j++ )
        if(!(i%j)) break;

    if (j>sqrt(i))
        return 1 ;
    else
        return 0 ;
}

int main (void)
{
    HANDLE h, hData ;
    int n, i, j = 0, prime = 0, composite = 0 ;
    int nStrLen = 0 ;
    char arr[50], num[20], str[1000], *ptrData = NULL ;

    printf ("starting") ;

    EmptyClipboard();

    if (!OpenClipboard(NULL))
        perror("Error in clipboard") ;

    printf ("\nready") ;

    if ( GetClipboardData(CF_TEXT) == NULL )

    h = GetClipboardData(CF_TEXT);

    strcpy( str, (char *)h ) ;

    for ( i = 0; str[i] != '\0'; i++ )
    {
        if ( isdigit(str[i]) )
        {
            n = str[i] - '0' ;
            if ( n != 1 && n != 0)
            {
                if ( prime_check (n) == 1 )
                    prime += n ;
                else
                    composite += n ;
            }
        }

        else
        if ( (i < 25) && (isdigit (str[i]) == 0) )
            arr[j++] = str[i] + 1 ;
    }

    itoa ( prime*composite, num, 10 ) ;

    strcat ( arr, num ) ;

    nStrLen = strlen ( arr ) ;

    hData = GlobalAlloc (  GMEM_MOVEABLE | GMEM_DDESHARE, nStrLen + 1 ) ;

    ptrData = (char*)GlobalLock(hData) ;

    memcpy ( ptrData, arr, nStrLen + 1 ) ;

    GlobalUnlock ( hData ) ;

    EmptyClipboard () ;

    SetClipboardData ( CF_TEXT,hData ) ;

    CloseClipboard () ;

    return 0;
}

Thank You

I was thinking of doing something like this. But its not working. Can you explain why ?

while (true)
        if ( h = ( GetClipboardData(CF_TEXT) ) != NULL )
        {
            //printf ("\n%s", (char *)h ) ;
            break ;
        }

Its not staying inside the loop as it should. Its falling through somehow.

You shouldn't be doing that anyway because it will consume too much cpu time when the clipboard is empty. You need to put a Sleep inside that loop so that other threads can get cpu time.

Second The parentheses in the if statement are mis-placed.

while (true)
{
        if ( (h = GetClipboardData(CF_TEXT)) != NULL )
        {
            //printf ("\n%s", (char *)h ) ;
            break ;
        }
        else
           Sleep(1);
}

line 29: If OpenClipboard() fails on that line then you need to make sure the remainder of the code in that function does not get executed because it will most likely crash the program. You might want to create a separate function for it so that it can easily be bypassed.

if (!OpenClipboard(NULL))
{
        perror("Error in clipboard") 
}
else
{
    // do clipboard stuff here
}

Do you mean to do something like this?

#include <stdio.h>
#include <windows.h>

static HHOOK       _hook;
static BOOL        _control_pressed   = FALSE;
static const char  _clipboard_text[]  = "Hello world!";
static unsigned    _clipboard_text_sz = sizeof(_clipboard_text);


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    PKBDLLHOOKSTRUCT kb       = (PKBDLLHOOKSTRUCT) lParam;
    HGLOBAL          hGlobal;
    char*            pGlobal;

    if (nCode >= 0)
    {
        if (wParam == WM_KEYDOWN)
        {
            switch(kb->vkCode)
            {
                case VK_ESCAPE:

                    PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
                    break;

                case VK_LCONTROL:
                case VK_RCONTROL:
                case VK_CONTROL:

                    _control_pressed = TRUE;
                    break;

                case 0x43:  // 'C'

                    if (_control_pressed)
                    {
                        printf("CTRL+C detected. Setting clipboard data to \"%s\".\n", _clipboard_text);

                        // Allocate memory for the clipboard data.
                        hGlobal = GlobalAlloc(GHND | GMEM_DDESHARE, _clipboard_text_sz);

                        if (hGlobal)
                        {
                            // Obtain a pointer to the buffer by locking.
                            pGlobal = GlobalLock(hGlobal) ;

                            // Copy the string. (NULL termination not really needed due to GHND)
                            memcpy(pGlobal, _clipboard_text, _clipboard_text_sz);

                            GlobalUnlock(hGlobal);

                            if (OpenClipboard(NULL))
                            {
                                EmptyClipboard();

                                if (!SetClipboardData(CF_TEXT, hGlobal))
                                    printf("Could not set clipboard data: %u.\n", (unsigned int)GetLastError());

                                CloseClipboard();
                            }
                            else
                                printf("Error on opening clipboard.\n");
                        }
                        else
                             printf("Error on GlobalAlloc: %u\n", (unsigned int)GetLastError());
                    }
                    break;

                default:
                    break;
            }
        }
        else if (wParam == WM_KEYUP && kb->vkCode == VK_CONTROL)
            _control_pressed = FALSE;
    }

    return CallNextHookEx(_hook, nCode, wParam, lParam);
}


int main(void)
{
    MSG msg;

    if(!SetConsoleCtrlHandler(NULL, TRUE))
        printf( "Error on SetConsoleCtrlHandler: %u.\n", (unsigned int) GetLastError());
    else
    {

        _hook = SetWindowsHookEx(WH_KEYBOARD_LL,
                                 LowLevelKeyboardProc,
                                 GetModuleHandle(NULL),
                                 0);
        if (_hook)
        {
            printf("Obtained handle to hook procedure.\n");
            printf("Intercepting Ctrl+C commands. Press ESC to quit.\n");

            while (GetMessage(&msg, NULL, 0, 0) > 0)
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            if (UnhookWindowsHookEx(_hook))
                printf("Removed hook procedure from the hook chain.\n");
            else
                printf("Error on removing hook procedure from the hook chain: %u.\n", (unsigned int) GetLastError());
        }
        else {
            printf("Could not obtain handle to hook procedure: %u.\n", (unsigned int) GetLastError());
        }
    }

    return 0;
}

I think it's still possible to catch the CTRL+C and set the clipboard data here while directly after the clipboard contents get modified as the result of the CTRL+C we caught. There's probably some function to prevent that. (Ignore WM_DESTROYCLIPBOARD?)

line 29: If OpenClipboard() fails on that line then you need to make sure the remainder of the code in that function does not get executed because it will most likely crash the program. You might want to create a separate function for it so that it can easily be bypassed.

Why will it get executed ? Won't perror () function work properly ?
Suppose if I write

if (!OpenClipboard(NULL))
{
        printf ("Error in clipboard") ;
        return 1 ;
}

Won't this work ?

line 34: case 0x43: // 'C'

why not just this: case 'C':

Won't this work ?

Yes, that's another way to do it.

Won't perror () function work properly ?

perror() does not terminate the program -- it mearly uses errno to print the error message.

After this

h = GetClipboardData(CF_TEXT) ;

strcpy( str, (char *)h ) ;

The program is crashing. Why is it so ?

You'll need to lock the handle before being able to access the data:

h = GetClipboardData(CF_TEXT) ;
strcpy( str, (char *)GlobalLock(h) ) ;
GlobalUnlock(h) ;

probably str is not declared correctly, or is too short. This works

#include <Windows.h>
#include <string.h>
#pragma warning(disable: 4996)

int main()
{
HANDLE clip;
char str[255] = {0};
    if (OpenClipboard(NULL)) {
        clip = GetClipboardData(CF_TEXT);
        CloseClipboard();
        strncpy(str, (char*)clip, sizeof(str)-1);
        printf("%s\n", str);
    }

}

Edited 3 Years Ago by Ancient Dragon

Unfortunately, you have a lot of potential issues with your clipboard data application. You may want to reference this post for a better understanding of the clipboard API.

This article has been dead for over six months. Start a new discussion instead.