0

グローバルフックでdllを書いています。タスクの 1 つは、クリップボードを表示し、誰かがコピー操作を実行したときにそこからすべてのデータを削除することです。ウィンドウのコールバック関数は次のとおりです。

string test("my data");

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            nextClipboardViewer = SetClipboardViewer(windowHandler);
            MessageBeep(MB_ICONINFORMATION);
            break;
        case WM_CHANGECBCHAIN:
            if((HWND) wParam == nextClipboardViewer) 
                nextClipboardViewer == (HWND) lParam;
            else if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DRAWCLIPBOARD:
            if(OpenClipboard(windowHandler)) {
                EmptyClipboard();
                HGLOBAL hClipboardData;
                hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
                char * pchData;
                pchData = (char*)GlobalLock(hClipboardData);
                memcpy(pchData, test.c_str(), test.size() + 1);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_TEXT, hClipboardData);
                CloseClipboard();
            }
            SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DESTROY:
            ChangeClipboardChain(windowHandler, nextClipboardViewer);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
            break;
    }
    return 0;
}

クリップボードの情報を置き換えようとしていますが、このコードは機能しません。

更新:現在、変更を監視するために非表示のウィンドウと SetClipboardViewer を使用しています。ただし、クリップボードのデータは変更されません。

4

1 に答える 1

1

メッセージの処理中にクリップボードの内容を変更するのは本当に安全だWM_DRAWCLIPBOARDとは思えません-少なくとも、無限ループをトリガーしないことに驚いています( EmptyClipboard()andの呼び出しが別のメッセージSetClipboardData()をトリガーする可能性があるため)。WM_DRAWCLIPBOARDおそらく、システムにはそれに対する保護があります-私は見つけようとしたことはありません-しかし、それでも間違っていると感じます:)

このバージョンを試してみてください。a) クリップボードの更新を、ウィンドウが投稿する別のメッセージに移動し (クリップボードの変更通知コードの外に移動)、b) グローバル フラグを使用して、それ自体が行った変更を無視します。

(注:あなたのコードの実際のバグは、あなたが処理しているときにWM_CREATEwindowHandlerまだ割り当てられていないことだと思います。おそらくそれを値に設定していますが、処理されているCreateWindowExときに実際にはまだ返されていません。これは、クリップボードを意味しますビューアーが実際に正しく確立されることはありません.これを修正するために使用する参照を変更しました.)WM_CREATECreateWindowExhwnd

string test("my data");

#define MSG_UPDATECLIPBOARD     (WM_APP + 1)
static bool g_fIgnoreClipboardChange = false;

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            nextClipboardViewer = SetClipboardViewer(hwnd);
            MessageBeep(MB_ICONINFORMATION);
            break;
        case WM_CHANGECBCHAIN:
            if((HWND) wParam == nextClipboardViewer) 
                nextClipboardViewer == (HWND) lParam;
            else if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DRAWCLIPBOARD:
            if (!g_fIgnoreClipboardChange)
                PostMessage(hwnd, MSG_UPDATECLIPBOARD, 0, 0);
            if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case MSG_UPDATECLIPBOARD:
            g_fIgnoreClipboardChange = true;
            if(OpenClipboard(hwnd)) {
                HGLOBAL hClipboardData;
                hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
                char * pchData;
                pchData = (char*)GlobalLock(hClipboardData);
                memcpy(pchData, test.c_str(), test.size() + 1);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_TEXT, hClipboardData);
                CloseClipboard();
            }
            g_fIgnoreClipboardChange = false;
            break;      
        case WM_DESTROY:
            ChangeClipboardChain(hwnd, nextClipboardViewer);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
            break;
    }
    return 0;
}
于 2013-08-19T19:59:11.913 に答える