コード例 #1
0
/*----------------------------------------------------------------------------------------------
	This initializes the string based after the pssl and pss have been set. It takes into
	account whether the view is hierarchical or not.
	@param fHier
	@param pnt
----------------------------------------------------------------------------------------------*/
void AfDeFeCliRef::InitContents(bool fHier, PossNameType pnt)
{
	Assert(m_hvoPssl); // This must be set prior to calling this method.
	Assert(pnt < kpntLim);

	SuperClass::Init(); // Initialize the superclass.

	m_fHier = fHier;
	m_pnt = pnt;

	if (!m_pss)
		return; // If the reference isn't set, we don't have anything to display.

	ITsStringPtr qtss;
	ITsStrFactoryPtr qtsf;
	StrUni stu;
	PossListInfoPtr qpli;
	PossItemInfo * ppii;
	int ipss;

	qtsf.CreateInstance(CLSID_TsStrFactory);
	GetLpInfo()->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
	AssertPtr(qpli);
	ipss = qpli->GetIndexFromId(m_pss);
	ppii = qpli->GetPssFromIndex(ipss);
	AssertPtr(ppii);
	if (m_fHier)
		ppii->GetHierName(qpli, stu, m_pnt);
	else
		ppii->GetName(stu, m_pnt);
	int ws = ppii->GetWs();
	qtsf->MakeStringRgch(stu.Chars(), stu.Length(), ws, &qtss);
	m_qtss = qtss;
	qpli->AddNotify(this);
}
コード例 #2
0
/*----------------------------------------------------------------------------------------------
	Refresh the field from the data cache.
----------------------------------------------------------------------------------------------*/
void AfDeFeCliRef::UpdateField()
{
	// Get the item info from the cache.
	CustViewDaPtr qcvd;
	GetDataAccess(&qcvd);
	AssertPtr(qcvd);
	HVO hvoPss;
	CheckHr(qcvd->get_ObjectProp(m_hvoObj, m_flid, &hvoPss));
	m_pss = hvoPss;

	// Get the string from the poss cache.
	ITsStringPtr qtss;
	ITsStrFactoryPtr qtsf;
	StrUni stu;
	PossListInfoPtr qpli;
	PossItemInfo * ppii;
	int ipss;

	qtsf.CreateInstance(CLSID_TsStrFactory);
	int ws = m_ws;
	if (m_pss)
	{
		GetLpInfo()->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
		AssertPtr(qpli);
		ipss = qpli->GetIndexFromId(m_pss);
		if (ipss >= 0)
		{
			ppii = qpli->GetPssFromIndex(ipss);
			AssertPtr(ppii);
			if (m_fHier)
				ppii->GetHierName(qpli, stu, m_pnt);
			else
				ppii->GetName(stu, m_pnt);
			ws = ppii->GetWs();
		}
	}
	qtsf->MakeStringRgch(stu.Chars(), stu.Length(), ws, &qtss);
	m_qtss = qtss;

	// If we have an edit box, update the contents.
	if (m_hwnd)
	{
		// Setting the property causes a recursive call to OnChange, so we want to block it
		// from making a further change. (e.g., when you backspace to set the string to null
		// then tab to the next field, we want it to stay null, not go to the first item in
		// the list.)
		m_fRecurse = true;
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
	}
}
コード例 #3
0
/*----------------------------------------------------------------------------------------------
	The Ok button in the list chooser has been hit. Process the results from the list chooser.
	@param pplc Pointer to the dialog box being closed.
	----------------------------------------------------------------------------------------------*/
void AfDeFeCliRef::ChooserApplied(PossChsrDlg * pplc)
{
	// Get the output values.
	StrUni stu;
	ITsStringPtr qtss;
	ITsStrFactoryPtr qtsf;
	HVO pssId;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	pplc->GetDialogValues(pssId);
	m_pss = pssId;
	m_fRecurse = true;
	if (pssId)
	{
		PossListInfoPtr qpli;
		AfLpInfo * plpi = GetLpInfo();
		AssertPtr(plpi);
		plpi->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
		AssertPtr(qpli);
		int ipss = qpli->GetIndexFromId(pssId);
		PossItemInfo * ppii = qpli->GetPssFromIndex(ipss);
		if (m_fHier)
			ppii->GetHierName(qpli, stu, m_pnt);
		else
			ppii->GetName(stu, m_pnt);
		int ws = ppii->GetWs();
		qtsf->MakeStringRgch(stu.Chars(), stu.Length(), ws, &qtss);
		m_qtss = qtss;
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
	}
	else
	{
		m_qtss = NULL;
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, NULL);
	}
	// I (KenZ) don't fully understand this. But if a user enters the chooser, and opens a
	// list editor from there and adds a new item, closes the list editor, checks the new
	// item in the chooser, selects OK, then moves to the next record without moving from
	// the field, the added item is lost. We get ksyncPossList and ksyncAddPss sync messages
	// from the list editor, but for some reason we are getting an extra ksyncPossList
	// message after this method completes. That extra message is calling ListChanged which
	// calls UpdateField, which reloads our temporary cache from the main cache and wipes out
	// the change we just made. So until we can do something better, we'll save the changes
	// here to make sure the UpdateField doesn't wipe out our change.
	SaveEdit();
	::InvalidateRect(m_hwnd, NULL, true);
}
コード例 #4
0
/*----------------------------------------------------------------------------------------------
	Check to see if the edit box has valid data.  if so return true.  If not then put up a
	message to the user, then return false.
----------------------------------------------------------------------------------------------*/
bool CleDeFeString::BeginEdit(HWND hwnd, Rect & rc, int dxpCursor, bool fTopCursor)
{
	SuperClass::BeginEdit(hwnd, rc, dxpCursor, fTopCursor);

	CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(m_qadsc->MainWindow());
	Assert(pcmw);
	PossListInfoPtr qpli = pcmw->GetPossListInfoPtr();
	int ipss = qpli->GetIndexFromId(m_hvoObj);
	PossItemInfo * ppii = qpli->GetPssFromIndex(ipss);
	AssertPtr(ppii);

	// Save the primary string for comparison.
	AfLpInfo * plpi = pcmw->GetLpInfo();
	AssertPtr(plpi);
	CustViewDaPtr qcvd = pcmw->MainDa();
	AssertPtr(qcvd);
	CheckHr(qcvd->get_MultiStringAlt(m_hvoObj, m_flid, plpi->ActualWs(qpli->GetWs()), &m_qtssOld));

	switch(m_flid)
	{
		case kflidCmPossibility_Name:
		{
			StrUni stu;
			ppii->GetName(stu, kpntName);
			StrUni stuNewItem(kstidNewItem);
			if (stu.Left(stuNewItem.Length()) == stuNewItem)
				m_qrootb->MakeSimpleSel(true, true, true, true, NULL);
			break;
		}
		case kflidCmPossibility_Abbreviation:
		{
			StrUni stu;
			ppii->GetName(stu, kpntAbbreviation);
			StrUni stuNew(kstidNew);
			if (stu.Left(stuNew.Length()) == stuNew)
				m_qrootb->MakeSimpleSel(true, true, true, true, NULL);
			break;
		}
	}
	return true;
}
コード例 #5
0
/*----------------------------------------------------------------------------------------------
	This is the main interesting method of displaying objects and fragments of them.
	Here a CmPossibilityList is displayed by displaying its Records.
	So far we only handle records that are objects of type CmPossibility (or a subclass).
	A CmPossibility (or derived object) is displayed according to the stored specifications.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP CleCustDocVc::Display(IVwEnv * pvwenv, HVO hvo, int frag)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pvwenv);

	bool fFlat = m_qcmw->IsFilterActive() || m_qcmw->IsSortMethodActive();

	// Constant fragments
	switch(frag)
	{
	case kfrcdSubItem:	// Override for special treatment.
		Assert(false); // sub-items are handled as main items; see below.
		break;
	case kfrcdMainItem:	// Override for special treatment.
		{
			// Get the complete list of the items in the order in which they are displayed.
			ISilDataAccessPtr qsda;
			CheckHr(pvwenv->get_DataAccess(&qsda));
			RecMainWndPtr qrmw = dynamic_cast<RecMainWnd *>(m_qcmw.Ptr());
			HVO hvoMain = qrmw->GetFilterId();
			int flidMain = qrmw->GetFilterFlid();
			Assert(qrmw);
			int chvoMain;
			Vector<HVO> vhvoMain;
			CheckHr(qsda->get_VecSize(hvoMain, flidMain, &chvoMain));
			for (int ihvo = 0; ihvo < chvoMain; ihvo++)
			{
				HVO hvoTmp;
				CheckHr(qsda->get_VecItem(hvoMain, flidMain, ihvo, &hvoTmp));
				vhvoMain.Push(hvoTmp);
			}

			ITsTextPropsPtr qttp;
			PossItemInfo * ppii;
			PossListInfoPtr qpli;
			m_qlpi->GetPossListAndItem(hvo, m_qlpi->AnalWs(), &ppii, &qpli);
			int ilevel; ilevel = ppii->GetLevel(qpli);
			int ipss;
			for (ipss = 0; ipss < vhvoMain.Size(); ipss++)
			{
				if (hvo == vhvoMain[ipss])
					break;
			}
			Assert(ipss < vhvoMain.Size());

			if (fFlat)
				qttp = m_qttpMainFlat;
			else if (ilevel > 0)
			{
				if (ipss == qpli->GetCount() - 1)
					qttp = m_qttpSubLast;
				else
					qttp = m_qttpSub;
				// Adjust the indentation to match the current level.
				ITsPropsBldrPtr qtpb;
				CheckHr(qttp->GetBldr(&qtpb));
				CheckHr(qtpb->SetIntPropValues(ktptPadLeading, ktpvMilliPoint,
					(ilevel * kdzmpInch / 5)));  // indent 1/5" per level
				CheckHr(qtpb->GetTextProps(&qttp));
			}
			else if (ipss == 0) // first item
				qttp = m_qttpMainFirst;
			else if (ipss == qpli->GetCount() - 1)
				qttp = m_qttpMainLast;
			else
				qttp = m_qttpMain;
			CheckHr(pvwenv->put_Props(qttp));
			BodyOfRecord(pvwenv, hvo, qttp);
			break;
		}
	default:
		return SuperClass::Display(pvwenv, hvo, frag);
	}
	return S_OK;

	END_COM_METHOD(g_fact1, IID_IVwViewConstructor)
}
コード例 #6
0
/*----------------------------------------------------------------------------------------------
	The edit box changed. We need to validate what was done.
	@param pedit
	@return
----------------------------------------------------------------------------------------------*/
bool AfDeFeCliRef::OnChange(AfDeFeEdBoxBut::DeEdit * pedit)
{
	if (m_fRecurse)
	{
		m_fRecurse = false;
		return true;
	}
	if (!m_hwnd)
		return true; // We aren't completely set up yet, so ignore this.

	// Get the characters from the edit box.
	ITsStringPtr qtss;
	::SendMessage(m_hwnd, FW_EM_GETTEXT, 0, (LPARAM)&qtss);

	int ichMin;
	int ichLim;
	::SendMessage(m_hwnd, EM_GETSEL, (WPARAM)&ichMin, (LPARAM)&ichLim);

	int cchTyped; // number of characters in the typed string
	// JohnT: use a StrUni rather than an StrUniBuf, because some user sometime will accidentally
	// paste something long here, and performance here is not critical.
	StrUni stuTyped;
	OLECHAR * pchBuf;
	qtss->get_Length(&cchTyped);

	if (cchTyped > kcchPossNameAbbrMax)
	{
		if (ichMin == cchTyped)
			ichMin = kcchPossNameAbbrMax;
		if (ichLim == cchTyped)
			ichLim = kcchPossNameAbbrMax;
		cchTyped = kcchPossNameAbbrMax;
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
	}

	stuTyped.SetSize(cchTyped, &pchBuf);
	qtss->FetchChars(0, cchTyped, pchBuf);

#ifdef DEBUG_THIS_FILE
	StrAnsi sta;
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_ch=%d; ichMin=%d; ichLim=%d; pedit->m_cchMatched=%d; cchTyped=%d.\n",
										 pedit->m_ch,    ichMin,    ichLim,    pedit->m_cchMatched,    cchTyped);
	OutputDebugString(sta.Chars());
#endif

	bool fTypeAhead = false; // allow type ahead only when adding characters at end of current item
							// or backspacing at end of current item.
	bool fNeedCompare;
	if (pedit->m_ch == 0) // (see kcidEditPaste special code)
	{
		// If we pasted something, force a compare.
		fNeedCompare = true;
	}
	else if (ichMin == pedit->m_cchMatched + 1 && pedit->m_ch != VK_BACK && pedit->m_ch != VK_DELETE)
	{
		// Need to compare if we typed a character and we are one greater than last match.
		fNeedCompare = true;
		if (cchTyped == ichMin)
		{
			fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
			sta.Format("OnChange: 1 - setting fTypeAhead to true.\n");
			OutputDebugString(sta.Chars());
#endif
		}
	}
	else if (ichMin > pedit->m_cchMatched)
	{
		// Don't compare any other time we are past the last match.
		fNeedCompare = false;
	}
//	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != kscDelForward))
	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != 46))
	{
		// Need to compare if we typed a character and we are at the end of the item
		// Need to compare if we delete the last character in the non-type-ahead string
		fNeedCompare = true;
		fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
		sta.Format("OnChange:  kscDelForward=%d.\n");
		OutputDebugString(sta.Chars());
		sta.Format("OnChange: 2 - setting fTypeAhead to true.\n");
		OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Always compare if we are not past the last match.
		fNeedCompare = true;
	}

	int cch;

	// Since the edit box deletes the selection on backspace, we need to use
	// some extra logic to make backspace actually move the selection back.
	if (pedit->m_cchMatched && pedit->m_ch == VK_BACK && m_pss)
	{
		// If we had a previous match and we got a backspace, we always decrement the matched
		// characters and start looking at that point.
		cch = --pedit->m_cchMatched;
	}
	else
	{
		// Otherwise we start looking at the cursor location.
		cch = ichMin;
	}

	AfLpInfo * plpi = GetLpInfo();
	AssertPtr(plpi);

	PossListInfoPtr qpli;
	plpi->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
	AssertPtr(qpli);

	PossItemInfo * ppii = NULL;
	ComBool fExactMatch = false;

	fNeedCompare = true;

	if (cchTyped == 0)
	{
		// If nothing to match, get the first item in the possibility list. If we are
		// already at that item, remove the item. If we are already cleared, do nothing.
		if (!m_pss)
			return true;
		// If everything is highlighted, we want to clear the item with Del or Bsp.
		// But when we are backspacing, if there is only one character left and we backspace
		// over that, we want to switch to the first item in the list.
		ppii = qpli->GetPssFromIndex(0);
		if (ichMin != 1)
		{
			m_pss = 0;
			m_qtss = NULL;
			pedit->m_cchMatched = 0; // Keep cursor at beginning of item.
			m_fRecurse = true;
			::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
			return true;
		}
	}
	else if (fNeedCompare)
	{
		// Try to find an item that matches what the user typed in the possibility list.
		StrUni stuMatch(stuTyped);
/////		stuMatch.Replace(cch, stuMatch.Length(), L"");// Delete chars to right of cursor.
		Locale loc = GetLpInfo()->GetLocale(m_ws);
		if (m_fHier)
		{
			ppii = qpli->FindPssHier(stuMatch.Chars(), loc, m_pnt, fExactMatch);
		}
		else
		{
			ppii = qpli->FindPss(stuMatch.Chars(), loc, m_pnt);
		}

		if (ppii)
		{
			// found a match that starts with stuTyped
			int ipssTemp;

			// TODO TimP:  check for hierarchy.  If stuTyped contains hierarchy,

			// Was the match exact (rather than just starting with stuTyped) ?
			if (fExactMatch) // May have matched in the FindPssHier() call above.
			{
#ifdef DEBUG_THIS_FILE
				sta.Format("OnChange:  Exact match (hier).\n");
				OutputDebugString(sta.Chars());
#endif
			}
			else
			{
				fExactMatch = ! qpli->PossUniqueName(-1, stuTyped, m_pnt, ipssTemp);
				if (fExactMatch)
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Exact match.\n");
					OutputDebugString(sta.Chars());
#endif
					// in case FindPss() above matches "ABC" but "AB" is also in list.
					ppii = qpli->GetPssFromIndex(ipssTemp);
				}
				else
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Not exact match.\n");
					OutputDebugString(sta.Chars());
#endif
				}
			}
		}
	}
	else
		ppii = NULL;

	StrUni stuFound;
	int ws = m_ws;
	if (ppii && (fTypeAhead || fExactMatch))
	{
		// If found, process the new item.
		int pss = ppii->GetPssId();
		m_pss = pss;
		if (m_fHier)
			ppii->GetHierName(qpli, stuFound, m_pnt);
		else
			ppii->GetName(stuFound, m_pnt);
		ws = ppii->GetWs();

		// If the last character was a delimiter, we need to set cch accordingly.
		if (m_fHier && (stuTyped.Length() > 0) && (pedit->m_ch != VK_BACK) &&
			(stuTyped.GetAt(stuTyped.Length() - 1) == kchHierDelim))
		{
			// Need to set cch to the position of the last delimiter.
			cch = stuFound.FindCh(kchHierDelim, cch - 1) + 1;
		}

		pedit->m_cchMatched = cch;
	}
	else
	{
		// Something illegal was typed. Assume they are adding a new item.
		if (pedit->m_cchMatched + 1 == cch && pedit->m_ch != VK_BACK)
			::MessageBeep(MB_ICONEXCLAMATION); // Beep on the first unmatched character.
		// Underline the string with a red squiggly.
		ITsIncStrBldrPtr qtisb;
		qtisb.CreateInstance(CLSID_TsIncStrBldr);
		qtisb->SetIntPropValues(ktptWs, ktpvDefault, m_ws);
		CheckHr(qtisb->SetIntPropValues(ktptUnderColor, ktpvDefault, kclrRed));
		CheckHr(qtisb->SetIntPropValues(ktptUnderline, ktpvEnum, kuntSquiggle));
		qtisb->AppendRgch(stuTyped.Chars(), stuTyped.Length());
		qtisb->GetString(&m_qtss);
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
		m_pss = 0; // We no longer have a matched HVO.
		return true;
	}

	// Update the edit box text and selection.
	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	qtsf->MakeStringRgch(stuFound.Chars(), stuFound.Length(), ws, &qtss);
	m_qtss = qtss;

#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_cchMatched=%d; stuFound.Length()=%d; ichMin=%d; ichLim=%d.\n",
										 pedit->m_cchMatched,    stuFound.Length(),    ichMin,    ichLim);
	OutputDebugString(sta.Chars());
#endif

	m_fRecurse = true; // Shortcut the recursion caused by the next instruction.
	if (fTypeAhead)
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, pedit->m_cchMatched, stuFound.Length());
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  NOT type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}

	return true;
}
コード例 #7
0
/*----------------------------------------------------------------------------------------------
	Something has changed in the possibility list.
----------------------------------------------------------------------------------------------*/
void RnDeFeRoleParts::ListChanged(int nAction, HVO hvoPssl, HVO hvoSrc, HVO hvoDst, int ipssSrc,
	int ipssDst)
{
	if (hvoPssl != m_psslRole)
	{
		// Process changes for people lists.
		SuperClass::ListChanged(nAction, hvoPssl, hvoSrc, hvoDst, ipssSrc, ipssDst);
		return;
	}

	// If someone deleted the role we are interested in we need to clean up.
	if (hvoSrc == m_pssRole && nAction == kplnaDelete)
	{
		// Remove the notifier for the role list.
		Assert(m_psslRole);
		PossListInfoPtr qpli;
		GetLpInfo()->LoadPossList(m_psslRole, m_wsMagic, &qpli);
		AssertPtr(qpli);
		qpli->RemoveNotify(this);
		m_psslRole = 0;
		m_pssRole = 0;
	}
	// At this point we are not getting kplnaMerged at all since we are just deleting all
	// fields and recreating new ones. But at some point down the road we may want to switch
	// to where we don't delete and recreate. This would be the right action to take then.
	if (hvoSrc == m_pssRole && nAction == kplnaMerged)
	{
		// Switch to the new role.
		m_pssRole = hvoDst;
	}
	// Now reset the label in case we changed.
	// Use Participants for the unspecified editor label.
	ITsStringPtr qtssName;
	int wsUser = GetLpInfo()->GetDbInfo()->UserWs();
	AfUtil::GetResourceTss(kstidTlsOptParticipants, wsUser, &qtssName);
	ITsStringPtr qtssHelp = m_qfsp->m_qtssHelp;
	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	if (m_pssRole)
	{
		PossItemInfo * ppii;
		GetLpInfo()->GetPossListAndItem(m_pssRole, wsUser, &ppii, NULL);
		StrUni stuName;  // the Role's name
		ppii->GetName(stuName, m_pnt);
		qtsf->MakeStringRgch(stuName.Chars(), stuName.Length(), wsUser, &qtssName);

		ITsIncStrBldrPtr qtisb;
		qtisb.CreateInstance(CLSID_TsIncStrBldr);

		// Add the first substring.
		qtisb->AppendTsString(m_qfsp->m_qtssHelp);

		// Add the second substring.
		StrUni stuTemp;
		stuTemp.Load(kstidRnRoledPartic_HelpA);
		qtisb->AppendRgch(stuTemp.Chars(), stuTemp.Length());

		// Turn bold on.
		qtisb->SetIntPropValues(ktptBold, ktpvEnum, kttvForceOn);
		// Add the Role's name
		qtisb->AppendRgch(stuName.Chars(), stuName.Length());
		// Turn bold off.
		qtisb->SetIntPropValues(ktptBold, ktpvEnum, kttvOff);

		// Add the third substring.
		stuTemp.Load(kstidRnRoledPartic_HelpB);
		qtisb->AppendRgch(stuTemp.Chars(), stuTemp.Length());

		// Get the completed TsString.
		qtisb->GetString(&qtssHelp);
	}
	m_qtssLabel = qtssName;
	m_qtssHelp = qtssHelp;

	// Force the label to redraw.
	Rect rcLabel;
	::GetClientRect(m_qadsc->Hwnd(),&rcLabel);
	Rect rcEdit(m_rcClip);
	if (m_hwnd)
	{
		// We have an open edit box, so get the correct coordinates for the client window.
		::GetClientRect(m_hwnd, &rcEdit);
		::MapWindowPoints(m_hwnd, m_qadsc->Hwnd(), (POINT *)&rcEdit, 2);
	}
	rcLabel.top = rcEdit.top;
	rcLabel.bottom = rcEdit.bottom;
	rcLabel.right = m_qadsc->GetTreeWidth();
	::InvalidateRect(m_qadsc->Hwnd(), &rcLabel, false);
}
コード例 #8
0
/*----------------------------------------------------------------------------------------------
	Close the current editor, saving changes that were made.  This also updates the the cache
	if the name or abbr fields were edited, this then causing the treebar to be updated.
	@param fForce True if we want to force the editor closed without making any
		validity checks or saving any changes.
----------------------------------------------------------------------------------------------*/
void CleDeFeString::EndEdit(bool fForce)
{
	if (fForce)
	{
		SuperClass::EndEdit(fForce);
		return;
	}

	CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(MainWindow());
	Assert(pcmw);

	PossListInfoPtr qpli = pcmw->GetPossListInfoPtr();
	int ipss = qpli->GetIndexFromId(m_hvoObj);
	if (ipss < 0)
	{
		SuperClass::EndEdit(fForce); // Closing an old editor after an item was removed.
		return;
	}
	PossItemInfo * ppii = qpli->GetPssFromIndex(ipss);
	AssertPtr(ppii);
	StrUni stu;

	const OLECHAR * prgwch;
	int cch;
	ITsStringPtr qtss;
	AssertPtr(m_qadsc->MainWindow());
	AfLpInfo * plpi = m_qadsc->MainWindow()->GetLpInfo();
	AssertPtr(plpi);
	AfDbInfo * pdbi;
	pdbi = plpi->GetDbInfo();
	AssertPtr(pdbi);
	int wsMagic = qpli->GetWs();
	int ws = plpi->ActualWs(wsMagic);

	// At this point, all strings in a PossList cache are assumed to have the same writing system.
	// However, if that writing system is missing, a non-null string from a different writing system is
	// loaded. Thus if FRN is the writing system for the PossList cache, we can't tell from the
	// cache whether the string we are getting is FRN or ENG, or some other writing system. When
	// we display strings in this editor, we show actual strings for each writing system shown.
	// Suppose we are showing FRN and ENG, but FRN is missing. If a person edits the ENG
	// string that is showing, the user would expect the tree to reflect this change, since
	// FRN is still missing. However we can't do this at this point because we don't know
	// which writing system is actually being substituted in the tree. It could actually be a GER
	// string because there also wasn't an ENG string. So until we cache encodings with each
	// string, the best we can do is only modify the PossList cache if the string for the
	// primary writing system changed. In that case, we now have a FRN string, so it should show
	// in the tree as well.
	CustViewDaPtr qcvd = pcmw->MainDa();
	AssertPtr(qcvd);

	// Get the current primary string.
	CheckHr(qcvd->get_MultiStringAlt(m_hvoObj, m_flid, ws, &qtss));
	if (qtss)
	{
		qtss->LockText(&prgwch, &cch);
		qtss->UnlockText(prgwch);
	}

	// Trim leading and trailing space characters.
	UnicodeString ust(prgwch, cch);
	ust.trim();
	stu.Assign(ust.getBuffer(), ust.length());

	// We don't expect to use this for anything except name or abbr.
	Assert(m_flid == kflidCmPossibility_Name || m_flid == kflidCmPossibility_Abbreviation);
	// We don't allow long strings.
	if (stu.Length() > kcchPossNameAbbrMax) // Need constant here and the line below.
	{
		::MessageBeep(MB_ICONEXCLAMATION); // Beep if we truncated the length.
		stu.Replace(kcchPossNameAbbrMax, stu.Length(), L"");
	}

	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	qtsf->MakeStringRgch(stu.Chars(), stu.Length(), ws, &qtss);

	// If we changed the length, store the trimmed string.
	if (cch != stu.Length())
	{
		// Check if the record has been edited by someone else since we first loaded the data.
		HRESULT hrTemp;
		if ((hrTemp = qcvd->CheckTimeStamp(m_hvoObj)) != S_OK)
		{
			// If it was changed and the user does not want to overwrite it, perform a refresh
			// so the displayed field will revert to its original value.
			CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1));
			return;
		}

		// Update the value in the cache and refresh views.
		CheckHr(qcvd->SetMultiStringAlt(m_hvoObj, m_flid, ws, qtss));
		CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1));
	}

	SuperClass::EndEdit(fForce);

	// See if the primary string has changed.
	ComBool fEqual;
	CheckHr(qtss->Equals(m_qtssOld, &fEqual));
	if (fEqual)
		return; // No change was made, so we don't need to do anything else.

	// A change was made.
	if (m_flid != kflidCmPossibility_Name && m_flid != kflidCmPossibility_Abbreviation)
		return; // Nothing more to do if it isn't a name or abbreviation.

	// We've changed the primary name or abbreviation, so update the PossList cache.
	ppii->SetName(stu, m_flid == kflidCmPossibility_Name ? kpntName : kpntAbbreviation);

	if (qpli->GetIsSorted())
	{
		// The list is sorted, so we need to move the item to its new location.
		if (qpli->PutInSortedPosition(m_hvoObj, false))
		{
			int ihvo;
			pcmw->LoadData();
			HvoClsidVec & vhc = pcmw->Records();
			for (ihvo = vhc.Size(); --ihvo >= 0; )
			{
				if (vhc[ihvo].hvo == m_hvoObj)
					break;
			}
			Assert(ihvo >= 0); // Should have found item.
			pcmw->SetCurRecIndex(ihvo);
		}
	}
	// We can't do a sync in this method that opens new editors, so just flag
	// that it needs to be done.
	// We need to sync if either name or abbreviation has changed. Even though we may only
	// be showing one or the other in our lists, there may be overlays or something else
	// showing the other, so to be safe, we need to do a sync if either changed.
	dynamic_cast<CleDeSplitChild *>(m_qadsc.Ptr())->SetNeedSync(true);
}
コード例 #9
0
/*----------------------------------------------------------------------------------------------
	Check to see if the edit box has valid data.  if so return true.  If not then put up a
	message to the user, then return false.
----------------------------------------------------------------------------------------------*/
bool CleDeFeString::IsOkToClose(bool fWarn)
{
	CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(m_qadsc->MainWindow());
	Assert(pcmw);

	IVwSelectionPtr qvwsel;
	CheckHr(m_qrootb->get_Selection(&qvwsel));
	if (qvwsel)
	{
		ComBool fOk;
		CheckHr(qvwsel->Commit(&fOk));
	}

	PossListInfoPtr qpli = pcmw->GetPossListInfoPtr();
	int ipss = qpli->GetIndexFromId(m_hvoObj);
	StrUni stuNew;

	const OLECHAR * prgwch;
	int cch;
	ITsStringPtr qtss;
	CustViewDaPtr qcvd;

	GetDataAccess(&qcvd);
	AssertPtr(qcvd);
	int ws = m_qsvc->WritingSystems()[0];

	CheckHr(qcvd->get_MultiStringAlt(m_hvoObj, m_flid, ws, &qtss));
	Assert(qtss);
	qtss->LockText(&prgwch, &cch);
	qtss->UnlockText(prgwch);

	// Trim leading and trailing space characters.
	UnicodeString ust(prgwch, cch);
	ust.trim();
	stuNew.Assign(ust.getBuffer(), ust.length());

	//  Obtain pointer to IOleDbEncap interface.
	IOleDbEncapPtr qode;
	IOleDbCommandPtr qodc;
	StrUni stuSql;
	ComBool fIsNull;
	ComBool fMoreRows;
	AssertPtr(m_qadsc->MainWindow());
	AfLpInfo * plpi = m_qadsc->MainWindow()->GetLpInfo();
	AssertPtr(plpi);
	AfDbInfo * pdbi = plpi->GetDbInfo();
	AssertPtr(pdbi);
	pdbi->GetDbAccess(&qode);
	AssertPtr(qode);
	CheckHr(qode->CreateCommand(&qodc));
	int cpii = qpli->GetCount();

	if ((m_flid == kflidCmPossibility_Name) || (m_flid == kflidCmPossibility_Abbreviation))
	{
		// Make sure it does not have a ":" or a " - " in the string
		int ich = stuNew.FindStr(L":");
		StrUni stuTmp;
		bool fFixed = false;
		while (ich > 0)
		{
			stuNew.Replace(ich,ich + 1,"-");
			fFixed = true;
			ich = stuNew.FindStr(L":");
		}
		ich = stuNew.FindStr(L" - ");
		while (ich > 0)
		{
			stuNew.Replace(ich,ich + 3,"-");
			fFixed = true;
			ich = stuNew.FindStr(L" - ");
		}
		if (fFixed)
		{
			if (fWarn)
			{
				ITsStrFactoryPtr qtsf;
				qtsf.CreateInstance(CLSID_TsStrFactory);
				qtsf->MakeStringRgch(stuNew.Chars(), stuNew.Length(), pcmw->UserWs(), &qtss);
				CheckHr(qcvd->SetMultiStringAlt(m_hvoObj, m_flid, ws, qtss));
				CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1));
				StrApp strMsg(kstidFixedStr);
				StrApp strTitle(kstidFixedStrTitle);
				::MessageBox(m_hwnd, strMsg.Chars(), strTitle.Chars(),
					MB_OK | MB_ICONINFORMATION);
			}
			return false;
		}
	}

	if (qpli->GetAllowDup())
		return true;

	ILgWritingSystemFactoryPtr qwsf;
	pdbi->GetLgWritingSystemFactory(&qwsf);
	AssertPtr(qwsf);
	switch (m_flid)
	{
		case kflidCmPossibility_Name:
		{
			for (int ipii = 0; ipii < cpii; ipii++)
			{
				if (ipii == ipss)
					continue;
				PossItemInfo * ppii = qpli->GetPssFromIndex(ipii);
				AssertPtr(ppii);
				StrUni stu;
				ppii->GetName(stu, kpntName);
				if (stu == stuNew)
				{
					stuSql.Format(L"select ws from CmPossibility_Name "
						L"where obj = %d and ws = %d",
						ppii->GetPssId(), ws);
					CheckHr(qode->CreateCommand(&qodc));
					CheckHr(qodc->ExecCommand(stuSql.Bstr(), knSqlStmtSelectWithOneRowset));
					CheckHr(qodc->GetRowset(0));
					CheckHr(qodc->NextRow(&fMoreRows));

					if (fMoreRows)
					{
						if (fWarn)
						{
							// this name already exists
							IWritingSystemPtr qws;
							CheckHr(qwsf->get_EngineOrNull(ws, &qws));
							AssertPtr(qws);
							SmartBstr sbstr;
							qws->get_Name(ws, &sbstr);

							StrUni stu(kstidDupItemName);
							StrUni stuMsg;
							stuMsg.Format(stu,sbstr.Chars());
							StrApp str(stuMsg);
							StrApp strTitle(kstidDupItemTitle);
							::MessageBox(m_hwnd, str.Chars(), strTitle.Chars(),
								MB_OK | MB_ICONINFORMATION);
						}
						return false;
					}
				}
			}
			break;
		}
		case kflidCmPossibility_Abbreviation:
		{
			for (int ipii = 0; ipii < cpii; ipii++)
			{
				if (ipii == ipss)
					continue;
				PossItemInfo * ppii = qpli->GetPssFromIndex(ipii);
				AssertPtr(ppii);
				StrUni stu;
				ppii->GetName(stu, kpntAbbreviation);
				if (stu == stuNew)
				{
					stuSql.Format(L"select ws from CmPossibility_Abbreviation "
						L"where obj = %d and ws = %d",
						ppii->GetPssId(), ws);
					CheckHr(qode->CreateCommand(&qodc));
					CheckHr(qodc->ExecCommand(stuSql.Bstr(), knSqlStmtSelectWithOneRowset));
					CheckHr(qodc->GetRowset(0));
					CheckHr(qodc->NextRow(&fMoreRows));

					if (fMoreRows)
					{
						if (fWarn)
						{
							// this abbreviation already exists
							IWritingSystemPtr qws;
							CheckHr(qwsf->get_EngineOrNull(ws, &qws));
							AssertPtr(qws);
							SmartBstr sbstr;
							qws->get_Name(ws, &sbstr);

							StrUni stu(kstidDupItemAbbr);
							StrUni stuMsg;
							stuMsg.Format(stu,sbstr.Chars());
							StrApp str(stuMsg);
							StrApp strTitle(kstidDupItemTitle);
							::MessageBox(m_hwnd, str.Chars(), strTitle.Chars(),
								MB_OK | MB_ICONINFORMATION);
						}
						return false;
					}
				}
			}
			break;
		}
	}
	return true;
}