• 第12章 剪贴板_12.2 剪贴板的高级用法


    12.2.1 使用多种数据项

    (1)设置多种数据项

    OpenClipboard(hwnd);
    
    EmptyClipboard(); 
    //下面设置多种数据项,但这3种数据项必须不同,且在Empty和CloseClipboard间设置。 //将文本字符串写到位图或图元文件中,这样字符串即可被文读文本的程序访问。也可 //被读位图的程序访问,但这些程序没办法轻易判断出位图中其实还含有字符串。

    SetClipboardData(CF_TEXT,hGlobalText); //每次,每个数据项只能是一种格式。 SetClipboardData(CF_BITMAP,hBitmap); //如文本,不能同时设CF_TEXT SetClipboardData(CF_METAFILEPICT,hGlobalMFP);//和CF_UNICODETEXT等格式 CloseClipboard();

    (2)取出这些数据项

    hGlobalText= GetClipboardData(CF_TEXT);
    
    hBitmap     = GetClipboardData(CF_BITMAP);
    
    hGlobalMFP  = GetClipboardData(CF_METAFILEPICT);

    (3)判断剪贴板里有几种存储的数据格式——EnumClipboardFormats(iFormat);

        ①函数枚举当前剪贴板中可用的数据格式

        ②iFormat指己知的数据格式,当设为0时,会自动获取第一个可用的数据格式。

        ③剪贴板的数据格式被存储在一个有序的链表里,每次调用该函数,会返回下一种格式。当返回值为0时,枚举结束。

    iFormat =0;
    
    OpenClipboard(hwnd);
    
    While (iFormat =EnumClipboardFormats(iFormat))
    {
         //针对每个iFormat数据格式的操作
    }
    
    CloseClipboard();

    (4)获取当前剪贴板不同格式的数目:iCount = CountClipboardFormats();

    12.2.2 延迟提交技术

    (1)复制数据端的程序——放完数据后,hwnd成为把数据放到剪贴板里的最后一个窗口,即剪贴板的最后Owner为hwnd。

    OpenClipboard(hwnd); //Windows先把新的窗口句柄(hwnd)保存下来,但并不立即变
                            //更剪贴者拥有者,要调用EmptyClipboard后才变更。
    EmptyClipboard();    //调用该函数时,Windows将剪贴板拥有者设为hwnd,并向旧拥有者发送一条WM_DESTROYCLIPBOARD消息
                         //以告知旧拥有者,剪贴板的内容己被我清空,而且我也正式接管理剪贴板的拥有权,而你失去拥有权了
                         //(呵呵,多有礼貌呀!)
    
    SetClipboardData(iFormat,NULL); //设为NULL,以延迟提交数据句柄。会一直等到有程序对剪贴板中的数据进行请求时,该程序
                                     //(也就是剪贴板的拥有者)才会按指定数据格式将数据复制到剪贴板中,这就是“延迟提交
                                     //技术”。
    CloseClipboard()

    (2)粘贴数据端的程序

      ①GetClipboardData时:先检查指定数据格式的句柄是否为NULL,如果是,则向剪贴板拥有者(hwnd)发送WM_RENDERFORMAT消息,请求得到实际的句柄。

      复制数据端的程序开始处理请求:

      case WM_RENDERFORMAT:    //wParam:要请求传送的数据格式

           [根据wParam的数据格式(iFormat),产生全局内存块];

           SetClipboardData(iFormat,hGlobal);

    ★注意

    A、处理该消息的过程无须打开、清空和关闭剪贴板,也不能那样做,因为剪贴板己被粘贴数据端的程序打开,这时复制端的程序无法进行打开、清空和关闭等操作。

    B、此时剪贴板虽然被粘贴端的程序打开,但其拥有者仍是复制数据端程序。(∵粘贴端的程序还没有调用EmptyClipboard函数,一旦调用该函数后,会导致剪贴板拥有者发生变更,从而这里收不到该消息,所有剪贴板拥有者仍然为复制端程序。另外,此处Windows好象为SetClipboardData开了个后门,如果是数据句柄为NULL的数据项,可以在不打开剪贴板的前提下修改剪贴板的数据!这是我的猜测而己哦!)

     ②粘贴端调用EmptyClipboard后:Windows会向复制端程序发送WM_DESTROYCLIPBOARD消息,告知剪贴板数据信息被清空了,同时告知拥有者也变更了。一般不需要处理该消息。

     ③如果延迟提交剪贴板拥有者进程将要终止,并且此时剪贴板仍然拥有为NULL的数据句柄,则系统将会为其发送一条WM_RENDERALLFORMATS消息,通知将所有为NULL的数据项拷贝到剪贴板。(课本的处理是将所有数据项重新设置到剪贴板)

    case WM_RENDERALLFORMATS:  //这里只需重新设置所有数据句柄为NULL的数据项,这情况可以不打开剪贴板。而课本的是处理
                               //所有的数据项(含不为NULL的),因为要设置不为NULL的数据项,就必须打开剪贴板。
           OpenClipboard(hwnd);
    
           EmptyClipboard();   //清空剪贴板,设置hwnd为剪贴板新的拥有者。
                               //调用后会发送WM_DESTROYCLIPBOARD消息
                                //设置所有的数据项(因为剪贴板己被Empty了)
    
           SetClipboard(CF_TEXT,hGlobalText); //之前不为NULL的数据项
           [根据iFormat,产生全局内存块];
    
           SetClipboardData(iFormat,hGlobal); //之前为句柄为NULL的数据项
         
           CloseClipboard();

    12.2.3 私有数据类型——3种方法

    (1)使用伪标准格式(CF_DSPTEXT、CF_DSPBITMAP等)——为使用DSP数据格式,必须确保进程本身与剪贴板拥有者进程同属一个程序。指定为这种格式时,剪贴板的这部分数据就被设成是私有的,只能通过CF_DSPXXX格式并且剪贴板的拥有者是同一程序(或不同实例间)才能被访问。

    ①设置数据:SetClipboardData(CF_DSPXXX,hGlobal);

    ②取出数据:

    A、获取剪贴板拥有者:hwndClipOwner = GetClipboardOwner();

    B、取得该拥有者的窗口类名称:GetClassName(hwndClipOwner,szClassName,32);

    C、如果类名与我们的程序名一样,就可以使用带有DSP前缀的剪贴板数据格式了。

    (2)使用CF_OWNERDISPLAY格式

    ①使该格式查看(粘贴)数据时,查看器程序要把自己的DC句柄交给剪贴板的拥有者,让它来帮忙绘制。(注意,完成绘图的是拥有者,即复制端程序而不是粘贴端)

    ②因为要显示时,才完成绘制,所以要采用“延迟提交技术”,即SetClipboardData(CF_OWNERDISPLAY,NULL);//NULL,指明了延迟提交数据句柄给剪贴板。

    ③剪贴板拥有者除了处理Windows发送的延迟提交消息外,一般还要处理发送查看器发送的5个消息。(注意这5个消息不是Windows自动发送的,要根据需要自己手动发送。)

     

    消息

    含义

    WM_ASKCBFORMATNAME

    获取得到数据格式的名称。

    lParam为这个名称的缓冲区。剪贴板拥有者必须把这个名称复制到这个缓冲区

    wParam为缓冲区能容纳的最大字符的数量。

    WM_SIZECLIPBOARD

    剪贴板查看器客户区大小改变时发送这消息。

    wParam为剪贴板查看器的句柄。

    lParam为客户区新的大小。

    WM_PAINTCLIPBOARD

    要求剪贴板所有者帮忙更新剪贴板查看器客户区内容。

    wParam:为剪贴板查看器的窗口句柄。

    lParam:指向PAINTSTRUCT结构的全局句柄。剪贴板拥有者可以锁定此句柄,从中得到hdc,并进行绘制

    WM_HSCROLLCLIPBOARD

    WM_VSCROLLCLIPBOARD

    剪贴板查看器移动了滚动条。

    wParam指向剪贴板查看器的窗口句柄。

    LOWORD(lParam):通知码

    HIWORD(lParam):滑块的位置(当通知码是SB_THUMBPOSITION时)

    (3)自定义的数据格式——不必像CF_OWNERDISPLAY那么费劲又允许其他程序从剪贴板里复制数据(只要知道了数据的格式就可以正确显示出来)。

    ①注册自定义的格式:iFormat = RegisterClipboardFormat(szFormatName);//iFormat要介于0xC000~0xFFFF之间。这种格式也可以被EnumClipboardFormats枚举出来。要获取该名称,可以调用:GetClipboardFormatName(iFormat,psBuffer,iMaxCount)取得。

    ②注册完就可以像CF_TEXT一样的使用这种格式了。

    //自定义要传送的结构体
    Struct MyFormatData
    {
       long val1;
       int val2;
    } 
    
    //注册自定义数据格式
    UINT iFormat = RegisterClipboardFormat(“MY_CUSTOM_FORMAT”); 
    
    //复制到剪贴板
    if(OpenClipboard(hwnd))
    {
        MyFormatData data;
        data.var1 = 100;
        data.var2 =200;
     
        HGLOBAL hGlobal;
        EmptyClipboard();
    
        hGlobal = GlobalAlloc(GHND |GMEM_SHARE, sizeof(MyFormatData));
        MyFormatData * pGlobal = (MyFormatData*)GlobalLock(hGlobal);
        *pGlobal = data; //保存数据
        GlobakUnlock(hGlobal);
    
        SetClipboardData(iFormat,hGlobal);
        CloseClipboard();
    }
    
    //从剪贴板中获取数据,读取数据使用以下代码:
    UINT iFormat = RegisterClipboardFormat("MY_CUSTOM_FORMAT"); //
    MyFormatData data;
    if(OpenClipboard(hwnd)) { HANDLE hGlobal =GetClipboardData(iFormat); MyFormatData * pGlobal = (MyFormatData*)GlobalLock(hGlobal); data = * pGlobal; GlobalUnlock(hGlobal); CloseClipboard(); }

     【ClipCustomFormat程序】
    效果图

    /*------------------------------------------------------------
    ClipCustomFormat.C -- The Clipboard and Text (c) Charles Petzold, 1998 ------------------------------------------------------------
    */ #include <windows.h> #include "resource.h" TCHAR szAppName[] = TEXT("ClipCustomFormat"); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { TCHAR szCaption[] = TEXT("Clipboard Custom Format Transfers"); HWND hwnd; MSG msg; WNDCLASSEX wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name szCaption, // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } typedef struct _tag_MyFormatData MyFormatData; struct _tag_MyFormatData { long var1; int var2; }; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int nSize = 64; TCHAR szBuffer[64]; HDC hdc; static PAINTSTRUCT ps; LPPAINTSTRUCT lpps; RECT rect; static PTSTR pText; PTSTR pOwnerText; HGLOBAL hGlobal; PTSTR pGlobal; HWND hwndClipOwner; static UINT iFormat; static TCHAR szFormatName[] = TEXT("MY_CUSTOM_FORMAT"); static MyFormatData data; switch (message) { case WM_CREATE: data.var1 = 100; data.var2 = 200; iFormat = RegisterClipboardFormat(szFormatName); //注册自定义的数据格式。 return 0; case WM_INITMENUPOPUP: break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_W_PASTE: //伪标准数据格式 hwndClipOwner = GetClipboardOwner(); GetClassName(hwnd, szBuffer, nSize); if (lstrcmp(szBuffer, szAppName) == 0) { OpenClipboard(hwnd); hGlobal = GetClipboardData(CF_DSPTEXT); if (hGlobal != NULL) { pGlobal = GlobalLock(hGlobal); //锁定内存块,获取指针 if (pText) { free(pText); pText = NULL; } wsprintf(szBuffer, TEXT("Data From CF_DSPEXT!")); pText = malloc((lstrlen(szBuffer) + 1)*sizeof(TCHAR)); lstrcpy(pText, szBuffer); GlobalUnlock(hGlobal); InvalidateRect(hwnd, NULL, TRUE); } CloseClipboard(); } return 0; case IDM_W_COPY: //伪标准数据格式 if (!pText) free(pText); pText = malloc((nSize + 1)*sizeof(TCHAR)); lstrcpy(pText, TEXT("Data From CF_DSPTEXT!")); //分配内存并拷贝数据到全局内存块里 hGlobal = GlobalAlloc(GHND | GMEM_SHARE, (lstrlen(pText) + 1)*sizeof(TCHAR)); pGlobal = GlobalLock(hGlobal); lstrcpy(pGlobal, pText); GlobalUnlock(hGlobal); //将内存块传入剪贴板 OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(CF_DSPTEXT, hGlobal); CloseClipboard(); return 0; case IDM_C_COPY: //自定义的数据格式 //分配内存并拷贝数据到全局内存块里 hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(MyFormatData)); pGlobal = GlobalLock(hGlobal); *((MyFormatData*)pGlobal) = data; GlobalUnlock(hGlobal); //将内存块传入剪贴板 OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(iFormat, hGlobal); CloseClipboard(); return 0; case IDM_C_PASTE: //自定义的数据格式 OpenClipboard(hwnd); hGlobal = GetClipboardData(iFormat); if (hGlobal != NULL) { pGlobal = GlobalLock(hGlobal); //锁定内存块,获取指针 if (pText) { free(pText); pText = NULL; } data = *((MyFormatData*)pGlobal); wsprintf(szBuffer, TEXT("Data From MyFormatData var1 =%d,var2=%d"), data.var1, data.var2); pText = malloc((lstrlen(szBuffer) + 1)*sizeof(TCHAR)); lstrcpy(pText, szBuffer); GlobalUnlock(hGlobal); InvalidateRect(hwnd, NULL, TRUE); } return 0; case IDM_O_PASTE: //OwnerDisplay数据,注意这里不GetClipboardData,而是将hdc交给剪贴板拥有者去帮忙绘图。 hwndClipOwner = GetClipboardOwner(); hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(PAINTSTRUCT)); lpps = (LPPAINTSTRUCT)GlobalLock(hGlobal); memcpy(lpps, &ps, sizeof(PAINTSTRUCT)); GlobalUnlock(hGlobal); SendMessage(hwndClipOwner, WM_PAINTCLIPBOARD, (WPARAM)hwnd, (LPARAM)hGlobal); GlobalFree(hGlobal); return 0; case IDM_O_COPY: //OwnerDisplay数据 OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(CF_OWNERDISPLAY, NULL); //OwnerDisplay;NULL——延迟提交 CloseClipboard(); return 0; } break; //处理延迟提交 case WM_RENDERALLFORMATS: OpenClipboard(hwnd); EmptyClipboard(); case WM_RENDERFORMAT: //分配内存并拷贝数据到全局内存块里 hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(MyFormatData)); pGlobal = GlobalLock(hGlobal); *((MyFormatData*)pGlobal) = data; GlobalUnlock(hGlobal); SetClipboardData(CF_OWNERDISPLAY, hGlobal); //这里不需要OpenClipboard! if (message == WM_RENDERALLFORMATS) CloseClipboard(); return 0; //处理OwnerDispay的消息 //在剪贴板查看器的WM_PAINT消息中,一般要手动发送WM_PAINTCLIPBOARD消息。 case WM_PAINTCLIPBOARD: //wParam为查看器窗口句柄,lParam为PAINTSTRUCT结构 OpenClipboard(hwnd); hGlobal = GetClipboardData(CF_OWNERDISPLAY); pGlobal = GlobalLock(hGlobal); data = *((MyFormatData*)pGlobal); wsprintf(szBuffer, TEXT("OwnerDisplay Data From MyFormatData var1 =%d,var2=%d"), data.var1, data.var2); pOwnerText = malloc((lstrlen(szBuffer) + 1)*sizeof(TCHAR)); lstrcpy(pOwnerText, szBuffer); GlobalUnlock(hGlobal); hdc = GetDC((HWND)wParam); TextOut(hdc, 0, 0, pOwnerText, lstrlen(pOwnerText)); ReleaseDC((HWND)wParam, hdc); CloseClipboard(); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); DrawText(hdc, pText, -1, &rect, DT_EXPANDTABS | DT_WORDBREAK); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 ClipCustomFormat.rc 使用
    //
    #define IDM_W_COPY                      40001
    #define IDM_W_PASTE                     40002
    #define IDM_O_COPY                       40003
    #define IDM_O_PASTE                     40004
    #define IDM_C_COPY                      40005
    #define IDM_C_PASTE                     40006
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        103
    #define _APS_NEXT_COMMAND_VALUE         40023
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //ClipCustomFormat.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    1 TEXTINCLUDE
    BEGIN
    "resource.h"
    END
    2 TEXTINCLUDE
    BEGIN
    "#include ""winres.h""
    "
    ""
    END
    3 TEXTINCLUDE
    BEGIN
    "
    "
    ""
    END
    #endif    // APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Menu
    //
    CLIPCUSTOMFORMAT MENU
    BEGIN
    POPUP "伪标准格式"
    BEGIN
    MENUITEM "W_复制", IDM_W_COPY
    MENUITEM "W_粘贴", IDM_W_PASTE
    END
    POPUP "OwnerDisplay格式"
    BEGIN
    MENUITEM "O_复制", IDM_O_COPY
    MENUITEM "O_粘贴", IDM_O_PASTE
    END
    POPUP "自定义格式"
    BEGIN
    MENUITEM "C_复制", IDM_C_COPY
    MENUITEM "C_粘贴", IDM_C_PASTE
    END
    END
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    //

  • 相关阅读:
    第二章Maven安装与配置
    第一章 Maven简介
    什么是Maven?
    jbpm与OA项目-oa概念
    Hadoop学习常用的Linux命令
    包名命名规则
    判断网络类型
    webview的设置
    AlertDialog的实现
    SharedPreferences保存用户偏好参数
  • 原文地址:https://www.cnblogs.com/5iedu/p/4695129.html
Copyright © 2020-2023  润新知