|
That is all you need .. you can then get the window size
RECT r;
GetWindowRect(hWnd, &r);
int Wth = r.right - r.left;
int Ht = r.bottom - r.top;
You also have the wonderful function CreateDIBSection which just needs a DC
CreateDIBSection function (Windows)[^]
You will need to allocate memory to hold the bits. That size is slightly tricky it depends on what color depth you are going to ask for in bits. Typically you want RGB24 or RGB32 and the size also needs to be aligned to a 4 byte boundary. Anyhow long story short its a funny maths calc and we need to setup a bitmap header info for the call ... Lets do 24 bit colour.
BITMAPINFOHEADER BMIH;
BMIH.biSize = sizeof(BITMAPINFOHEADER);
BMIH.biBitCount = 24;
BMIH.biPlanes = 1;
BMIH.biCompression = BI_RGB;
BMIH.biWidth = Wth;
BMIH.biHeight = Ht;
BMIH.biSizeImage = ((((BMIH.biWidth * BMIH.biBitCount)+ 31) & ~31) >> 3) * BMIH.biHeight;
See that funny calc at end well BMIH.biSizeImage now has the memory size you need to allocate. So allocate it and then call CreateDIBSection
char* myBits = malloc(BMIH.biSizeImage);
CreateDIBSection(hDC, (CONST BITMAPINFO*)&BMIH, DIB_RGB_COLORS, (void**)&myBits, NULL, 0);
myBits now has all your image data from the DC now all you need to do is save it!!!!
For a BMP file that is trivial
FILE *pFile = fopen( , "wb");
BITMAPFILEHEADER bmfh;
int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize;
LONG lImageSize = BMIH.biSizeImage;
LONG lFileSize = nBitsOffset + lImageSize;
bmfh.bfType = 'B'+('M'<<8);
bmfh.bfOffBits = nBitsOffset;
bmfh.bfSize = lFileSize;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
UINT nWrittenFileHeaderSize = fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER), pFile);
UINT nWrittenInfoHeaderSize = fwrite(&BMIH, 1, sizeof(BITMAPINFOHEADER), pFile);
UINT nWrittenDIBDataSize = fwrite(myBits, 1, lImageSize, pFile);
fclose(pFile);
Now don't forget to free myBits when you are done that is alot of memory to bleed if you forget
In vino veritas
modified 11-Nov-16 0:33am.
|
|
|
|
|
Hi
I am getting ERROR_INVALID_HANDLE on GetLastError after WaitForSingleObject returns -1
I more or Less followed the MSDN example Using Mutex
My main thread does muthandle = CreateMutex(NULL,FALSE,NULL);
Second parameter is FALSE indicating it is not owned
Later a second Thread calls WaitForSingleObject(muthandle,INFINITE) and gets a -1 which
GetLastError retuns ERROR_INVALID_HANDLE
THANKS
|
|
|
|
|
what does CreateMutex return?
|
|
|
|
|
Well it's not NULL some low number like X'00000010' or X'00000030' now running x64 a handle is 64 bits I was looking at the RAX register
I tried the last parameter For CreateMutex NULL and with a string didn't matter the createmutex and WaitForSigleIbject are different threads
|
|
|
|
|
Hi,
The function returning the error does not lie.
The first parameter you are passing to the WaitForSingleObject function[^] is not a valid HANDLE.
If I were a gambling man... I would bet that you are attempting to pass the pointer to a HANDLE.
Best Wishes,
-David Delaune
|
|
|
|
|
It's the handle I guess the next step is to go to disassembly mode and see
|
|
|
|
|
ForNow wrote: go to disassembly mode Shouldn't be necessary. You should be able to step through with your debugger to check if the handle is valid. Remember, it could easily have been corrupted by your (or someone's) code.
|
|
|
|
|
For some reason i am not able to display certain data areas on quick watch
That's the only reason I got intobinto disassembly mode
Thanks
|
|
|
|
|
You are inside a thread the debugger doesn't always have access to all the memory.
In vino veritas
|
|
|
|
|
That's it I was never able to display the global block storage with quick watch
I think it was build as a DLL on its own
Thanks
|
|
|
|
|
ForNow wrote: It's the handle I guess the next step is to go to disassembly mode and see
Since you are such an expert at x86/x64 assembler perhaps you should utilize WinDbg:
Common WinDBG Commands Reference[^]
!handle displays information about a handle or handles that one or all processes in the target system own.
0:000> !handle c0dedbad f
Handle 38
Type Mutant
Attributes 0
GrantedAccess 0x1f0001:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState
HandleCount 1
PointerCount 96605
Name <none>
Object Specific Information
Mutex is Owned
Mutant Owner 11bc.1418
Here are some other ideas in case you don't know how to use WinDbg:
BOOL IsValidHandle(HANDLE h)
{
DWORD dwFlags = 0;
return GetHandleInformation(h,&dwFlags);
}
BOOL IsValidHandle(HANDLE h)
{
return CompareObjectHandles(h,h);
}
use it like this to debug your code:
if (IsValidHandle(h))
{
DWORD dwResult = ::WaitForSingleObject(h, INFINITE);
DWORD dwError = GetLastError();
}
Best Wishes,
-David Delaune
|
|
|
|
|
How are you passing muthandle to your second thread? ...is it possible that you're not passing that correctly (for example, if you passed by pointer that you're not dereferencing your pointer)?
|
|
|
|
|
There is a global block accessible to all the threads
This is one of the fields
I going to double check that
The handle has the value initialized by CreateMutex later in tonite
|
|
|
|
|
Since it's a different thread... also check that the thread going to the wait state isn't waiting on a handle that hasn't been created yet.
|
|
|
|
|
You do realize you don't pass the handle around between threads right?
Read carefully
Two or more processes can call CreateMutex to create the same named mutex. The first process actually creates the mutex, and subsequent processes open a handle to the existing mutex. This enables multiple processes to get handles of the same mutex, while relieving the user of the responsibility of ensuring that the creating process is started first. When using this technique, you should set the bInitialOwner flag to FALSE; otherwise, it can be difficult to be certain which process has initial ownership.
If you go the other way and guarantee the inital thread opens it first you need to set the bInitialOwner flag and do a release. So your other choice.
The creating thread can use the bInitialOwner flag to request immediate ownership of the mutex. Otherwise, a thread must use one of the wait functions to request ownership. When the mutex's state is signaled, one waiting thread is granted ownership, the mutex's state changes to nonsignaled, and the wait function returns. Only one thread can own a mutex at any given time. The owning thread uses the ReleaseMutex function to release its ownership.
You seem to get getting confused between the two modes from what I am reading. You need to make a choice (a) or (b).
So I think you are getting this error because you are using the named technique without a name.
If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same namespace.
In vino veritas
modified 10-Nov-16 14:53pm.
|
|
|
|
|
I am modifying the Hercules mainframe emulator code
I have created a child
Process a Windows MFC
Program
Basically the data shared between all of the threads is stored in a DLL named sysblk
Thanks
|
|
|
|
|
Hi All,
We are trying to upgrade 32 bit MFC application to 64 bit application. In this process we are getting the
Debug Assertion Failed! error when the synchronization function WaitForMultipleObjectsEx() is called as
dwWaitResult=::WaitForMultipleObjectsEx(dwNumWaits,hWaits,FALSE,dwTimeout,TRUE);
where dwNumWaits values is 2, dwTimeout is INFINITE and hWaits is an array of 32 handles, in which only the first 2 handles are initialized.
This is perfectly worked with 32 bit application, but when we are testing the application in 64 bit, getting the above error.
Please let me know how we can resolve it.
Thanks,
Lakshmi Chowdam.
|
|
|
|
|
Member 12335695 wrote: Please let me know how we can resolve it. Step 1 is to use your debugger to trap the assertion and find out why it is occurring.
|
|
|
|
|
Hi,
Member 12335695 wrote: hWaits is an array of 32 handles
That is a alot of synchronization objects for a single thread. Please perform an audit/review on your code and check to see if your application is using greater than MAXIMUM_WAIT_OBJECTS which is probably defined as 64 on your operating system. Exceeding this number will cause failures at run-time that the compiler does not catch.
You might want to ask your engineers to design a better architecture that does not require single threads to wait on such a large number of handles.
Also please paste the entire contents of the "Debug Assertion Failed!" error message so we can further assist.
Best Wishes,
-David Delaune
modified 10-Nov-16 10:38am.
|
|
|
|
|
Please find the contents of the "Debug Assertion Failed!" error message as:
Debug Assertion Failed!
Program: C:\Windows\system32\mfc120ud.dll
File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\barstat.cpp
Line: 99
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winfrm.cpp(1628) : AppMsg - Warning: no message line prompt for ID 0xE001.
Even though I restricted the synchronization objects to 2 only, then also I am getting the above same error.
Please let me know if you need more information on this?
|
|
|
|
|
And also, the creating events are:
hInterruptEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hTDEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hWaits[0]=hInterruptEvent;
hWaits[1]=hTDEvent;
Thanks,
Lakshmi Chowdam.
|
|
|
|
|
Member 12335695 wrote: Program: C:\Windows\system32\mfc120ud.dll
File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\barstat.cpp
Line: 99
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winfrm.cpp(1628) : AppMsg - Warning: no message line prompt for ID 0xE001.
This means that your status bar is missing an ATL/MFC resource string for the ATL_IDS_IDLEMESSAGE.
Add this to your .RC resource file:
STRINGTABLE
BEGIN
ATL_IDS_IDLEMESSAGE "Ready"
END
You may be missing other resource strings.
Best Wishes,
-David Delaune
|
|
|
|
|
Look at the call stack to see what the assertion was checking, that should give you clues as to where the actual problem may be. Are you using the same exact MFC version (other than 32v64bit) on both compilations?
|
|
|
|
|
I developed an exe,which would exports some pure C APIs for plugin dlls.
the code for the main exe is something like bellow:
class CA{};
class CB{};
class CC{};
class CCore
{
private:
CA* m_pCA;
CB* m_pCB;
CC* m_pCC;
};
void main()
{
CCore* pCore = new CCore;
while(true)
{
pCore->DoSomething();
}
delete pCore;
}
the code for a plugin is something like this
class CTestPlugin : public IPlugin
{
public:
virtual void Init()
{
}
virtual void UnInit()
{
}
};
I do not want to expose the pCore pointer or any other pointers from main exe to any plugin. so I need pure c style apis.
any ideas?thank you.
modified 10-Nov-16 2:40am.
|
|
|
|
|