Edit
Attach
Printable
topic end
<!-- * Set TOPICTITLE = #define private public - Pasting my own dogfood, part 3 (14 Apr 2006) --> <style type="text/css"> pre {background-color:#ffeecc;} </style> %STARTINCLUDE% <a name="14"></a> ---+++ [[BlogOnSoftware20060414][Pasting my own dogfood, part 3]] (14 Apr 2006) [[BlogOnSoftware20060409][Last time around]], I discussed a slightly kludgy approach for automatic testing of clipboard code, which was based on =clipbrd.exe= and some <nop>VBscript code. That wasn't bad, but I wasn't really satisfied. After all, the original goal was to write rock-solid unit tests for clipboard code. I wanted a more reliable tool to copy data from and to the clipboard in arbitrary formats. I needed more control. And, most important of all, I was in the mood for reinventing wheels (really fancy ones, of course). The key Win32 APIs for clipboard handling are [[http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardreference/clipboardfunctions/setclipboarddata.asp][SetClipboardData]] and [[http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardreference/clipboardfunctions/getclipboarddata.asp][GetClipboardData]]. Their signatures are as follows: <pre> HANDLE SetClipboardData(UINT uFormat, HANDLE hMem); HANDLE GetClipboardData(UINT uFormat); </pre> So when you post to the clipboard, all you need to specify is a format and a memory handle, as it seems! This looks so trivial that I had my strategy laid out almost immediately: I would allocate a global memory block using [[http://msdn.microsoft.com/library/en-us/memory/base/globalalloc.asp][GlobalAlloc]]. Then I would read some clipboard data from a file into that block, and finally call =SetClipboardData= - like in the following code: <pre> HANDLE ReadFileToMemory(const TCHAR *filename) { FILE *f; errno_t error = _tfopen_s(&f, filename, _T("rb")); if (error) { _ftprintf(stderr, _T("ERROR: Cannot open %s\n"), filename); return 0; } // get size of file fseek(f, 0, SEEK_END); long size=ftell(f); fseek(f, 0, SEEK_SET); // allocate memory HANDLE hMem = ::GlobalAlloc(GMEM_MOVEABLE, size); if (!hMem) { fclose(f); return 0; } LPVOID mem = ::GlobalLock(hMem); if (!mem) { fclose(f); ::GlobalFree(hMem); return 0; } // read the file into memory size_t bytes_read = fread(mem, 1, size, f); fclose(f); ::GlobalUnlock(mem); if (bytes_read != size) { ::GlobalFree(hMem); return 0; } return hMem; } bool FileToClipboard(TCHAR *filename, UINT clipid, HWND ownerWindow) { if (::OpenClipboard(ownerWindow)) { HANDLE hClip = ReadFileToMemory(filename); ::EmptyClipboard(); HANDLE h = ::SetClipboardData(clipid, hClip); ::CloseClipboard(); ::DestroyWindow(owner); return true; } return false; } </pre> And the reverse code to get data from the clipboard and save it to a file would be just as simple: <pre> FILE *f = fopen(filename, "wb"); if (f) { HANDLE hClip = GetClipboardData(clipID); // clipID culled from looping over // available formats using <a href="http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardreference/clipboardfunctions/enumclipboardformats.asp">EnumClipboardFormats</a> void *pData = (void*)GlobalLock(hClip); if (pData) { SIZE_T sz = ::GlobalSize(pData); if (sz) { size_t written = fwrite(pData, 1, sz, f); ret = (written == sz); } } ::GlobalUnlock(hClip); fclose(f); } </pre> Piece of cake! Mission accomplished! I slapped the usual boilerplate code for a console app onto the above, and ran my first successful tests: I could read text from the clipboard, and post text to it just fine. However, several formats stubbornly refused to cooperate. In particular, the really useful stuff, like metafiles. Or bitmaps. What was going on? When calling =GetClipboardData= for these formats, the code that interprets the returned handle as a global memory handle flatly falls on its face. It turns out that I had jumped to conclusions way too early when I read the first few lines of the =SetClipboardData= documentation - some of those clipboard handles are actually anything _but_ memory handles! Examples for such formats: * =CF_ENHMETAFILE=, =CF_DSPENHMETAFILE= * =CF_METAFILEPICT=, =CF_DSPMETAFILEPICT= * =CF_BITMAP=, =CF_DSPBITMAP= * =CF_PALETTE= And then, of course, there are whole classes of clipboard formats which I had not even explored yet, such as application-defined formats. Next time: How I learnt to peacefully coexist with all the various classes of clipboard formats. --- %STOPINCLUDE% %COMMENT{type="below" nonotify="on"}% ---
to top
End of topic
Skip to action links
|
Back to top
Edit
|
Attach image or document
|
Printable version
|
Raw text
|
Refresh
|
More topic actions
Revisions: | r1.5 |
>
|
r1.4
|
>
|
r1.3
|
Total page history
|
Backlinks
You are here:
Blog
>
BlogOnSoftware20060414
r1.5 - 16 Apr 2006 - 12:31 -
ClausBrod
to top
Blog
This site
2017
:
12
-
11
-
10
2016
:
10
-
7
-
3
2015
:
11
-
10
-
9
-
4
-
1
2014
:
5
2013
:
9
-
8
-
7
-
6
-
5
2012
:
2
-
10
2011
:
1
-
8
-
9
-
10
-
12
2010
:
11
-
10
-
9
-
4
2009
:
11
-
9
-
8
-
7
-
6
-
5
-
4
-
3
2008
:
5
-
4
-
3
-
1
2007:
12
-
8
-
7
-
6
-
5
-
4
-
3
-
1
2006:
4
-
3
-
2
-
1
2005:
12
-
6
-
5
-
4
2004:
12
-
11
-
10
C++
CoCreate Modeling
COM & .NET
Java
Mac
Lisp
OpenSource
Scripting
Windows
Stuff
Changes
Index
Search
Maintenance
Impressum
Datenschutzerklärung
Home
Webs
Atari
Blog
Claus
CoCreateModeling
Klassentreffen
Main
Sandbox
Sommelier
TWiki
Xplm
Jump:
Copyright © 1999-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki?
Send feedback