|
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.
|
|
|
|
|
You can use a variable to count the threads
Global declaration:
<code>volatile </code>UINT RunningThread;
The main function:
foo(){
RunningThread=0;
for(i=0;i<200;i++){
if(RunningThread<10){
RunningThread++;
}else{
wait(100);
i--;
continue;
}
}
}
The thread:
Thread(...){
RunningThread--;
}
Russell
|
|
|
|
|
i tried Russell's procedure but its hanging my application and not solving my problem completely....in my thread i m finding out a particular website's html code so, because of so many threads trying to do it, many times it gives page cannot be displayed....how to solve it
|
|
|
|
|
Probally you have to use a semaphore to use the connection in a more efficient way, limiting the simultaneus request to the web.
You can use for example a boolean variable (like BOOL ConnectionIsBusy ). If a thread find it TRUE then it waits that it becomes FALSE , then it lock itself the flag to TRUE , talk with the web, and at the end restore the flag value to FALSE .
A similar way is to limit the number of simultaneus connections using a variable like UINT ConnectionsNumber , that you could use to check that the connection opened are less of a particular value (i.e. 2 or 4).
But the problem depends also on the speed of your connection and/or the amount of traffic that you need to exchange with the web. You have to do some tests.
Russell
|
|
|
|
|
Another way to implement Russell's suggestion is to use an I/O Completion Port[^]
This essentially combines a thread pool with a semaphore. With an I/O Completion Port you could
easily create a pool of 10 threads and queue up 200 operations to be executed by the threads as
they become available.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hello
I am VS 2005 for the first time. I have selected a Dialog based application which uses MFC and I want to add a WM_INITDIALOG message handler. We use "Ctrl + W" for VC 6 to invoke class wizard and add a message handler for WM_INITDIALOG.
But in VS 2005, I selected properties of the dialog and looked under the "Messages" tab and dint find the WM_INITDIALOG message to add a handler for that. Do should I do this in VS 2005 ?
Thanx
|
|
|
|
|
Add a class for the dialog if not added.
Go to Class view, Right click that class, go to property, then you will find all the virtual functions in the 3rd tab.
Anurag Gandhi.
http://www.softgandhi.co.nr
|
|
|
|
|
I still miss the Class wizzard with its "Ctrl+W" feature.
IMHO this is a sign how carefully sometimes the job is done in the big M$-code machine
Greetings from Germany
|
|
|
|
|
Hello All,
i have to find Partition name like(New Volume(K ) but by using partition number because i am having PARTITION_INFORMATION structure in the project.
now i am unable to get PArtition Name by using Partition Number.
if you have any idea about this please please share with me.
thanks
bankey
|
|
|
|
|
the volume name can be found out from the from GetVolumeInformation(). This function requires the drive letter not the partion number.If you manage to get the drive letter, you can get the volume name.
If there is no staright way for doing this, you can use the below method.
You can use the QueryDosDevice() function to find the diive letter from parition name. for eg consider the below code. If 'c' is the first partion, the tcDeviceName will contain \Device\HarddiskVolume1. and if you give 'd:', it will be \Device\HarddiskVolume2 and so on
TCHAR tcDeviceName[50];
QueryDosDevice( _T("C:"), tcDeviceName, 50 );
suppose you got 1 in the PARTITION_INFORMATION. then make string like "\Device\HarddiskVolume1". Now starting from A to Z, put a loop and call the QueryDosDevice. Compare the device name with the "\Device\HarddiskVolume1". If it matches, you have the drive letter.
|
|
|
|
|
Hello there!
i work in VC++ and i want to write an asm code in my code
in this code, i want to write an interrupt,
i don't know list of interrupts in windows system???
I'd like to know how I can find the IDT addresses?
how do i access to this address (IDT) and how do i change address of an interrupt? (whit assembly code)
Zo.Naderi-Iran
|
|
|
|