|
Hi All,
I am looking some code in a dll which is part of a project I inherited & see the following code in a CWinThread derived class:
<br />
BOOL CMyThread::InitInstance()<br />
{<br />
AfxEnableControlContainer();<br />
AfxOleInit();<br />
<br />
CoInitialize(NULL);<br />
<br />
AFX_MANAGE_STATE(AfxGetStaticModuleState());<br />
<br />
return TRUE;<br />
}<br />
Is it me, or does AFX_MANAGE_STATE() not belong here? The thread is instantiated from other plaes in code where AFX_MANAGE_STATE has already been called & there is no cross-thread communication w/ other threads or the calling process.
Is it common practice to call AFX_MANAGE_STATE from a CWinThread derived class's InitInstance() ?
Also, does it matter if I call CoInitialize/CoInitializeEx before calls to AfxEnableControlContainer()/AfxOleInit()?
Thanks!
|
|
|
|
|
Wes Jones wrote: Is it common practice to call AFX_MANAGE_STATE from a CWinThread derived class's InitInstance() ?
Only if the place in which it is called will be loading resources from the DLL.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Hmm.. so if the InitInstance brought up a CDialog based class & called DoModal(), it'd be loading resources & it'd be a good idea to call this?
such as:
<br />
viod MyDll_ShowScreen()<br />
{<br />
AFX_MANAGE_STATE(...);
...<br />
AfxBeginThread( RUNTIME_CLASS(CMyThread) );<br />
}<br />
<br />
CMyThread::InitInstance()<br />
{<br />
AFX_MANAGE_STATE(....);
<br />
CMyDlg dlg(...);<br />
dlg.DoModal();<br />
<br />
PostThreadMessage(WM_QUIT,0,0);<br />
return TRUE;<br />
}<br />
<br />
MyDll_ShowScreen();<br />
|
|
|
|
|
Yes, otherwise the InitInstance() method would be looking for CMyDlg 's dialog template in the EXE that owns your DLL.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
My understanding is that AFX_MANAGE_STATE is it's on more of a module level, not so much on a per-thread level.
|
|
|
|
|
Wes Jones wrote: does it matter if I call CoInitialize/CoInitializeEx before calls to AfxEnableControlContainer()/AfxOleInit()?
CoInitialize(Ex), if needed, should be called before AfxOleInit().
I don't know if this note from the docs is relevant here...
"If AfxOleInit is called from an MFC DLL, the call will fail. The failure
occurs because the function assumes that, if it is called from a DLL, the
OLE system was previously initialized by the calling application."
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Isn't DLLMain() a more appropriate place for initialization calls. Doesn't the documentation even say that? I have always initialized OLE and cleaned it up in DLLMain for DLL_THREAD_ATTACH/DLL_PROCESS_ATTACH and DLL_THREAD_DETACH/DLL_PROCESS_DETACH and have never had any problems.
led mike
|
|
|
|
|
hmm I thought one wasn't supposed to call any ole init funcs from dllmain.
Maybe this is irrelevant, but from the docs:
"Because there is no way to control the order in which in-process servers
are loaded or unloaded, do not call CoInitialize, CoInitializeEx, or
CoUninitialize from the DllMain function."
What thread is DllMain called on? Does it even make sense there? I dunno...
my brain is fried today (death in family...nightmare week).
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
in-process servers, hmm, I would like to see more of that. Do you have a link? I was not thinking about COM servers but just DLL's as it has been many years since I have developed any COM servers. I guess my recent experience has limited my thinking *that's weak*. In the recent past my DLL models have been for libraries that use COM servers rather than implementing them. I have never had a problem even though multiple init's are surely happening within the process.
Mark Salsbery wrote: What thread is DllMain called on?
The current process is creating a new thread. When this occurs, the system calls the entry-point function of all DLLs currently attached to the process. The call is made in the context of the new thread.
link[^]
led mike
|
|
|
|
|
led mike wrote: I would like to see more of that. Do you have a link?
CoInitializeEx()[^] - Remarks, last line.
That's why I said it might be irrelevant to this case....maybe that just applies to COM servers.
Thanks for the link about the DllMain thread! I was just reading that
Mark
*EDIT* OOps - fixed the post LOL
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I did follow the code into AfxOleInit(), & since it's in the context of a DLL, it just sets a variable to -1 & returns TRUE w/out really doing anything. It assumes calling process as initialized OLE.
|
|
|
|
|
Cool. Thanks for the update!
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi i had posted this before too i have and image acquisition code that acquires image from CCD camera and stores it to pointer named "*memory"
pl_exp_start_seq(hCam, memory)
i want to display this memory as bmp file and save it to my hard disk, i did write code for it but that saves it in 8 bit format and i loose a lot of valuable information can any one please help, y code is as follows and thankz in advance
void Create_DIB( HWND hWnd )
{
HDC hDC;
unsigned char i;
long k,j, NumBytes;
LPBITMAPINFO info;
unsigned char *dat;
DWORD error;
hDC = GetDC (hWnd) ;
// Intialize BITMAPINFOHEADER data.
//.................................
bi.biSize = sizeof (BITMAPINFOHEADER) ;
bi.biWidth = W;
bi.biHeight = -H; // top-down DIB
bi.biPlanes = 1;
bi.biBitCount = COLORBITS;
bi.biCompression = BI_RGB;
bi.biSizeImage = ( ALIGNLONG( (W * COLORBITS)/8 ) * H);
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 256;
bi.biClrImportant = 256;
// Allocate memory for BITMAPINFO structure.
//..........................................
NumBytes = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); // +
//( ALIGNLONG( ( W * COLORBITS ) / 8 ) * H );
lpbi = (BITMAPINFOHEADER*)GlobalAlloc( GPTR, NumBytes );
if( lpbi == NULL )
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL );
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
exit( EXIT_FAILURE ); // Get out now!
}
// Copy BITMAPINFOHEADER information.
//...................................
*lpbi = bi;
// Create The Palette
info = (LPBITMAPINFO) lpbi;
for ( i=0; i<255; i++ )
{
info->bmiColors[i].rgbRed = i;
info->bmiColors[i].rgbBlue = i;
info->bmiColors[i].rgbGreen = i;
info->bmiColors[i].rgbReserved = 0;
}
// Set pointer to bitmap’s bit data.
//..................................
// lpstBitmap = (LPSTR)lpbi + (WORD)sizeof(BITMAPINFOHEADER) +
// (256 * sizeof(RGBQUAD));
hBitmap = ::CreateDIBSection(hDC,(LPBITMAPINFO)lpbi, DIB_RGB_COLORS,(VOID **)&lpstBitmap, NULL,0);
dat = (unsigned char*)lpstBitmap;
for ( k=0; k< H; k++ )
for ( j = 0; j < W; j++ )
*dat++ = (unsigned char)k;
// Create uninitialized DIB bitmap.
//.................................
/* hBitmap = CreateDIBitmap( hDC,
&bi,
0 ,
0,
(LPBITMAPINFO) lpbi, */
error = GetLastError();
ReleaseDC( hWnd, hDC);
}
void Save(int num)
{
CString prefix = "C:\\Documents and Settings\\Garner Lab\\My Documents\\Xanoscopeimages\\image";
char buf[4];
itoa(num, buf, 10);
CString number = buf;
CString suffix = ".bmp";
fullname = prefix + number + suffix;
CImage image;
image.Attach(hBitmap);
image.Save(fullname); // save as BMP
image.Detach();
|
|
|
|
|
Since you're using CImage, you can simplify this and let the CImage class do the work.
Create a CImage object and use its Create() or CreateEx() methods to
create the DIB section. Then you can use the GetBits() and GetPitch()
methods to copy your pixel data into the DIB section.
Review the BITMAPINFOHEADER documentation (see biBitCount) for 16-bit support
in DIBs. Note 16-bit grayscale is not supported.
24 bit DIBs are straight-forward.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark
hey thnkz a ton Mark for the help but i had one more query if you could help i m trying to save an image from CCD camera dats sending data as pointer now is there a way i can convert this image data into TIFF fileand save it on disk , as TIFF supports 12bit to my knowledge if yes where can i look for help or could you help me with it, as currently i m converting it to bitmap and dats where i m lossing all my information in terms of resolution.
Dipen
|
|
|
|
|
GDI+[^] supports loading/saving TIFF files but doesn't support 12-bit images.
16-bit color and grayscale images are supported, so you could upsample the
image data to 16bpp.
The most difficult option for working with TIFF files would be to write your own
loader/saver using the TIFF Specification[^]
An easier method would be to use a third party library, like LibTIFF[^]
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I have a legacy VC++ 6.0 program that is quite large. Every dialog is user created, even though for many of the dialogs, there was a template created in the resources for the dialog. The problem I am having is that when I call a dialog that allows the user to input an ID number and a PIN to log on to this application, the first time the 'keypad' is displayed, it is displayed in the context of the template that was created, but the second time it is called, the 'keypad' is displayed in the 'user defined' context. Is there a way to get around this problem? It has been baffling me now for months, and granted, I am not a VC++ power user by any means.
Thanks for your assistance.
John P.
|
|
|
|
|
What happens if you remove the template dialog?
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
If I remove the template, then I get nothing when I call the keypad class.
The operation of this application is quite large. I'm not sure if you have some idea of what an "Instructor Operating System (IOS)" is to a flight simulator, but it controls every aspect of the flight simulator as far as settings go. In order to use this system, it was decided that it should be user and password protected, so that not just anyone could enter the cockpit and use the simulator. Before I added the password protection modules, the keypad came up as it was designed (being the user design and not just the template). The user design uses some of the template and adds on to it's functionality. It would take paragraphs to fully explain the inner workings of this application, so I'm not sure that you might be able to come up with a viable suggestion as to how to make this work correctly.
I was wondering if it was possible to 'create' the keypad at some other location that's not visible, and then delete it, so that when I call it again, it will not be the first time it has been called and created??
John P.
|
|
|
|
|
Are you using MFC?
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
|
Ok, so how are you instantiating and creating the "login" dialog?
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
I create an instantiation of CLogin clog. This creates the login dialog which has text boxes for holding the UserID and PIN values. There are buttons to select the entry for the UserId and PIN and this in turn calls the Keypad dialog. When the user enters the UserID and PIN numbers, they are placed in the text boxes (one at a time).
John P.
|
|
|
|
|
jparken wrote: I create an instantiation of CLogin clog.
Do you then call Create() , CreateIndirect() , or InitModalIndirect() ?
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
I don't call any of these, David. And none of these are called for Keypad as well.
John P.
|
|
|
|