1

I need to handle the event of changing caret pos in edit control (not richedit control).

I know how to handle event of changing text in the edit, but I don't know how to handle the event of changing caret position in edit control.

I hope someone can help me. Thanks to all.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • As best I can recall there is no notification about change of caret pos, i.e. change of selection, for an ordinary edit control. One way to deal with that is to use a rich edit control and handle [`EN_SELCHANGE`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb787987(v=vs.85).aspx). Another approach could be keep using the ordinary edit control and handle all events that could possibly change the caret pos, namely the navigation keys and mouseclicks. Disclaimer: I'm not 100% sure that `EN_SELCHANGE` covers all caret position changes. I think selection lacks indication of where caret – Cheers and hth. - Alf Nov 19 '17 at 00:08
  • Sounds much like an [XY Problem](http://xyproblem.info). What are you *really* trying to accomplish? – IInspectable Nov 19 '17 at 00:42
  • 2
    Why the downvotes? Don't vote out of **sheer ignorance**. When you don't understand a question, consider whether it could be because you lack the competence to understand it. And keep in mind, lack of understanding doesn't mean you're qualified to vote. It means the opposite, that you should abstain from voting. – Cheers and hth. - Alf Nov 19 '17 at 00:42
  • 1
    @IInspectable: For example, Notepad is not much more than a wrapper around an edit control, and it displays caret position in the status bar. – Cheers and hth. - Alf Nov 19 '17 at 00:44

2 Answers2

2

Once I have done this for displaying line number on status bar by subclassing Edit Control (SetWindowLongPtr) and sending message to parent window on messages that could potentialy move caret.

#define CARET_MOVED_COMMAND_ID    50001

WNDPROC OriginalEditProc = 0;
HWND OriginalEditParent = 0;

LRESULT WINAPI MyEditProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
    // Handle message by original edit control procedure.
    LRESULT result = CallWindowProc( OriginalEditProc, hwnd, msg, wparam, lparam );

    switch ( msg )
    {
    case WM_CHAR:
    case WM_KEYDOWN:
    case WM_KEYUP:
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_LBUTTONDBLCLK:
    case WM_RBUTTONDOWN:
    case WM_RBUTTONUP:
    case WM_RBUTTONDBLCLK:
    case WM_MBUTTONDOWN:
    case WM_MBUTTONUP:
    case WM_MBUTTONDBLCLK:
    case EM_SETSEL:
    // And maybe others...
        // Notify parent of posible caret move.
        // You can recreate EN_SELCHANGE behavior, I have been too lazy
        // and was just sending command (like from menu).
        SendMessage( OriginalEditParent, WM_COMMAND, MAKEWPARAM( CARET_MOVED_COMMAND_ID, 0 ), 0 );
        break;
    }
    return result;
}

// ---- In initialization code ----
// subclass
OriginalEditParent = MyMainWindow;
OriginalEditProc = (WNDPROC) SetWindowLongPtr( EditBoxHwnd, GWLP_WNDPROC, (LONG_PTR)MyEditProc );

// ---- In parent window message handling ----
case WM_COMMAND:
    switch ( LOWORD( wparam ) )
    {
    case CARET_MOVED_COMMAND_ID:
        {
            // You sould execute this code in EN_CHANGE handler,
            // so it can handle cuting, pasting, undo etc.
            int line = (int) SendMessage( EditBoxHwnd, EM_LINEFROMCHAR, -1, 0 );
            // Update status bar. Could be optimized by remembering
            // displayed line number and updating only when it changes.
            wchar_t buff[50];
            wsprintf( buff, L"%d", line );
            SendMessage( StatusBarHwnd, SB_SETTEXT, MAKEWPARAM( 1, SBT_NOBORDERS ), (LPARAM) buff );
        }
        break;
    }
    break;
Daniel Sęk
  • 2,504
  • 1
  • 8
  • 17
  • Calling `SetWindowLongPtr` to [subclass a control](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773183.aspx) has been the wrong solution for more than a decade. – IInspectable Nov 19 '17 at 13:00
  • I have only made this work by using `PostMessage` instead of `SendMessage`, it seems like when you try to get any info from the edit control in it's custom `WNDPROC` (even **after** `CallWindowProc` is called), it doesn't provide the updated state (it is "behind" for some ungodly reason). Could you explain why this happens and/or fix your post? – Jacob Jan 14 '21 at 18:29
1

You can set the position of the caret in the edit control by sending an EM_SETSEL message, that selects from the desired position to the same position:

SendMessage(hWnd, EM_SETSEL, pos, pos);

Getting the position of the caret requires to send an EM_GETSEL message. Note that the if the start and the end are at same position, you know the precise position of the caret. If there's a difference, it means that text is selected, and you could take as position the last one.

There's no specific event for tracking only caret/selection changes. In your event loop, you need to catch key press and mouse events, and check if they changed the position. But wouldn't it possible for you to read the caret position only when you need it instead of actively tracking it ?

Christophe
  • 68,716
  • 7
  • 72
  • 138