How to make a checkbox to enable checkboxes in a fragment - android-studio

I need help making a Checkbox that when is checked it enables the other 4 checkboxes so i can decide which dice rolls
this is the part of the code where the botton make the app works is a dice app
the 4 checkboxes are disabled at the start of the app
private void rollDice () {
int d1 = this.random.nextInt(3) - 1;
int d2 = this.random.nextInt(3) - 1;
int d3 = this.random.nextInt(3) - 1;
int d4 = this.random.nextInt(3) - 1;
if (cb1.isChecked()) {
switch (d1) {
case -1:
iv_dice1.setImageResource(R.drawable.dice_1);
break;
case 0:
iv_dice1.setImageResource(R.drawable.dice_2);
break;
case +1:
iv_dice1.setImageResource(R.drawable.dice_3);
break;
}
}
if (cb2.isChecked()) {
switch (d2) {
case -1:
iv_dice2.setImageResource(R.drawable.dice_4);
break;
case 0:
iv_dice2.setImageResource(R.drawable.dice_5);
break;
case +1:
iv_dice2.setImageResource(R.drawable.dice_6);
break;
}
}
if (cb3.isChecked()) {
switch (d3) {
case -1:
iv_dice3.setImageResource(R.drawable.d_1);
break;
case 0:
iv_dice3.setImageResource(R.drawable.d_2);
break;
case +1:
iv_dice3.setImageResource(R.drawable.d_3);
break;
}
}
if (cb4.isChecked()) {
switch (d4) {
case -1:
iv_dice4.setImageResource(R.drawable.d_4);
break;
case 0:
iv_dice4.setImageResource(R.drawable.d_5);
break;
case +1:
iv_dice4.setImageResource(R.drawable.d_6);
break;
}
}
}
}

You should try to first find your checkbox object:
CheckBox checkBox = (CheckBox) findViewById(R.id.checkBoxID);
Then you attach an EventListener listening for Change-Events and there you can enable your other checkboxes:
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if ( isChecked )
{
// enable other checkboxes
cb1.setEnabled(true);
cb2.setEnabled(true);
cb3.setEnabled(true);
cb4.setEnabled(true);
}
}
});

Related

How to fix invalid query filter exception when dealing with LDAP search?

Escaping comma in distinguished name is throwing "Invalid LDAP search query".
I am trying to fix a security ldap injection violation. When I search with dn, special characters needs to be escaped per owasp recommendation. So, I have added the below method to escape.
The below method return this string for dn "ou=User Accounts\,dc=abc\,dc=com" and same passed to ldap. Finally, it throws "Invalid LDAP search query".
public static String encodeDistinguishedName(String name) {
StringBuilder sb = new StringBuilder();
if ((name.length() > 0) && ((name.charAt(0) == ' ') || (name.charAt(0) == '#'))) {
sb.append('\\'); // add the leading backslash if needed
}
for (int i = 0; i < name.length(); i++) {
char curChar = name.charAt(i);
switch (curChar) {
case '\\':
sb.append("\\\\");
break;
case ',':
sb.append("\\\\,");
break;
case '+':
sb.append("\\+");
break;
case '"':
sb.append("\\\"");
break;
case '<':
sb.append("\\<");
break;
case '>':
sb.append("\\>");
break;
case ';':
sb.append("\\;");
break;
default:
sb.append(curChar);
}
}
if ((name.length() > 1) && (name.charAt(name.length() - 1) == ' ')) {
sb.insert(sb.length() - 1, '\\'); // add the trailing backslash if needed
}
return sb.toString();
}
public static final String encodeSearchFilter(String filter) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filter.length(); i++) {
char curChar = filter.charAt(i);
switch (curChar) {
case '\\':
sb.append("\\5c");
break;
case '*':
sb.append("\\2a");
break;
case '(':
sb.append("\\28");
break;
case ')':
sb.append("\\29");
break;
case '\u0000':
sb.append("\\00");
break;
default:
sb.append(curChar);
}
}
return sb.toString();
}

Creating Custom attribute

I have to show the price in a mask based on the alphabets setup in the configuration screen.
I am trying to write a custom attribute for the DAC field so that I can use the same in reports.
I have given the existing piece of code below. The function calls are working fine and i am using it for getting value, but I am not able to use it as DAC Attribute
#region PXPriceMaskAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXPriceMaskAttribute : PXStringAttribute
{
#region Ctor
public PXPriceMaskAttribute()
: base()
{
}
#endregion
#region Implementation
/// <exclude/>
///
public static string GetPriceMask(PXGraph grp , decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
MemoSetUp setUp = PXSelect<MemoSetUp>.Select(grp);
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public static string GetPriceMask(MemoSetUp setUp, decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
if (e.NewValue != null && !e.Cancel)
{
decimal? value = Convert.ToDecimal(e.NewValue);
e.NewValue = GetPriceMask(sender.Graph, value);
}
}
/// <exclude/>
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (_AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
{
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, _Length, _IsUnicode, _FieldName, _IsKey, null, _InputMask, null, null, null, null);
}
}
/// <exclude/>
#endregion
}
#endregion
The above piece of code is not working. What is the best way to fix the issue.
Update
I have created a BQL Evaluator and attached to DAC and it always returns zero.
public class PriceRounding<PriceField> : BqlFormulaEvaluator<PriceField>, IBqlOperand
where PriceField : IBqlField
{
public override object Evaluate(PXCache cache, object item,
Dictionary<Type, object> pars)
{
PXFieldState fState = cache.GetStateExt<PriceField>(item) as PXFieldState;
return GetSortOrderValueExt(Convert.ToDecimal(fState.Value));
}
public decimal GetSortOrderValueExt(decimal dVal)
{
dVal = Math.Round(dVal, 0);
decimal divider = (dVal <= 5000) ? 25m : (dVal <= 10000) ? 50m : (dVal <= 100000) ? 100m : 500m;
decimal reminder = dVal % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
dVal = dVal + diff;
}
return dVal;
}
}
The DAC field
#region RetailPrice
public abstract class retailPrice : PX.Data.IBqlField
{
}
protected decimal? _RetailPrice;
[PXDBDecimal(2)]
[PXUIField(DisplayName = "Retail Price")]
[PXFormula(typeof(PriceRounding<InfoInventoryItemAttributeExtNV.retailPrice>))]
public virtual decimal? RetailPrice
{
get
{
return this._RetailPrice;
}
set
{
this._RetailPrice = value;
}
}
#endregion
Consider using custom BQL Function (derived from BqlFormulaEvaluator) – You can refer out-of-box custom BQL functions available in formula sub-folder of PX.Objects source code. Or you can refer KB article where such custom BQL function HierarchySorting is used.
The following code works fine for me for custom rounding off than using BQL Formula Evaluator
#region PXDBPriceRoundingAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXDBPriceRoundingAttribute : PXDBDecimalAttribute
{
#region Implementation
public static decimal Round(decimal value)
{
value = Math.Round(value, 0);
decimal divider = (value <= 5000) ? 25m : (value <= 10000) ? 50m : (value <= 100000) ? 100m : 500m;
decimal reminder = value % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
value = value + diff;
}
return value;
}
public override void RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
base.RowSelecting(sender, e);
string name = _FieldName;
if (sender.GetValue(e.Row, _FieldOrdinal) == null)
{
sender.SetValue(e.Row, _FieldOrdinal, 0m);
}
else
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
base.FieldUpdating(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value??0m);
if((value??0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public void FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
base.RowPersisting(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
#endregion
#region Initialization
public override void CacheAttached(PXCache sender)
{
base.CacheAttached(sender);
_Precision = CommonSetupDecPl.PrcCst;
}
#endregion
}
#endregion
Using In DAC
#region WholeSalesPrice
public abstract class wholeSalesPrice : PX.Data.IBqlField
{
}
protected decimal? _WholeSalesPrice;
[PXDBPriceRoundingAttribute()]
[PXUIField(DisplayName = "Wholesale Price")]
public virtual decimal? WholeSalesPrice
{
get
{
return this._WholeSalesPrice;
}
set
{
this._WholeSalesPrice = value;
}
}
#endregion

Transaction Module for a Banking app - Is Answered

I need help in Transaction Class:
The transaction class with contain the following data:
A counter to track the number of transactions. Increment for every deposit or
withdrawal made. A customer is allowed to make up to 5 transactions on a single login.
o A history of the 5 possible transactions. This will be an array of dollar amounts where a
negative amount is a withdrawal and a positive number is a deposit. Clear the history
each time a customer logs in.
Transaction objects will perform the following:
o Update history to reflect any transaction made when a user is logged in. Keep track of
each transaction value made as described above in the transaction data section. After
each transaction, increment the transaction counter.
o Clear history of all amounts stored and reset the transaction count
Menu Class
Account[] myCustAcc = new Account[10];
Transaction myCustTrans = new Transaction();
string adminInput = "" adminName = "adm1";
int pinInput = 0, adminChoice = 0,adminPin = 9999,user = 0, input, custCount = 0;
Boolean adminQuit = false;
Boolean appQuit = false;
myCustAcc[0] = new Account();
myCustAcc[0].setCustomerFirstName("Sneha");
myCustAcc[0].setCustomerLastName("Dadhania");
myCustAcc[0].setCustomerAddress("2323 S Dobson Rd");
myCustAcc[0].setCustomerState("AZ");
myCustAcc[0].setCustomerZip(85001);
myCustAcc[0].setCustomerUserName("SMD28");
myCustAcc[0].setCustomerPin(3333);
myCustAcc[0].setCustomerBalance(87000);
custCount++;
myCustAcc[1] = new Account();
myCustAcc[1].setCustomerFirstName("Justine");
myCustAcc[1].setCustomerLastName("Timberlake");
myCustAcc[1].setCustomerAddress("TriBeca, New York. ");
myCustAcc[1].setCustomerState("NY");
myCustAcc[1].setCustomerZip(11013);
myCustAcc[1].setCustomerUserName("JTL00");
myCustAcc[1].setCustomerPin(8989);
myCustAcc[1].setCustomerBalance(34);
custCount++;
myCustAcc[2] = new Account();
myCustAcc[2].setCustomerFirstName("Guest");
myCustAcc[2].setCustomerLastName("Ghost");
myCustAcc[2].setCustomerAddress("Ghost Street");
myCustAcc[2].setCustomerState("CO");
myCustAcc[2].setCustomerZip(87655);
myCustAcc[2].setCustomerUserName("GG111");
myCustAcc[2].setCustomerPin(1111);
myCustAcc[2].setCustomerBalance(0);
custCount++;
do
{
appQuit = false;
Console.Clear();
Console.Write("Enter UserName");
adminInput = Console.ReadLine();
if (adminInput == adminName)
{
Console.Write("Enter Admin Pin");
pinInput = Convert.ToInt32(Console.ReadLine());
if (pinInput != adminPin)
{
Console.WriteLine("You Have Entered Wrong Password");
Console.ReadKey();
continue;
}
else
{
do
{
Console.Clear();
adminQuit = false;
Console.WriteLine("\t\tPlease Select from the Menu");
Console.WriteLine("\t1. Add Customer to Application");
Console.WriteLine("\t2. Return Back to Login Screen");
Console.WriteLine("\t3. Exit the Application");
adminChoice = Convert.ToInt32(Console.ReadLine());
switch (adminChoice)
{
case 1:
//Add customer
break;
case 2:
adminQuit = true;
break;
case 3:
appQuit = true;
break;
default:
Console.WriteLine("Invalid Menu Selection");
return;
}} while (adminQuit == false && appQuit == false);
}}
else {
user = -1;
for (int i = 0; i < custCount; i++)
{
if (adminInput == myCustAcc[i].getCustomerUserName())
{
user = i;
break;} }
if (user == -1)
{
Console.WriteLine("User Does Not Exit !!! Please Try Again");
Console.ReadKey();
continue;
}
Console.Write("Enter User Pin");
if (Convert.ToInt32(Console.ReadLine()) != myCustAcc[user].getCustomerPin() )
{
Console.WriteLine("Invalid Pin");
Console.ReadKey();
continue;
}
do
{
Console.WriteLine("\t\t Welcome to Super Fast Banking Application");
Console.WriteLine("\n<<<Please Select Following Menus>>>");
Console.WriteLine("\t1> GetBalance");
Console.WriteLine("\t2> Deposit");
Console.WriteLine("\t3> Withdraw");
Console.WriteLine("\t4> Modify");
Console.WriteLine("\t5> Display");
Console.WriteLine("\t6> Exit");
input = Convert.ToInt32(Console.ReadLine());
switch (input)
{
case 1:
double balance;
balance = myCustAcc[user].getBalance();
Console.Write("Your Current Balance is {0:C} ",balance);
break;
case 2:
Console.Write("\nPlease enter Numbers to Deposit balance :");
myCustAcc[user].Customerdeposit();
Console.WriteLine("New Balance after Deposit is {0:C}", myCustAcc[user].getBalance());
break;
case 3:
Console.Write("\n Please enter Dollar Amount to Withdraw:");
myCustAcc[user].customerWithdraw();
Console.WriteLine("New Balance after Withdraw is {0:C}",myCustAcc[user].getBalance());
break;
case 4:
//modify
break;
case 5:
double newDisplay;
newDisplay = myCustAcc[user].getBalance();
Console.WriteLine("The Balance in your Account is {0:C}",newDisplay);
break;
case 6:
break;
default: Console.WriteLine("Exit the Application!!!");
break;
}
} while (appQuit == false);
}
Console.ReadKey();
} while (appQuit != true);
}}}
Some code from Account Class
public double getBalance()
{
return customerBalance;
}
public void Customerdeposit()
{
double deposit = Convert.ToDouble(Console.ReadLine());
if (deposit <= 0)
{
Console.WriteLine("\nCannot Deposit");
}
else
{
customerBalance = customerBalance + deposit;
}
}
public void customerWithdraw()
{
double withdraw = Convert.ToDouble(Console.ReadLine());
{
if (withdraw >= 0)
{
customerBalance = customerBalance - withdraw;
}
else
{
Console.WriteLine("There is not Sufficient fund in your account to withdraw");
} }}}
I try to write code for transaction class using the code below
But there are many errors at obj.Customerdeposit(amount); in both if condition and at Update(amount);
class Transaction
{
private int[] arr;
private int cntr;
Transaction()
{
arr = new int[5];
cntr = 0;
}
private void update(int amount)
{
arr[cntr] = amount;
cntr++;
}
public void credit(Account obj, int amount)
{
if(cntr!=5)
{
obj.Customerdeposit(amount);
return;
Update(amount);
}
else
{
Console.WriteLine("Transaction limit exceeded");
}}
public void debit(Account obj, int amount)
{
if(cntr!=5)
{
obj.customerWithdraw(amount);
return;
Update(-amount);
}
else
{
Console.WriteLine("Transaction limit exceeded");
}
}
}
}
You have specified everything from attributes to functions, just write the code.
Now this will be spoonfeeding but then too, your changes are wrong.
Account Class:
public double getBalance()
{
return customerBalance;
}
public bool Customerdeposit()
{
double deposit = Convert.ToDouble(Console.ReadLine());
if (deposit <= 0)
{
return false;
}
customerBalance = customerBalance + deposit;
return true;
}
public bool customerWithdraw()
{
double withdraw = Convert.ToDouble(Console.ReadLine());
{
if (withdraw <= 0 || customerBalance < withdraw )
{
return false;
}
customerBalance = customerBalance - withdraw;
return true;
}
}
}
Now your TransactionClass can be: (add other functionalities yourself)
class Transaction
{
private int[] arr;
private int cntr;
Transaction()
{
arr = new int[5];
cntr = 0;
}
private void update(int amount)
{
arr[cntr]=amount;
cntr++;
}
public void credit(Account obj, int amount)
{
if(cntr!=5)
{
if(obj.CustomerDeposit(amount))
Update(amount); //works only when true returned from above.
else
//print message
}
else
Console.WriteLine("Transaction limit exceeded");
}
public void debit(Account obj, int amount)
{
if(cntr!=5)
{
if(obj.CustomerWithdraw(amount))
Update(-amount);
else
//print any message
}
else
Console.WriteLine("Transaction limit exceeded");
}
}
Call will be made for each transaction:
Transaction trans= new Transaction();
trans.credit(myCustAcc[user],500);

ClistCtrl set color of an item

I have ClistView control in my MFC application. I need to color some of the items according to its content. For example, if it begins with "No Response to", i need to make it red.
So far, i've tried
BEGIN_MESSAGE_MAP(CMessageView, CListView)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,customDraw)
END_MESSAGE_MAP()
void CMessageView::Update()
{
CListCtrl& refCtrl = GetListCtrl();
refCtrl.InsertItem(LVIF_TEXT|LVIF_PARAM,0,CTime::GetCurrentTime().Format("%H:%M:%S"),0,0,0,42);
refCtrl.SetItemText(0,1,"some text");
refCtrl.SetItemText(0,2,"No response to open");
}
void CMessageView::customDraw(NMHDR * pNMHDR, LRESULT * pResult)
{
_ASSERTE(*pResult == 0);
NMLVCUSTOMDRAW * pnmlvcd = (NMLVCUSTOMDRAW *)pNMHDR;
DWORD dwDrawStage = pnmlvcd->nmcd.dwDrawStage;
BOOL bSubItem = dwDrawStage & CDDS_SUBITEM;
dwDrawStage &= ~CDDS_SUBITEM;
switch (dwDrawStage)
{
case CDDS_PREPAINT:
{
*pResult = CDRF_NOTIFYITEMDRAW;
break;
}
case CDDS_ITEMPREPAINT:
case CDDS_SUBITEM:
{
if(pnmlvcd->nmcd.lItemlParam == 42)
{
pnmlvcd->clrText = RGB(255,0,0);
}
*pResult = 0;
break;
}
default:
{
*pResult = 0;
break;
}
}
}
But it does not work. The color does not change. Am i missing something or doing something wrong?
If you have VS2008 SP1, it's much easier to use CMFCListCtrl instead - it has virtual functions you can override to set the foreground and background colours of each row.
This code in a simple example application worked for me. My list control has two columns and two items. The second item, second column has item data set to 42, in this case, only that particular subitem had the text changed to red.
void CMFCTestDlg::OnNMCustomdrawList1(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
// TODO: Add your control notification handler code here
*pResult = CDRF_DODEFAULT;
switch(pLVCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW;
break;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
{
if(1 == pLVCD->iSubItem)
{
if(pLVCD->nmcd.lItemlParam == 42)
{
pLVCD->clrText = RGB(255, 0, 0);
}
}
}
break;
}
}

Can't display Tool Tips in VC++6.0

I'm missing something fundamental, and probably both simple and obvious.
My issue:
I have a view (CPlaybackView, derived from CView).
The view displays a bunch of objects derived from CRectTracker (CMpRectTracker).
These objects each contain a floating point member.
I want to display that floating point member when the mouse hovers over the CMpRectTracker.
The handler method is never executed, although I can trace through OnIntitialUpdate, PreTranslateMessage,
and OnMouseMove.
This is in Visual C++ v. 6.0.
Here's what I've done to try to accomplish this:
1. In the view's header file:
public:
BOOL OnToolTipNeedText(UINT id, NMHDR * pNMHDR, LRESULT * pResult);
private:
CToolTipCtrl m_ToolTip;
CMpRectTracker *m_pCurrentRectTracker;//Derived from CRectTracker
2. In the view's implementation file:
a. In Message Map:
ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnToolTipNeedText)
b. In CPlaybackView::OnInitialUpdate:
if (m_ToolTip.Create(this, TTS_ALWAYSTIP) && m_ToolTip.AddTool(this))
{
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, SHRT_MAX);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, 200);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_RESHOW, 200);
}
else
{
TRACE("Error in creating ToolTip");
}
this->EnableToolTips();
c. In CPlaybackView::OnMouseMove:
if (::IsWindow(m_ToolTip.m_hWnd))
{
m_pCurrentRectTracker = NULL;
m_ToolTip.Activate(FALSE);
if(m_rtMilepostRect.HitTest(point) >= 0)
{
POSITION pos = pDoc->m_rtMilepostList.GetHeadPosition();
while(pos)
{
CMpRectTracker tracker = pDoc->m_rtMilepostList.GetNext(pos);
if(tracker.HitTest(point) >= 0)
{
m_pCurrentRectTracker = &tracker;
m_ToolTip.Activate(TRUE);
break;
}
}
}
}
d. In CPlaybackView::PreTranslateMessage:
if (::IsWindow(m_ToolTip.m_hWnd) && pMsg->hwnd == m_hWnd)
{
switch(pMsg->message)
{
case WM_LBUTTONDOWN:
case WM_MOUSEMOVE:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
m_ToolTip.RelayEvent(pMsg);
break;
}
}
e. Finally, the handler method:
BOOL CPlaybackView::OnToolTipNeedText(UINT id, NMHDR * pNMHDR, LRESULT * pResult)
{
BOOL bHandledNotify = FALSE;
CPoint CursorPos;
VERIFY(::GetCursorPos(&CursorPos));
ScreenToClient(&CursorPos);
CRect ClientRect;
GetClientRect(ClientRect);
// Make certain that the cursor is in the client rect, because the
// mainframe also wants these messages to provide tooltips for the
// toolbar.
if (ClientRect.PtInRect(CursorPos))
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
CString str;
str.Format("%f", m_pCurrentRectTracker->GetMilepost());
ASSERT(str.GetLength() < sizeof(pTTT->szText));
::strcpy(pTTT->szText, str);
bHandledNotify = TRUE;
}
return bHandledNotify;
}
Got it:
Just to put it to bed, here's the result:
BEGIN_MESSAGE_MAP(CPlaybackView, CThreadView)
ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnToolTipNeedText)
END_MESSAGE_MAP()
void CPlaybackView::OnInitialUpdate()
{
if (m_ToolTip.Create(this, TTS_ALWAYSTIP) && m_ToolTip.AddTool(this))
{
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, 2000);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, 1);
m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_RESHOW, 1);
m_ToolTip.Activate(FALSE);
BOOL ena = EnableToolTips(TRUE);
}
else
{
TRACE("Error in creating ToolTip");
}
}
void CPlaybackView::OnMouseMove(UINT nFlags, CPoint point)
{
CPlaybackDoc* pDoc = (CPlaybackDoc*) GetDocument();
if (::IsWindow(m_ToolTip.m_hWnd))
{
CMpRectTracker *pRectTracker = HitTest(point);
if(pRectTracker)
{
m_ToolTip.Activate(TRUE);
}
else
{
m_ToolTip.Activate(FALSE);
}
}
}
BOOL CPlaybackView::OnToolTipNeedText(UINT id, NMHDR * pNMHDR, LRESULT * pResult)
{
BOOL bHandledNotify = FALSE;
CPoint CursorPos;
VERIFY(::GetCursorPos(&CursorPos));
ScreenToClient(&CursorPos);
CRect MilepostRect;
m_rtMilepostRect.GetTrueRect(MilepostRect);
// Make certain that the cursor is in the client rect, because the
// mainframe also wants these messages to provide tooltips for the
// toolbar.
if(MilepostRect.PtInRect(CursorPos))
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
CMpRectTracker *pRectTracker = HitTest(CursorPos);
if(pRectTracker)
{
CString str;
str.Format("%f", pRectTracker->GetMilepost());
ASSERT(str.GetLength() < sizeof(pTTT->szText));
::strcpy(pTTT->szText, str);
bHandledNotify = TRUE;
}
}
return bHandledNotify;
}
BOOL CPlaybackView::PreTranslateMessage(MSG* pMsg)
{
if (::IsWindow(m_ToolTip.m_hWnd) && pMsg->hwnd == m_hWnd)
{
switch(pMsg->message)
{
case WM_LBUTTONDOWN:
case WM_MOUSEMOVE:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
m_ToolTip.RelayEvent(pMsg);
break;
}
}
return CView::PreTranslateMessage(pMsg);
}
CMpRectTracker* CPlaybackView::HitTest(CPoint &point)
{
CPlaybackDoc* pDoc = (CPlaybackDoc*) GetDocument();
ASSERT_VALID(pDoc);
CMpRectTracker *pTracker = NULL;
POSITION pos = pDoc->m_rtMilepostList.GetHeadPosition();
while(pos)
{
CMpRectTracker tracker = pDoc->m_rtMilepostList.GetNext(pos);
if(tracker.HitTest(point) >= 0)
{
m_CurrentRectTracker = tracker;
pTracker = &m_CurrentRectTracker;
break;
}
}
return pTracker;
}

Resources