Advanced MFC Programming
Advanced MFC Programming Advanced MFC Programming
Chapter 13. Adding Special Features to Application The file or memory used for this purpose is called File Mapping Object and must be created using special function. After it is created successfully, each process can open a view of the file or memory, which will be mapped to the address space of the calling process. File Mapping Functions There are three functions that can be used to implement file or memory mapping: HANDLE ::CreateFileMapping ( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName ); HANDLE ::OpenFileMapping ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName ); LPVOID ::MapViewOfFile ( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap ); File mapping object can be initiated by calling function ::CreateFileMapping(…). If we want to share a file, we need to pass the file handle to the first parameter (hFile) of this function. If we want to share a block of memory, we need to pass 0xFFFFFFFF to this parameter. The fourth and fifth parameters specify the size of the object. For file sharing, they can be set to zero, in which case the whole file will be shared. In the case of memory sharing, they must be greater than zero. Parameter lpFileMappingAttributes can be used to specify the security attributes of the object, in most cases we can assign zero to it and use the default attributes. Parameter flprotect specifies read and write permission. The most important parameter is the last one, which must be the address of buffers that contain a name assigned to the file mapping object. If any other process wants to access this object, it must also use the same name to create a view of the file mapping object. After the file mapping object is created successfully, the owner (the process that created the object) can create a view of file to map the buffers to its own address space by calling function ::MapViewOfFile(…). When doing this, we must pass the handle returned by function ::CreateFileMapping(…) to parameter hFileMappingObject. If we pass 0 to parameters dwFileOffsetHigh, dwFileOffsetLow and dwNumberOfBytesToMap, the whole file or memory will be mapped. Finally, parameter dwDesiredAccess allows us to specify desired access right. This function will return a void type pointer, which could be cast to any type of pointer. If any other process wants to access the file mapping object, it must call functions ::OpenFileMapping(…) and ::MapViewOfFile(…) to first access it then create a view of file. When calling function ::OpenFileMapping(…), it must pass the object name (specified by function ::CreateFileMapping(…) when the file mapping object was created) to parameter lpName. The buffers can be mapped to the address space of the process by calling function ::MapViewOffile(…), which is exactly the same with creating view of file for the owner of the object. Samples Samples 13.12\Send and 13.12\MsgRcv demonstrate how to share a block of memory between two applications. They are based on samples 13.8\Send and 13.8\MsgRcv respectively. First, the “Sender” application is modified so that its edit box will allow multiple line text input (When inputting the text, CTRL+RETURN key stroke can be used to start a new line), and the original variable CSenderDlg::m_nSent is replaced by CSenderDlg::m_szText, which is a CString type variable. The file mapping object is created in function CSenderDlg::OnInitDialog() as follows: BOOL CSenderDlg::OnInitDialog() { g_uMsgSendStr=::RegisterWindowMessage(MSG_SENDSTRING); g_uMsgReceived=::RegisterWindowMessage(MSG_RECEIVED); 424
Chapter 13. Adding Special Features to Application …… } m_hMapFile=::CreateFileMapping ( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, BUFFER_SIZE, MAPPING_PROJECT ); Here, BUFFER_SIZE is a macro defined as an integer in header file “Common.h”. Also, MAPPING_PROJECT is a macro defined as a string. They will be used by both “Sender” and “MsgRcv”. In message handler CSenderDlg::OnButtonSend(), before the message is sent out, we obtain the text from the edit box, create a view of file and put the text into the buffers. Then message MSG_SENDSTRING is sent to “MsgRcv”: void CSenderDlg::OnButtonSend() { CWnd *pWnd; LPSTR lpMapAddress; UpdateData(TRUE); lpMapAddress=(LPSTR)MapViewOfFile ( m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); } if(lpMapAddress != NULL) { memcpy(lpMapAddress, m_szText, max(m_szText.GetLength(), BUFFER_SIZE)); } pWnd=CWnd::FindWindow(CLASS_NAME_RECIEVER, NULL); if(pWnd != NULL && ::IsWindow(pWnd->m_hWnd)) { pWnd->PostMessage(g_uMsgSendStr, (WPARAM)GetSafeHwnd(), (LPARAM)NULL); } In project “MsgRcv”, the client window is implemented using edit view instead of original list view, this makes it easier for us to display text. After receiving the message, we open the file mapping object, create a view of file, then retrieve text from the buffers. Then we access the edit view, select all the text contained in the view, and replace the selected text with the newly obtained text. Finally, the acknowledge message is sent back: LONG CMainFrame::OnSendStr(UINT wParam, LONG lParam) { CWnd *pWnd; CString szText; HANDLE hMapFile; LPSTR lpMapAddress; pWnd=CWnd::FromHandle((HWND)wParam); ASSERT(pWnd != NULL); pWnd->PostMessage(g_uMsgReceived); hMapFile=::OpenFileMapping ( FILE_MAP_ALL_ACCESS, FALSE, 425
- Page 389 and 390: Chapter 12. Screen Capturing & Prin
- Page 391 and 392: Chapter 12. Screen Capturing & Prin
- Page 393 and 394: Chapter 12. Screen Capturing & Prin
- Page 395 and 396: Chapter 12. Screen Capturing & Prin
- Page 397 and 398: Chapter 12. Screen Capturing & Prin
- Page 399 and 400: Chapter 12. Screen Capturing & Prin
- Page 401 and 402: Chapter 12. Screen Capturing & Prin
- Page 403 and 404: Chapter 12. Screen Capturing & Prin
- Page 405 and 406: Chapter 12. Screen Capturing & Prin
- Page 407 and 408: Chapter 13. Adding Special Features
- Page 409 and 410: Chapter 13. Adding Special Features
- Page 411 and 412: Chapter 13. Adding Special Features
- Page 413 and 414: Chapter 13. Adding Special Features
- Page 415 and 416: Chapter 13. Adding Special Features
- Page 417 and 418: Chapter 13. Adding Special Features
- Page 419 and 420: Chapter 13. Adding Special Features
- Page 421 and 422: Chapter 13. Adding Special Features
- Page 423 and 424: Chapter 13. Adding Special Features
- Page 425 and 426: Chapter 13. Adding Special Features
- Page 427 and 428: Chapter 13. Adding Special Features
- Page 429 and 430: Chapter 13. Adding Special Features
- Page 431 and 432: Chapter 13. Adding Special Features
- Page 433 and 434: Chapter 13. Adding Special Features
- Page 435 and 436: Chapter 13. Adding Special Features
- Page 437 and 438: Chapter 13. Adding Special Features
- Page 439: Chapter 13. Adding Special Features
- Page 443 and 444: Chapter 13. Adding Special Features
- Page 445 and 446: Chapter 14. Views ID_EDIT_PASTE pas
- Page 447 and 448: Chapter 14. Views Another feature o
- Page 449 and 450: Chapter 14. Views szFind=newName; s
- Page 451 and 452: Chapter 14. Views ON_COMMAND(ID_BUT
- Page 453 and 454: Chapter 14. Views IDB_BITMAP_CLOSEF
- Page 455 and 456: Chapter 14. Views Because we do not
- Page 457 and 458: Chapter 14. Views For the root dire
- Page 459 and 460: Chapter 14. Views The columns are a
- Page 461 and 462: Chapter 14. Views } ff.Close(); Des
- Page 463 and 464: Chapter 14. Views …… …… if(
- Page 465 and 466: Chapter 14. Views void CDirView::Ad
- Page 467 and 468: Chapter 14. Views Actually, in the
- Page 469 and 470: Chapter 14. Views } if(szName1.GetL
- Page 471 and 472: Chapter 14. Views Mouse Cursor Coor
- Page 473 and 474: Chapter 16. Context Sensitive Help
- Page 475 and 476: Chapter 16. Context Sensitive Help
- Page 477 and 478: Chapter 16. Context Sensitive Help
- Page 479 and 480: Chapter 16. Context Sensitive Help
- Page 481 and 482: Chapter 16. Context Sensitive Help
- Page 483 and 484: Chapter 16. Context Sensitive Help
- Page 485 and 486: Chapter 16. Context Sensitive Help
- Page 487 and 488: Chapter 16. Context Sensitive Help
- Page 489 and 490: Chapter 16. Context Sensitive Help
Chapter 13. Adding Special Features to Application<br />
……<br />
}<br />
m_hMapFile=::CreateFileMapping<br />
(<br />
(HANDLE)0xFFFFFFFF,<br />
NULL,<br />
PAGE_READWRITE,<br />
0,<br />
BUFFER_SIZE,<br />
MAPPING_PROJECT<br />
);<br />
Here, BUFFER_SIZE is a macro defined as an integer in header file “Common.h”. Also,<br />
MAPPING_PROJECT is a macro defined as a string. They will be used by both “Sender” and “MsgRcv”. In<br />
message handler CSenderDlg::OnButtonSend(), before the message is sent out, we obtain the text from the<br />
edit box, create a view of file and put the text into the buffers. Then message MSG_SENDSTRING is sent to<br />
“MsgRcv”:<br />
void CSenderDlg::OnButtonSend()<br />
{<br />
CWnd *pWnd;<br />
LPSTR lpMapAddress;<br />
UpdateData(TRUE);<br />
lpMapAddress=(LPSTR)MapViewOfFile<br />
(<br />
m_hMapFile,<br />
FILE_MAP_ALL_ACCESS,<br />
0,<br />
0,<br />
0<br />
);<br />
}<br />
if(lpMapAddress != NULL)<br />
{<br />
memcpy(lpMapAddress, m_szText, max(m_szText.GetLength(), BUFFER_SIZE));<br />
}<br />
pWnd=CWnd::FindWindow(CLASS_NAME_RECIEVER, NULL);<br />
if(pWnd != NULL && ::IsWindow(pWnd->m_hWnd))<br />
{<br />
pWnd->PostMessage(g_uMsgSendStr, (WPARAM)GetSafeHwnd(), (LPARAM)NULL);<br />
}<br />
In project “MsgRcv”, the client window is implemented using edit view instead of original list view,<br />
this makes it easier for us to display text. After receiving the message, we open the file mapping object,<br />
create a view of file, then retrieve text from the buffers. Then we access the edit view, select all the text<br />
contained in the view, and replace the selected text with the newly obtained text. Finally, the acknowledge<br />
message is sent back:<br />
LONG CMainFrame::OnSendStr(UINT wParam, LONG lParam)<br />
{<br />
CWnd *pWnd;<br />
CString szText;<br />
HANDLE hMapFile;<br />
LPSTR lpMapAddress;<br />
pWnd=CWnd::FromHandle((HWND)wParam);<br />
ASSERT(pWnd != NULL);<br />
pWnd->PostMessage(g_uMsgReceived);<br />
hMapFile=::OpenFileMapping<br />
(<br />
FILE_MAP_ALL_ACCESS,<br />
FALSE,<br />
425