Clipboard の書き込みと読み出し



Clipboard への TEXT の書き込みと読み出しのプログラムです。
Edit Control への Copy & Paste はもっと簡単に操作できますが、ここでは Clipboard の基礎を説明します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 新規プロジェクト(Cliptxt)を作成して下さい。
  2. クリップボードの書き込みと読み出しのメニューを設定します。
    キャプション ID
    クリップボード(&C)
    書き込み(&W) IDM_WRITE
    読み出し(&R) IDM_READ
  3. クリップボードに格納する TEXT を入力する DialogBox を作成します。
    EditControl のプロパティで次の設定をチェックして下さい。
    [複数行][水平オートスクロール][垂直オートスクロール][改行を許可]
    BOX キャプション ID
    DialogBox クリップボード書き込み IDD_DIALOG1
    EditControl IDC_EDIT1
    Button OK IDOK
    Button キャンセル IDCANCEL
  4. 関数の Prototype 宣言です。
        BOOL            CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
        int             WriteClip(HWND, char *);
        int             ReadClip(HWND, char *);
        
  5. クリップボードの書き込みと読み出しを処理するソースコードです。
    string[1024] は文字列を格納する領域です。
    rc は DrawText() で表示する矩形領域を設定する構造体です。
    IDM_WRITE: では Dialog Box を表示してタイプされた文字列をクリップボードに書き込みます。
    IDM_READ: ではクリップボードから文字列を取得して string に格納します。
        RECT        rc;
        static char string[1024];
    
            case IDM_WRITE:
                DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),hWnd,(DLGPROC)DlgProc);
                break;
            case IDM_READ:
                ReadClip(hWnd, string);
                break;
        
  6. 読み出した TEXT を描画するコードです。
    rc に Window の矩形領域を取得して string の文字列を DrawText() で表示します。
            case WM_PAINT:
                hdc = BeginPaint (hWnd, &ps);
                // TODO: この位置に描画用のコードを追加してください...
                GetClientRect(hWnd, &rc);
                DrawText(hdc,string,strlen(string),&rc,DT_WORDBREAK | DT_EXPANDTABS);
                EndPaint( hWnd, &ps );
                break;
        
  7. IDM_WRITE: から呼ばれる Dialog Box の CALLBACK 関数です。
    IDOK: で文字列をクリップボードに書き込みます。
        BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
        {   char str[1024];
    
            switch(msg)
            {   case WM_INITDIALOG:
                    SendMessage(GetDlgItem(hDlg,IDC_EDIT1),EM_SETLIMITTEXT,(WPARAM)1024, 0L);
                    SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
                    break;
                case WM_COMMAND:
                    switch(LOWORD(wp))
                    {   case IDOK:
                            GetWindowText(GetDlgItem(hDlg,IDC_EDIT1),str,sizeof(str));
                            WriteClip(hDlg, str);
                            EndDialog(hDlg, IDOK);
                            return TRUE;
                        case IDCANCEL:
                            EndDialog(hDlg, IDCANCEL);
                            return TRUE;
                    }
                    break;
            }
            return FALSE;
        }
        
  8. クリップボードに書き込む関数を追加して下さい。
        int WriteClip(HWND hwnd, char *str)
        {   HGLOBAL hGlobal;
            int     iLength;
            LPSTR   lpStr;
            int     i;
    
            iLength = lstrlen(str);
            if (iLength > 1024)     iLength = 1024;
            hGlobal = GlobalAlloc(GHND, iLength + 1);
            if (hGlobal == NULL)    return -1;
            lpStr = (LPSTR)GlobalLock(hGlobal);
            for(i= 0; i<iLength; i++)   *lpStr++ = *str++;
            GlobalUnlock(hGlobal);
            if (OpenClipboard(hwnd) == 0)
            {   GlobalFree(hGlobal);
                return -2;
            }
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hGlobal);
            CloseClipboard();
            return 0;
        }
        
  9. クリップボードから読み出す関数を追加して下さい。
        int ReadClip(HWND hwnd, char *str)
        {   HGLOBAL hGlobal;
            LPSTR   lpStr;
            int     iLength, i;
    
            if (!IsClipboardFormatAvailable(CF_TEXT))
            {   MessageBox(hwnd, "クリップボードを読めません", "失敗", MB_OK);
                return -1;
            }
            OpenClipboard(hwnd);
            hGlobal = (HGLOBAL)GetClipboardData(CF_TEXT);
            if (hGlobal == NULL)
            {   CloseClipboard();
                return -2;
            }
            lpStr = (LPSTR)GlobalLock(hGlobal);
            iLength = lstrlen(lpStr) + 1;
            if (iLength > 1024)     iLength = 1024;
            for(i=0; i<iLength; i++)    str[i] = lpStr[i];
            GlobalUnlock(hGlobal);
            CloseClipboard();
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        }
        
  10. [ビルド]から[実行]を選択して下さい。
    ビルド(コンパイル)に続いて、エラーが無ければプログラムが実行されます。

プログラムの説明

  1. メニューから「書き込み(&W)」が選択されたときの処理です。
    TEXT 入力の DialogBox を表示します。
    クリップボードに書きこむ関数は DialogBox の CALLBACK 関数から呼ばれます。
            case IDM_WRITE:
                DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),hWnd,(DLGPROC)DlgProc);
                break;
        
  2. メニューから「読み出し(&R)」が選択されたときの処理です。
    ReadClip() でクリップボードに格納されている TEXT を string[] に読み出します。
            case IDM_READ:
                ReadClip(hWnd, string);
                break;
        
  3. GetClientRect() でウインドウのサイズを取得して、string[] に格納されている TEXT を表示します。
        RECT        rc;
        static char string[1024];
            case WM_PAINT:
                hdc = BeginPaint (hWnd, &ps);
                // TODO: この位置に描画用のコードを追加してください...
                GetClientRect(hWnd, &rc);
                DrawText(hdc,string,strlen(string),&rc,DT_WORDBREAK | DT_EXPANDTABS);
                EndPaint( hWnd, &ps );
                break;
        
  4. Dialog Box の CALLBACK 関数です。
    WM_INITDIALOG: で EditControl に表示する文字の最大長を制限してフォーカスを設定します。
    OK ボタンがクリックされたとき EditControl に格納されている TEXT を WriteClip() で書き込みます。
        BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
        {   char str[1024];
    
            switch(msg)
            {   case WM_INITDIALOG:
                    SendMessage(GetDlgItem(hDlg,IDC_EDIT1),EM_SETLIMITTEXT,(WPARAM)1024, 0L);
                    SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
                    break;
                case WM_COMMAND:
                    switch(LOWORD(wp))
                    {   case IDOK:
                            GetWindowText(GetDlgItem(hDlg,IDC_EDIT1),str,sizeof(str));
                            WriteClip(hDlg, str);
                            EndDialog(hDlg, IDOK);
                            return TRUE;
                        case IDCANCEL:
                            EndDialog(hDlg, IDCANCEL);
                            return TRUE;
                    }
                    break;
            }
            return FALSE;
        }
        
  5. クリップボードに書きこむ関数です。
    GlobalAlloc() でメモリ領域を要求して、ハンドルを hGlobal に格納します。
    GlobalLock() でバッファのポインタを取得します。
    バッファ領域に TEXT 文字列を格納します。
    GlobalUnlock() でバッファのロックを解除します。
    OpenClipboard() でクリップボードをオープンします。
    EmptyClipboard() でクリップボードを空にします。
    SetClipboardData() でクリップボードにハンドルを設定します。
    CloseClipboard() でクリップボードをクローズします。
        //★ クリップボードに書きこむ
        int WriteClip(HWND hwnd, char *str)
        {   HGLOBAL hGlobal;
            int     iLength;
            LPSTR   lpStr;
            int     i;
    
            iLength = lstrlen(str);
            if (iLength > 1024)     iLength = 1024;
            hGlobal = GlobalAlloc(GHND, iLength + 1);
            if (hGlobal == NULL)    return -1;
            lpStr = (LPSTR)GlobalLock(hGlobal);
            for(i= 0; i<iLength; i++)   *lpStr++ = *str++;
            GlobalUnlock(hGlobal);
            if (OpenClipboard(hwnd) == 0)
            {   GlobalFree(hGlobal);
                return -2;
            }
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hGlobal);
            CloseClipboard();
            return 0;
        }
        
  6. クリップボードから読み出す関数です。
    IsClipboardFormatAvailable() で TEXT がクリップボードに格納されていることを確認します。
    OpenClipboard() でクリップボードをオープンします。
    GetClipboardData() でメモリ領域のハンドルを hGlobal に取得します。
    GlobalLock() でバッファのポインタを取得します。
    バッファ領域から *str に TEXT 文字列をコピーします。
    GlobalUnlock() でバッファのロックを解除します。
    CloseClipboard() でクリップボードをクローズします。
    InvalidateRect() でウインドウを描画します。
        //★ クリップボードから読み出す
        int ReadClip(HWND hwnd, char *str)
        {   HGLOBAL hGlobal;
            LPSTR   lpStr;
            int     iLength, i;
    
            if (!IsClipboardFormatAvailable(CF_TEXT))
            {   MessageBox(hwnd, "クリップボードを読めません", "失敗", MB_OK);
                return -1;
            }
            OpenClipboard(hwnd);
            hGlobal = (HGLOBAL)GetClipboardData(CF_TEXT);
            if (hGlobal == NULL)
            {   CloseClipboard();
                return -2;
            }
            lpStr = (LPSTR)GlobalLock(hGlobal);
            iLength = lstrlen(lpStr) + 1;
            if (iLength > 1024)     iLength = 1024;
            for(i=0; i<iLength; i++)    str[i] = lpStr[i];
            GlobalUnlock(hGlobal);
            CloseClipboard();
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        }
        
  7. C# でも同様のプログラムを作成しています。
    Clipboard Text を参照して下さい。

【演習】

  1. Text Editor でクリップボードに格納した TEXT を このプログラムで表示して下さい。
  2. このプログラムでクリップボードに格納した TEXT を Text Editor で表示して下さい。
  3. クリップボードに格納するプログラムと、クリップボードから読み出すプログラムを分けて作成して下さい。

超初心者のプログラム入門(Win32API C++)