I am writing for PocketPC 2002 using Embedded Visual Tools 3.0 (EVT3.0). The on-line documentation for CFile::Write() says "Write throws an exception in response to several conditions, including the disk-full condition." When I compile a try{ cfile->Write(...) } catch{...} code segment, the compiler flags the first of several cfile->Write() statements with: "... warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX". My problem is where to insert this switch in the EVT3.0 environment? I've found prerelease MSDN documentation on Structured Exception Handling , which says "Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++. Although destructors for local objects will be called if you use structured exception handling in a C++ program (if you use the /GX compiler option), you can ensure that your code is more portable by using C++ exception handling. The C++ exception handling mechanism is more flexible, in that it can handle exceptions of any type." BUT, I think they're referring to Visual Studio 5 or 6, which has a slightly different Project interface than EVT3.0. I also get the following linker errors due to the try/catch segment: "error LNK2001: unresolved external symbol "const type_info::`vftable'" (??_7type_info@@6B@) error LNK2001: unresolved external symbol ___CxxFrameHandler" Does anybody know how to make EVT3.0 happy here? Thanks Mike Landis
Mike Landis
Posts
-
CFile C++ exceptions in EVT3.0 -
GetItemText returns bad CString & can't change subitem color in CustomDrawOn subclassing, I've been using the Wizard to define classes. Finish the dialog in the resource, Ctrl-W, New class, etc. I think it's sewn together right. If you bring up the Wizard over any of my dialogs, you immediately see the subclass, messages, member functions... Can you post example code or suggest a URL where strncpy is used to solve the longevity problem? I tried boosting the pool size to 12, just to see if it made any difference. It didn't. I am fairly convinced that defeating buffer release will solve this. The application is stable elsewhere. If you find something that gets me valid CString's from GetItemText in the CustomDraw routine, I owe you $100. - Mike Landis
-
GetItemText returns bad CString & can't change subitem color in CustomDrawpCustomDraw->clrText = RGB(255,0,0); works like a charm. Saw it in the structure and forgot about it until you reminded me. I am not sure what you're referring to regarding the controls. I build up dialogs by adding controls in the resource editor. I've been finding them by calling GetDlgItem(). It's been working for responding to other messages. I didn't think NM_CUSTOMDRAW worked differently. On Pooling - all I know is that there is a data longevity requirement which Blazczak's AddPool solves. If you don't do it absolutely nothing displays in the list control. This is behaving exactly the same way that it did before I put the pooling in. Blazczak says that you have to cache strings through two LBN_GETDISPINFO notifications after the one where you set the value. - Mike Landis
-
GetItemText returns bad CString & can't change subitem color in CustomDrawThere are real MFC objects behind the GetDlgItem call, so I think the CWnd*s are real. I use the (cast)ptrs to call CCtrlList, CEdit, etc. functions. I'm not wrapping anything, just subclassing, so I hope I haven't killed NM_CUSTOMDRAW passthrough. The reason I don't suspect OnGetDispInfoList() is because the control behaves quite rationally in all other cases. I can scroll the view generating update events and it handily fetches the right stuff from OnGetDispInfoList() and displays it in the control. The only other code I know is: const unsigned short StringPoolSize = 3; unsigned short nextFreeSlot; CString cstPool[StringPoolSize ]; LPTSTR pBufPool[StringPoolSize ]; from the PosDialog's .h file and GetItemText in the ListCtrl itself, excerpted here: CString CListCtrl::GetItemText(int nItem, int nSubItem) const { ASSERT(::IsWindow(m_hWnd)); LVITEM lvi; memset(&lvi, 0, sizeof(LVITEM)); lvi.iSubItem = nSubItem; CString str; int nLen = 128; int nRes; do { nLen *= 2; lvi.cchTextMax = nLen; lvi.pszText = str.GetBufferSetLength(nLen); nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); } while (nRes == nLen-1); str.ReleaseBuffer(); return str; } The chain of events is: the CustomDraw handler calls GetItemText which sends a LVM_GETITEMTEXT message, received by GetDispInfoPosList which puts the CString in the pool (calls AddPool). AddPool plays with the reference count so the CString can't be released and sends back its pool copy. The LPTSTR retVal also looks good every time and its still okay when pDispInfo->item.pszText is assigned in OnGetDispInfoPosList(). Then you're back in _AfxDispatchCmdMsg (which can hardly be screwed up). str still shows the correct value after ReleaseBuffer in GetItemText and is good when you are at the final brace. The next thing you know, you're in OnCustomDraw and the string is gone. Apparently ReleaseBuffer decrements the reference count to 0 and the string goes away when the stack unrolls. Thinking that Blazczak's pooling didn't anticipate CustomDraw calling GetItemText(), ultimately leading to one ReleaseBuffer() call he hadn't anticipated, I tried setting: const unsigned short StringPoolSize = 4; in the PosDialog's .h file and modifying the circular indexing in AddPool to use StringPoolSize (instead of 3), so it now reads: if ( ++nextFreeSlot > StringPoolSize-1 ) nextFreeSlot = 0; No change was evident. As soon as you return from GetItemText
-
GetItemText returns bad CString & can't change subitem color in CustomDrawI don't think eVC 3.0 will load the resource file if you have conflicting IDs in the same dialog (I've had to fix this after hand editing the resource files before). I have hundreds of calls where I cast from CWnd* to a *Ctrl of some sort - the eVC3 documentation for CWnd::GetDlgItem says: This method retrieves a pointer to the specified control or child window in a dialog box or other window. The pointer returned is usually cast to the type of control identified by nID. The struct pointed to by pCustomDraw looks normal as does the nmcd struct. You're absolutely right that GetItemTxt() could be returning an empty string. Its returning an empty string for every subitem in the list control. Why would that happen? The following: if ( cst.GetLength() > 0 ) { bool red = ( cst[0] == '-' ); CDC* dc = CDC::FromHandle( nmcd.hdc ); dc->SetTextColor( red ? RGB(255,0,0) : RGB(0,0,0) ); } prevents access violations, but doesn't explain why cst comes back "" for every subitem. In watching the code that responds to the LVN_GETDISPINFO messages to the PosListCtrl just before the CustomDraw messages come in, I can see normal looking CString values coming out of the LVN_GETDISPINFO handler: void CSPosDialog::OnGetDispInfoPosList( NMHDR* pNMHDR, LRESULT* pResult ) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; if ( pDispInfo->item.mask & LVIF_TEXT ) { SPosListItemInfo* pItem = (SPosListItemInfo*) pDispInfo->item.lParam; CString cst = this->GetPosItemText( pDispInfo->item.iItem, pDispInfo->item.iSubItem ); LPTSTR pBuf = this->AddPool( &cst ); pDispInfo->item.pszText = pBuf; } *pResult = 0; } CString CSPosDialog::GetPosItemText( int rr, int si ) { // get the sortCol for this subitem CBOSListCtrl* pLC = (CBOSListCtrl*)this->GetDlgItem( IDC_PosList ); short msi = pLC->MapSubitem( si ); // column reordering CHeaderCtrl* pHdr = pLC->GetHeaderCtrl(); short nItems = pHdr->GetItemCount(); if ( msi < 0 || msi >= nItems-1 ) return _T(""); SPosListItemInfo* pItem = (SPosListItemInfo*)pLC->GetItemData( rr ); if ( !pItem ) return _T(""); // impossible CPos* pos = pItem->thePos; bool itsTheTotalRow = ( pos == 0 ); double res; if ( msi == 8 ) return itsTheTotalRow ? _T("") : pos->note; unsigned short buf[20]; switch ( msi ) { case 0: swprintf( buf, "first col ..." ); // ... case 7: swprintf( buf, "other ..." );
-
GetItemText returns bad CString & can't change subitem color in CustomDrawTom, I appreciate the fast reply, but I'm fairly certain the dialog's ON_NOTIFY( NM_CUSTOMDRAW, IDC_PosList, OnCustDrwPosLst ) effectively filters out messages meant for controls other than PosList. When I get PosList messages in the debugger, the other controls seem to have finished painting, though the list control is the only one listening for CustomDraw messages. View derived classes apparently get their CustomDraw messages and (from what I can tell) CtrlList derived classes get REFLECTed CustomDraw messages on other targets, but CtrlLists on PocletPC 2002 don't get notified without the hack. Possibly comctl32 builds are customized per target. I'd love not to have the hack, but at this point, I just want GetItemText to stop crashing and subitem text to paint red when I tell it to. -Mike Landis
-
GetItemText returns bad CString & can't change subitem color in CustomDrawI am attempting to write a CListCtrl with CustomDraw for PocketPC 2002 in Embedded C++ 3.0. I hoped to have the list control handle custom draw messages (to display red text for negative numbers) so three dialogs could benefit. Have found that ON_NOTIFY_REFLECT messages never arrive in the control. Brad Spencer at Group1 Software verified that list controls don't receive custom draw events. I began catching NOTIFY messages in the dialog and directly handing them off to a custom draw message handler in the control. The handler code follows below: The PosDialog transfers control to a public function of the control which hands the call to a (protected) custom draw message handler. ON_NOTIFY( NM_CUSTOMDRAW, IDC_PosList, OnCustDrwPosLst ) void CPosDialog::OnCustDrwPosLst( NMHDR* pNMHDR, LRESULT* pResult ) { CRBListCtrl* pLC = (CRBListCtrl*)this->GetDlgItem( IDC_PosList ); pLC->ReflectCustomDraw( pNMHDR, pResult ); } The control passes control to a handler written to respond to ON_NOTIFY_REFLECT messages (which never arrive). In the control's .h file: public: void ReflectCustomDraw( NMHDR* pNMHDR, LRESULT* pResult ) { OnCustomDraw( pNMHDR, pResult); }; and its .cpp file: ON_NOTIFY_REFLECT( NM_CUSTOMDRAW, OnCustomDraw ) void CRBListCtrl::OnCustomDraw( NMHDR* pNMHDR, LRESULT* pResult ) { NMLVCUSTOMDRAW* pCustomDraw = (NMLVCUSTOMDRAW*)pNMHDR; NMCUSTOMDRAW nmcd = pCustomDraw->nmcd; int rr = nmcd.dwItemSpec; DWORD drawStage = nmcd.dwDrawStage; switch ( drawStage ) { case CDDS_PREPAINT: *pResult = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: *pResult = CDRF_NOTIFYSUBITEMDRAW; break; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: { // which subitem? int si = pCustomDraw->iSubItem; CString cst = GetItemText( rr, si ); bool red = (cst[0] == '-'); //access violation CDC* dc = CDC::FromHandle( nmcd.hdc ); dc->SetTextColor( red ? RGB(255,0,0) : RGB(0,0,0) ); *pResult = CDRF_NOTIFYPOSTPAINT; break; } case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: { CDC* dc = CDC::FromHandle( nmcd.hdc ); dc->SetTextColor( RGB(0,0,0) ); *pResult = CDRF_DODEFAULT; break; } default: break; } } GetItemText() above returns a CString which (if accessed) will produce a memory access violation. The other possibly relevant code is functionally identical to Mike Blazczak's AddPool() on p. 443 of "MFC with Visual C++ 6", excerpted here: LPTSTR CPosDialog::AddPool( CString* cst ) { CString& nxCStr = cstPool[ nextFreeSlo
-
Not receiving NM_CUSTOMDRAW messasgesNo, I didn't set owner draw. Archer & Whitechapel describe owner draw as a second option for handling ListViews (requiring you to draw the entire control in one fell swoop). When I check owner draw fixed in the resource editor (without making any other changes), the LVN_GETDISPINFO events that currently drive the drawing process in the content area stop being sent as well. Changing to owner draw therefore requires a complete redesign of the way the content area of the control is drawn (ouch). Archer & Whitechapel describe custom draw as a third approach, distinct from owner draw, giving you more flexibility and less responsibility (for clipping and such), i.e. I think its something else.
-
Not receiving NM_CUSTOMDRAW messasgesI have a report mode list control on which I've set up NOTIFY_REFLECT so I can change text color based on the content of the subitem, but I'm not receiving NM_CUSTOMDRAW messages. I've set up the message maps as described in Archer & Whitechapel's Visual C++ .Net (not to mention a slew of places on the web), but there must be something else required. My environment is eVC++ 3.0. I'm using the emulator (because it runs faster than an actual PocketPC. What else can I tell you? Any suggestions would be appreciated. Thanks, Mike