|
I tried this:
void CMainDlg::CopyWndToClipboard(HWND pWnd )
{
CBitmap bitmap;
CClientDC dc(pWnd);
CDC memDC;
RECT rect;
memDC = ::CreateCompatibleDC(dc.m_hDC);
::GetWindowRect(pWnd,&rect);
bitmap.CreateCompatibleBitmap(dc.m_hDC, rect.right-rect.left,rect.top-rect.bottom );
CBitmap* pOldBitmap= (CBitmap*)(HBITMAP)::SelectObject(memDC,&bitmap);
::BitBlt(memDC,0, 0, rect.right-rect.left,rect.top-rect.bottom, dc.m_hDC, 0, 0, SRCCOPY);
::OpenClipboard(::GetParent(pWnd)) ;
EmptyClipboard() ;
SetClipboardData (CF_BITMAP, (HBITMAP)bitmap ) ;
CloseClipboard () ;
SelectObject(memDC,pOldBitmap);
bitmap.Detach();
}
But it doesn't work; all it does is throwing rubbish on the clipboard.
Any help is highly appreciated.
|
|
|
|
|
It definitely can be easily done as that method uses very little MFC and all of the MFC commands used in there directly map to standard windows API calls. Just look at their help and it wil tell you what the MFC does.
Maybe you should try not writing hybrid MFC/windows code in your example and rip out all of the MFC you still have in there. I.e. no CBitMap, ClientDC or CDC.
|
|
|
|
|
Hi. I have a problem that you may help me on:
I need to implement a hook that is triggered each time the screen is captured. More specifically, it must be activated BEFORE the screen capture is made.
Can you shed some light on this subject?
Thanks in advance!!!!!
|
|
|
|
|
I do not believe there is any such capability defined for Windows. You might consider trying to intercept the print-screen key with a keyboard hook, but that’s about the best I can suggest.
joe
|
|
|
|
|
Hello all
Once the screen is in a bitmap form, in the clipboard, how can I print it to my default printer?
Hope someone can help
Thanks
Alex
aevans@microknox.com.au
|
|
|
|
|
// Insert the following to capture the whole window
// as long as it fits on the screen
// display is of type CWnd* (or derived from)
CWnd * savedParent = display->GetParent();
CRect r;
display->GetWindowRect(&r);
WINDOWPLACEMENT wp;
display->GetWindowPlacement(&wp);
display->SetParent(NULL);
display->ModifyStyleEx(0, WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOMOVE);
// this might be a good place to force the with or height of the window bounds r
display->MoveWindow(10, 10, r.Width(), r.Height());
display->UpdateWindow();
/*
** PASTE THE CAPTURE CODE HERE
*/
// restore parent window
display->SetParent(savedParent);
// restore style without moving it
display->ModifyStyleEx( WS_EX_TOOLWINDOW | WS_EX_TOPMOST, 0,
SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOMOVE|WS_EX_TOOLWINDOW);
// restore window position
display->SetWindowPlacement(&wp);
-arne
|
|
|
|
|
|
Why this two lines of code in you code?
CString s;
wnd->GetWindowText(s);
|
|
|
|
|
It has been a long time since I wrote that, but I was probably capturing the caption for some reason.
|
|
|
|
|
when I use
wnd = CWnd::GetDesktopWindow();
there's an error caused by
wnd->GetParent()->OpenClipboard();
I have to modify this clause to be following:
wnd->OpenClipboard();
|
|
|
|
|
Hello Joseph,
Thanks very much for the sample code. I plan to use it in an article that I'm writing for CodeProject that incorporates your cool Window capturing code with my Window Finder utility.
However, Joseph, I found that the sample code contains some possible resoure leakage bug. The following is the code location where the bug is located (at the beginning of the toClipboard() function) :
CDC dc;
if(FullWnd)
{ /* full window */
HDC hdc = ::GetWindowDC(wnd->m_hWnd);
dc.Attach(hdc);
} /* full window */
else
{ /* client area only */
HDC hdc = ::GetDC(wnd->m_hWnd);
dc.Attach(hdc);
} /* client area only */
The problem is that when the CDC object "dc" is destroyed at the end of the function, DeleteDC() will be called instead of ReleaseDC() :
(snippet from the MFC source codes) :
CDC::~CDC()
{
if (m_hDC != NULL)
::DeleteDC(Detach());
}
The Win32 API documentation for DeleteDC() states the following :
"An application must not delete a device context whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the device context. "
Also, the documentation for GetWindowDC() states :
"After painting is complete, the ReleaseDC function must be called to release the device context."
A good solution is to use CWindowDC and CClientDC classes instead of CDC :
CDC *dc;
if(FullWnd)
{ /* full window */
dc = new CWindowDC(wnd);
//HDC hdc = ::GetWindowDC(wnd->m_hWnd);
//dc -> Attach(hdc);
} /* full window */
else
{ /* client area only */
dc = new CClientDC(wnd);
//HDC hdc = ::GetDC(wnd->m_hWnd);
//dc -> Attach(hdc);
} /* client area only */
And later, at the end of the function, to delete the dc :
delete dc;
I discovered the possible resource leak while debugging with NuMega Bounds Checker.
Best Regards,
Bio.
|
|
|
|
|
Well, I am still new to C.
I have all the code implemented but I dont' know how to format the call of toClipboard?
How do you get the wnd?
toClipboard(wnd,TRUE);
Thanks,
Doug
|
|
|
|
|
Hello Doug,
You need to use C++ in order to use toClipboard(). Here is an example code that uses the toClipboard() function :
BOOL CaptureWindowToClipboard (HWND hwndToCapture)
{
BOOL bRet = FALSE;
if((hwndToCapture) && (::IsWindow (hwndToCapture)))
{
bRet = TRUE;
toClipboard((CWnd *)CWnd::FromHandle (hwndToCapture), TRUE);
}
return bRet;
}
1. We use the CWnd::FromHandle() function to dynamically create a CWnd object.
2. CWnd::FromHandle() will create a CWnd object and return a pointer to us.
The CWnd pointer returned is temporary and will be deleted by the MFC framework automatically (see documentation of CWnd::DeleteTempMap() for details).
Best Regards,
Bio.
|
|
|
|
|
Well, what window do you want to capture? If you know what window you want to capture, you only need a reference to it. For example, if you want to capture the entire app, put your handler in the mainframe class and call it as
toClipboard(this, TRUE);
|
|
|
|
|
Indeed, this appears to be a bug. I should fix it. Thanks for the pointer, and I'll update this the next time I get some time.
|
|
|
|
|
Hello Joseph,
You're most welcome, Joseph. And thanks for the toClipboard() function code. It's very useful nevertheless.
Best Regards,
Bio.
|
|
|
|
|
This text comes straight out of MSVC++ 6.0 ...
An application can simulate a press of the PRINTSCREEN key in order to obtain a screen snapshot and save it to the clipboard. To do this, call keybd_event with the bVk parameter set to VK_SNAPSHOT, and the bScan parameter set to 0 for a snapshot of the full screen or set bScan to 1 for a snapshot of the active window
|
|
|
|
|
I am unable to capture mouse ptr.
|
|
|
|
|
That's right. This is how Windows works. Whenever a DC is created for a window, the mouse pointer is hidden.
I'll think about this...
|
|
|
|
|
That's right. This is how Windows works. Whenever a DC is created for a window, the mouse pointer is hidden.
Of course, there is no good way to capture the mouse cursor anyway, since the cursor you want is somewhere on the screen, and to execute my code, you have to have moved it to someplace else on the screen (a menu item or button item), so there isn't even a meaningful cursor handle or mouse location at the time you activate my code.
One possibility is to use a delay. That is, when executing the code to capture the window, set up a timer event, and when it fires, do the capture then. This gives you time to reposition the mouse and have the cursor be reselected.
|
|
|
|
|
a way is to getcursorpos() and bitblt a mouse pointer icon over the DC.
|
|
|
|
|
How to capture mediaplayer window?
|
|
|
|
|
I want to know how to do that
|
|
|
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case ID_TEST:
ShowOpenedWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam )
{
char str[64];
char fullstr[128];
if (IsWindowVisible(hwnd))
{
GetWindowText(hwnd,str,64);
wsprintf(fullstr,"Windiw [Handle] : %d [Caption] : %s",hwnd,str);
iYPos += 20;
TextOut(GetDC(HWND(lParam)),10,iYPos,fullstr,strlen(fullstr));
}
return TRUE;
}
void ShowOpenedWindow(HWND hWnd)
{
iYPos = 10; //Global Variable
HWND lnDesktop;
lnDesktop = GetDesktopWindow();
EnumWindows(EnumWindowsProc, (long)hWnd);
}
|
|
|
|
|