2

好的,所以我正在用 C++ 编写这个程序,它应该将剪贴板文本附加到自动剪贴板选项卡内的编辑控件中。我已经设置了程序,以便它支持 unicode 文本。

当我在程序外复制文本时,程序会正确附加文本。但是,如果我复制来自程序的文本,它会向我显示好像它正在复制需要转换为 int unicode 的 ansi 字符。

我不确定问题是来自编辑控件还是来自剪贴板。编辑控件输出不是 unicode 格式吗?还是剪贴板复制为ansi并粘贴为unicode?

编辑:所以我发现根据 MSDN 文档,编辑控件中的 WM_COPY 是在 CF_TEXT 模式下处理的,而不是剪贴板的 CF_UNICODETEXT:http: //msdn.microsoft.com/en-us/library/windows/desktop/ms649022( v=vs.85).aspx

因此,我从我的 AutoClipboardEdit 控件开始添加了一些子类,但由于某种原因,我在 WM_DRAWCLIPBOARD 消息上收到了损坏的堆错误。所以我被困在那里:

Edit2:我通过不释放剪贴板上使用的文本字符串的分配内存来使其工作。在这种情况下,变量的名称是 hMem2。似乎如果我释放 hMem2,程序会因“堆损坏”错误而崩溃。我的猜测是操作系统本身管理和释放内存。这似乎是可能的,因为数据的 SetClipboardData 参数是一个指针。我还尝试通过将 WM_COPY 消息发送到无限循环中来测试内存是否真的泄漏,以查看堆是否会永远增加;但到目前为止似乎并非如此。

所以,我需要有人向我确认没有内存泄漏,或者操作系统确实相应地管理和释放剪贴板。

这是完整的源代码:

        #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;
        }
4

0 回答 0