084 - 问,程序与资源管理器交互及delayed rendering

084 - 问,程序与资源管理器交互及delayed rendering

参考资料

Transferring Shell Objects with Drag-and-Drop and the Clipboard

Using the CFSTR_FILECONTENTS Format to Extract Data from a File

Transfering Data to and from Virtual Folders 

Accepting Data from a Virtual Folder 

clipboard delayed rendering

http://www.codeproject.com/Articles/6842/SmartClip-A-Clipboard-enhancement-utility#SmartCliparchitecture10

Advanced clipboard capabilities - Delayed rendering

When placing a clipboard format on the clipboard, an application can delay rendering the data in that format until the data is needed. To do so, an application can specify NULL for the hData parameter of the SetClipboardDatafunction. This is useful if the application supports several clipboard formats, some or all of which are time-consuming to render. By passing a NULL handle, a window renders complex clipboard formats only when and if they are needed.

If a window delays rendering a clipboard format, it must be prepared to render the format upon request for as long as it is the clipboard owner. The system sends the clipboard owner a WM_RENDERFORMAT message when a request is received for a specific format that has not been rendered. Upon receiving this message, the window should call theSetClipboardData function to place a global memory handle on the clipboard in the requested format. If the clipboard owner is destroyed and has delayed rendering some or all clipboard formats, it receives theWM_RENDERALLFORMATS message. Upon receiving this message, the window should place valid memory handles on the clipboard for all clipboard formats that it provides. This ensures that these formats remain available after the clipboard owner is destroyed. Microsoft Office applications use 'delayed rendering' to avoid memory wastage while putting so many formats into clipboard. If you try copying a lot of stuff from within MSWord just before closing it, you will receive the following message.

http://hcmfys.iteye.com/blog/1233400

  在数据提供进程创建了剪贴板数据后,一直到有其他进程获取剪贴板数据前,这些数据都要占据内存空间。如在剪贴板放置的数据量过大,就会浪费内存空间,降低对资源的利用率。为避免这种浪费,可以采取延迟提交(Delayed rendering)技术,即由数据提供进程先创建一个指定数据格式的空(NULL)剪贴板数据块,直到有其他进程需要数据或自身进程要终止运行时才真正提交数据。

  延迟提交的实现并不复杂,只需剪贴板拥有者进程在调用SetClipboardData()将数据句柄参数设置为NULL 即可。延迟提交的拥有者进程需要做的主要工作是对WM_RENDERFORMAT、WM_DESTORYCLIPBOARD和 WM_RENDERALLFORMATS等剪贴板延迟提交消息的处理。

  当另一个进程调用GetClipboardData()函数时,系统将会向延迟提交数据的剪贴板拥有者进程发送WM_RENDERFORMAT消息。剪贴板拥有者进程在此消息的响应函数中应使用相应的格式和实际的数据句柄来调用SetClipboardData()函数,但不必再调用OpenClipboard()和EmptyClipboard()去打开和清空剪贴板了。在设置完数据有也无须调用CloseClipboard()关闭剪贴板。如果其他进程打开了剪贴板并且调用EmptyClipboard()函数去清空剪贴板的内容,接管剪贴板的拥有权时,系统将向延迟提交的剪贴板拥有者进程发送WM_DESTROYCLIPBOARD消息,以通知该进程对剪贴板拥有权的丧失。而失去剪贴板拥有权的进程在收到该消息后则不会再向剪贴板提交数据。另外,在延迟提交进程在提交完所有要提交的数据后也会收到此消息。如果延迟提交剪贴板拥有者进程将要终止,系统将会为其发送一条WM_RENDERALLFORMATS消息,通知其打开并清除剪贴板内容。在调用 SetClipboardData()设置各数据句柄后关闭剪贴板。

  下面这段代码将完成对数据的延迟提交,WM_RENDERFORMAT消息响应函数OnRenderFormat()并不会立即执行,当有进程调用GetClipboardData()函数从剪贴板读取数据时才会发出该消息。在消息处理函数中完成对数据的提交:

  进行延迟提交:

HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄

::OpenClipboard(hWnd); // 打开剪贴板

::EmptyClipboard(); // 清空剪贴板

::SetClipboardData(CF_TEXT, NULL); // 进行剪贴板数据的延迟提交

::CloseClipboard(); // 关闭剪贴板

  在WM_RENDERFORMAT消息的响应函数中:

DWORD dwLength = 100; // 要复制的字串长度

HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLength + 1); // 分配内存块

LPBYTE lpGlobalMemory = (LPBYTE)GlobalLock(hGlobalMemory); // 锁定内存块

for (int i = 0; i 〈 dwLength; i++) // 将"*"复制到全局内存块

*lpGlobalMemory++ = '*';

GlobalUnlock(hGlobalMemory); // 锁定内存块解锁

::SetClipboardData(CF_TEXT, hGlobalMemory); // 将内存中的数据放置到剪贴板

DSP和自定义数据格式的使用

Windows系统预定义了三个带“DSP”前缀的数据格式:CF_DSPTEXT、CF_DSPBITMAP和 CF_DSPMETAFILEPICT。这是一些伪标准格式,用于表示在程序中定义的私有剪贴板数据格式。对于不同的程序,这些格式的规定是不同的,因此这些格式只针对某一具体程序的不同实例才有意义。

  为使用DSP数据格式,必须确保进程本身与剪贴板拥有者进程同属一个程序。可以调用GetClipboardOwner()函数来获取剪贴板拥有者窗口句柄,并调用GetClassName()来获取窗口类名:

HWND hClipOwner = GetClipboardOwner();

GetClassName(hClipOwner, &ClassName, 255);

  如果剪贴板拥有者窗口类名同本进程的窗口类名一致,就可以使用带有DSP前缀的剪贴板数据格式了。

除了使用Windows预定义的剪贴板数据格式外,也可以在程序中使用自定义的数据格式。对于自定义的数据格式lpszFormat,可以调用RegisterClipboardFormat()函数来登记,并获取其返回的格式标识值:

UINT format = RegisterClipboardFormat(lpszFormat);

对此返回的格式标识值的使用与系统预定义的格式标识是一样的。可以通过GetClipboardFormatName()函数来获取自定义格式的ASCII名。

http://blog.csdn.net/lanruochen/article/details/5944186

你可能感兴趣的:(084 - 问,程序与资源管理器交互及delayed rendering)