|
Hey everyone, I'm a little stuck with this and this is my fist question on these boards, and any advice anyone could give would be greatly appreciated
So basically, I have these two COM components that share memory using a MapViewOfFile object... like so:
-----------------------------------------------------------------
In the "server" component:
HANDLE hBlockMap;
...
hBlockMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,
PAGE_READWRITE, 0,
sizeof(Block), "SharedBlockMemory");
In the "client" component:
HANDLE hBlockMap;
...
hBlockMap = ::OpenFileMapping(FILE_MAP_WRITE, FALSE, "SharedBlockMemory");
-----------------------------------------------------------------
I also have a simple "Block" object, just to test sharing data, which looks like this:
-----------------------------------------------------------------
class Block
{
public:
void Write(char* msg);
char* Read();
int getSize() { return n_size; }
Block();
~Block();
private:
BYTE* data;
int n_size;
};
and just the Write and Read methods:
void Block::Write(char* msg, int size)
{
data = new BYTE[strlen(msg) + 1];
memcpy(data, (BYTE* )msg, strlen(msg));
n_size = size;
}
char* Block::Read(int size)
{
char* result = new char[n_size + 1];
memcpy(result, (char* )data, n_size);
return result;
}
-----------------------------------------------------------------
So basically, my problem is this:
The Write and Read methods both actually "work", and by that I mean I'm not getting any wierd memory access violations... If I expand the write method to check and make sure its writing, like so,
void Block::Write(char* msg)
{
...
n_size = size;
char* check = new char[strlen(msg) + 1];
memcpy(check, (char* )data, strlen(msg));
check[strlen(msg)] = '\0';
cout << check << endl;
delete[] check;
}
It outputs the correct string. However, no matter what I seem to do, the Read method just outputs garbage... I'm completely mystified, because if I change, in the Block class, the definition of data to
BYTE data[250];
and then change my Write and Read method to deal with that accordingly, I get the correct output in the Read method. But if use BYTE* data, I just get garbage...
Am I just missing something small, maybe some syntactical error? I haven't programmed in C++ as much lately, and I wouldn't put that myself, but I'm fairly sure my code dealing with the pointers and copying memory is correct... Or is it something else, could I be using the MapViewOfFile incorrectly?
And also, here is an example of how I read from it, just to demonstrate that access to the shared memory is synchronized (using a seperate mutex)...
-----------------------------------------------------------------
class CMemoryMgr
{
public:
...
private:
Block* c_Block;
...
};
void __stdcall CMemoryMgr::TPF_PrintMessage()
{
if(::WaitForSingleObject(hBlockMutex, 5000L) == WAIT_OBJECT_0)
{
cout << c_Block->Read(c_Block->getSize());
cout << endl;
::ReleaseMutex(hBlockMutex);
}
}
-----------------------------------------------------------------
Also, the reason I want to dynamically allocate the data array is because I will be developing a customized circular buffer, and I want to be able to allow data of any reasonable size to be enqueued, so thats why I'm trying to stay away from a fixed array size.
Anyway, thank you all for reading my problem!
Like I said, any advice would be greatly appreciated
|
|
|
|
|
Is is safe to assume you did call MapViewOfFile after creating or opening the memory mapped file?
And this is the 'block' of memory you read and write to?
There is a memory mapped file sample here on CodeProject:
CMemMapFile v1.41
Interprocess communication tutorial
|
|
|
|
|
How do I do a DFT of an image using a FFT to speed things up? My code does not work but is :
int X, Y, num;
long int R;
float data[4096], scale;
RGBQUAD rgb;
num = max(pImage->GetWidth(),pImage->GetHeight());
const DWORD RGB_MAX=RGB(255,255,255);
if (!IsPowerOfTwo(num))
{
return;
}
if (dir == 1)
{
scale = num*num;
}
else scale = 1.0;
for (Y=0; Y<num; Y++)
{
for (X=0;X<=2*num-1;X+=2)
{
data[X] = data[X+1] = pImage->GetPixelGray(X/2,Y);
}
if (!fft(data,num,dir))
return;
for (X=0;X<num;X++)
{
pImage->SetPixelColor(X,Y,RGB(abs(data[X*2]),abs(data[X*2]),abs(data[X*2])));
}
}
for (X=0;X<=2*num-1;X+=2)
{
for (Y=0; Y<num; Y++)
{
R=Y*2;
data[R] = data[R+1] = pImage->GetPixelGray(X/2,Y);
}
if (!fft(data,num,dir))
return;
for (Y=0;Y<num;Y++)
{
R=Y*2;
pImage->SetPixelColor(X/2,Y,RGB(abs(data[R]),abs(data[R]),abs(data[R])));
}
}
Nothing is impossible, It's merely a matter of finding an answer to the question of HOW? ... And answering that question is usually the most difficult part of the job!!!
|
|
|
|
|
I am drawing with a CDC object as follows:
CDC example;
example.Rect ......etc and all the drawing takes place on screen
thne i attempt to convert the CDC to an enhanced Metafile:
CMetaFileDC File;
File.CreateEnhanced(&example, "path", NULL, "NAme");
File.CloseEnhanced();
The file is created but it does not contain anything on it. When i create a simple Metafile, it works fine and makes the file and shows all the drawing info. However this enhanced thing only creates an empty file that is 1 pix x 1 pix.
What am i doing wrong?
thank you
|
|
|
|
|
What code did you use to create the image list?
Don't try it, just do it!
|
|
|
|
|
Here is code that I used for create Image list
<br />
imgList.Create(16, 16, ILC_COLORDDB | ILC_MASK, 6, 1);
|
|
|
|
|
I have an SDI application that is supposed to close it self when finished. To do this it sends a
m_pMainFrame->PostMessage(WM_SYSCOMMAND, SC_CLOSE);
The application appears to stop running and it gives no errors or warnings in release or debug mode. However, task manager almost always shows the application is still in memory. Is there a more forceful way to close an app.
P.S. I have also tried combinations of SW_CLOSE and SendMessage().
Thanks
|
|
|
|
|
Hello,
MSDN says that SC_CLOSE will only close the window. What happens if you try PostQuitMessage() ?
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
Thank you.
That worked nicely.
|
|
|
|
|
See here.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
Generally the method I use is to send the ID_APP_EXIT command to the main window. This will then use the same exit procedure as if the user clicked "Exit" from the File menu.
For example:
AfxGetMainWnd()->SendMessage( WM_COMMAND, ID_APP_EXIT );
|
|
|
|
|
Thank you. This is good information.
|
|
|
|
|
I think you first need to understand how the application executes and how an application terminates. It seems as though you are using MFC which hides how things work and most likely why you don't see why this doesn't terminate the application.
A process terminates when "ExitProcess" is called. Simple, right? Just as a thread terminates when "ExitThread" is called. Also pretty simple, right?
So, do you need to call ExitProcess and ExitThread in your application? No, you don't! The main thread of an application will call "ExitProcess" once you return from the "WinMain" or "main" API. There is wrapper code around this thread which will call this for you (unless you've turned this code generation off which is not likely if you are using MFC).
So, once the main thread exits the process will exit. What about threads? An individual thread will terminate also once it returns. "CreateThread" and "BeginThread" do not start a thread as your function but actually start a wrapper function which calls your threadproc. The exit code again will call "ExitThread" so you do not need to call this API yourself.
So, why isn't your application closing? Well the main thread never exited. You should nicely terminate all other threads, however the reason is that your main thread never exited. So why wouldn't it exit?
Well, you called "WM_CLOSE" and that's nice. Your window closes, but the thread didn't terminate if this is your main thread. So, what happens? You need to get the "Message Loop" to quit. The message loop looks like this generally:
while(GetMessage(...))
{
TranslateMessage(...);
DispatchMessage(...);
}
This message loop is dupliated a lot. As an example, "MessageBox" API implements it's own however these are speical. They will exit when the window goes away. The way the one above works is that it will only exit if GetMessage returns 0, which it only does when WM_QUIT is processed. How is this processed? By using PostQuitMessage(); which poses the quit message to that thread.
So, it's generally considered appropriate to call "DestroyWindow()" then in your WM_DESTROY (or in WM_CLOSE call DestroyWindow() as well, but you should handle clean up appropriately) to then call "PostQuitMessage" to exit the thread. This way you clean up properly, send the quit message so the loop exits and the thread should then exit. (Well, the message loop exits at least, doesn't mean that the thread would exit but generally there's no code after this so usually it's the case).
If this is the main thread then your application should exit. If it is not your main thread then you need to also do whatever it takes to get your main thread to exit.
If this is your main thread and it doesn't exit there could still be reasons. As an example in order for it to exit it will possibly need to grab the loader lock or even the heap lock, which could have been held by a terminating thread or have some deadlock contention with something else in your application.
The best thing to do is get the debugger fired up and find out what's going on in that case.
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
Thank you.
I very much appreciate the background information.
|
|
|
|
|
I made a program and produced the exe file with visual studio 6. But when I sent the exe to another computer it couldn't work because dlls were missing. How can I know what dlls to have with the exe files in order to work and how will I find them? Isn't there an automated way to do this?
|
|
|
|
|
Use DependcyWalker. This tool is included with Visual Studio. It will show you all the dll's required by your application to run.
|
|
|
|
|
Have a look at "static linking" in Visual Studio.
If you static link then the necessary functions are included in your EXE (This also makes the EXE much bigger, but EXE size is good to impress unknowledgeable customers!)
|
|
|
|
|
No luck. I put it in: use mfc as a static library, and errors were created..
I can't seem to find a way to see what dlls are called..
I must be doing something wrong and I don't have DependcyWalker. How do they do it?..
|
|
|
|
|
Are you sure you don't have DependencyWalker ?
Look for a file called depends.exe, under
[Path to Visual Studio]\Common\Tools
Hope this helps
|
|
|
|
|
That helped, thanks!
I found it. Now what remains is to send the prorgam to someone ans see if it works
|
|
|
|
|
Hi everyone, forgive me if my errors will seem trivial to you, I've only recently starting working with Windows programming and MFC (although I've had plenty of experience programming in console), and my program doesn't seem to work as expected.
First of all, let me explain what it should do and how it's set up. Basically, I have a dialog box with 5 edit boxes and 1 "ok" button on it. I'm trying to get the dialog boxes to work like the ones for the registration key with one little extra feature. The caret should jump to the next box after 5 characters are put into one box, and also if the user uses copy/paste command, the pasted text gets split into the boxes. Well, I wrote the program that should do all this, but there are some things that happen that should not happen and I have no clue why. Basically I have the first 4 boxes carry identical code:
<br />
void Dlg2::OnChangeEdit1() <br />
{<br />
<br />
CWnd* m_wEdit1=GetDlgItem(IDC_EDIT1);<br />
m_wEdit1->GetWindowText(key1);<br />
temp=key1.GetLength();<br />
if (temp>4)<br />
{<br />
temp-=5;<br />
CWnd* m_wEdit2=GetDlgItem(IDC_EDIT2);<br />
m_wEdit2->SetWindowText ( _T(key1.Right(temp)));
m_wEdit1->GetWindowText(key1);<br />
if(temp>0) m_wEdit1->SetWindowText ( _T(key1.Left(5)));<br />
m_wEdit2->SetFocus();<br />
}<br />
}<br />
and the fifth box just limits the maximum text to 5. The above code works fine for typing the key in manually, the cursor switches to next window after 5 characters are typed in. However, copy/pasting the code in doesn't work like I expected it to. Instead, the first box gets all of the pasted text, the 2nd gets all but the first 5 characters, and so on. So for example if I type in "abcdefghijklmno", the first box will have "abcdefghijklmno", 2nd will have "fghijklmno" and 3rd "klmno".
Now here is what's even weirder. If I take the exact same code from above, change the "if (temp>4)" statement to "if (temp>5)" and remove the "if (temp>0)" part from the "if (temp>0) m_wEdit1->SetWindowText(_T(key1.Left(5)));" then the copy/pasting works like it should with each box only receiving 5 characters, but when the text is put in manually the cursor goes right before the last character when it is moved to the new box. This makes sense, since I never ordered the caret to move, but as I will explain in a moment even ordering it to move won't do anything. Another thing is, if I leave the "if (temp>4)" message alone, and just remove the "if (temp>0)" part, the program crashes when it processes the 5th character. This I don't udnerstand either, the if is in front of the statement that selects the 5 characters to be put into the first box. Therefore it's guaranteed that when the user puts in 5 characters there should be enough characters for the first box, yet it always crashes after 5th character is put in (or when the message is pasted into it that's longer than 5 characters). I'm very confused by this error as well.
Last, but not least, the caret isn't moving. If I add the code below to the code above after the last line (SetFocus one) then it gives the same result as if there is no code at all:
<br />
CPoint myPoint = m_wEdit2->GetCaretPos();<br />
CDC* pDC = m_wEdit2->GetDC();<br />
myPoint.x += (pDC->GetTextExtent (_T(key1.Right(temp)), temp)).cx;<br />
SetCaretPos (myPoint);<br />
And I don't understand why this doesn't work either. Basically all I'm doing is taking the current caret position, figuring out the physical length of the text, and offsetting the caret. But it doesn't get offset. I even tried creating a new function "OnSetFocusEdit2" so that it gets called as soon as focus is set to second edit box, which box 1 does when it finishes and copying the caret code there instead, but still no effect. If anyone can explain to me these weird happenings, I would appreciate it.
|
|
|
|
|
At least for setting the caret position, you can 'select' text in the edit field, just have the start and end at same position. It will position caret in the edit field at that character position, but none of the text will be selected.
For example:
m_wEdit2->SetSel(4,4);
|
|
|
|
|
Using the Office XP Professional installation as a guide, I put this together (extraneous code has been removed):
class CMyDlg : public CDialog
{
CButton m_btnOK;
CEdit m_ebKey5;
CEdit m_ebKey4;
CEdit m_ebKey3;
CEdit m_ebKey2;
CEdit m_ebKey1;
afx_msg void OnChangeEdit1();
afx_msg void OnChangeEdit2();
afx_msg void OnChangeEdit3();
afx_msg void OnChangeEdit4();
afx_msg void OnChangeEdit5();
void EnableOKButton( void );
};
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDOK, m_btnOK);
DDX_Control(pDX, IDC_EDIT5, m_ebKey5);
DDX_Control(pDX, IDC_EDIT4, m_ebKey4);
DDX_Control(pDX, IDC_EDIT3, m_ebKey3);
DDX_Control(pDX, IDC_EDIT2, m_ebKey2);
DDX_Control(pDX, IDC_EDIT1, m_ebKey1);
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2)
ON_EN_CHANGE(IDC_EDIT3, OnChangeEdit3)
ON_EN_CHANGE(IDC_EDIT4, OnChangeEdit4)
ON_EN_CHANGE(IDC_EDIT5, OnChangeEdit5)
END_MESSAGE_MAP()
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_ebKey1.SetLimitText(5);
m_ebKey2.SetLimitText(5);
m_ebKey3.SetLimitText(5);
m_ebKey4.SetLimitText(5);
m_ebKey5.SetLimitText(5);
return TRUE;
}
void CMyDlg::OnChangeEdit1()
{
if (m_ebKey1.GetWindowTextLength() == 5)
m_ebKey2.SetFocus();
EnableOKButton();
}
...
void CMyDlg::OnChangeEdit4()
{
if (m_ebKey4.GetWindowTextLength() == 5)
m_ebKey5.SetFocus();
EnableOKButton();
}
void CMyDlg::OnChangeEdit5()
{
EnableOKButton();
}
void CMyDlg::EnableOKButton( void )
{
bool bEnable = true;
bEnable &= (m_ebKey1.GetWindowTextLength() == 5);
bEnable &= (m_ebKey2.GetWindowTextLength() == 5);
bEnable &= (m_ebKey3.GetWindowTextLength() == 5);
bEnable &= (m_ebKey4.GetWindowTextLength() == 5);
bEnable &= (m_ebKey5.GetWindowTextLength() == 5);
m_btnOK.EnableWindow(bEnable);
} I did not do anything for the copy/paste requirement.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
I want to do Owner draw in ClistCtrl.
When ever a new Item is inserted to the report view of CListCtrl, the total list is getting painted.
Is there any way that I can only paint the new item to the Report View.
Nagarjuna
|
|
|
|
|
Hi everyone!
I don't know how to process the message when you use arrow key to move to next item in ListView like LBN_SELCHANGE in ListBox.
Please help me!
Thanks
Love
|
|
|
|
|