|
well, it IS part of the ATL namespace... :p
|
|
|
|
|
MFC CString is typedefed as typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
Come online at:-
jubinc@skype
|
|
|
|
|
Starting with VC7, some utility classes were changed to be shared between ATL and MFC to reduce code duplication.
|
|
|
|
|
Suppose I have a HWND from enumerating the top level windows, how can I replace the Device Context of the drawing process of this window, so that I can get a snapshot of this window?
|
|
|
|
|
Do you want to draw on the window of other programs?
|
|
|
|
|
No, I want to get a snapshot of another application, for example, to make a album of all the running applications
|
|
|
|
|
I tried to use CWnd::GetDC(), and select a CBitmap created by my own, then call CWnd::RedrawWindow(), after that, I suppose the content in CBitmap should be the window, but it failed.
|
|
|
|
|
This isn't tested, or even compiled, just quickly typed up...
CClientDC dcOther (GetDesktopWindow ());
CRect rc;
::GetWindowRect (hWndToClone, &rc);
CBitmap bmpTemp, *bmpOld;
CDC dcClone;
dcClone.CreateCompatibleDC (&dcOther);
bmpTemp.CreateCompatibleBmp (&dcOther, rc.Width (), rc.Height ());
bmpOld = dcClone.SelectObject (&bmpTemp);
dcClone.BitBlt (0,0, rc.Width (), rc.Height (), &dcOther, 0,0, SRCCPY);
dcClone.SelectObject (bmpOld);
and now dcClone should hold a copy of the contents of the first window - or at least what it shows on the screen.
You should look at the very useful article by PJ Arends: Image Viewer[^].
Good luck,
Iain.
|
|
|
|
|
Really thanks, I tried this, the rect is right, but the contents is from the corresponding top level windows, do i need to bring the window to top, and then use this method, but if so, the orders of the windows will be totally ruined.
<br />
CDC dc;<br />
CDC* pDC = pWnd->GetDC();<br />
CRect rc;<br />
pWnd->GetWindowRect(rc);<br />
dc.CreateCompatibleDC(pDC);<br />
CBitmap bmp;<br />
bmp.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());<br />
HBITMAP bmpOld;<br />
bmpOld = (HBITMAP)dc.SelectObject(bmp);<br />
dc.BitBlt(0, 0, rc.Width(), rc.Height(), pDC, 0, 0, SRCCOPY);<br />
CxImage imgSnapshot;<br />
imgSnapshot.CreateFromHBITMAP(bmp);<br />
|
|
|
|
|
Yes, this is a screen capture.
Unfortunately, unless the window is visible, window's won;t actually bother sending a WM_PAINT to it, so it won't bother to redraw (this may not be the truth under Vista).
Which is what the WM_PRINT message is for. But as you said, it does require the "victim" app to play nicely. You could try replacing the GetDesktopWindow call in my code with hWndFromOtherApp, and use GetClientRect (hWndFromOtherApp), but I'm not sure how nicely it will work.
Its worth a try though, as it won't take much effort to test!
Good luck,
Iain.
|
|
|
|
|
I tried, the WM_PRINT approach generally fails because I cannot suppose other application to implement it. And using BringWindowToTop, it still have some problems:
(1) When a window is maximized, the rect from GetWindowRect is the one when not maximized.
(2) When something was set to be always on top, it will appear on the resulted images.
I wonder whether subclassing of a window can do it correctly.
|
|
|
|
|
Im not sure its your answer or no but if its not your answer reply to me
HDC m_hdcMem,hdc;
HBITMAP m_Bitmap,m_OldBitmap,hMainBmp ;
hdc=GetDesktopWindow()->GetDC()->m_hDC;
m_hdcMem= CreateCompatibleDC(hdc);
m_Bitmap = CreateCompatibleBitmap(hdc,800,600);
m_OldBitmap=(HBITMAP) SelectObject(m_hdcMem, m_Bitmap);
BitBlt(m_hdcMem, 0,0,800,600, hdc,0,0,SRCCOPY);
hMainBmp =(HBITMAP) SelectObject(m_hdcMem, m_OldBitmap);
CImage m_Image;
m_Image.Attach(hMainBmp);
m_Image.Save("c:\\test.bmp");
m_Image.Detach();
DeleteDC(m_hdcMem);
DeleteObject(hMainBmp );
DeleteObject(m_OldBitmap);
|
|
|
|
|
I want a snapshot for a specific application, which I only has its HWND, and I don't want the always-on-top things to appear in the resulted image, besides, the orginal orders of the windows should not be changed, this is pretty like the window mode of SnagIt, thanks
|
|
|
|
|
Well you can use of hwnd on the GetDC that retrieves a handle to dc of current window did you try with it HDC hdc=::GetDC(hWnd);.
|
|
|
|
|
hDC = ::GetDC (hWnd);
::ReleaseDC (hWnd, hDC);
Sometimes its simpler that you think!
You should also have a peek at WM_PRINT, as it asks the other window to draw itself nicely in a DC you provide.
Iain.
|
|
|
|
|
Thanks, i tried the WM_PRINT way, code like this:
<br />
CDC dc;<br />
dc.CreateCompatibleDC(NULL);<br />
CBitmap bmp;<br />
CRect rc;<br />
pWnd->GetClientRect(rc);<br />
bmp.CreateBitmap(rc.Width(), rc.Height(), 1, 24, NULL);<br />
HBITMAP hbmp = (HBITMAP)dc.SelectObject(bmp.GetSafeHandle());<br />
pWnd->SendMessage(WM_PRINT, WPARAM(dc.GetSafeHdc()), PRF_CHILDREN);<br />
CxImage imgSnapshot;<br />
imgSnapshot.CreateFromHBITMAP(bmp);<br />
But the resulted image seems invalid, does that require the target window to write code for processing WM_PRINT message, otherwise it doesn't work?
|
|
|
|
|
Shouldn't you use the window rect instead of the client rect?
What's wrong with the resulting bitmap?
Did you un-select the bitmap from the DC?
This works for me:
CWindowDC WindowDC(this);
CDC MemoryDC;
MemoryDC.CreateCompatibleDC(&WindowDC);
CBitmap WindowBitmap;
CRect WindowRect;
GetWindowRect(&WindowRect);
WindowBitmap.CreateCompatibleBitmap(&WindowDC, WindowRect.Width(), WindowRect.Height());
CBitmap *pOldBitmap = MemoryDC.SelectObject(&WindowBitmap);
SendMessage(WM_PRINT, (WPARAM)(HDC)MemoryDC, PRF_ERASEBKGND | PRF_CHILDREN | PRF_CLIENT | PRF_NONCLIENT);
BitBlt(WindowDC,100,100,WindowRect.Width(), WindowRect.Height(), MemoryDC, 0, 0, SRCCOPY);
MemoryDC.SelectObject(pOldBitmap);
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Thanks, this does not work for all the applications, I guess it uses SendMessage(WM_PRINT) internally.
|
|
|
|
|
Problem solved, thanks for all your help
|
|
|
|
|
Hello,
I have old VC6 compiled at VS2005.
I would like to keep 'Enable C++ Exceptions' = Yes (/EHsc) option at the project properties.
One of the functions: __event - is not compiled.
Do you know if I can use another function? Should I do any changes?
Thanks!
|
|
|
|
|
Are you not using the statement try-catch ?
like:
try{
...
}catch(CMemoryException +pErr){
...
}
Russell
|
|
|
|
|
Hi all,
I have made a for loop which has to execute 200 times. In that loop i have a started a worker thread. Now what i want is after 10 times that loop should wait for 1 of the thread to finish and then start next thread i.e only 10 thread can execute at a time.How to do it??
Thanks in advance
|
|
|
|
|
I;d question your design decision as desiribed, but I'll assume your simplifying your actual problem.
Thread handles also act as signalling handles.
So:
....
HANDLE hThread [MAX] = { NULL, NULL, ... NULL };
DWORD dwID [MAX];
for (nTest = 0; nTest < 10; nTest++)
{
hThread [nTest] = CreateThread (......., &(dwID [nTest], lParam);
if (!hThread [nTest])
{
Handle error somehow
}
}
for (nTest = 10; nTest < XXXXX; nTest++)
{
dwWait = WaitForMultipleObjects (hThread, 10, INFINITE);
if (dwWait >= WAIT_OBJECT_0 && dwWait < WAIT_OBJECT_0+10)
{
nThread = dwWait - WAIT_OBJECT_0;
hThread [dwThread] = CreateThread (......., &(dwID [nThread], lParam);
if (!hThread [nTest])
{
Handle error somehow
}
}
}
/pre>
Tada!
Iain.
<div class="CPhogPost"></div>
<div class="ForumSig"></div>
|
|
|
|
|
I would also point out that I have answered your question very literally. My answer would block your initial thread, is very fragile, etc.
Much better would be to look into thread pools (which I have no experience of), of have your thread posting a "I'm done!" message to a UI main thread, which would then fire off another thread. You could then give the user a more interactive experience, without thinking the process has hung. It would also allow you to handle failure more gracefully.
Iain.
|
|
|
|
|