• 第12章 剪贴板_12.3 实现一个剪贴板查看器


     12.3.1 剪贴板查看器链

    (1)Windows下可运行任意个剪贴板查看器,但只有一个是“当前剪贴板查看器”,Windows只维护这个剪贴板查看器的窗口句柄,并在剪贴板内容改变时,通知它。

    (2)当A程序注册为剪贴板查看器时,就成为当前查看器。Windows会把上个当前查看器B的窗口句柄交给A程序来保存。当A收到剪贴板消息时,要发送给查看器链中的下一个程序,即B的窗口过程。

    12.3.2 剪贴板查看器函数和消息

    (1)将程序加入剪贴板查看器链

     static HWND hwndNextViewer;

     case WM_CREATE:

    hwndNextViewer =SetClipboardViewer(hwnd);//hwndNextViewer得保存下来,这是

                                            //剪贴板消息的下一个接收者。

     (2)WM_DRAWCLIPBOARD消息

         ①剪贴板内板改变时,会发送这消息给当前查看器(最新注册的那个)。

         ②剪贴板查看器链中的每个程序都应通用SendMessage把消息传给下一个查看器

    (hwndNextViewer),直到hwndNextViewer为NULL。

    ③不要把WM_DRAWCLIPBOARD与WM_PAINTCLIPBOARD混为一谈

     消息

    消息发起者

    WM_DRAWCLIPBOARD

    Windows自动发送的,通知查看器剪贴板内容发生了变化。

    WM_PAINTCLIPBOARD

    查看器(即手动发送的),发给使用CF_OWNERDISP格式的程序

    ④WM_DRAWCLIPBOARD消息的处理

        case WM_DRAWCLIPBOARD:

           if(hwndNextViewer)SendMessage(hwndNextViewer,message,wParam,lParam);

           InvalidateRect(hwnd,NULL,TRUE);

           return 0;

    (3)退出剪贴板查看器链:ChangeClipboardChain(hwnd,hwndNextViewer);

      ①当某个程序退出查看器链时,Windows会向当前查看器发送WM_CHANGECBCHAIN消息。

    case WM_CHANGECBCHAIN:  //wParam:要退出链的窗口句柄。lParam:它的下个剪贴板查看器
         if((HWND)wParam == hwndNextViewer) //要退出的窗口w是不是我的下个查看器消息接收者?
              hwndNextViewer =(HWND)lParam; //如果是,将A的消息接收者(lParam)转到我的接收者。
         else if(hwndNextViewer)   //如果要退出的不是我的下个接收者,将退出消息转发下去。
            SendMessage(hwndNextViewer,message,wParam,lParam);
    
         return 0;

      ②程序终止时,必须从查看器链退出中。

       case WM_DESTROY:

            ChangeClipboardChain(hwnd,hwndNextViewer);

            PostQuitMessage(0);

    (4)获得第一个剪贴板查看器(即当前查看器)的窗口句柄:hwndViewer= GetClipboardViewer();

    12.3.3 一个简单的剪贴板查看器

      ①可实时感知剪贴板内容发生变化(eg.迅雷的下载地址监测)

      ②本程序只监测CF_TEXT的变化。

    【ClipView程序】
    效果图

    /*------------------------------------------------------------
    CLIPVIEW.C -- Simple Clipboard Viewer
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("ClipView");
        HWND         hwnd;
        MSG          msg;
        WNDCLASS     wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                       szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
                            TEXT("Simple Clipboard Viewer(Text Only)"), // 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;
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HDC         hdc;
        PAINTSTRUCT ps;
        RECT        rect;
        static HWND hwndNextViewer;
        HGLOBAL     hGlobal;
        PTSTR       pGlobal;
        switch (message)
        {
        case WM_CREATE:
            //加入剪贴板查看器链
            hwndNextViewer = SetClipboardViewer(hwnd);
            return 0;
        case WM_CHANGECBCHAIN: //当有程序退出剪贴板查看器链时
            //wParam:要退出查看器链的窗口句柄,lParam:它的下一个消息接收者。
            if ((HWND)wParam == hwndNextViewer) //退出窗口是我的下个消息接收者?
            {
                hwndNextViewer = (HWND)lParam; //如果是,将该窗的下个消息接收者(lParam)转到我的名下。
            } else if (hwndNextViewer)  //要退出的不是我的下个接收者,则直接将退出消息向下通知出去。
                SendMessage(hwndNextViewer, message, wParam, lParam);
            return 0;
        case WM_DRAWCLIPBOARD:  //当剪贴板内容改变时,将消息通知下去。
            if (hwndNextViewer)
                SendMessage(hwndNextViewer, message, wParam, lParam);
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
    
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &rect);
            OpenClipboard(hwnd);
    #ifdef UNICODE
            hGlobal = GetClipboardData(CF_UNICODETEXT);
    #else 
            hGlobal = GetClipboardData(CF_TEXT);
    #endif
            if (hGlobal != NULL)
            {
                pGlobal = GlobalLock(hGlobal);
                DrawText(hdc, pGlobal, -1, &rect,
                         DT_EXPANDTABS);
                GlobalUnlock(hGlobal);
            }
    
            CloseClipboard();
    
            EndPaint(hwnd, &ps);
            return 0;
    
        case WM_DESTROY:
            //退出剪贴板查看器链
            ChangeClipboardChain(hwnd, hwndNextViewer);
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
  • 相关阅读:
    Struts2学习笔记《三》
    《Shiro框架》shiro学习中报错解决方法
    android
    MAC 设置环境变量path的几种方法
    利用ant脚本 自动构建svn增量/全量 系统程序升级包
    Jenkins2 插件 Pipeline+BlueOcean 实现持续交付的初次演练
    Jenkins2 实现持续交付初次演练(MultiJob,Pipeline,Blue Ocean)
    jenkins2 -pipeline 常用groovy脚本
    jenkins2 pipeline介绍
    scala学习(1)----map和flatMap的区别
  • 原文地址:https://www.cnblogs.com/5iedu/p/4695148.html
Copyright © 2020-2023  润新知