|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThere are many sharewares that capture screen and copy image to clipboard or save as a file. Some of them charge more than $15 and can't capture dropdown menu/list. The problem is when user "active CaptureScreen" program, all other windows become inactive and close their file menu or dropdown list. This simple program can capture any screen image including dropdown menu or combobox list. Basic ideaSince clicking on "PrintScreen" will send an entire window screen to the clipboard, we can read "entire window screen" from clipboard and then let users copy any portion of screen to clipboard. To implement this we need
[DLL] Hook keyboardTo hook system wide keyboard event, we need a DLL. The demo source code BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,to BOOL APIENTRY DllMain( HINSTANCE hInstance,DWORD ul_reason_for_call,And implement your InstallKBHook() and UnInstallKBHook() that simply use API: SetWindowsHookEx() and UnhookWindowsHookEx(), to hook/unhook keyboard event.hookKeyBoard = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardHook,hInst,0);
BOOL bUnHook = UnhookWindowsHookEx(hookKeyBoard);You may want to pay a little attention to the declaration of __declspec(dllexport) BOOL InstallKBHook(HWND hWnd); __declspec(dllexport) BOOL UnInstallKBHook(HWND hWnd);Because we will export those methods to the application, we declare them as __declspec(dllexport); and, on the other hand, application need to import them (See HScr2ClpDlg.cpp)__declspec(dllimport) BOOL InstallKBHook(HWND hWnd); __declspec(dllimport) BOOL UnInstallKBHook(HWND hWnd); If you like to know more about API Hook, please refer Joseph[2], Ivo[3], and Kyle[4] for more detail. [DLL] Post message to applicationSo far, we can UWM_ClickPrnScrn = ::RegisterWindowMessage(Once we have our Window Message, we can Post Message to notify our application that user clicks "PrintScreen" if( (nCode >=0) && (nCode == HC_ACTION) && (wParam == VK_SNAPSHOT)) ::PostMessage(hWndReceiver,UWM_ClickPrnScrn,0,0);It's pretty simple to hook system wide keyboard. Isn't it? Please refer Joseph[1] for more, wide and deep, detail [Apps] Read image from clipboardWhen 1. in header file, afx_msg BOOL OnClickPrintScreen(WPARAM wParam, LPARAM lParam); 2. in cpp file, HScr2ClpDlg.cpp, message map add this ON_REGISTERED_MESSAGE(UWM_ClickPrnScrn, OnClickPrintScreen)BEGIN_MESSAGE_MAP(CHScr2ClpDlg, CDialog) ON_REGISTERED_MESSAGE(UWM_ClickPrnScrn, OnClickPrintScreen) //{{AFX_MSG_MAP(CHScr2ClpDlg) ... //}}AFX_MSG_MAP END_MESSAGE_MAP()In the definition of OnClickPrintScreen(), we first verify using IsClipboardFormatAvailable(CF_BITMAP) that the clipboard contains BITMAP data and then open (using OpenClipboard()) clipboard. If so far is fine, attach a CBitmap to clipboard BITMAP HandleHBITMAP hBm;
CBitmap cBm;
hBm = (HBITMAP)GetClipboardData(CF_BITMAP);
...
if(!cBm.Attach(hBm))
...Since we have a CBitmap now, we can Copy it to our application's panel and let user "select" any image she/he needsCClientDC dcScreen(this); CDC dcMem; dcMem.CreateCompatibleDC(&dcScreen); CBitmap* pOldBitmap = dcMem.SelectObject(&cBm); dcScreen.BitBlt(0,0,bBm.bmWidth,bBm.bmHeight ,&dcMem,0,0,SRCCOPY); dcMem.SelectObject(pOldBitmap); [Apps] Copy image and paste to clipboardWe copy user's "selection" from client area and paste to clipboard BOOL CHScr2ClpDlg::CopyRect2Clipboard()
{
CRect rect(m_ptFirst,m_ptLast);
rect.NormalizeRect();
if(rect.IsRectEmpty() || rect.IsRectNull())
return FALSE;
//CDC *pDc = GetWindowDC();//include Non-Client area.
CClientDC dcScrn(this);
CDC memDc;
if(!memDc.CreateCompatibleDC(&dcScrn))
return FALSE;
CBitmap bitmap;
if( !bitmap.CreateCompatibleBitmap(&dcScrn,rect.Width(),
SummaryThis tiny program is very simple because it doesn't have any complicated coding. You can find many articles showing you how to Copy images to the clipboard, Hook keyboard, or, Capture mouse movement... from CodeProject.com or other web sites. However, there is one cool/neat "mailto button" on the demo program panel; it's, IMHO, the most difficult coding in this tiny utility. Please refer Chris Maunder's "Tray Calendar", Chris[5]. The idea of this program is "put people's idea together and have fun"; and, of course, I need to capture screen for my work. I may enhance it that provide a "Preview" panel which has "Copy", "Save as file", and "Discard" options for user when I have time. If anyone can post your enhancement, I would love to update the article, and thank you. Known bugIf you run program and leave it on screen, don't minimize it to taskbar, and click "PrintScreen", apps will set itself as MostTop Window as expected. But "minimize" and "close" buttons will not work until you set it to non-top Z-order. In other words, you need to click another window to make apps "inactive" and click apps itself to make it "active"; therefore, "minimize" and "close" buttons will work as usual. On the other hand, if you "minimize" apps to taskbar and "click "PrintScreen", everything just works fine. Reference[1]: "Message Management", Joseph M. Newcomer, 05/17/2000
|
||||||||||||||||||||||