2

OK, so i am writing this program in C++ that is supposed to append the clipboard text into the edit control inside the Auto-Clipboard tab. I have setup the program so that it supports unicode text.

The program appends the text correctly when i copy text outside the program. But if i copy text that is from the program, it shows me as if it is copying ansi characters that needs to be converted int unicode.

I am not sure if the problem is from the edit control or from the Clipboard. Is the edit control output not in unicode? Or is the clipboard copying as ansi and pasting as unicode?

Edit: So i find out that according to MSDN documentations, WM_COPY in edit controls are handled in CF_TEXT mode instead of CF_UNICODETEXT for the clipboard: http://msdn.microsoft.com/en-us/library/windows/desktop/ms649022(v=vs.85).aspx

And so, i added some subclassing starting with my AutoClipboardEdit control but for some reason i get currupted heap error on WM_DRAWCLIPBOARD messages. So i am stuck there:

Edit2: I got it working by not freeing the allocated memory of the text string used on the clipboard. In this case the name of the variable is hMem2. It seems that if i free hMem2, the program crashes with a "corrupted heap" error. My guess is that the OS itself manages and frees the memory. It does seem possible since the SetClipboardData argument for the data is a pointer. I also tried to test if memory actually leaked by sending a WM_COPY message into a infinite loop to see if the heap would increase forever; but far it didn't seem so.

So, i need someone to confirm to me that there is no memory leak or that the OS actually does manage and free the clipboard accordingly.

Here is the complete source code:

        #define UNICODE
        #define _UNICODE

        #pragma comment(linker,"\"/manifestdependency:type='win32' \
        name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
        processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
        #pragma comment(lib, "Comctl32.lib")
        #include <tchar.h>
        #include <Windows.h>
        #include <CommCtrl.h>

        #include <sstream>
        using namespace std;
        TCHAR temp[1024];

        enum TabIndexes
        {
            ID_ReadingPageTab,
            ID_AutoClipboardTab
        };
        enum WindowControls
        {
            ID_SelectAll,
            ID_TabControls,
            ID_ReadingPageEdit,
            ID_AutoClipboardEdit,
            ID_AutoClipboardCheckbox,
            ID_AutoReadCheckbox,
            ID_AutoClearCheckbox,
            ID_ReadPauseResumeButton,
            ID_StopButton
        };

        //***************Global Variables***************
        HWND MainWindowHandle;
        HWND ClipboardViewer;
        HWND TabControls;
        HWND ReadingPageEdit;
        HWND AutoClipboardEdit;
        HWND AutoClipboardCheckbox;
        HWND AutoReadCheckbox;
        HWND AutoClearCheckbox;
        HWND ReadPauseResumeButton;
        HWND StopButton;
        RECT WindowReactangle;
        RECT EditControlsDimension;
        HACCEL SelectAll;
        int Textlength;

        void ShowReport()
        {
            LPTSTR ErrorText = NULL;
            FormatMessage
                (
                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS, //dwFlags
                    NULL, //lpSource
                    GetLastError(), //dwMessageId
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //dwLanguageId
                    (LPTSTR)&ErrorText, //lpBuffer
                    0, //nSize
                    NULL //*Arguments
                );
            MessageBox(NULL, ErrorText, TEXT("Last Error:"), MB_OK);
        }
        void OutputBox(LPTSTR OutputText)
        {
            MessageBox(NULL, OutputText, _T("WARNING!!!"), MB_OK);
        }

WNDPROC OldProc;
LRESULT CALLBACK EditControl
    (
        HWND hwnd,
        UINT uMsg,
        WPARAM wParam,
        LPARAM lParam
    )
{
    WPARAM StartOfSelectection;
    LPARAM EndOfSelection;
    int SelectionSize;
    int TextSize;
    TCHAR* hMem1;
    TCHAR* hMem2;

    if (uMsg == WM_COPY)
    {
        OpenClipboard(NULL);

        SendMessage(hwnd, EM_GETSEL, (WPARAM)&StartOfSelectection, (LPARAM)&EndOfSelection);
        SelectionSize = EndOfSelection - StartOfSelectection + 1;

        TextSize = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
        TextSize -= (TextSize - EndOfSelection - 1);
        hMem1 = new TCHAR[TextSize]();
        ZeroMemory(hMem1, TextSize*sizeof(TCHAR));
        SendMessage(hwnd, WM_GETTEXT, TextSize, (LONG)hMem1);

        hMem2 = new TCHAR[SelectionSize]();
        ZeroMemory(hMem2, SelectionSize*sizeof(TCHAR));
        for(int Index=0; StartOfSelectection<EndOfSelection; ++StartOfSelectection)
            hMem2[Index++] = hMem1[StartOfSelectection];
        SetClipboardData(CF_UNICODETEXT, (HANDLE)hMem2);

        CloseClipboard();
        delete[] hMem1;
        //delete[] hMem2;
    }
    return OldProc(hwnd, uMsg, wParam, lParam);
}

        void CreateControls(HWND hWndParent)
        {
            GetClientRect(hWndParent, &WindowReactangle);
            const INITCOMMONCONTROLSEX CommonControls = {sizeof(INITCOMMONCONTROLSEX), ICC_TAB_CLASSES};
            InitCommonControlsEx(&CommonControls);
            TabControls = CreateWindow
            (
                WC_TABCONTROL, //lpClassName
                NULL, //lpWindowName
                WS_VISIBLE | WS_CHILD, //dwStyle
                WindowReactangle.left, //x
                WindowReactangle.top, //y
                WindowReactangle.right, //nWidth
                WindowReactangle.bottom - 100, //nHeight
                hWndParent, //hWndParent
                (HMENU)ID_TabControls, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );
            TCITEM TabItemStructure = {0};
            TabItemStructure.mask = TCIF_TEXT;
            TabItemStructure.pszText = _T("Reading Page");
            SendMessage(TabControls, TCM_INSERTITEM, ID_ReadingPageTab, (LPARAM)&TabItemStructure);
            TabItemStructure.pszText = _T("Auto-Clipboard");
            SendMessage(TabControls, TCM_INSERTITEM, ID_AutoClipboardTab, (LPARAM)&TabItemStructure);

            ACCEL AcceleratorStructure;
            AcceleratorStructure.fVirt = FCONTROL | FVIRTKEY;
            AcceleratorStructure.key = 0x41;
            AcceleratorStructure.cmd = ID_SelectAll;
            SelectAll = CreateAcceleratorTable(&AcceleratorStructure, 1);

            ReadingPageEdit = CreateWindow
            (
                _T("EDIT"), //lpClassName
                NULL, //lpWindowName
                WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_BORDER | ES_MULTILINE, //dwStyle
                5, //x
                30, //y
                WindowReactangle.right - 10, //nWidth
                WindowReactangle.bottom - 135, //nHeight
                TabControls, //hWndParent
                (HMENU)ID_ReadingPageEdit, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );

            AutoClipboardEdit = CreateWindow
            (
                _T("EDIT"), //lpClassName
                NULL, //lpWindowName
                WS_CHILD | WS_VSCROLL | WS_BORDER | ES_MULTILINE, //dwStyle
                5, //x
                30, //y
                WindowReactangle.right - 10, //nWidth
                WindowReactangle.bottom - 135, //nHeight
                TabControls, //hWndParent
                (HMENU)ID_AutoClipboardEdit, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );

            AutoClipboardCheckbox = CreateWindow
            (
                _T("BUTTON"), //lpClassName
                _T("Auto-Clipboard"), //lpWindowName
                BS_AUTOCHECKBOX | WS_VISIBLE | WS_CHILD, //dwStyle
                10, //x
                WindowReactangle.bottom -100 +10, //y
                150, //nWidth
                25, //nHeight
                hWndParent, //hWndParent
                (HMENU)ID_AutoClipboardCheckbox, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );
            SendMessage(AutoClipboardCheckbox, BM_CLICK, TRUE, 0);
    OldProc = (WNDPROC)SetWindowLongPtr(AutoClipboardEdit, GWLP_WNDPROC, (LONG)EditControl);    

            AutoReadCheckbox = CreateWindow
            (
                _T("BUTTON"), //lpClassName
                _T("Auto-Read"), //lpWindowName
                BS_AUTOCHECKBOX | WS_VISIBLE | WS_CHILD, //dwStyle
                10, //x
                WindowReactangle.bottom -100 +35, //y
                150, //nWidth
                25, //nHeight
                hWndParent, //hWndParent
                (HMENU)ID_AutoReadCheckbox, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );

            AutoClearCheckbox = CreateWindow
            (
                _T("BUTTON"), //lpClassName
                _T("Auto-Clear"), //lpWindowName
                BS_AUTOCHECKBOX | WS_VISIBLE | WS_CHILD, //dwStyle
                10, //x
                WindowReactangle.bottom -100 +60, //y
                150, //nWidth
                25, //nHeight
                hWndParent, //hWndParent
                (HMENU)ID_AutoReadCheckbox, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );
        }

        LRESULT WINAPI MainWindowProcedure
            (
                HWND hwnd,
                UINT uMsg,
                WPARAM wParam,
                LPARAM lParam
            )
        {
            switch(uMsg)
            {
            //Clipboard Events
            case WM_CHANGECBCHAIN:
                if ((HWND)wParam == ClipboardViewer)
                    ClipboardViewer = (HWND)lParam;
                return 0;
            case WM_DRAWCLIPBOARD:
                OpenClipboard(NULL);
                SendMessage(AutoClipboardEdit, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
                SendMessage(AutoClipboardEdit, EM_REPLACESEL, 0, (LPARAM)GetClipboardData(CF_UNICODETEXT)); //CF_TEXT //CF_UNICODETEXT
                CloseClipboard();
                break;

            //Window Controls Events
            case WM_COMMAND:
                switch (LOWORD(wParam))
                {
                case ID_SelectAll:
                    if (HIWORD(wParam)==1)
                        SendMessage(GetFocus(), EM_SETSEL, (WPARAM)0, (LPARAM)-1);
                    break;
                case ID_AutoClipboardCheckbox:
                    if (SendMessage(AutoClipboardCheckbox, BM_GETCHECK, 0, 0) == BST_CHECKED)   
                        ClipboardViewer = SetClipboardViewer(hwnd);
                    else
                        ChangeClipboardChain(hwnd, ClipboardViewer);
                    break;
                }
                return 0;

            //Tab Controls Events
            case WM_NOTIFY:
                if (SendMessage(TabControls, TCM_GETCURSEL, 0, 0))
                {
                    ShowWindow(ReadingPageEdit, SW_HIDE);
                    ShowWindow(AutoClipboardEdit, SW_SHOW);
                } else
                {
                    ShowWindow(AutoClipboardEdit, SW_HIDE);
                    ShowWindow(ReadingPageEdit, SW_SHOW);
                }
            break;

            //Main Window Events
            case WM_SIZE:
            {   
                int LOPARAM = lParam & 0xFFFF;
                int HIPARAM = lParam >> 16;
                SetWindowPos(TabControls, NULL, 0, 0, LOPARAM, HIPARAM-100, SWP_DRAWFRAME);
                SetWindowPos(ReadingPageEdit, NULL, 5, 30, LOPARAM-10, HIPARAM-100-35, SWP_DRAWFRAME);
                SetWindowPos(AutoClipboardEdit, NULL, 5, 30, LOPARAM-10, HIPARAM-100-35, SWP_DRAWFRAME);
                SetWindowPos(AutoClipboardCheckbox, NULL, 10, HIPARAM-100+10, 150, 25, SWP_DRAWFRAME);
                SetWindowPos(AutoReadCheckbox, NULL, 10, HIPARAM-100+35, 150, 25, SWP_DRAWFRAME);
                SetWindowPos(AutoClearCheckbox, NULL, 10, HIPARAM-100+60, 150, 25, SWP_DRAWFRAME);
                return 0;
            }
            case WM_CREATE:
                CreateControls(hwnd);
                return 0;
            case WM_DESTROY:
                DestroyAcceleratorTable(SelectAll);
                ChangeClipboardChain(hwnd, ClipboardViewer);
                PostQuitMessage(ERROR_SUCCESS);
                return 0;
            }
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }

        void CreateMainWindow()
        {
            WNDCLASSEX WindowClassStructure;
            WindowClassStructure.cbSize = sizeof(WNDCLASSEX);
            WindowClassStructure.style = CS_HREDRAW | CS_VREDRAW;
            WindowClassStructure.lpfnWndProc = MainWindowProcedure;
            WindowClassStructure.cbClsExtra = 0;
            WindowClassStructure.cbWndExtra = 0;
            WindowClassStructure.hInstance = NULL;
            WindowClassStructure.hIcon = LoadIcon(NULL, IDI_INFORMATION);
            WindowClassStructure.hCursor = LoadCursor(NULL, IDC_ARROW);
            WindowClassStructure.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
            WindowClassStructure.lpszMenuName = NULL;
            WindowClassStructure.lpszClassName = _T("MainClass");
            WindowClassStructure.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
            RegisterClassEx(&WindowClassStructure);

            MainWindowHandle = CreateWindow
            (
                _T("MainClass"), //lpClassName
                _T("Clipboard Reader"), //lpWindowName
                WS_VISIBLE | WS_OVERLAPPEDWINDOW, //dwStyle
                CW_USEDEFAULT, //x
                CW_USEDEFAULT, //y
                640, //nWidth
                480, // nHeight
                NULL, //hWndParent
                NULL, //hMenu
                NULL, //hInstance
                NULL //lpParam
            );
        }

        int WINAPI _tWinMain
            (
                HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPTSTR lpCmdLine,
                int nCmdShow
            )
        {
            CreateMainWindow();

            MSG MessageStructure = {0};
            while(MessageStructure.message != WM_QUIT)
            {
                if (PeekMessage(&MessageStructure, NULL, 0, 0, PM_REMOVE))
                {
                    if (!TranslateAccelerator(MainWindowHandle, SelectAll, &MessageStructure))
                    {
                        TranslateMessage(&MessageStructure);
                        DispatchMessage(&MessageStructure);
                    }
                }
            }

            return MessageStructure.wParam;
        }

0 Answers0