《Windows核心编程》---剪贴板

【MoreWindows工作笔记12】WM_DRAWCLIPBOARD 监视剪切板 有很多程序会监视剪贴板,比如迅雷,这样当你复制一个迅雷下载链接时,迅雷就可以自动启动并创建一个新的下载任务。下面我们就来看看如何实现这个技术。 实现这个技术一共需要4步: 第一步:Add the window to the clipboard viewer chain. 通过SetClipboardViewer()传入窗口句柄,所有监视剪贴板的窗口句柄会组成一 阅读详情

剪贴板是由系统定义的,并不属于任何一个特定的进程。系统中所有进程都可以访问和设置剪贴板。剪贴板最大的特点就是数据传输没有明确的目标,数据是被动访问的;剪贴板的内容可以被多次访问,直到新的数据写入。剪贴板是一种可供选择的进程间通信方式,但由于系统中任何一个进程都可以都可以无限制地访问剪贴板,因此,它是一种不可靠的通信方式。

1)获取和设置剪贴板数据

涉及到的API有:OpenClipboard、EmptyClipboard、SetClipboardData、GetClipboardData、CloseClipboard等。

 

OpenClipboard用于打开剪贴板,获得剪贴板的句柄:

BOOL WINAPI OpenClipboard(

  __in_opt  HWND hWndNewOwner //指定的窗口可以收到剪贴板操作所产生的消息

                                               //如果为NULL,则采用当前任务的窗口

);

 

EmptyClipboard用于清空剪贴板中的内容:

BOOL WINAPI EmptyClipboard(void);

 

SetClipboardData用于设置剪贴板的内容:

HANDLE WINAPI SetClipboardData(

  __in      UINT uFormat,       //指定数据格式,可以是标准系统格式,也可以是用户自定义格式

  __in_opt  HANDLE hMem     //需要设置的数据的内存句柄;需使用全局内存管理的函数分配和

                                     //设置,且在分配时需指定GMEM_MOVEABLE标志

);

 

GetClipboardData用于从剪贴板获取数据:

HANDLE WINAPI GetClipboardData(

  __in  UINT uFormat //指定获取的数据的格式,获得的数据使用句柄返回

);

 

2)一般来说利用剪贴板进行数据通信是不具有实时性,所有操作都依赖于用户。除非使用剪贴板查看器Viewer,这样就可以立即知道剪贴板中内容的变化。

系统提供了WM_DRAWCLIPBOARD消息用于监视剪贴板的变化。如果调用SetClipboardViewer函数设置了窗口为剪贴板查看器,那么当剪贴板中内容变化时,所注册的查看器窗口就会收到WM_CHANGECBCHAIN消息和WM_DRAWCLIPBOARD消息。SetClipboardViewer函数原型如下:

HWND WINAPI SetClipboardViewer(

  __in  HWND hWndNewViewer //指定监视窗口

);

剪贴板查看器的代码例子如下:

HINSTANCE hinst;

UINT uFormat = (UINT)(-1);

BOOL fAuto = TRUE;

 

LRESULT CALLBACK MainWndProc(HWND hwnd,

UINT uMsg,

WPARAM wParam,

LPARAM lParam)

{

    static HWND hwndNextViewer;

 

    HDC hdc;

    HDC hdcMem;

    PAINTSTRUCT ps;

    LPPAINTSTRUCT lpps;

    RECT rc;

    LPRECT lprc;

    HGLOBAL hglb;

    LPSTR lpstr;

    HBITMAP hbm;

    HENHMETAFILE hemf;

    HWND hwndOwner;

 

    switch (uMsg)

    {

        case WM_PAINT: //收到WM_PAINT消息后显示剪贴板中的数据

            hdc = BeginPaint(hwnd, &ps);

            // Branch depending on the clipboard format.

              //uFormat全局变量,在WM_DRAWCLIPBOARD和WM_COMMAND

            //消息处理中,使用SetAutoView设置

            //根据剪贴板中数据的不同格式,使用不同的显示方式

            switch (uFormat)

            {

                case CF_OWNERDISPLAY: //剪贴板的所有者必须显示并刷新Viewer的窗口

                    hwndOwner = GetClipboardOwner();//获得剪贴板的所有者

                            //获取剪贴板的数据

                    hglb = GlobalAlloc(GMEM_MOVEABLE,

                        sizeof(PAINTSTRUCT));

                    lpps = (LPPAINTSTRUCT)GlobalLock(hglb);

                    memcpy(lpps, &ps, sizeof(PAINTSTRUCT));

                    GlobalUnlock(hglb);

                           //向剪贴板所有者发送WM_PAINTCLIPBOARD消息

                    SendMessage(hwndOwner, WM_PAINTCLIPBOARD,

                        (WPARAM) hwnd, (LPARAM) hglb);

                    GlobalFree(hglb);

                    break;

 

                case CF_BITMAP: //位图

                    hdcMem = CreateCompatibleDC(hdc);

                    if (hdcMem != NULL)

                    {

                        if (OpenClipboard(hwnd)) //打开剪贴板

                        {

                            hbm = (HBITMAP)

                                GetClipboardData(uFormat); //获取剪贴板的数据

                                      //将位图选择进DC,显示在窗口客户区

                            SelectObject(hdcMem, hbm);

                            GetClientRect(hwnd, &rc);

                            BitBlt(hdc, 0, 0, rc.right, rc.bottom,

                                hdcMem, 0, 0, SRCCOPY);

                            CloseClipboard();//关闭剪贴板

                        }

                        DeleteDC(hdcMem); //释放DC

                    }

                    break;

 

                case CF_TEXT: //文本

                    if (OpenClipboard(hwnd)) //打开剪贴板

                    {

                        hglb = GetClipboardData(uFormat); //获得剪贴板数据

                        lpstr = GlobalLock(hglb);

                               //将文本绘制在窗口客户区

                        GetClientRect(hwnd, &rc);

                        DrawText(hdc, lpstr, -1, &rc, DT_LEFT);

                        GlobalUnlock(hglb);

                        CloseClipboard();//关闭剪贴板

                    }

                    break;

 

                case CF_ENHMETAFILE: //增强格式图元文件

                    if (OpenClipboard(hwnd)) //打开剪贴板

                    {

                        hemf = GetClipboardData(uFormat); //获取剪贴板数据

                                //调用PlayEnhMetaFile在窗口客户区上显示

                        GetClientRect(hwnd, &rc);

                        PlayEnhMetaFile(hdc, hemf, &rc);

                        CloseClipboard();

                    }

                    break;

 

                case 0: //剪贴板为空

                    GetClientRect(hwnd, &rc);

                    //在客户区中央显示

                    DrawText(hdc, "The clipboard is empty.", -1,

                        &rc, DT_CENTER | DT_SINGLELINE |

                        DT_VCENTER);

                    break;

 

                default: //不支持的其他格式

                    GetClientRect(hwnd, &rc);

                    DrawText(hdc, "Unable to display format.", -1,

                        &rc, DT_CENTER | DT_SINGLELINE |

                        DT_VCENTER);

            }

            EndPaint(hwnd, &ps);

            break;

 

        case WM_SIZE: //如果窗口大小改变,通知剪贴板所有者窗口

            if (uFormat == CF_OWNERDISPLAY)

            {

                hwndOwner = GetClipboardOwner();//获取剪贴板所有者

                hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(RECT));

                lprc = GlobalLock(hglb);

                GetClientRect(hwnd, lprc);

                GlobalUnlock(hglb);

 

                SendMessage(hwndOwner, WM_SIZECLIPBOARD,

                    (WPARAM) hwnd, (LPARAM) hglb);

 

                GlobalFree(hglb);

            }

            break;

 

        case WM_CREATE: //当窗口创建时,在剪贴板Viewer链中增加一个

            hwndNextViewer = SetClipboardViewer(hwnd);

            break;

 

        case WM_CHANGECBCHAIN:

            // If the next window is closing, repair the chain.

            if ((HWND) wParam == hwndNextViewer)

                hwndNextViewer = (HWND) lParam;

            // Otherwise, pass the message to the next link.

            else if (hwndNextViewer != NULL)

                SendMessage(hwndNextViewer, uMsg, wParam, lParam);

            break;

 

        case WM_DESTROY:

              //窗口hwnd销毁时,从剪贴板查看器链中移除

            ChangeClipboardChain(hwnd, hwndNextViewer);

            PostQuitMessage(0);

            break;

 

        case WM_DRAWCLIPBOARD:  // clipboard contents changed.

            // Update the window by using Auto clipboard format.

            SetAutoView(hwnd);

            // Pass the message to the next window in clipboard

            // viewer chain.

            SendMessage(hwndNextViewer, uMsg, wParam, lParam);

            break;

 

        case WM_INITMENUPOPUP: //当popup菜单弹出时收到此消息

            if (!HIWORD(lParam)) //根据剪贴板中内容的格式设置菜单

                InitMenu(hwnd, (HMENU) wParam);

            break;

 

        case WM_COMMAND: //处理用户菜单输入

            switch (LOWORD(wParam))

            {

                case IDM_EXIT: //用户点击“退出”菜单项

                    DestroyWindow(hwnd);

                    break;

 

                case IDM_AUTO: //用户点击“Auto”菜单项

                    SetAutoView(hwnd); //设置显示格式为自动

                    break;

 

                default:

                    fAuto = FALSE;

                    uFormat = LOWORD(wParam);

                    InvalidateRect(hwnd, NULL, TRUE);

            }

            break;

 

        default: //其他消息

            return DefWindowProc(hwnd, uMsg, wParam, lParam);

    }

    return (LRESULT) NULL;

}

 

/**********************************************************

* void WINAPI SetAutoView(HWND hwnd)

* 获取剪贴板的主要格式,并设置显示方式

**********************************************************/

void WINAPI SetAutoView(HWND hwnd)

{

    static UINT auPriorityList[] = {

        CF_OWNERDISPLAY,

        CF_TEXT,

        CF_ENHMETAFILE,

        CF_BITMAP

    };

//设置剪贴板主要格式,设置显示格式

//uFormat在收到WM_PAINT消息时用到

    uFormat = GetPriorityClipboardFormat(auPriorityList, 4);

    fAuto = TRUE;

 

    InvalidateRect(hwnd, NULL, TRUE);

    UpdateWindow(hwnd);

}

 

/**************************************************************

* 功能:根据剪贴板中内容的格式,设置菜单项供用户选择显示方式

* 参数:hwnd--窗口句柄

*       hmenu--菜单句柄

**************************************************************/

void WINAPI InitMenu(HWND hwnd, HMENU hmenu)

{

    UINT uFormat;

    char szFormatName[80];

    LPCSTR lpFormatName;

    UINT fuFlags;

    UINT idMenuItem;

 

    // If a menu is not the display menu, no initialization is necessary.

    if (GetMenuItemID(hmenu, 0) != IDM_AUTO)

        return;

    // Delete all menu items except the first.

    while (GetMenuItemCount(hmenu) > 1)

        DeleteMenu(hmenu, 1, MF_BYPOSITION);

 

    // Check or uncheck the Auto menu item.

    fuFlags = fAuto ? MF_BYCOMMAND | MF_CHECKED :

        MF_BYCOMMAND | MF_UNCHECKED;

    CheckMenuItem(hmenu, IDM_AUTO, fuFlags);

 

    // If there are no clipboard formats, return.

    if (CountClipboardFormats() == 0)

        return;

 

    // Open the clipboard.

    if (!OpenClipboard(hwnd))

        return;

 

    // Add a separator and then a menu item for each format.

    AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);

    uFormat = EnumClipboardFormats(0);

    while (uFormat)

    {

        // Call an application-defined function to get the name

        // of the clipboard format.

        lpFormatName = GetPredefinedClipboardFormatName(uFormat);

        // For registered formats, get the registered name.

        if (lpFormatName == NULL)

        {

                   // Note that, if the format name is larger than the

                   // buffer, it is truncated.

            if (GetClipboardFormatName(uFormat, szFormatName,

                    sizeof(szFormatName)))

                lpFormatName = szFormatName;

            else

                lpFormatName = "(unknown)";

        }

 

        // Add a menu item for the format. For displayable

        // formats, use the format ID for the menu ID.

        if (IsDisplayableFormat(uFormat))

        {

            fuFlags = MF_STRING;

            idMenuItem = uFormat;

        }

        else

        {

            fuFlags = MF_STRING | MF_GRAYED;

            idMenuItem = 0;

        }

        AppendMenu(hmenu, fuFlags, idMenuItem, lpFormatName);

        uFormat = EnumClipboardFormats(uFormat);

    }

    CloseClipboard();

}

 

BOOL WINAPI IsDisplayableFormat(UINT uFormat)

{

    switch (uFormat)

    {

        case CF_OWNERDISPLAY:

        case CF_TEXT:

        case CF_ENHMETAFILE:

        case CF_BITMAP:

            return TRUE;

    }

    return FALSE;

}

 

3)剪贴板中存在各种数据格式,系统使用一个UINT类型的数据来表示剪贴板中数据类型。在这些格式信息中,有很多是各种应用程序之间通用的,比如文本、位图等。这些数据格式由系统预先定义,称为标准格式;当然应用程序也可自行定义剪贴板的数据格式,这样可以方便地在同一个应用程序的不同实例间进行数据传递而不用对数据格式进行过多的处理(典型的就包括word)。

 

常见标准格式:

CF_BITMAP    //位图句柄(HBITMAP)

CF_DIB             //内存位置包含BITMAPINFO结构和位图数据

CF_ENHMETAFILE         //增强的图元文件句柄(HENHMETAFILE)

CF_OEMTEXT        //OEM字符集的字符串(以CR-LF格式换行)

CF_OWNERDISPLAY    //由剪贴板查看器查看的格式

CF_PALETTE  //调色板数据

CF_RIFF  //标准的CF_WAVE波形数据

CF_TEXT          //ANSI字符串(以CR-LF格式换行)

CF_WAVE       //PCM波形

CF_TIFF  //Tagged图像文件格式

CF_UNICODETEXT       //Unicode字符串

 

自定义格式:

调用函数RegisterClipboardFormat可以自定义格式:

UINT WINAPI RegisterClipboardFormat(//返回值是系统分配的格式类型值(UINT)

  __in  LPCTSTR lpszFormat //格式名,

);

 

多种格式:

很多情况下,数据的格式不止一种,比如格式化的文本有效的格式不止一种(例如从Word中复制的数据、从网页中复制的数据等),因此可能存在多重格式。

以下几个API函数是用于获取当前剪贴板中的格式信息的:

GetPriorityClipboardFormat的功能是检测剪贴板中是否有paFormatPriorityList参数指定的格式数组中的格式存在,如果有则返回格式数组中的第一个剪贴板当前具有的格式:

int WINAPI GetPriorityClipboardFormat(

  __in  UINT *paFormatPriorityList, //格式数组,存储用于检测的格式信息

  __in  int cFormats    //paFormatPriorityList数组的大小

);

 

CountClipboardFormats函数用于返回当前剪贴板中具有的不同格式的数量:

int WINAPI CountClipboardFormats(void);

 

EnumClipboardFormats函数用于列举当前剪贴板中的所有格式:

UINT WINAPI EnumClipboardFormats(

  __in  UINT format   //指定一个已知的格式,通过函数返回值返回下一个格式

);

 

GetUpdatedClipboardFormats函数用于获取当前剪贴板的所有格式:

BOOL WINAPI GetUpdatedClipboardFormats(

  __out  PUINT lpuiFormats, //指向用于保存返回的格式数组的缓冲区

  __in   UINT cFormats, //lpuiFormats可以容纳的格式信息的数量

  __out  PUINT pcFormatsOut //返回真是的数组大小

);

 

由于剪贴板数据会有多种格式,在调用GetClipboardData函数获取数据时,应该指定格式。一般情况下,指定不同格式,将获得不同的内容。

 

剪贴板数据的格式信息:

每一个剪贴板格式都有一个格式名,格式名是一个字符串,使用GetClipboardFormatName函数可以获得:

int WINAPI GetClipboardFormatName(

  __in   UINT format, //要检索的格式ID

  __out  LPTSTR lpszFormatName, //存储返回的格式名的缓冲区

  __in   int cchMaxCount //拷贝到缓冲区的最大数据长度

);

win32剪贴板操作 参考 https://blog.youkuaiyun.com/gjtboa/article/details/50562614 因为最近有使用QQ截图的内容的需求,所以看了下剪贴板的操作,参考了很多文章,基本都是MFC版本的,所以写个win32版本的,供自己以后使用 这次画图和DC相关的内容也被整的够呛,优快云编辑页面提交错误,写完整片文章内容全部丢失一次,所以这一次可能质量没有第一次的高 将数据放入... 阅读详情

相关推荐

浅析Windows编程的剪贴板机制

 本文对Windows剪贴板机制作了深入、全面的阐述,具体内容包括:文本、位图、DSP、自定义格式剪贴板的使用和多数据项和延迟提交技术。Windows剪贴板是一种比较简单同时也是开销比较小的IPC(InterProcess Communication,进程间通讯)机制。Windows系统支持剪贴板IPC的基本机制是由系统预留的一块全局共享内存,用来暂存在各进程间进行交换的数据:提供数据的进

592

使用API SetClipboardViewer来监视剪贴板

public partial class Form1 : Form  {         private const int WM_DRAWCLIPBOARD = 776;         [DllImport("user32.dll")]         public static extern int SetClipboardViewer(int windowHandle);

Huron Studio 4899

屏幕截图小软件的编写——WINDOWS API

近期在学习windows api编程,完全模仿的学习了,熟悉windows api和纯windows api编程 屏幕截图步骤: 1.如何捕获屏幕 2.捕获屏幕后怎么做到选定区域 3.选定区域后将图片写入剪贴板 具体还有很多细节需要考虑,如选定区域需要用不同颜色的画笔,如何知道区域被选择了...... 主要代码如下,核心都在窗口回调函数中,不详细解释,几个重要的API函数在后面说明

ProgrammingLearner的博客 5413

探索CopyQ:高级剪贴板管理器的强大功能

探索CopyQ:高级剪贴板管理器的强大功能 在日常的数字生活中,剪贴板是我们不可或缺的工具之一。然而,传统的剪贴板功能往往有限,无法满足我们日益增长的需求。今天,我要向大家推荐一款强大的开源项目——CopyQ,它不仅是一个剪贴板管理器,更是一个功能丰富的编辑和脚本工具。 项目介绍 CopyQ是一款高级剪贴板管理器,支持Linux、Windows和macOS系统。它能够监控系统剪贴板并将其内容保存在...

gitblog_00459的博客 804

智能车‘大脑’的诞生:揭秘电磁循迹代码背后的控制论与系统思维

本文深入探讨智能车电磁循迹系统的核心架构与控制原理,揭示了其作为精密闭环系统如何通过模块化设计、信号处理、PID控制算法及电机驱动实现自主导航。重点分析了电磁信号采集与处理流程框架,为开发者提供从理论到实践的全面指南。

arduino9maker的博客 531

国密证书实战:在CentOS 7上构建GmSSL私有CA与完整证书链

本文详细介绍了在CentOS 7操作系统上,使用GmSSL工具构建私有国密证书颁发机构(CA)与完整证书链的实战指南。内容涵盖从部署GmSSL、创建国密根CA、签发服务器与客户端证书,到生产环境安全加固与最佳实践的全流程,旨在帮助系统管理员和安全工程师建立统一、可控的内部国密安全通信体系。

jenkins8butler的博客 495

【转】剪贴板的操作

拷贝与粘贴文本   下边的源代码演示了如何将文本(包含在CString对象“source”中)拷贝到剪贴板上。  CString source;  //put your text in source if(OpenClipboard()) {          HGLOBAL clipbuffer;          char * buffer;          EmptyClipboard()

1362

LEAP模型—低排放分析平台

LEAP 正在迅速成为进行综合资源规划、温室气体 (GHG) 缓解评估和低排放发展战略 (LEDS) 的国家的事实标准,尤其是在发展中国家,许多国家也选择使用 LEAP 作为其承诺的一部分向联合国气候变化框架公约(UNFCCC)报告。至少有 32 个国家使用 LEAP 来创建能源和排放情景,这些情景是其国家自主气候变化贡献计划 (INDC) 的基础:具有历史意义的巴黎气候协议的基础旨在表明各国开始经济脱碳的意图和投资于气候适应力。

weixin_54697010的博客 3280

EcoPaste:开源剪贴板管理工具,提升多平台工作效率

EcoPaste 是一款适用于 Windows、macOS 和 Linux(x11) 的开源剪贴板管理工具。它基于 Tauri v2 开发,具备轻量级、跨平台特性,让用户在不同操作系统间切换时,能够无缝地管理和同步剪贴板内容。EcoPaste 旨在通过简洁直观的用户界面和丰富的功能,帮助用户提升日常工作效率。 ## 项目技术分析 EcoPaste 的技术架构基于 Tauri 框架,这是一种轻量...

gitblog_00987的博客 915

学习笔记7--激光雷达标定

本系列博客包括6个专栏,分别为:《自动驾驶技术概览》、《自动驾驶汽车平台技术基础》、《自动驾驶汽车定位技术》、《自动驾驶汽车环境感知》、《自动驾驶汽车决策与控制》、《自动驾驶系统设计及应用》,笔者不是自动驾驶领域的专家,只是一个在探索自动驾驶路上的小白,此系列丛书尚未阅读完,也是边阅读边总结边思考,欢迎各位小伙伴,各位大牛们在评论区给出建议,帮笔者这个小白挑出错误,谢谢! 此专栏是关于《自动驾驶汽车环境感知》书籍的笔记。 2.激光雷达标定 2.1 概述 激光雷达内参标定:内部激光发射器坐标系与雷达本

FUXI_Willard 8025

期货缠论实战:文华财经笔中枢指标公式解析与博易大师应用指南

本文深入解析期货缠论实战中的文华财经笔中枢指标公式及其在博易大师平台的应用技巧。详细介绍了笔中枢指标的核心逻辑、公式拆解、参数设置及多周期联合作战策略,帮助交易者提升市场分析能力与交易胜率。特别适合期货交易者学习缠论指标的实际应用。

weixin_42522552的博客 356

C++ Windows 编程(七)

本章描述了以下内容的实现:注册表:一个 Windows 数据库,用于存储应用程序执行之间的信息。剪贴板:一个 Windows 数据库,用于存储已剪切、复制和粘贴的信息。标准对话框:用于保存和打开文档、颜色和字体以及打印。打印预览:在类中,可以像打印一样在屏幕上查看文档。类中的静态写入、读取和擦除方法在、、和类型的值以及 Windows 注册表中的内存块上操作。Registry.h: Registry.cpp: 全局常量持有 Small Windows 注册表域的路径: 、和函数简单地将值转换为字符串并调用:

龙哥盟 382

芯片良率提升:从设计到制造的系统性工程实践

在半导体制造领域,良率是衡量生产效率和成本控制的核心指标,直接关系到芯片的经济效益与市场竞争力。其本质是合格芯片占总产出芯片的百分比,提升良率需要从设计源头到制造末端的全流程协同优化。从技术原理看,它涉及可制造性设计、工艺过程控制、缺陷检测与根因分析等多个复杂环节,尤其在先进制程下,随机缺陷和参数变异成为主要挑战。其技术价值不仅在于降低单颗芯片成本,更能加速产品上市、保障可靠性,并成为企业技术实力的关键体现。应用场景贯穿智能手机、数据中心、自动驾驶和人工智能等所有高端芯片领域。本文将结合【芯片制造】与【良率

weixin_42526068的博客 632

C++ Windows 编程(二)

本章介绍了绘图程序的图形类。每个图形负责决定它是否被鼠标点击击中,或者它是否被矩形包围。它还负责移动或修改,以及绘制以及与文件流和剪贴板进行通信。绘图图形层次结构由、、、和类组成,如下图所示:https://github.com/OpenDocCN/freelearn-c-cpp-zh/raw/master/docs/cpp-win-prog/img/image_05_001.jpg类是层次结构的根类,主要由虚拟方法和纯虚拟方法组成,旨在由子类重写。虚拟方法和纯虚拟方法之间的区别是,虚拟方法有一个主体,并且

龙哥盟 444

枚举 ACS 电机状态位 完全解析

本文解析了ACS运动控制器SDK中的MotorStates枚举,该枚举对应控制器状态标志位?MFLAGS。主要介绍了6个核心状态:ACSC_ALL(-1)表示所有轴,ACSC_NONE(0)为空闲状态,ACSC_MST_ENABLE(1)为轴使能,ACSC_MST_INPOS(16)表示到位,ACSC_MST_MOVE(32)为运动中,ACSC_MST_ACC(64)为加速中。文章还补充了完整的枚举定义,包含报警、回零等状态,并提供了在晶圆AOI4轴运动中的典型应用场景,如判断轴状态、运动条件等。最后强调只

StevenChen的博客 245

爬虫面试:关于爬虫破解验证码的13个经典面试题

​解释:验证码是一种用于区分人类用户和自动化程序(如爬虫)的技术,通常通过显示图形、文字或音频等方式,要求用户完成特定任务(如识别扭曲的字母、点击特定区域等)。​作用:防止恶意爬虫滥用网站资源、进行批量注册、登录破解等行为,保护网站的安全性和数据的完整性。

数据知道的博客 1万+

Clibor:开源轻量剪贴板增强工具,重塑文本复制粘贴工作流

剪贴板是操作系统提供的基础数据交换机制,其核心原理是在内存中开辟临时存储区域,实现应用间数据传递。然而,原生剪贴板仅支持单条记录,导致工作流频繁中断与信息丢失,成为效率瓶颈。剪贴板增强技术通过历史记录、格式转换与快速检索等功能,解决了这一痛点,在编程开发、资料整理与日常办公等场景中价值显著。Clibor作为一款聚焦文本处理的剪贴板增强工具,以开源、轻量为设计哲学,通过全局快捷键驱动与纯文本粘贴等核心功能,实现了流畅的“无感”交互体验。其历史记录与收藏夹机制,有效支持了代码调试与文本片段管理等高阶需求,是提升

weixin_34161083的博客 626

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

常用的user32说明

函数名称 说明 ActiveKeyboardLayout 激活一个不同的键盘布局,该布局必须先由LoadKeyBoardLayout函数装载AdjustWindowRect 根据希望的用户矩形大小来计算所需矩形窗口的大小,然后将该窗口矩形给CreateWindow函数,以创建所需的窗口AdjustWindowRectEx 根据希望的客户矩形大小来计算具有扩展式样的窗口所需的矩形窗口大小,然后将该...

weixin_30852451的博客 580

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

3分钟搞定跨平台剪贴板管理:EcoPaste终极使用指南

还在为频繁切换窗口复制粘贴而烦恼吗?EcoPaste作为一款开源免费的跨平台剪贴板管理工具,能帮你彻底告别重复劳动,提升工作效率!无论你是Windows、macOS还是Linux用户,这款智能剪贴板增强工具都能让你的复制粘贴体验焕然一新。本文将为你提供完整的EcoPaste使用指南,从快速安装到高级技巧,一步步教你如何最大化利用这个生产力神器。 ## 🚀 快速上手:3步完成安装配置 ###

gitblog_00166的博客 954

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 《Windows核心编程》---邮槽通信
下一篇: 《Windows核心编程》---数据复制消息WM_COPYDATA
ACE1985
博客等级 码龄17年 1307粉丝 308原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值