Text Selection with CRichEditCtrl in MFC - c++

I have CRichEditCtrl object which is read only(Text is for read and not allowed to modified). I want to provide functionality of Text Selection with Mouse for text displayed with CRichEditCtrl object.
Following Code is working to capture event for Left Mouse Button - DOWN & UP
BOOL CReportFormView::PreTranslateMessage(MSG* pMsg)
{
if (m_EditNs->GetFocus()!=NULL)
{
switch (pMsg->message)
{
case WM_LBUTTONDOWN:
return TRUE;
case WM_LBUTTONUP:
return TRUE;
}
}
}
Now looking for some code to write in case block which will highlight selected text. I want to know if there is any API available for CRichEditCtrl object which help to track at which location user pressed Left Mouse Button and released

You could use member function CString strText = m_myRichEditCtrl.GetSelText(); or some other member function. Like GetSel() just a suggestion.

I think you will need to use the EM_CHARFROMPOS message. ex. some form of this:
POINTL pt { x,y }; // ... screen coordinates to test relative to edit
DWORD info = m_EditNS->SendMessage(EM_CHARFROMPOS, 0, pt);
int charIndex = LOWORD(info);
int line = HIWORD(info);
After that, set the selection with normal selection methods.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb761566(v=vs.85).aspx

Related

CMFCToolBarComboBoxEdit handle delete button

CMFCToolBarComboBoxEdit handles the BackSpace button but it doesn't handle the delete button.
Is there any way to handle the delete button except PreTranslateMessage?
if yes, what is this way?
if no, then how can I get the current cursor position in the control and how to remove specific char using its index so I can remove the char which on the right of the cursor if nothing is selected?
Thanks in advance.
Yes use, PreTranslateMessage. If you detected the sequence that should be handled, call:
if (..) // Check if you have a message that should
// be passed to the window directly
{
TranslateMessage(pMsg);
DispatchMessage(pMsg);
return TRUE;
}
You can do this always in PreTranslateMessage, when you detect that the message should be handled by the default control, and should not be handled by any other control in the chain of windows that execute PreTranslateMessage. This is also helpful if you have a combo box open and want the Page Down/Up handled internally and not by the view or any accelerator.
I've handled the delete key in the PreTranslateMessage as follows:
BOOL PreTranslateMessage(MSG* pMsg)
{
if(WM_KEYDOWN == pMsg->message && VK_DELETE == pMsg->wParam)
{
int iStartChar = -1, iEndChar = -1;
GetSel(iStartChar, iEndChar);
if(iStartChar != iEndChar)
Clear(); //clear the selected text
else
{
SetSel(iStartChar, iStartChar + 1);
Clear();
}
}
return CMFCToolBarComboBoxEdit::PreTranslateMessage(pMsg);
}

How to make MFC Ribbon Statusbar act like the regular CStatusBar

The first image shows what I want to do. The second one shows what I get.
I want the status bar to show the state of the special keys CAPS LOCK, NUM LOCK and SCROLL LOCK. This image is from an old project using the CStatusBar.
This snapshot is from CMainFrame class.
This image shows how I am doing it in Visual C++ 2015 MFC and the results I get. This snapshot is from CMainFrame class, too.
My question is : Can anyone tell me how my application can intercept the change from toggle buttons CAPS LOCK and NUM LOCK then update the user interface.
I tried to use this code but it doesn't work :
ON_UPDATE_COMMAND_UI(ID_INDICATOR_STYLE, &CMainFrame::OnUpdateStyle)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_FOLD, &CMainFrame::OnUpdateFold)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_OVR, &CMainFrame::OnUpdateInsert)
Thanks in advance.
First of all the standard behavior of CStatusBar is not supported by CMFCRibbonStatusBar.
The good news is that it is very easy to implement the same behavior.
Here is what you have to do in order to implement it in your application:
Add this to message map of your main frame class or child frame in case of MDI:
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, &CMainFrame::OnUpdateButtonsState)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, &CMainFrame::OnUpdateButtonsState)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, &CMainFrame::OnUpdateButtonsState)
The actual update handler should look like this:
void CMainFrame::OnUpdateButtonsState(CCmdUI* pCmdUI)
{
UINT nVK;
UINT flag = 0x0001;
switch (pCmdUI->m_nID)
{
case ID_INDICATOR_CAPS:
nVK = VK_CAPITAL;
break;
case ID_INDICATOR_NUM:
nVK = VK_NUMLOCK;
break;
case ID_INDICATOR_SCRL:
nVK = VK_SCROLL;
break;
case ID_INDICATOR_KANA:
nVK = VK_KANA;
break;
default:
TRACE(traceAppMsg, 0, "Warning: OnUpdateKeyIndicator - unknown indicator 0x%04X.\n",
pCmdUI->m_nID);
pCmdUI->ContinueRouting();
return; // not for us
}
pCmdUI->SetCheck(::GetKeyState(nVK) & flag);
}
I solved it by moving the code to CChildFrame class.
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, &CChildFrame::OnUpdateIndicators)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, &CChildFrame::OnUpdateIndicators)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, &CChildFrame::OnUpdateIndicators)
And then
void CChildFrame::OnUpdateIndicators(CCmdUI *pCmdUI)
{
pCmdUI->Enable();
// ... the rest of the above code
CString text;
if (::GetKeyState(nVK) & flag)
text.LoadStringW(pCmdUI->m_nID);
pCmdUI->SetText(text);
}

Working with Windows mouse event states in c++ VS2012 - 13

I am working on a GameEngine Project and my framework is as follows I have an Engine Class that is a base class that creates a window and setups up an open GL context and handles windows message events. From this I have a derived class that is a Game class. Some functions are purely virtual. My project is too large to post here so I will show code segments that are relevant.
I am working within these two classes and the task I am trying to achieve is to make an object fade in and out of view with a left mouse click. The position of the mouse cursor is irrelevant. This can easily be done by changing the alpha value from 1.0f to 0.0f. The object is initially visible and when the first mouse click & release operation happens I need it to fade out. Then the next time the mouse button is pressed & released I need it to fade back into view to full opacity. I am stuck at this point.
This is the section of my Engine::messageHandler() that is of importance
Engine::MessageHandler( unsigned uMsg, WPARAM wParam, LPARAM lParam ) {
switch( uMsg ) {
// ... Irrelevant Code Here
case WM_LBUTTONDOW: {
m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = true;
mouseInput(); // purely virtual - implemented by Game class
return true;
}
case WM_LBUTTONUP: {
m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTOM] = false;
mouseInput(); // purely virtual - implemented by Game class
return true;
}
// ... More Irrelevant Code Here
default {
return false;
}
}
} // messageHandler
It is in my Game::mouseInput() function where I need to change the alpha value of my rendered object with a mouse click & release operation.
void Game::mouseInput() {
} // mouseInput
And I have tried if statements & while loops to no avail.
I was able to get the object to fade by an incremental amount each time as I continued to clicking the left mouse button. The code looked something like this
Game::mouseInput {
static glm::vec4 sliceColor = m_pSliceFade->getColor();
if ( m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] == true ) {
sliceColor.a -= 0.05f;
m_pSliceFade->setColor( sliceColor );
}
} // mouseInput
However, this is not the behavior I want or need. I am struggling here because each time we go into the Engine::messageHandler() for both mouse down & up events my purely virtual Game::mouseInput() is being called. I guess I am having writers block because I can not seem to figure out how to continuously change the alpha value after each click & release event and then reverse the direction of the alpha value on the following click & release event within this framework. Initially all mouse buttons bool tracking variables are set to false by default on initialization.
Any kind of suggestions or help would be supportive and helpful. Thank you kindly in advance.

Why double click event detecting on empty area of listBox in mfc

case 1 : I have a MFC dialog box having a LisBox.
I have added two items in listbox.
Whenever i am double clicking on empty area of list box i.e. not double clicking
on either of two item.
Double click is detecting on empty area of listbox.
case 2: When i created a small MFC test application with listbox. it iis detecting double click only on item, not on empty area.
I compared all properties of both cases but couldn't figure out what is the problem.
Anyone has idea what is going wrong in case 1.
I think it is abnormal process. I've tested your situation in VS2010. In my MFC test application sent LBN_DBLCLK when I double clicked on empty area. If you do not really want to know the reason this weired situation, you can just check whether double click event is occurred on empty area or not. I think it is better way for saving your time.
void CMfcDlgTestDlg::OnLbnDblclkList2()
{
// TODO: Add your control notification handler code here
CListBox* list = (CListBox*)(GetDlgItem(IDC_LIST2));
int cur_sel = list->GetCurSel();
if (cur_sel == -1)
{
return;
}
}
EDIT : FOR ANOTHER CASE
When one of list box item is already selected, how can it handle on ON_LBN_DBLCLK handler?
I think there will be some available methods for solving this, however I use below code and it can be useful way, also.
void CMfcDlgTestDlg::OnLbnDblclkList2()
{
// TODO: Add your control notification handler code here
CListBox* list = (CListBox*)(GetDlgItem(IDC_LIST2));
CPoint cursor;
cursor.x = GetCurrentMessage()->pt.x;
cursor.y = GetCurrentMessage()->pt.y;
list->ScreenToClient(&cursor);
BOOL is_outside = FALSE;
UINT item_index = list->ItemFromPoint(cursor, is_outside);
if(is_outside)
{
//mouse clicked on empty area
return ;
}
else
{
// do something with 'item_index'
}
}
I hope this will help you a little.

Changing color of a specific character in an item in CListCtrl in MFC

I have a CListCtrl and I need to change the color of A SPECIFIC character/set of characters (which I choose by comparison) from the text of every cell in the list.
I know how to change the color of the entire text of the cell when I find the character/set of characters (by using 'strstr' command), but I can't find an example which shows how to change ONLY the character/set of characters.
Here is a sample of my code:
void Agenda::OnCustomdrawMyList( NMHDR* pNMHDR, LRESULT* pResult )
{
NMLVCUSTOMDRAW* pLVCD = (NMLVCUSTOMDRAW*)pNMHDR;
*pResult = CDRF_DODEFAULT;
if (CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
{
*pResult = CDRF_NOTIFYITEMDRAW;
return;
}else if (CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
{
*pResult = CDRF_NOTIFYSUBITEMDRAW;
return;
}else if ( (CDDS_SUBITEM | CDDS_ITEMPREPAINT) == pLVCD->nmcd.dwDrawStage )
{
// So right now I am in the stage where a SUBITEM is PREPAINTED
int nItem = pLVCD->nmcd.dwItemSpec;
int nSubItem = pLVCD->iSubItem;
char a[100];
listControl.GetItemText(nItem,nSubItem,a,100);
COLORREF textColorFound, textColorDefault;
textColorDefault = RGB(0,0,0);
pLVCD->clrText = textColorDefault;
char* startingFrom;
if( (startingFrom = strstr(a,filterText)) != NULL ) {
// Could I set a pointer here or something like that so
// the coloring could start only from 'startingFrom'
// and stop at 'strlen(filterText)' characters?
textColorFound = RGB(205,92,92);
pLVCD->clrText = textColorFound;
}
*pResult = CDRF_DODEFAULT;
}
}
listControl is the variable for my CListCtrl
the other things are pretty self-explanatory
No, you cannot do this. What you will have to do is custom-draw the text in question. This will be tricky because you will have to do it with two different calls, between which you will have to manually adjust the color and the drawing location to account for the intercharacter spacing etc. And you better hope that you don't need to do multi-line output.
Take a look at the article Neat Stuff to Do in List Controls Using Custom Draw by Michael Dunn on CodeProject to get some ideas on how to proceed.
Alternatively, if you can use the Toolkit Pro toolkit from CodeJock you can leverage their "XAML" support (I use quotes because it's not really XAML, but their own implementation of a subset of XAML) and let them do all the hard work.
Digging on the same issue; But I wouldn't go so far as modifying/adding to the default Windows behaviour for painting strings... apparently that would be the endpoint of having it owner-drawn.(aici am murit si eu :).